Merge branch 'dev' into Vincent
04/03/2022
This commit is contained in:
commit
475587d541
13
build.gradle
13
build.gradle
@ -13,11 +13,14 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
implementation group: 'io.jsonwebtoken', name: 'jjwt', version: '0.9.0'
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-web'
|
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||||
runtimeOnly 'mysql:mysql-connector-java'
|
implementation 'org.springframework.boot:spring-boot-starter-web'
|
||||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
implementation 'org.springframework.boot:spring-boot-starter-security'
|
||||||
developmentOnly 'org.springframework.boot:spring-boot-devtools'
|
developmentOnly 'org.springframework.boot:spring-boot-devtools'
|
||||||
|
runtimeOnly 'mysql:mysql-connector-java'
|
||||||
|
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||||
|
testImplementation 'org.springframework.security:spring-security-test'
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
|
@ -1,13 +1,33 @@
|
|||||||
package fr.cardon.simpleat;
|
package fr.cardon.simpleat;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
|
||||||
|
import fr.cardon.simpleat.exception.ExistingUsernameException;
|
||||||
|
import fr.cardon.simpleat.model.EnumRole;
|
||||||
|
import fr.cardon.simpleat.model.Personne;
|
||||||
|
import fr.cardon.simpleat.service.PersonneService;
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
public class SimpleatApplication {
|
public class SimpleatApplication {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(SimpleatApplication.class, args);
|
SpringApplication.run(SimpleatApplication.class, args);
|
||||||
}
|
}
|
||||||
|
@Bean
|
||||||
|
public BCryptPasswordEncoder bCryptPasswordEncoder() {
|
||||||
|
return new BCryptPasswordEncoder();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import java.util.Collection;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@ -12,16 +13,21 @@ import org.springframework.web.bind.annotation.PathVariable;
|
|||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.PutMapping;
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import fr.cardon.simpleat.dto.JsonWebToken;
|
||||||
|
import fr.cardon.simpleat.exception.ExistingUsernameException;
|
||||||
|
import fr.cardon.simpleat.exception.InvalidCredentialsException;
|
||||||
import fr.cardon.simpleat.model.Personne;
|
import fr.cardon.simpleat.model.Personne;
|
||||||
import fr.cardon.simpleat.model.Role;
|
import fr.cardon.simpleat.model.Role;
|
||||||
import fr.cardon.simpleat.repository.PersonneRepository;
|
import fr.cardon.simpleat.repository.PersonneRepository;
|
||||||
import fr.cardon.simpleat.repository.RoleRepository;
|
import fr.cardon.simpleat.repository.RoleRepository;
|
||||||
|
import fr.cardon.simpleat.service.PersonneService;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@CrossOrigin("*")
|
@CrossOrigin("http://localhost:4200")
|
||||||
public class PersonneController {
|
public class PersonneController {
|
||||||
|
|
||||||
|
|
||||||
@ -31,6 +37,11 @@ public class PersonneController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private RoleRepository roleRepository;
|
private RoleRepository roleRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PersonneService personneService;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@GetMapping("/")
|
@GetMapping("/")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String home(){
|
public String home(){
|
||||||
@ -57,18 +68,21 @@ public class PersonneController {
|
|||||||
|
|
||||||
|
|
||||||
@GetMapping("/users")
|
@GetMapping("/users")
|
||||||
|
//@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||||
public Collection<Personne> findAll(){
|
public Collection<Personne> findAll(){
|
||||||
|
|
||||||
return personneRepository.findAll();
|
return personneRepository.findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/user/{id}")
|
@GetMapping("/user/{id}")
|
||||||
|
//@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||||
public Personne findPersonneById(@PathVariable int id){
|
public Personne findPersonneById(@PathVariable int id){
|
||||||
|
|
||||||
return personneRepository.findById(id);
|
return personneRepository.findById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/add-user")
|
@PostMapping("/add-user")
|
||||||
|
//@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||||
public ResponseEntity<?> ajoutPersonne(@RequestBody Personne personne){
|
public ResponseEntity<?> ajoutPersonne(@RequestBody Personne personne){
|
||||||
return ResponseEntity.status(HttpStatus.OK).body(personneRepository.save(personne));
|
return ResponseEntity.status(HttpStatus.OK).body(personneRepository.save(personne));
|
||||||
}
|
}
|
||||||
@ -99,6 +113,28 @@ public class PersonneController {
|
|||||||
return roleRepository.findCollectionById(idRole);
|
return roleRepository.findCollectionById(idRole);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/signin")
|
||||||
|
public ResponseEntity<JsonWebToken> signIn(@RequestBody Personne personne) {
|
||||||
|
try {
|
||||||
|
// ici on créé un JWT en passant l'email et le mot de passe
|
||||||
|
// récupéré de l'objet user passé en paramètre.
|
||||||
|
return ResponseEntity.ok(new JsonWebToken(personneService.signin(personne.getEmail(), personne.getPassword())));
|
||||||
|
} catch (InvalidCredentialsException ex) {
|
||||||
|
// on renvoie une réponse négative
|
||||||
|
return ResponseEntity.badRequest().build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/sign-up")
|
||||||
|
public ResponseEntity<JsonWebToken> signUp(@RequestBody Personne personne) {
|
||||||
|
try {
|
||||||
|
return ResponseEntity.ok(new JsonWebToken(personneService.signup(personne)));
|
||||||
|
} catch (ExistingUsernameException ex) {
|
||||||
|
return ResponseEntity.badRequest().build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// public Personne findById(int id) {
|
// public Personne findById(int id) {
|
||||||
// return personneRepository.getById(id);
|
// return personneRepository.getById(id);
|
||||||
// }
|
// }
|
||||||
|
@ -11,7 +11,6 @@ import org.springframework.web.bind.annotation.DeleteMapping;
|
|||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.PutMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
@ -66,6 +65,4 @@ public class PreferenceController {
|
|||||||
PreferencePK id = new PreferencePK(personneRepository.getById(iduser) ,restaurantRepository.getById(idrestau));
|
PreferencePK id = new PreferencePK(personneRepository.getById(iduser) ,restaurantRepository.getById(idrestau));
|
||||||
preferenceRepository.deleteById(id);
|
preferenceRepository.deleteById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import java.util.Collection;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@ -37,12 +38,14 @@ public class RestaurantController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/add-restaurant")
|
@PostMapping("/add-restaurant")
|
||||||
|
//@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||||
public ResponseEntity<?> ajoutRestaurant(@RequestBody Restaurant personne){
|
public ResponseEntity<?> ajoutRestaurant(@RequestBody Restaurant personne){
|
||||||
return ResponseEntity.status(HttpStatus.OK).body(restaurantRepository.save(personne));
|
return ResponseEntity.status(HttpStatus.OK).body(restaurantRepository.save(personne));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@PutMapping(value = "/update-restaurant/{id}")
|
@PutMapping(value = "/update-restaurant/{id}")
|
||||||
|
|
||||||
public ResponseEntity<?> modifRestaurant(@PathVariable int id, @RequestBody Restaurant personne){
|
public ResponseEntity<?> modifRestaurant(@PathVariable int id, @RequestBody Restaurant personne){
|
||||||
return ResponseEntity.status(HttpStatus.OK).body(restaurantRepository.save(personne));
|
return ResponseEntity.status(HttpStatus.OK).body(restaurantRepository.save(personne));
|
||||||
}
|
}
|
||||||
|
21
src/main/java/fr/cardon/simpleat/dto/JsonWebToken.java
Normal file
21
src/main/java/fr/cardon/simpleat/dto/JsonWebToken.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package fr.cardon.simpleat.dto;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classe spécifique DTO (Data Transfer Object) qui retourne un Jeton au format JSON (REST response)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class JsonWebToken {
|
||||||
|
|
||||||
|
private final String token;
|
||||||
|
|
||||||
|
public JsonWebToken(String token) {
|
||||||
|
this.token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getToken() {
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
55
src/main/java/fr/cardon/simpleat/dto/PersonneDto.java
Normal file
55
src/main/java/fr/cardon/simpleat/dto/PersonneDto.java
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
package fr.cardon.simpleat.dto;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
import com.sun.istack.NotNull;
|
||||||
|
|
||||||
|
import fr.cardon.simpleat.model.Role;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifique : AppUser DTO permet de renvoyer un User sans le mot de passe (REST response).
|
||||||
|
*/
|
||||||
|
public class PersonneDto {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
private String email;
|
||||||
|
private List<Role> roleList;
|
||||||
|
|
||||||
|
public PersonneDto() { }
|
||||||
|
|
||||||
|
public PersonneDto(@NotNull String email) {
|
||||||
|
this(email,null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersonneDto(@NotNull String email, List<Role> roleList) {
|
||||||
|
this.email = email;
|
||||||
|
this.roleList = roleList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Role> getRoleList() {
|
||||||
|
return roleList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRoleList(List<Role> roleList) {
|
||||||
|
this.roleList = roleList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package fr.cardon.simpleat.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classe personnalisée pour gérer un message si l'utilisateur (User) existe en Base de données
|
||||||
|
*/
|
||||||
|
public class ExistingUsernameException extends Exception {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage()
|
||||||
|
{
|
||||||
|
return "Désolé, l'utilisateur existe déjà en Base de données !";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package fr.cardon.simpleat.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specific exception that should be thrown when user credentials are not valid.
|
||||||
|
*/
|
||||||
|
public class InvalidCredentialsException extends Exception {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -6483691380297851921L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage()
|
||||||
|
{
|
||||||
|
return "L'accréditation est invalide !";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package fr.cardon.simpleat.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specific exception that should be thrown when a JWT has an invalid format.
|
||||||
|
*/
|
||||||
|
public class InvalidJWTException extends Exception {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -6546999838071338632L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage()
|
||||||
|
{
|
||||||
|
return "Le format JWT est invalide !";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
14
src/main/java/fr/cardon/simpleat/model/EnumRole.java
Normal file
14
src/main/java/fr/cardon/simpleat/model/EnumRole.java
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package fr.cardon.simpleat.model;
|
||||||
|
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
|
||||||
|
public enum EnumRole implements GrantedAuthority {
|
||||||
|
|
||||||
|
ROLE_ADMIN, ROLE_CREATOR, ROLE_READER;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAuthority() {
|
||||||
|
return name();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -3,10 +3,15 @@ package fr.cardon.simpleat.model;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import javax.persistence.CascadeType;
|
import javax.persistence.CascadeType;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.ElementCollection;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.EnumType;
|
||||||
|
import javax.persistence.Enumerated;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
import javax.persistence.GeneratedValue;
|
import javax.persistence.GeneratedValue;
|
||||||
import javax.persistence.GenerationType;
|
import javax.persistence.GenerationType;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
@ -18,6 +23,8 @@ import javax.persistence.OneToMany;
|
|||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
public class Personne {
|
public class Personne {
|
||||||
|
|
||||||
@ -28,6 +35,7 @@ public class Personne {
|
|||||||
private String password;
|
private String password;
|
||||||
private Collection<Role> roles = new ArrayList<Role>();
|
private Collection<Role> roles = new ArrayList<Role>();
|
||||||
private Collection<Preference> preference = new ArrayList<Preference>();
|
private Collection<Preference> preference = new ArrayList<Preference>();
|
||||||
|
private List<EnumRole> roleList;
|
||||||
|
|
||||||
|
|
||||||
public Personne() {
|
public Personne() {
|
||||||
@ -35,6 +43,30 @@ public class Personne {
|
|||||||
// TODO Auto-generated constructor stub
|
// TODO Auto-generated constructor stub
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public Personne(String nom, String prenom, String email, String password, List<EnumRole> roleList) {
|
||||||
|
super();
|
||||||
|
this.nom = nom;
|
||||||
|
this.prenom = prenom;
|
||||||
|
this.email = email;
|
||||||
|
this.password = password;
|
||||||
|
this.roleList = roleList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public Personne(String email, String password, List<EnumRole> roleList) {
|
||||||
|
super();
|
||||||
|
this.email = email;
|
||||||
|
this.password = password;
|
||||||
|
this.roleList = roleList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public Personne(String nom, String prenom, String email, String password) {
|
public Personne(String nom, String prenom, String email, String password) {
|
||||||
super();
|
super();
|
||||||
@ -45,17 +77,20 @@ public class Personne {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Personne(String nom, String prenom, String email, String password,
|
||||||
|
Collection<fr.cardon.simpleat.model.Role> roles, Collection<Preference> preference,
|
||||||
public Personne(String nom, String prenom, String email, String password, Collection<Role> roles) {
|
List<EnumRole> roleList) {
|
||||||
super();
|
super();
|
||||||
this.nom = nom;
|
this.nom = nom;
|
||||||
this.prenom = prenom;
|
this.prenom = prenom;
|
||||||
this.email = email;
|
this.email = email;
|
||||||
this.password = password;
|
this.password = password;
|
||||||
this.roles = roles;
|
this.roles = roles;
|
||||||
|
this.preference = preference;
|
||||||
|
this.roleList = roleList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
@Column(name = "id_personne")
|
@Column(name = "id_personne")
|
||||||
@ -113,7 +148,7 @@ public class Personne {
|
|||||||
|
|
||||||
|
|
||||||
@OneToMany(mappedBy = "preferencePK.personne", cascade = CascadeType.REMOVE)
|
@OneToMany(mappedBy = "preferencePK.personne", cascade = CascadeType.REMOVE)
|
||||||
@JsonIgnore
|
//@JsonIgnore
|
||||||
public Collection<Preference> getPreference() {
|
public Collection<Preference> getPreference() {
|
||||||
return preference;
|
return preference;
|
||||||
}
|
}
|
||||||
@ -123,4 +158,17 @@ public class Personne {
|
|||||||
this.preference = preference;
|
this.preference = preference;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ElementCollection(fetch = FetchType.EAGER)
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
public List<EnumRole> getRoleList() {
|
||||||
|
return roleList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setRoleList(List<EnumRole> roleList) {
|
||||||
|
this.roleList = roleList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -51,4 +51,4 @@ public class Preference {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -10,6 +10,7 @@ import javax.persistence.JoinColumn;
|
|||||||
import javax.persistence.ManyToOne;
|
import javax.persistence.ManyToOne;
|
||||||
import javax.persistence.PrimaryKeyJoinColumn;
|
import javax.persistence.PrimaryKeyJoinColumn;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
|
||||||
|
|
||||||
@ -39,7 +40,7 @@ public class PreferencePK implements Serializable {
|
|||||||
|
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
@PrimaryKeyJoinColumn(name="id_personne", referencedColumnName ="id_personne" )
|
@PrimaryKeyJoinColumn(name="id_personne", referencedColumnName ="id_personne" )
|
||||||
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
|
@JsonIgnore
|
||||||
public Personne getPersonne() {
|
public Personne getPersonne() {
|
||||||
return personne;
|
return personne;
|
||||||
}
|
}
|
||||||
@ -64,4 +65,4 @@ public class PreferencePK implements Serializable {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -14,9 +14,7 @@ import javax.persistence.JoinTable;
|
|||||||
import javax.persistence.ManyToMany;
|
import javax.persistence.ManyToMany;
|
||||||
import javax.persistence.OneToMany;
|
import javax.persistence.OneToMany;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonBackReference;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
|
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@ -35,8 +33,6 @@ public class Restaurant {
|
|||||||
private String website;
|
private String website;
|
||||||
private Collection<TypeRestau> typerestaus = new ArrayList<TypeRestau>();
|
private Collection<TypeRestau> typerestaus = new ArrayList<TypeRestau>();
|
||||||
private Collection<Preference> preference = new ArrayList<Preference>();
|
private Collection<Preference> preference = new ArrayList<Preference>();
|
||||||
//TODO @OneToMany relier avec une collec de preferences
|
|
||||||
|
|
||||||
public Restaurant() {
|
public Restaurant() {
|
||||||
super();
|
super();
|
||||||
// TODO Auto-generated constructor stub
|
// TODO Auto-generated constructor stub
|
||||||
@ -152,7 +148,6 @@ public class Restaurant {
|
|||||||
this.typerestaus = typerestaus;
|
this.typerestaus = typerestaus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@OneToMany(mappedBy = "preferencePK.restau", cascade = CascadeType.REMOVE)
|
@OneToMany(mappedBy = "preferencePK.restau", cascade = CascadeType.REMOVE)
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
public Collection<Preference> getPreference() {
|
public Collection<Preference> getPreference() {
|
||||||
@ -163,5 +158,4 @@ public class Restaurant {
|
|||||||
public void setPreference(Collection<Preference> preference) {
|
public void setPreference(Collection<Preference> preference) {
|
||||||
this.preference = preference;
|
this.preference = preference;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@ import javax.persistence.ManyToMany;
|
|||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonBackReference;
|
import com.fasterxml.jackson.annotation.JsonBackReference;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
|
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package fr.cardon.simpleat.repository;
|
package fr.cardon.simpleat.repository;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
@ -9,5 +11,11 @@ import fr.cardon.simpleat.model.Personne;
|
|||||||
public interface PersonneRepository extends JpaRepository<Personne, Integer> {
|
public interface PersonneRepository extends JpaRepository<Personne, Integer> {
|
||||||
|
|
||||||
Personne findById(int id);
|
Personne findById(int id);
|
||||||
|
|
||||||
|
Optional<Personne> findByEmail(String email);
|
||||||
|
|
||||||
|
boolean existsByEmail(String email);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
package fr.cardon.simpleat.security;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.servlet.FilterChain;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
|
import fr.cardon.simpleat.exception.InvalidJWTException;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filtre specifique en charge d'analyser la requête HTTP qui arrive vers notre Serveur et qui doit
|
||||||
|
* contenir un JWT valide.
|
||||||
|
*/
|
||||||
|
public class JwtTokenFilter extends OncePerRequestFilter {
|
||||||
|
private JwtTokenProvider jwtTokenProvider;
|
||||||
|
|
||||||
|
public JwtTokenFilter(JwtTokenProvider jwtTokenProvider) {
|
||||||
|
this.jwtTokenProvider = jwtTokenProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
|
||||||
|
String token = jwtTokenProvider.resolveToken(httpServletRequest);
|
||||||
|
try {
|
||||||
|
if (token != null && jwtTokenProvider.validateToken(token)) {
|
||||||
|
Authentication auth = jwtTokenProvider.getAuthentication(token);
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||||
|
}
|
||||||
|
} catch (InvalidJWTException ex) {
|
||||||
|
// permet de garantir que le AppUser n'est pas authentifié
|
||||||
|
SecurityContextHolder.clearContext();
|
||||||
|
httpServletResponse.sendError(HttpStatus.BAD_REQUEST.value(), "JWT invalide !");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
filterChain.doFilter(httpServletRequest, httpServletResponse);
|
||||||
|
}
|
||||||
|
}
|
189
src/main/java/fr/cardon/simpleat/security/JwtTokenProvider.java
Normal file
189
src/main/java/fr/cardon/simpleat/security/JwtTokenProvider.java
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
package fr.cardon.simpleat.security;
|
||||||
|
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
|
||||||
|
import fr.cardon.simpleat.exception.InvalidJWTException;
|
||||||
|
import fr.cardon.simpleat.model.EnumRole;
|
||||||
|
import fr.cardon.simpleat.repository.PersonneRepository;
|
||||||
|
import io.jsonwebtoken.Claims;
|
||||||
|
import io.jsonwebtoken.JwtException;
|
||||||
|
import io.jsonwebtoken.Jwts;
|
||||||
|
import io.jsonwebtoken.SignatureAlgorithm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JWT : classe utilitaire chargée de fournir le Jeton (Token) et les vérifications
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class JwtTokenProvider {
|
||||||
|
|
||||||
|
// on récupère le secret dans notre fichier application.properties
|
||||||
|
@Value("${security.jwt.token.secret-key:secret-key}")
|
||||||
|
private String secretKey;
|
||||||
|
|
||||||
|
// ici on met la valeur par défaut
|
||||||
|
@Value("${security.jwt.token.expire-length:3600000}")
|
||||||
|
private long validityInMilliseconds = 3600000; // 1h pour être pénard
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserDetailsService userDetailsService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PersonneRepository personneRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cette méthode d'initialisation s'exécute avant le constructeur
|
||||||
|
* Elle encode notre code secret en base64 pour la transmission dans le header
|
||||||
|
*/
|
||||||
|
@PostConstruct
|
||||||
|
protected void init() {
|
||||||
|
secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Methode qui crée le Token avec :
|
||||||
|
* username comme un champ "sub",
|
||||||
|
* User Role comme champ "auth"
|
||||||
|
* "iat" comme date du jour ,
|
||||||
|
* "exp" as now date + validity time.
|
||||||
|
* claims = les droits
|
||||||
|
struture :
|
||||||
|
HEADER : Algo + Type de Token
|
||||||
|
{
|
||||||
|
"alg": "HS256",
|
||||||
|
"typ": "JWT"
|
||||||
|
}
|
||||||
|
|
||||||
|
PAYLOAD : data
|
||||||
|
{
|
||||||
|
"sub": "pbouget",
|
||||||
|
"auth": [
|
||||||
|
"ROLE_ADMIN",
|
||||||
|
"ROLE_CREATOR",
|
||||||
|
"ROLE_READER"
|
||||||
|
],
|
||||||
|
"iat": 1589817421,
|
||||||
|
"exp": 1589821021
|
||||||
|
}
|
||||||
|
|
||||||
|
Signature :
|
||||||
|
|
||||||
|
Signature avec code secret :
|
||||||
|
|
||||||
|
HMACSHA256(
|
||||||
|
base64UrlEncode(header) + "." +
|
||||||
|
base64UrlEncode(payload),
|
||||||
|
03888dd6ceb88c3fee410a70802fb93d483fd52d70349d8f7e7581ae346cf658
|
||||||
|
)
|
||||||
|
|
||||||
|
JWT génèrer avec cette info :
|
||||||
|
header = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
|
||||||
|
payload = eyJzdWIiOiJwYm91Z2V0IiwiYXV0aCI6WyJST0xFX0FETUlOIiwiUk9MRV9DUkVBVE9SIiwiUk9MRV9SRUFERVIiXSwiaWF0IjoxNTg5ODE3NDIxLCJleHAiOjE1ODk4MjEwMjF9.
|
||||||
|
signature = lrKQIkrCzNMwzTN-hs_EdoYYxrb59sAlku7nmaml0vk
|
||||||
|
|
||||||
|
vérifier sur https://jwt.io
|
||||||
|
|
||||||
|
* @param username the user username.
|
||||||
|
* @param roles the user roles.
|
||||||
|
* @return the created JWT as String.
|
||||||
|
* @throws JsonProcessingException
|
||||||
|
*/
|
||||||
|
public String createToken(String email, List<EnumRole> roleList){
|
||||||
|
|
||||||
|
Claims claims = Jwts.claims().setSubject(email);
|
||||||
|
claims.put("userId", personneRepository.findByEmail(email).get().getId());
|
||||||
|
claims.put("auth", roleList.stream().map(s -> new SimpleGrantedAuthority(s.getAuthority())).filter(Objects::nonNull).collect(Collectors.toList()));
|
||||||
|
|
||||||
|
System.out.println("claims = "+claims);
|
||||||
|
// claims = {sub=pbouget, auth=[ROLE_ADMIN, ROLE_CREATOR, ROLE_READER]}
|
||||||
|
Date now = new Date();
|
||||||
|
Date validity = new Date(now.getTime() + validityInMilliseconds);
|
||||||
|
|
||||||
|
String leToken = Jwts.builder()//
|
||||||
|
.setClaims(claims)// le username avec les roles ou setPayload()
|
||||||
|
.setIssuedAt(now)// 1589817421 pour le 18 mai 2020 à 17 heure 57
|
||||||
|
.setExpiration(validity)// 1589821021 même date avec 1 heure de plus
|
||||||
|
.signWith(SignatureAlgorithm.HS256, secretKey) // la signature avec la clef secrête.
|
||||||
|
.compact(); // concatène l'ensemble pour construire une chaîne
|
||||||
|
System.out.println(leToken); // pour test cela donne ceci
|
||||||
|
/*
|
||||||
|
site pour convertir une date en millisecondes : http://timestamp.fr/?
|
||||||
|
site structure du jeton : https://www.vaadata.com/blog/fr/jetons-jwt-et-securite-principes-et-cas-dutilisation/
|
||||||
|
site jwt encoder / décoder : https://jwt.io/
|
||||||
|
eyJhbGciOiJIUzI1NiJ9.
|
||||||
|
eyJzdWIiOiJwYm91Z2V0IiwiYXV0aCI6W3siYXV0aG9yaXR5IjoiUk9MRV9BRE1JTiJ9LHsiYXV0aG9yaXR5IjoiUk9MRV9DUkVBVE9SIn0seyJhdXRob3JpdHkiOiJST0xFX1JFQURFUiJ9XSwiaWF0IjoxNTg5ODE2OTIyLCJleHAiOjE1ODk4MjA1MjJ9.
|
||||||
|
Cn4_UTjZ2UpJ32FVT3Bd1-VN8K62DVBHQbWiK6MNZ04
|
||||||
|
|
||||||
|
*/
|
||||||
|
// https://www.codeflow.site/fr/article/java__how-to-convert-java-object-to-from-json-jackson
|
||||||
|
|
||||||
|
return leToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Methode qui retourne un objet Authentication basé sur JWT.
|
||||||
|
* @param token : le token pour l'authentification.
|
||||||
|
* @return the authentication si Username est trouvé.
|
||||||
|
*/
|
||||||
|
public Authentication getAuthentication(String token) {
|
||||||
|
UserDetails userDetails = userDetailsService.loadUserByUsername(getUsername(token));
|
||||||
|
return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Methode qui extrait le userName du JWT.
|
||||||
|
* @param token : Token a analyser.
|
||||||
|
* @return le UserName comme chaîne de caractères.
|
||||||
|
*/
|
||||||
|
public String getUsername(String token) {
|
||||||
|
|
||||||
|
return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getSubject();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Méthode qui récupère la requete HTTP.
|
||||||
|
* L'entête doit contenir un champ d'autorisation ou JWT ajoute le token après le mot clef Bearer.
|
||||||
|
* @param requete : la requête à tester.
|
||||||
|
* @return le JWT depuis l'entête HTTP.
|
||||||
|
*/
|
||||||
|
public String resolveToken(HttpServletRequest requeteHttp) {
|
||||||
|
String bearerToken = requeteHttp.getHeader("Authorization");
|
||||||
|
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
|
||||||
|
return bearerToken.substring(7);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Methode qui v<EFBFBD>rifie que JWT est valide.
|
||||||
|
* La signature doit <EFBFBD>tre correcte et la dur<EFBFBD>e de validit<EFBFBD> du Token doit <EFBFBD>tre apr<EFBFBD>s "now" (maintenant)
|
||||||
|
* @param token : Token <EFBFBD> valider
|
||||||
|
* @return True si le Token est valide sinon on lance l'exception InvalidJWTException.
|
||||||
|
* @throws InvalidJWTException
|
||||||
|
*/
|
||||||
|
public boolean validateToken(String token) throws InvalidJWTException {
|
||||||
|
try {
|
||||||
|
Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token);
|
||||||
|
return true;
|
||||||
|
} catch (JwtException | IllegalArgumentException e) {
|
||||||
|
throw new InvalidJWTException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
package fr.cardon.simpleat.security;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.config.BeanIds;
|
||||||
|
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||||
|
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||||
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration de Sécurité globale pour notre REST API.
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||||
|
@EnableWebSecurity
|
||||||
|
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JwtTokenProvider jwtTokenProvider;
|
||||||
|
|
||||||
|
@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
|
||||||
|
@Override
|
||||||
|
public AuthenticationManager authenticationManagerBean() throws Exception {
|
||||||
|
return super.authenticationManagerBean();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Methode qui configure la sécurité HTTP.
|
||||||
|
* @param http the HttpSecurity object to configure.
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
|
|
||||||
|
// Disable CSRF (Cross Site Request Forgery comme votre Token sera stocké dans le session storage)
|
||||||
|
http.cors();
|
||||||
|
|
||||||
|
http.csrf().disable()
|
||||||
|
.sessionManagement()
|
||||||
|
// Les sessions sont sans états et non créés ni utilisées par Spring security
|
||||||
|
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||||
|
.and()
|
||||||
|
// nos endpoints (points d'entrée de notre API)
|
||||||
|
.authorizeRequests()
|
||||||
|
// .anyRequest().authenticated()
|
||||||
|
.antMatchers("/v2/api-docs", "/configuration/**", "/swagger*/**", "/webjars/**")
|
||||||
|
.permitAll()
|
||||||
|
.antMatchers("**").permitAll() // se connecter
|
||||||
|
.antMatchers("**").permitAll() // s'inscrire
|
||||||
|
.antMatchers("api/user/all").hasAuthority("ROLE_ADMIN") // que pour le rôle admin
|
||||||
|
.antMatchers("/v2/api-docs", "/webjars/**", "/swagger-resources/**", "/configuration/**", "/swagger-ui.html/**").permitAll()
|
||||||
|
// .antMatchers("/api/admin/**").hasAuthority("ROLE_ADMIN") // que pour le rôle admin
|
||||||
|
// on désactive le reste...
|
||||||
|
.anyRequest().authenticated(); // tout le reste est autorisé.
|
||||||
|
// Appliquer JWT
|
||||||
|
http.addFilterBefore(new JwtTokenFilter(jwtTokenProvider), UsernamePasswordAuthenticationFilter.class);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Methode qui configure la sécurité web.
|
||||||
|
* Utilisé pour interdire l'accès à certains répertoires.
|
||||||
|
* @param web : WebSecurity
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void configure(WebSecurity web) throws Exception {
|
||||||
|
web.ignoring().antMatchers("/resources/**");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,48 @@
|
|||||||
|
package fr.cardon.simpleat.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import fr.cardon.simpleat.exception.ExistingUsernameException;
|
||||||
|
import fr.cardon.simpleat.exception.InvalidCredentialsException;
|
||||||
|
import fr.cardon.simpleat.model.Personne;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public interface PersonneService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Methode qui permet à un utilisateur de se connecter.
|
||||||
|
* @param email : mail de l'utilisateur.
|
||||||
|
* @param password : mot de passe de l'utilisateur.
|
||||||
|
* @returnun JWT si credentials est valide, throws InvalidCredentialsException otherwise.
|
||||||
|
* @throws InvalidCredentialsException
|
||||||
|
*/
|
||||||
|
String signin(String email, String password) throws InvalidCredentialsException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Methode qui permet de s'inscrire.
|
||||||
|
* @param user nouvel utilisateur.
|
||||||
|
* @return un JWT si user n'existe pas déjà !
|
||||||
|
* @throws ExistingUsernameException
|
||||||
|
*/
|
||||||
|
String signup(Personne personne) throws ExistingUsernameException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Methode qui retourne tous les utilisateurs de la bd
|
||||||
|
* @return the list of all application users.
|
||||||
|
*/
|
||||||
|
List<Personne> findAllUsers();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Methode qui retourne un utilisateur à partir de son username
|
||||||
|
* @param username the username to look for.
|
||||||
|
* @return an Optional object containing user if found, empty otherwise.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
Optional<Personne> findUserByEmail(String email);
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
package fr.cardon.simpleat.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import org.hibernate.internal.build.AllowSysOut;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.AuthenticationException;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import fr.cardon.simpleat.exception.ExistingUsernameException;
|
||||||
|
import fr.cardon.simpleat.exception.InvalidCredentialsException;
|
||||||
|
import fr.cardon.simpleat.model.Personne;
|
||||||
|
import fr.cardon.simpleat.repository.PersonneRepository;
|
||||||
|
import fr.cardon.simpleat.security.JwtTokenProvider;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class PersonneServiceImpl implements PersonneService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PersonneRepository personneRepository; // permet communication avec la BD
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BCryptPasswordEncoder passwordEncoder; // permet l'encodage du mot de passe
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JwtTokenProvider jwtTokenProvider; // permet la fourniture du Jeton (Token)
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthenticationManager authenticationManager; // gestionnaire d'authentification
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permet de se connecter en encodant le mot de passe avec génération du token.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String signin(String email, String password) throws InvalidCredentialsException {
|
||||||
|
try {
|
||||||
|
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(email, password));
|
||||||
|
return jwtTokenProvider.createToken(email, personneRepository.findByEmail(email).get().getRoleList());
|
||||||
|
} catch (AuthenticationException e) {
|
||||||
|
throw new InvalidCredentialsException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String signup(Personne personne) throws ExistingUsernameException {
|
||||||
|
System.out.println(personne .getNom());
|
||||||
|
if (!personneRepository.existsByEmail(personne.getEmail())) {
|
||||||
|
System.out.println(personne .getEmail());
|
||||||
|
Personne personneToSave = new Personne(personne.getNom(),personne.getPrenom(),personne.getEmail(), passwordEncoder.encode(personne.getPassword()), personne.getRoleList());
|
||||||
|
personneRepository.save(personneToSave);
|
||||||
|
return jwtTokenProvider.createToken(personne.getEmail(), personne.getRoleList());
|
||||||
|
} else {
|
||||||
|
throw new ExistingUsernameException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Personne> findAllUsers() {
|
||||||
|
return personneRepository.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Personne> findUserByEmail(String email) {
|
||||||
|
return personneRepository.findByEmail(email);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
package fr.cardon.simpleat.service;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.userdetails.User;
|
||||||
|
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 fr.cardon.simpleat.model.Personne;
|
||||||
|
|
||||||
|
import fr.cardon.simpleat.repository.PersonneRepository;
|
||||||
|
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class UserDetailsServiceImpl implements UserDetailsService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PersonneRepository personneRepository;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserDetails loadUserByUsername(String email) {
|
||||||
|
final Optional<Personne> personne = personneRepository.findByEmail(email);
|
||||||
|
|
||||||
|
if (!personne.isPresent()) {
|
||||||
|
throw new UsernameNotFoundException("utilisateur '" + email + "' introuvable");
|
||||||
|
}
|
||||||
|
|
||||||
|
return User
|
||||||
|
.withUsername(email)
|
||||||
|
.password(personne.get().getPassword())
|
||||||
|
.authorities(personne.get().getRoleList())
|
||||||
|
.accountExpired(false)
|
||||||
|
.accountLocked(false)
|
||||||
|
.credentialsExpired(false)
|
||||||
|
.disabled(false)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,8 @@
|
|||||||
|
#security.jwt.token.secret-key=03888dd6ceb88c3fee410a70802fb93d483fd52d70349d8f7e7581ae346cf658
|
||||||
|
security.jwt.token.secret-key=simpleat
|
||||||
|
spring.main.allow-circular-references=true
|
||||||
|
# pour comprendre le but de cette ligne ci-dessus : https://www.baeldung.com/circular-dependencies-in-spring
|
||||||
|
# ===============================
|
||||||
# ===============================
|
# ===============================
|
||||||
# base de données MySQL
|
# base de données MySQL
|
||||||
# ===============================
|
# ===============================
|
||||||
|
Loading…
Reference in New Issue
Block a user