diff --git a/.file.swp b/.file.swp new file mode 100644 index 0000000..97eb5de Binary files /dev/null and b/.file.swp differ diff --git a/.idea/Organizee.iml b/.idea/Organizee.iml deleted file mode 100644 index d6ebd48..0000000 --- a/.idea/Organizee.iml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 6f8f4ad..b197f48 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -6,12 +6,17 @@ +<<<<<<< HEAD +======= + +>>>>>>> b147bc406c22caa9c817c7189a325058d8550a69 diff --git a/pom.xml b/pom.xml index 32eb628..dbaf653 100644 --- a/pom.xml +++ b/pom.xml @@ -25,6 +25,15 @@ org.springframework.boot spring-boot-starter-jdbc + + org.springframework.boot + spring-boot-starter-security + + + io.jsonwebtoken + jjwt + 0.9.1 + org.springframework.boot spring-boot-starter-web diff --git a/src/main/java/fr/organizee/OrganizeeApplication.java b/src/main/java/fr/organizee/OrganizeeApplication.java index e1323b4..6e2aaa4 100644 --- a/src/main/java/fr/organizee/OrganizeeApplication.java +++ b/src/main/java/fr/organizee/OrganizeeApplication.java @@ -1,13 +1,47 @@ package fr.organizee; +import fr.organizee.model.Membre; +import fr.organizee.model.Role; +import fr.organizee.service.MembreService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; + +import java.util.ArrayList; +import java.util.Arrays; @SpringBootApplication -public class OrganizeeApplication { +public class OrganizeeApplication implements CommandLineRunner { + + @Autowired + private MembreService membreService; public static void main(String[] args) { SpringApplication.run(OrganizeeApplication.class, args); } + /** + * Ceci est un Bean, un composant + * Méthode de Hachage + * Bcrypt est un algorithme de hachage considé comme le plus sûr. + * bcrypt est un algorithme de hashage unidirectionnel, + * vous ne pourrez jamais retrouver le mot de passe sans connaitre à la fois le grain de sel, + * la clé et les différentes passes que l'algorithme à utiliser. + * Voir le site pour effectuer un test + * + * @return + */ + @Bean + public BCryptPasswordEncoder bCryptPasswordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Override + public void run(String... args) throws Exception { + + } } + diff --git a/src/main/java/fr/organizee/controller/ContactController.java b/src/main/java/fr/organizee/controller/ContactController.java new file mode 100644 index 0000000..5186d12 --- /dev/null +++ b/src/main/java/fr/organizee/controller/ContactController.java @@ -0,0 +1,93 @@ +package fr.organizee.controller; + +import fr.organizee.model.Contact; +import fr.organizee.model.Membre; +import fr.organizee.model.Team; +import fr.organizee.repository.ContactRepository; +import fr.organizee.repository.TeamRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.persistence.EntityNotFoundException; +import java.util.List; +import java.util.Optional; + +@RestController +@CrossOrigin("*") +@RequestMapping("/contacts") +public class ContactController { + + @Autowired + private ContactRepository contactRepo; + + @GetMapping(value = "/{id}") + @PreAuthorize("hasRole('ROLE_PARENT') or hasRole('ROLE_ENFANT')") + public ResponseEntity findById(@PathVariable int id){ + Optional contact = null; + try + { + contact = contactRepo.findById(id); + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null); + } + + return ResponseEntity.status(HttpStatus.OK).body(contact); + } + + @GetMapping(value = "team/{team_id}") + @PreAuthorize("hasRole('ROLE_PARENT') or hasRole('ROLE_ENFANT')") + public ResponseEntity findByTeamId(@PathVariable int team_id){ + List contacts = null; + try + { + contacts = contactRepo.FindContactsByTeam(team_id); + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null); + } + + return ResponseEntity.status(HttpStatus.OK).body(contacts); + } + + @PostMapping(value="/add") + @PreAuthorize("hasRole('ROLE_PARENT') or hasRole('ROLE_ENFANT')") + public ResponseEntity addContact(@RequestBody Contact contact){ + Contact resultContact = null; + try { + resultContact = contactRepo.saveAndFlush(contact); + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage()); + } + + return ResponseEntity.status(HttpStatus.CREATED).body(resultContact); + } + + @PutMapping("/update/{id}") + @PreAuthorize("hasRole('ROLE_PARENT') or hasRole('ROLE_ENFANT')") + public ResponseEntity updateContact(@RequestBody Contact contact, @PathVariable Integer id) throws Exception { + Contact resultContact = null; + try { + resultContact = contactRepo.save(contact); + + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(e.getMessage()); + } + + return ResponseEntity.status(HttpStatus.OK).body(resultContact); + } + + @DeleteMapping(value = "/delete/{id}") + @PreAuthorize("hasRole('ROLE_PARENT')") + public ResponseEntity deleteContact(@PathVariable int id){ + try { + contactRepo.delete(contactRepo.getById(id)); + return ResponseEntity.status(HttpStatus.OK).body("Contact effacé !"); + + } catch (EntityNotFoundException e) { + + return ResponseEntity.status(HttpStatus.OK).body("Contact introuvable !"); + } + } +} diff --git a/src/main/java/fr/organizee/controller/MembreController.java b/src/main/java/fr/organizee/controller/MembreController.java index c69d234..2e9f691 100644 --- a/src/main/java/fr/organizee/controller/MembreController.java +++ b/src/main/java/fr/organizee/controller/MembreController.java @@ -1,17 +1,28 @@ package fr.organizee.controller; +import fr.organizee.dto.JsonWebToken; +import fr.organizee.dto.MembreDto; +import fr.organizee.exception.ExistingUsernameException; +import fr.organizee.exception.InvalidCredentialsException; import fr.organizee.model.Membre; import fr.organizee.model.Team; import fr.organizee.repository.MembreRepository; +<<<<<<< HEAD import fr.organizee.repository.TeamRepository; +======= +//import fr.organizee.repository.TeamRepository; +import fr.organizee.service.MembreService; +>>>>>>> b147bc406c22caa9c817c7189a325058d8550a69 import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import javax.persistence.EntityNotFoundException; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; /* toto */ @RestController @@ -22,7 +33,14 @@ public class MembreController { @Autowired private MembreRepository membreRepo; +<<<<<<< HEAD // @Autowired +======= + @Autowired + private MembreService membreService; + +// @Autowired +>>>>>>> b147bc406c22caa9c817c7189a325058d8550a69 // private TeamRepository teamRepo; // @RequestMapping("/membres") @@ -36,6 +54,7 @@ public class MembreController { } @GetMapping(value = "/all") + @PreAuthorize("hasRole('ROLE_PARENT') or hasRole('ROLE_ENFANT')") public ResponseEntity getAll(){ List liste = null; try @@ -48,6 +67,13 @@ public class MembreController { return ResponseEntity.status(HttpStatus.OK).body(liste); } + @GetMapping("/admin/all") + @PreAuthorize("hasRole('ROLE_PARENT')") + public List getAllAdminUsers() { + return membreService.findAllUsers().stream().map(appUser -> new MembreDto(appUser.getEmail(), appUser.getRoleList())).collect(Collectors.toList()); + + } + // @GetMapping(value = "/team/all") // public ResponseEntity getAllTeam(){ // List liste = null; @@ -62,6 +88,7 @@ public class MembreController { // } @GetMapping(value = "/{id}") + @PreAuthorize("hasRole('ROLE_PARENT') or hasRole('ROLE_ENFANT')") public ResponseEntity findById(@PathVariable int id){ Optional membre = null; try @@ -82,11 +109,12 @@ public class MembreController { // } @DeleteMapping(value = "/delete/{id}") + @PreAuthorize("hasRole('ROLE_PARENT')") public ResponseEntity deleteMembre(@PathVariable int id){ try { membreRepo.delete(membreRepo.getById(id)); //membreRepo.deleteById(id); - return ResponseEntity.status(HttpStatus.OK).body("Membre effacée !"); + return ResponseEntity.status(HttpStatus.OK).body("Membre effacé !"); } catch (EntityNotFoundException e) { @@ -94,19 +122,26 @@ public class MembreController { } } - @PostMapping(value="/add", produces="application/json", consumes="application/json") - public ResponseEntity addMembre(@RequestBody Membre membre){ - Membre resultMembre = null; + @PostMapping("/sign-up") + public ResponseEntity signUp(@RequestBody Membre membre) { try { - resultMembre = membreRepo.saveAndFlush(membre); - } catch (Exception e) { - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage()); + return ResponseEntity.ok(new JsonWebToken(membreService.signup(membre))); + } catch (ExistingUsernameException ex) { + return ResponseEntity.badRequest().build(); } + } - return ResponseEntity.status(HttpStatus.CREATED).body(resultMembre); + @PostMapping("/sign-in") + public ResponseEntity signIn(@RequestBody Membre membre) { + try { + return ResponseEntity.ok(new JsonWebToken(membreService.signin(membre.getEmail(), membre.getPassword()))); + } catch (InvalidCredentialsException ex) { + return ResponseEntity.badRequest().build(); + } } @PutMapping("/update/{id}") + @PreAuthorize("hasRole('ROLE_PARENT')") public ResponseEntity updateMembre(@RequestBody Membre membre, @PathVariable Integer id) throws Exception { Membre resultMembre = null; try { @@ -148,22 +183,4 @@ public class MembreController { // // return ResponseEntity.status(HttpStatus.OK).body(liste); // } - - @PostMapping(value="/login", produces="application/json", consumes="application/json") - public ResponseEntity login(@RequestBody Membre membre){ - Membre resultMembre = null; - try { - resultMembre = membreRepo.findByNom(membre.getNom()); - if(resultMembre == null){ - throw new RuntimeException("User inexistant."); - } - if(!resultMembre.getPassword().equals(membre.getPassword())){ - throw new RuntimeException("mauvais password."); - } - } catch (Exception e) { - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage()); - } - - return ResponseEntity.status(HttpStatus.CREATED).body(resultMembre); - } } diff --git a/src/main/java/fr/organizee/controller/MenuController.java b/src/main/java/fr/organizee/controller/MenuController.java new file mode 100644 index 0000000..f4e4ec8 --- /dev/null +++ b/src/main/java/fr/organizee/controller/MenuController.java @@ -0,0 +1,90 @@ +package fr.organizee.controller; + +import fr.organizee.model.Contact; +import fr.organizee.model.Menu; +import fr.organizee.repository.MenuRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.persistence.EntityNotFoundException; +import java.util.List; +import java.util.Optional; + +@RestController +@CrossOrigin("*") +@RequestMapping("/menus") +public class MenuController { + + @Autowired + private MenuRepository menuRepository; + + @GetMapping(value = "/{id}") + @PreAuthorize("hasRole('ROLE_PARENT') or hasRole('ROLE_ENFANT')") + public ResponseEntity findById(@PathVariable int id){ + Optional menu = null; + try + { + menu = menuRepository.findById(id); + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null); + } + + return ResponseEntity.status(HttpStatus.OK).body(menu); + } + + @GetMapping(value = "team/{team_id}") + @PreAuthorize("hasRole('ROLE_PARENT') or hasRole('ROLE_ENFANT')") + public ResponseEntity findByTeamId(@PathVariable int team_id) { + List menus = null; + try { + menus = menuRepository.FindMenusByTeam(team_id); + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null); + } + return ResponseEntity.status(HttpStatus.OK).body(menus); + } + + @PostMapping(value="/add") + @PreAuthorize("hasRole('ROLE_PARENT') or hasRole('ROLE_ENFANT')") + public ResponseEntity addMenu(@RequestBody Menu menu){ + Menu resultMenu = null; + try { + resultMenu = menuRepository.saveAndFlush(menu); + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage()); + } + + return ResponseEntity.status(HttpStatus.CREATED).body(resultMenu); + } + + @PutMapping("/update/{id}") + @PreAuthorize("hasRole('ROLE_PARENT')") + public ResponseEntity updateMenu(@RequestBody Menu menu, @PathVariable Integer id) throws Exception { + Menu resultMenu = null; + try { + resultMenu = menuRepository.save(menu); + + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(e.getMessage()); + } + + return ResponseEntity.status(HttpStatus.OK).body(menuRepository); + } + + @DeleteMapping(value = "/delete/{id}") + @PreAuthorize("hasRole('ROLE_PARENT')") + public ResponseEntity deleteMenu(@PathVariable int id){ + try { + menuRepository.delete(menuRepository.getById(id)); + return ResponseEntity.status(HttpStatus.OK).body("Menu effacé !"); + + } catch (EntityNotFoundException e) { + + return ResponseEntity.status(HttpStatus.OK).body("Menu introuvable !"); + } + } +} + diff --git a/src/main/java/fr/organizee/controller/TeamController.java b/src/main/java/fr/organizee/controller/TeamController.java index 632f368..f8766ca 100644 --- a/src/main/java/fr/organizee/controller/TeamController.java +++ b/src/main/java/fr/organizee/controller/TeamController.java @@ -1,10 +1,12 @@ package fr.organizee.controller; +import fr.organizee.model.Membre; import fr.organizee.model.Team; import fr.organizee.repository.TeamRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import javax.persistence.EntityNotFoundException; @@ -32,6 +34,7 @@ public class TeamController { // Récupération de toutes les teams @GetMapping(value = "/all") + @PreAuthorize("hasRole('ROLE_PARENT')") public ResponseEntity getAllTeam(){ List liste = null; try @@ -45,6 +48,7 @@ public class TeamController { } @GetMapping(value = "/{id}") + @PreAuthorize("hasRole('ROLE_PARENT') or hasRole('ROLE_ENFANT')") public ResponseEntity findTeamById(@PathVariable int id){ Optional liste = null; try @@ -57,4 +61,44 @@ public class TeamController { return ResponseEntity.status(HttpStatus.OK).body(liste); } + @PostMapping(value="/add", produces="application/json", consumes="application/json") + @PreAuthorize("hasRole('ROLE_PARENT')") + public ResponseEntity addTeam(@RequestBody Team team){ + Team resultTeam = null; + try { + resultTeam = teamRepo.saveAndFlush(team); + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage()); + } + + return ResponseEntity.status(HttpStatus.CREATED).body(resultTeam); + } + + @PutMapping("/update/{id}") + @PreAuthorize("hasRole('ROLE_PARENT')") + public ResponseEntity updateTeam(@RequestBody Team team, @PathVariable Integer id) throws Exception { + Team resultTeam = null; + try { + resultTeam = teamRepo.save(team); + + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(e.getMessage()); + } + + return ResponseEntity.status(HttpStatus.OK).body(resultTeam); + } + + @DeleteMapping(value = "/delete/{id}") + @PreAuthorize("hasRole('ROLE_PARENT')") + public ResponseEntity deleteTeam(@PathVariable int id){ + try { + teamRepo.delete(teamRepo.getById(id)); + //membreRepo.deleteById(id); + return ResponseEntity.status(HttpStatus.OK).body("Team effacée !"); + + } catch (EntityNotFoundException e) { + + return ResponseEntity.status(HttpStatus.OK).body("Team introuvable !"); + } + } } diff --git a/src/main/java/fr/organizee/dto/JsonWebToken.java b/src/main/java/fr/organizee/dto/JsonWebToken.java new file mode 100644 index 0000000..5f608a6 --- /dev/null +++ b/src/main/java/fr/organizee/dto/JsonWebToken.java @@ -0,0 +1,18 @@ +package fr.organizee.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; + } +} + diff --git a/src/main/java/fr/organizee/dto/MembreDto.java b/src/main/java/fr/organizee/dto/MembreDto.java new file mode 100644 index 0000000..c62999c --- /dev/null +++ b/src/main/java/fr/organizee/dto/MembreDto.java @@ -0,0 +1,53 @@ +package fr.organizee.dto; + +import java.util.List; + +import com.sun.istack.NotNull; + +import fr.organizee.model.Role; + +/** + * Specifique : AppUser DTO permet de renvoyer un User sans le mot de passe (REST response). + */ +public class MembreDto { + + private Long id; + private String email; + private List roleList; + + public MembreDto() { + } + + public MembreDto(@NotNull String email) { + this(email, null); + } + + public MembreDto(@NotNull String email, List 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 getRoleList() { + return roleList; + } + + public void setRoleList(List roleList) { + this.roleList = roleList; + } +} diff --git a/src/main/java/fr/organizee/exception/ExistingUsernameException.java b/src/main/java/fr/organizee/exception/ExistingUsernameException.java new file mode 100644 index 0000000..85e3bd8 --- /dev/null +++ b/src/main/java/fr/organizee/exception/ExistingUsernameException.java @@ -0,0 +1,15 @@ +package fr.organizee.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 !"; + } +} diff --git a/src/main/java/fr/organizee/exception/InvalidCredentialsException.java b/src/main/java/fr/organizee/exception/InvalidCredentialsException.java new file mode 100644 index 0000000..82f1155 --- /dev/null +++ b/src/main/java/fr/organizee/exception/InvalidCredentialsException.java @@ -0,0 +1,15 @@ +package fr.organizee.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 !"; + } +} \ No newline at end of file diff --git a/src/main/java/fr/organizee/exception/InvalidJWTException.java b/src/main/java/fr/organizee/exception/InvalidJWTException.java new file mode 100644 index 0000000..314385f --- /dev/null +++ b/src/main/java/fr/organizee/exception/InvalidJWTException.java @@ -0,0 +1,17 @@ +package fr.organizee.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 !"; + } + +} + diff --git a/src/main/java/fr/organizee/model/Membre.java b/src/main/java/fr/organizee/model/Membre.java index 36f2bd8..5733712 100644 --- a/src/main/java/fr/organizee/model/Membre.java +++ b/src/main/java/fr/organizee/model/Membre.java @@ -2,9 +2,11 @@ package fr.organizee.model; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.sun.istack.NotNull; import javax.persistence.*; import java.time.LocalDate; +import java.util.List; @Entity @@ -15,8 +17,19 @@ public class Membre { private String nom; private String prenom; private LocalDate dateNaissance; + + @NotNull + @Column(nullable = false) private String email; + + @NotNull + @Column(nullable = false) private String password; + + @ElementCollection(fetch = FetchType.EAGER) + @Enumerated(EnumType.STRING) + private List roleList; + private String isAdmin; private String couleur; private String smiley; @@ -31,7 +44,7 @@ public class Membre { public Membre() { } - public Membre(String nom, String prenom, LocalDate dateNaissance, String email, String password, String isAdmin, String couleur, String smiley, Team team) { + public Membre(String nom, String prenom, LocalDate dateNaissance, @NotNull String email, @NotNull String password, String isAdmin, String couleur, String smiley, Team team, List roleList) { this.nom = nom; this.prenom = prenom; this.dateNaissance = dateNaissance; @@ -41,8 +54,16 @@ public class Membre { this.couleur = couleur; this.smiley = smiley; this.team = team; + this.roleList=roleList; } + public Membre(@NotNull String email, @NotNull String password, List roleList) { + this.email = email; + this.password = password; + this.roleList=roleList; + } + + public int getId() { return id; } @@ -109,6 +130,13 @@ public class Membre { this.smiley = smiley; } + public List getRoleList() { + return roleList; + } + public void setRoleList(List roleList) { + this.roleList = roleList; + } + @Override public String toString() { return "Membre{" + diff --git a/src/main/java/fr/organizee/model/Menu.java b/src/main/java/fr/organizee/model/Menu.java index 67b1531..b486e2b 100644 --- a/src/main/java/fr/organizee/model/Menu.java +++ b/src/main/java/fr/organizee/model/Menu.java @@ -12,6 +12,7 @@ public class Menu { private int id; private String libelle; private LocalDate dateMenu; + private int validationProposition; @ManyToOne(cascade = CascadeType.MERGE) @JoinColumn(name="TEAM_ID") @JsonIgnoreProperties("menu") @@ -22,9 +23,10 @@ public class Menu { public Menu() { } - public Menu(String libelle, LocalDate dateMenu) { + public Menu(String libelle, LocalDate dateMenu, int validationProposition) { this.libelle = libelle; this.dateMenu = dateMenu; + this.validationProposition=validationProposition; } public int getId() { diff --git a/src/main/java/fr/organizee/model/Role.java b/src/main/java/fr/organizee/model/Role.java new file mode 100644 index 0000000..b183ca2 --- /dev/null +++ b/src/main/java/fr/organizee/model/Role.java @@ -0,0 +1,16 @@ +package fr.organizee.model; + +import org.springframework.security.core.GrantedAuthority; + +/** + * User possible roles. + */ +public enum Role implements GrantedAuthority { + + ROLE_PARENT, ROLE_ENFANT; + + @Override + public String getAuthority() { + return name(); + } +} diff --git a/src/main/java/fr/organizee/model/Team.java b/src/main/java/fr/organizee/model/Team.java index 0b9ddbe..1da65d5 100644 --- a/src/main/java/fr/organizee/model/Team.java +++ b/src/main/java/fr/organizee/model/Team.java @@ -55,8 +55,16 @@ public class Team { this.membres = membre; } + public List getContacts() { + return contacts; + } + + public void setContacts(List contacts) { + this.contacts = contacts; + } + @Override public String toString() { - return "Team [id=" + id + ", nom=" + nom + ", membre=" + membres + "]"; + return "Team [id=" + id + ", nom=" + nom + ", membre=" + membres + ", contact=" + contacts + "]"; } } diff --git a/src/main/java/fr/organizee/repository/ContactRepository.java b/src/main/java/fr/organizee/repository/ContactRepository.java index b670634..ed1612a 100644 --- a/src/main/java/fr/organizee/repository/ContactRepository.java +++ b/src/main/java/fr/organizee/repository/ContactRepository.java @@ -1,4 +1,19 @@ package fr.organizee.repository; -public interface ContactRepository { +import fr.organizee.model.Contact; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Optional; + +@Repository +public interface ContactRepository extends JpaRepository { + +@Query(value = "select * from contact where team_id = :team_id", nativeQuery = true) + List FindContactsByTeam(@Param("team_id") int team_id); + + } diff --git a/src/main/java/fr/organizee/repository/MembreRepository.java b/src/main/java/fr/organizee/repository/MembreRepository.java index a8aafe8..f431da3 100644 --- a/src/main/java/fr/organizee/repository/MembreRepository.java +++ b/src/main/java/fr/organizee/repository/MembreRepository.java @@ -4,7 +4,15 @@ import fr.organizee.model.Membre; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.Optional; + @Repository public interface MembreRepository extends JpaRepository { Membre findByNom(String nom); + + Optional findByEmail(String email); + + boolean existsByEmail(String email); + + void deleteByEmail(String email); } diff --git a/src/main/java/fr/organizee/repository/MenuRepository.java b/src/main/java/fr/organizee/repository/MenuRepository.java index b9bb652..1f22d7d 100644 --- a/src/main/java/fr/organizee/repository/MenuRepository.java +++ b/src/main/java/fr/organizee/repository/MenuRepository.java @@ -1,4 +1,17 @@ package fr.organizee.repository; -public interface MenuRepository { +import fr.organizee.model.Contact; +import fr.organizee.model.Menu; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface MenuRepository extends JpaRepository { + + @Query(value = "select * from menu where team_id = :team_id", nativeQuery = true) + List FindMenusByTeam(@Param("team_id") int team_id); } diff --git a/src/main/java/fr/organizee/security/JwtTokenFilter.java b/src/main/java/fr/organizee/security/JwtTokenFilter.java new file mode 100644 index 0000000..93ab540 --- /dev/null +++ b/src/main/java/fr/organizee/security/JwtTokenFilter.java @@ -0,0 +1,46 @@ +package fr.organizee.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.organizee.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 AppClient n'est pas authentifié + SecurityContextHolder.clearContext(); + httpServletResponse.sendError(HttpStatus.BAD_REQUEST.value(), "JWT invalide !"); + return; + } + + filterChain.doFilter(httpServletRequest, httpServletResponse); + } +} diff --git a/src/main/java/fr/organizee/security/JwtTokenProvider.java b/src/main/java/fr/organizee/security/JwtTokenProvider.java new file mode 100644 index 0000000..9ec508d --- /dev/null +++ b/src/main/java/fr/organizee/security/JwtTokenProvider.java @@ -0,0 +1,185 @@ +package fr.organizee.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.organizee.exception.InvalidJWTException; +import fr.organizee.model.Role; +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; + + /** + * 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 email the user email. + * @param roles the user roles. + * @return the created JWT as String. + * @throws JsonProcessingException + */ + public String createToken(String email, List roles){ + + Claims claims = Jwts.claims().setSubject(email); + claims.put("auth", roles.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(getEmail(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 getEmail(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�rifie que JWT est valide. + * La signature doit �tre correcte et la dur�e de validit� du Token doit �tre apr�s "now" (maintenant) + * @param token : Token � 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(); + } + } +} + diff --git a/src/main/java/fr/organizee/security/WebSecurityConfig.java b/src/main/java/fr/organizee/security/WebSecurityConfig.java new file mode 100644 index 0000000..358ce32 --- /dev/null +++ b/src/main/java/fr/organizee/security/WebSecurityConfig.java @@ -0,0 +1,72 @@ +package fr.organizee.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() + .authorizeRequests() + .antMatchers("/**").permitAll() // accessible sans besoin de s'authentifier + .and() + .authorizeRequests() + .antMatchers("/membres/sign-in").permitAll() // se connecter + .antMatchers("/membres/sign-up").permitAll() // s'inscrire + .antMatchers("membres/all").hasAuthority("ROLE_PARENT") // uniquement pour le r�le admin + .anyRequest().authenticated(); // tout le reste est autoris� par un utilisateur authentifi� + // Appliquer un filtre avec le token pour toutes requ�tes HTTP + 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/**"); + } +} + + + diff --git a/src/main/java/fr/organizee/service/MembreService.java b/src/main/java/fr/organizee/service/MembreService.java new file mode 100644 index 0000000..4000c67 --- /dev/null +++ b/src/main/java/fr/organizee/service/MembreService.java @@ -0,0 +1,45 @@ +package fr.organizee.service; + +import java.util.List; +import java.util.Optional; + +import org.springframework.stereotype.Service; + +import fr.organizee.exception.ExistingUsernameException; +import fr.organizee.exception.InvalidCredentialsException; +import fr.organizee.model.Membre; + +@Service +public interface MembreService { + + /** + * Methode qui permet à un utilisateur de se connecter. + * @param email : nom 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 membre nouvel utilisateur. + * @return un JWT si user n'existe pas déjà ! + * @throws ExistingUsernameException + */ + String signup(Membre membre) throws ExistingUsernameException; + + /** + * Methode qui retourne tous les utilisateurs de la bd + * @return the list of all application users. + */ + List findAllUsers(); + + /** + * Methode qui retourne un utilisateur à partir de son username + * @param email the username to look for. + * @return an Optional object containing user if found, empty otherwise. + */ + Optional findUserByEmail(String email); +} + diff --git a/src/main/java/fr/organizee/service/MembreServiceImpl.java b/src/main/java/fr/organizee/service/MembreServiceImpl.java new file mode 100644 index 0000000..6304d86 --- /dev/null +++ b/src/main/java/fr/organizee/service/MembreServiceImpl.java @@ -0,0 +1,69 @@ +package fr.organizee.service; + +import java.util.List; +import java.util.Optional; + +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.organizee.exception.ExistingUsernameException; +import fr.organizee.exception.InvalidCredentialsException; +import fr.organizee.model.Membre; +import fr.organizee.repository.MembreRepository; +import fr.organizee.security.JwtTokenProvider; + +@Service +public class MembreServiceImpl implements MembreService { + + @Autowired + private MembreRepository membreRepository; // 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, membreRepository.findByEmail(email).get().getRoleList()); + } catch (AuthenticationException e) { + throw new InvalidCredentialsException(); + } + } + + @Override + public String signup(Membre membre) throws ExistingUsernameException { + if (!membreRepository.existsByEmail(membre.getEmail())) { + Membre membreToSave = new Membre(membre.getEmail(), passwordEncoder.encode(membre.getPassword()), membre.getRoleList()); + membreRepository.save(membreToSave); + return jwtTokenProvider.createToken(membre.getEmail(), membre.getRoleList()); + } else { + throw new ExistingUsernameException(); + } + } + + @Override + public List findAllUsers() { + return membreRepository.findAll(); + } + + @Override + public Optional findUserByEmail(String email) { + return membreRepository.findByEmail(email); + } +} + diff --git a/src/main/java/fr/organizee/service/UserDetailsServiceImpl.java b/src/main/java/fr/organizee/service/UserDetailsServiceImpl.java new file mode 100644 index 0000000..3ea4151 --- /dev/null +++ b/src/main/java/fr/organizee/service/UserDetailsServiceImpl.java @@ -0,0 +1,40 @@ +package fr.organizee.service; + +import java.util.Optional; + +import org.springframework.beans.factory.annotation.Autowired; +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.organizee.model.Membre; +import fr.organizee.repository.MembreRepository; + +@Service +public class UserDetailsServiceImpl implements UserDetailsService { + + @Autowired + private MembreRepository userRepository; + + @Override + public UserDetails loadUserByUsername(String email) { + final Optional user = userRepository.findByEmail(email); + + if (!user.isPresent()) { + throw new UsernameNotFoundException("utilisateur '" + email + "' introuvable"); + } + + return User + .withUsername(email) + .password(user.get().getPassword()) + .authorities(user.get().getRoleList()) + .accountExpired(false) + .accountLocked(false) + .credentialsExpired(false) + .disabled(false) + .build(); + } +} + diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql index 3f92821..ff765bf 100644 --- a/src/main/resources/data.sql +++ b/src/main/resources/data.sql @@ -1,3 +1,4 @@ +<<<<<<< HEAD -- -------------------------------------------------------- -- Hôte : 192.168.1.16 -- Version du serveur: 10.3.32-MariaDB-0ubuntu0.20.04.1 - Ubuntu 20.04 @@ -60,6 +61,26 @@ CREATE TABLE IF NOT EXISTS `membre` ( -- Export de données de la table organizee.membre : ~0 rows (environ) /*!40000 ALTER TABLE `membre` DISABLE KEYS */; +======= +INSERT INTO `team` (`id`, `nom`) VALUES + (1, 'Team JAVA'), + (2, 'Team Angular'), + (3, 'Team PHP'), + (4, 'Team Bancal'); + +INSERT INTO `contact` (`id`, `adresse`, `date_naissance`, `email`, `nom`, `prenom`, `telephone`, `team_id`) VALUES + (1, '7554 Messerschmidt Center', '2021-01-24', 'oogleasane0@cargocollective.com', 'Ophelia', 'O\'Gleasane', '913-198-6499','1'), + (2, '534 Jay Way', '2021-03-26', 'fmowett1@ocn.ne.jp', 'Fiann', 'Mowett', '248-224-7233','1'), + (3, '077 Buell Place', '2021-06-24', 'vlewknor2@spotify.com', 'Vladamir', 'Lewknor', '922-822-3626','1'), + (4, '6226 Esker Street', '2021-04-13', 'jbarmadier3@opensource.org', 'Jervis', 'Barmadier', '838-581-8112','2'), + (5, '28531 Luster Circle', '2021-06-15', 'tmee4@ameblo.jp', 'Tuesday', 'Mee', '761-975-7324','2'), + (6, '96 Hallows Avenue', '2021-08-13', 'tcolvine5@elegantthemes.com', 'Toni', 'Colvine', '348-778-7679','2'), + (7, '6401 Jay Crossing', '2021-01-14', 'rrielly6@netlog.com', 'Riane', 'Rielly', '740-571-0835','3'), + (8, '3273 Cascade Pass', '2021-03-22', 'jlauder7@rambler.ru', 'Juieta', 'Lauder', '928-408-6855','3'), + (9, '1170 Burning Wood Road', '2021-05-31', 'tbolver8@google.ca', 'Thibaut', 'Bolver', '681-860-8291','4'), + (10, '1 Westridge Road', '2021-03-11', 'emebs9@uol.com.br', 'Evered', 'Mebs', '898-483-6075','4'); + +>>>>>>> b147bc406c22caa9c817c7189a325058d8550a69 INSERT INTO `membre` (`id`, `couleur`, `date_naissance`, `email`, `is_admin`, `nom`, `password`, `prenom`, `smiley`, `team_id`) VALUES (1, '#fcba03', '2021-12-13', 'hedi@simplon.com', '0', 'SKYWALKER', 'toto', 'Hédi', NULL, 1), (2, '#8df505', '2021-07-03', 'aline@simplon.com', '0', 'FETT', 'tata', 'Aline', NULL, 1), @@ -67,6 +88,7 @@ INSERT INTO `membre` (`id`, `couleur`, `date_naissance`, `email`, `is_admin`, `n (4, '#ed09de', '2021-06-29', 'blandine@simplon.com', '0', 'VADER', 'tutu', 'Blandine', NULL, 3), (5, '#ed09de', '2021-08-29', 'sana@simplon.com', '0', 'C3PO', 'riri', 'Sana', NULL, 4), (6, '#ed09de', '2021-10-29', 'cecile@simplon.com', '0', 'R2D2', 'loulou', 'Cecile', NULL, 4); +<<<<<<< HEAD /*!40000 ALTER TABLE `membre` ENABLE KEYS */; -- Export de la structure de la table organizee.menu @@ -145,3 +167,21 @@ INSERT INTO `todo_list` (`id`, `nom`, `team_id`) VALUES /*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; /*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +======= + +INSERT INTO `todo_list` (`id`, `nom`, `team_id`) VALUES + (1, 'Pour Blandine',1), + (2, 'Corvées',1), + (3, 'Noel',1); + + +INSERT INTO `tache` (`id`, `etat`, `texte`, `todolist_id`) VALUES + (1, 0, 'Apprendre le PHP', 1), + (2, 0, 'Revoir CRUD', 1), + (3, 0, 'Acheter des guirlandes', 3), + (4, 0, 'Acheter un sapin', 3), + (5, 0, 'Trouver un repas', 3); + +INSERT INTO `evenement` (`id`, `all_day`, `event_debut`, `event_fin`, `libelle`, `membre_id`, `team_id`) VALUES + (1, 0, '2022-01-13 09:00:33', '2022-01-13 13:04:38', 'Simplon', 1, 1); +>>>>>>> b147bc406c22caa9c817c7189a325058d8550a69