From 3f0e3c801ca4a78fc474c9b6af15c5a88a2e8875 Mon Sep 17 00:00:00 2001 From: Vu Tuan Minh Date: Wed, 22 Oct 2025 01:39:18 +0200 Subject: [PATCH] Maybe add thymeleaf? need to test and add config keycloak --- pom.xml | 45 +-------- run-hsqldb-server.bat | 3 - run-hsqldb-server.sh | 4 - show-hsqldb.bat | 2 - show-hsqldb.sh | 2 - .../data/jpa/SampleDataJpaApplication.java | 8 +- .../java/sample/data/jpa/SecurityConfig.java | 21 ----- .../sample/data/jpa/WebSecurityConfig.java | 41 +++++++++ .../data/jpa/controller/ViewController.java | 38 ++++++++ .../java/sample/data/jpa/domain/User.java | 66 ------------- .../sample/data/jpa/metier/Utilisateur.java | 4 + .../sample/data/jpa/service/QuestionDao.java | 2 - .../java/sample/data/jpa/service/UserDao.java | 20 ---- .../data/jpa/service/UtilisateurDao.java | 3 +- .../data/jpa/web/QuestionController.java | 68 +++++++------- .../sample/data/jpa/web/QuizzController.java | 71 +++++++------- .../data/jpa/web/ReponseController.java | 34 ++++--- .../data/jpa/web/SessionController.java | 89 ++++++++++-------- .../sample/data/jpa/web/UserController.java | 92 ------------------- .../data/jpa/web/UtilisateurController.java | 50 +++++----- src/main/resources/application.properties | 16 +++- src/main/resources/templates/admin.html | 14 +++ src/main/resources/templates/index.html | 14 +++ src/main/resources/templates/indexmain.html | 15 +++ src/main/resources/templates/logout.html | 14 +++ 25 files changed, 323 insertions(+), 413 deletions(-) delete mode 100755 run-hsqldb-server.bat delete mode 100755 run-hsqldb-server.sh delete mode 100644 show-hsqldb.bat delete mode 100755 show-hsqldb.sh delete mode 100644 src/main/java/sample/data/jpa/SecurityConfig.java create mode 100644 src/main/java/sample/data/jpa/WebSecurityConfig.java create mode 100644 src/main/java/sample/data/jpa/controller/ViewController.java delete mode 100644 src/main/java/sample/data/jpa/domain/User.java delete mode 100644 src/main/java/sample/data/jpa/service/UserDao.java delete mode 100644 src/main/java/sample/data/jpa/web/UserController.java create mode 100644 src/main/resources/templates/admin.html create mode 100644 src/main/resources/templates/index.html create mode 100644 src/main/resources/templates/indexmain.html create mode 100644 src/main/resources/templates/logout.html diff --git a/pom.xml b/pom.xml index 791f54e..7272806 100755 --- a/pom.xml +++ b/pom.xml @@ -15,8 +15,8 @@ ${basedir}/../.. - 11 - 11 + 17 + 17 @@ -90,9 +90,9 @@ - javax.validation - validation-api - 2.0.1.Final + jakarta.validation + jakarta.validation-api + 3.1.1 @@ -196,41 +196,7 @@ - - - spring-snapshots - Spring Snapshots - http://repo.spring.io/snapshot - - true - - - - spring-milestones - Spring Milestones - http://repo.spring.io/milestone - - false - - - - - spring-snapshots - Spring Snapshots - http://repo.spring.io/snapshot - - true - - - - spring-milestones - Spring Milestones - http://repo.spring.io/milestone - - false - - spring-releases Spring Releases @@ -240,5 +206,4 @@ - diff --git a/run-hsqldb-server.bat b/run-hsqldb-server.bat deleted file mode 100755 index 0885654..0000000 --- a/run-hsqldb-server.bat +++ /dev/null @@ -1,3 +0,0 @@ -mkdir data -cd data -java -cp ..\hsqldb-2.7.2.jar org.hsqldb.Server diff --git a/run-hsqldb-server.sh b/run-hsqldb-server.sh deleted file mode 100755 index 5fc9a89..0000000 --- a/run-hsqldb-server.sh +++ /dev/null @@ -1,4 +0,0 @@ -mvn dependency:copy-dependencies -mkdir data 2> /dev/null -cd data -java -cp ../target/dependency/hsqldb-2.7.2.jar org.hsqldb.Server diff --git a/show-hsqldb.bat b/show-hsqldb.bat deleted file mode 100644 index 3bf6df2..0000000 --- a/show-hsqldb.bat +++ /dev/null @@ -1,2 +0,0 @@ -java -cp ./target/dependency/hsqldb-2.7.2.jar org.hsqldb.util.DatabaseManagerSwing --driver org.hsqldb.jdbcDriver --url jdbc:hsqldb:hsql://localhost/ --user SA - diff --git a/show-hsqldb.sh b/show-hsqldb.sh deleted file mode 100755 index 41305d6..0000000 --- a/show-hsqldb.sh +++ /dev/null @@ -1,2 +0,0 @@ -#mvn dependency:copy-dependencies -java -cp ./target/dependency/hsqldb-2.7.2.jar org.hsqldb.util.DatabaseManagerSwing --driver org.hsqldb.jdbcDriver --url jdbc:hsqldb:hsql://localhost/ --user SA diff --git a/src/main/java/sample/data/jpa/SampleDataJpaApplication.java b/src/main/java/sample/data/jpa/SampleDataJpaApplication.java index 09f78ef..4cca251 100644 --- a/src/main/java/sample/data/jpa/SampleDataJpaApplication.java +++ b/src/main/java/sample/data/jpa/SampleDataJpaApplication.java @@ -21,9 +21,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SampleDataJpaApplication { - - public static void main(String[] args) throws Exception { - SpringApplication.run(SampleDataJpaApplication.class, args); - } - + public static void main(String[] args) throws Exception { + SpringApplication.run(SampleDataJpaApplication.class, args); + } } diff --git a/src/main/java/sample/data/jpa/SecurityConfig.java b/src/main/java/sample/data/jpa/SecurityConfig.java deleted file mode 100644 index 37da8eb..0000000 --- a/src/main/java/sample/data/jpa/SecurityConfig.java +++ /dev/null @@ -1,21 +0,0 @@ -package sample.data.jpa; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.web.SecurityFilterChain; - -@Configuration -public class SecurityConfig { - - @Bean - public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - http - .csrf(csrf -> csrf.disable()) - .authorizeHttpRequests(auth -> auth - .anyRequest().permitAll() - ); - - return http.build(); - } -} diff --git a/src/main/java/sample/data/jpa/WebSecurityConfig.java b/src/main/java/sample/data/jpa/WebSecurityConfig.java new file mode 100644 index 0000000..23be87d --- /dev/null +++ b/src/main/java/sample/data/jpa/WebSecurityConfig.java @@ -0,0 +1,41 @@ +package sample.data.jpa; + + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; +import org.springframework.security.web.SecurityFilterChain; + +@Configuration +@EnableWebSecurity +public class WebSecurityConfig { + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http.authorizeHttpRequests(auth -> auth + .requestMatchers("/").permitAll() + .requestMatchers("/index").hasAuthority("USER") + .requestMatchers("/admin").hasAuthority("ADMIN") + .requestMatchers("/session/**").hasAnyAuthority("USER", "ADMIN") + .requestMatchers("/quizz/**").hasAuthority("ADMIN") + .anyRequest().authenticated() + ) + .oauth2ResourceServer(oauth2 -> oauth2 + .jwt(jwt -> jwt.jwtAuthenticationConverter(jwtToken -> { + Map> realmAccess = jwtToken.getClaim("realm_access"); + Collection roles = realmAccess.get("roles"); + List grantedAuthorities = roles.stream() + .map(role -> new SimpleGrantedAuthority(role.toUpperCase())) + .toList(); + return new JwtAuthenticationToken(jwtToken, grantedAuthorities); + })) + ); + return http.build(); + } +} \ No newline at end of file diff --git a/src/main/java/sample/data/jpa/controller/ViewController.java b/src/main/java/sample/data/jpa/controller/ViewController.java new file mode 100644 index 0000000..564d39f --- /dev/null +++ b/src/main/java/sample/data/jpa/controller/ViewController.java @@ -0,0 +1,38 @@ +package sample.data.jpa.controller; + +import java.security.Principal; + +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.servlet.ModelAndView; + +@Controller +public class ViewController { + @GetMapping("/index") + @PreAuthorize("hasRole('USER')") + public ModelAndView index(JwtAuthenticationToken authentication) { + + ModelAndView modelAndView = new ModelAndView("index"); + authentication.getToken().getClaims().forEach((e, v) -> { + System.err.println(e + ' ' + v); + }); + modelAndView.addObject("user", authentication); + return modelAndView; + } + + @GetMapping("/") + public ModelAndView main() { + ModelAndView modelAndView = new ModelAndView("indexmain"); + return modelAndView; + } + + @GetMapping("/admin") + @PreAuthorize("hasRole('ADMIN')") + public ModelAndView admin(Principal principal) { + ModelAndView modelAndView = new ModelAndView("admin"); + modelAndView.addObject("user", principal); + return modelAndView; + } +} \ No newline at end of file diff --git a/src/main/java/sample/data/jpa/domain/User.java b/src/main/java/sample/data/jpa/domain/User.java deleted file mode 100644 index 0607348..0000000 --- a/src/main/java/sample/data/jpa/domain/User.java +++ /dev/null @@ -1,66 +0,0 @@ -package sample.data.jpa.domain; -// Imports ... - -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.Table; -import javax.validation.constraints.NotNull; - -@Entity -@Table(name = "users") -public class User { - - // An autogenerated id (unique for each user in the db) - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - private long id; - - @NotNull - private String email; - - @NotNull - private String name; - - // Public methods - - public User() { } - - public User(long id) { - this.id = id; - } - - public User(String email, String name) { - this.email = email; - this.name = name; - } - -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 String getName() { - return name; -} - -public void setName(String name) { - this.name = name; -} - - // Getter and setter methods - // ... - -} \ No newline at end of file diff --git a/src/main/java/sample/data/jpa/metier/Utilisateur.java b/src/main/java/sample/data/jpa/metier/Utilisateur.java index 3c03d16..1f32b74 100644 --- a/src/main/java/sample/data/jpa/metier/Utilisateur.java +++ b/src/main/java/sample/data/jpa/metier/Utilisateur.java @@ -16,6 +16,10 @@ public class Utilisateur implements Serializable { private int id; private String name; + //Pour génénrer un sub diff pour chaque persone + @Column(unique = true) + private String keycloakId; + @Column(unique=true) private String email; private String password; diff --git a/src/main/java/sample/data/jpa/service/QuestionDao.java b/src/main/java/sample/data/jpa/service/QuestionDao.java index 74d02ad..4a03156 100644 --- a/src/main/java/sample/data/jpa/service/QuestionDao.java +++ b/src/main/java/sample/data/jpa/service/QuestionDao.java @@ -7,6 +7,4 @@ import sample.data.jpa.metier.Question; @Transactional public interface QuestionDao extends JpaRepository { - - } diff --git a/src/main/java/sample/data/jpa/service/UserDao.java b/src/main/java/sample/data/jpa/service/UserDao.java deleted file mode 100644 index bd152a0..0000000 --- a/src/main/java/sample/data/jpa/service/UserDao.java +++ /dev/null @@ -1,20 +0,0 @@ -package sample.data.jpa.service; - -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.transaction.annotation.Transactional; - -import sample.data.jpa.domain.User; - -// Imports ... - -@Transactional -public interface UserDao extends JpaRepository { - - /** - * This method will find an User instance in the database by its email. - * Note that this method is not implemented and its working code will be - * automagically generated from its signature by Spring Data JPA. - */ - public User findByEmail(String email); - -} \ No newline at end of file diff --git a/src/main/java/sample/data/jpa/service/UtilisateurDao.java b/src/main/java/sample/data/jpa/service/UtilisateurDao.java index b0c51c7..f2080c0 100644 --- a/src/main/java/sample/data/jpa/service/UtilisateurDao.java +++ b/src/main/java/sample/data/jpa/service/UtilisateurDao.java @@ -5,4 +5,5 @@ import org.springframework.data.jpa.repository.JpaRepository; import sample.data.jpa.metier.Utilisateur; public interface UtilisateurDao extends JpaRepository { -} + Utilisateur findByKeycloakId(String keycloakId); +} \ No newline at end of file diff --git a/src/main/java/sample/data/jpa/web/QuestionController.java b/src/main/java/sample/data/jpa/web/QuestionController.java index a96ef33..2e1fe1f 100644 --- a/src/main/java/sample/data/jpa/web/QuestionController.java +++ b/src/main/java/sample/data/jpa/web/QuestionController.java @@ -13,14 +13,13 @@ import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.security.access.prepost.PreAuthorize; import sample.data.jpa.metier.Question; import sample.data.jpa.metier.Reponse; import sample.data.jpa.service.QuestionDao; import sample.data.jpa.service.ReponseDao; - - @Controller @RequestMapping("/question") public class QuestionController { @@ -46,21 +45,20 @@ public class QuestionController { */ @PostMapping("/create") @ResponseBody + @PreAuthorize("hasRole('ADMIN')") public String create(@RequestBody Map body) { String qId = ""; Question q = new Question(); try { - if(body.containsKey("enonce")){ + if (body.containsKey("enonce")) { q.setEnonce(body.get("enonce")); - } - else q.setEnonce(""); + } else q.setEnonce(""); qDao.save(q); qId = String.valueOf(q.getId()); + } catch (Exception ex) { + return "Error creating the question : " + ex.toString(); } - catch (Exception ex) { - return "Error creating the question : " + ex.toString(); - } - return "Question \""+q.getEnonce()+"\" succesfully created with id = " + qId; + return "Question \"" + q.getEnonce() + "\" succesfully created with id = " + qId; } /* @@ -69,21 +67,22 @@ public class QuestionController { */ @PutMapping("/update/{id}") @ResponseBody + @PreAuthorize("hasRole('ADMIN')") public String update(@PathVariable("id") int id, @RequestBody Map body) { Question q; try { q = qDao.findById(id).get(); q.setEnonce(body.get("enonce")); qDao.save(q); - } - catch (Exception ex) { + } catch (Exception ex) { return "Error updating the question: " + ex.toString(); } - return "Question "+id+" succesfully updated! : " + q.getEnonce(); + return "Question " + id + " succesfully updated! : " + q.getEnonce(); } @GetMapping("/get/{id}") @ResponseBody + @PreAuthorize("hasAnyRole('ADMIN','USER')") public String get(@PathVariable("id") int id) { Question q; String res = ""; @@ -99,13 +98,14 @@ public class QuestionController { @GetMapping("/getAll") @ResponseBody - public String getAll(){ + @PreAuthorize("hasAnyRole('ADMIN','USER')") + public String getAll() { try { List questions = qDao.findAll(); String res = ""; - for(Question question : questions){ - res+="id: " + question.getId() + " , "; - res+="enonce: \"" + question.getEnonce() + "\"\n"; + for (Question question : questions) { + res += "id: " + question.getId() + " , "; + res += "enonce: \"" + question.getEnonce() + "\"\n"; } @@ -115,35 +115,33 @@ public class QuestionController { } } - - @GetMapping("/getReponses/{id}") @ResponseBody + @PreAuthorize("hasAnyRole('ADMIN','USER')") public String getReponses(@PathVariable("id") int id) { try { Question question = qDao.findById(id).get(); Reponse rep = question.getReponse(); - if(rep != null){ + if (rep != null) { List reponses = rep.getReponses(); String res = "["; - for(int i = 0; i < reponses.size(); i++){ - res+=reponses.get(i); - if(i sessions = q.getSessions(); @@ -148,39 +143,37 @@ public class QuizzController { @GetMapping("/getAll") @ResponseBody - public String getAll(){ + @PreAuthorize("hasAnyRole('ADMIN', 'USER')") + public String getAll() { String res = ""; try { List quizzs = qDao.findAll(); for (Quizz quizz : quizzs) { - res+="id: " + quizz.getId() + " , "; - res+=" nbQuestion:" + quizz.getQuestions().size() + "]\n"; + res += "id: " + quizz.getId() + " , "; + res += " nbQuestion:" + quizz.getQuestions().size() + "]\n"; } - } - catch (Exception ex) { - return "Error get all Quizz :" + ex.toString(); + } catch (Exception ex) { + return "Error get all Quizz :" + ex.toString(); } return "Quizzs : \n" + res; } @GetMapping("/getQuestions/{id}") @ResponseBody - public String getQuestion(@PathVariable("id") int id){ + @PreAuthorize("hasAnyRole('ADMIN', 'USER')") + public String getQuestion(@PathVariable("id") int id) { String res = ""; - try {; + try { + ; Quizz quizz = qDao.findById(id).get(); - for(Question question : quizz.getQuestions()){ - res+="id: " + question.getId() + " , "; - res+="enonce: \"" + question.getEnonce() + "\"\n"; + for (Question question : quizz.getQuestions()) { + res += "id: " + question.getId() + " , "; + res += "enonce: \"" + question.getEnonce() + "\"\n"; } - - } - catch (Exception ex) { - return "Error get question of the Quizz :" + ex.toString(); + + } catch (Exception ex) { + return "Error get question of the Quizz :" + ex.toString(); } return "Questions : \n" + res; } - - - } \ No newline at end of file diff --git a/src/main/java/sample/data/jpa/web/ReponseController.java b/src/main/java/sample/data/jpa/web/ReponseController.java index 28824c3..d9e4920 100644 --- a/src/main/java/sample/data/jpa/web/ReponseController.java +++ b/src/main/java/sample/data/jpa/web/ReponseController.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -41,10 +42,11 @@ public class ReponseController { */ /* - * Créer une réponse de type Choix - */ + * Créer une réponse de type Choix + */ @PostMapping("/create/choix") @ResponseBody + @PreAuthorize("hasRole('ADMIN')") public String createReponseChoix() { try { Choix r = new Choix(); @@ -56,10 +58,11 @@ public class ReponseController { } /* - * Créer une réponse de type ReponseCourte - */ + * Créer une réponse de type ReponseCourte + */ @PostMapping("/create/courte") @ResponseBody + @PreAuthorize("hasRole('ADMIN')") public String createReponseCourte() { try { ReponseCourte r = new ReponseCourte(); @@ -72,12 +75,13 @@ public class ReponseController { @GetMapping("/getAll") @ResponseBody + @PreAuthorize("hasAnyRole('ADMIN','USER')") public String getAll() { try { String res = ""; List reponses = rDao.findAll(); for (Reponse reponse : reponses) { - res+="id : " + reponse.getId() + "\n" + reponse.prettyPrinter(1) + "\n"; + res += "id : " + reponse.getId() + " , " + reponse.toString() + "\n"; } return res; } catch (Exception ex) { @@ -87,6 +91,7 @@ public class ReponseController { @GetMapping("/get/{id}") @ResponseBody + @PreAuthorize("hasAnyRole('ADMIN','USER')") public String get(@PathVariable("id") int id) { try { String res = ""; @@ -101,14 +106,14 @@ public class ReponseController { @DeleteMapping("/delete/{id}") @ResponseBody + @PreAuthorize("hasRole('ADMIN')") public String delete(@PathVariable("id") int id) { try { Reponse r = rDao.findById(id).get(); rDao.delete(r); - } - catch (Exception ex) { - return "Erreur pendant la suppression de la Reponse " + id + " :" + ex.toString(); + } catch (Exception ex) { + return "Erreur pendant la suppression de la Reponse " + id + " :" + ex.toString(); } return "Reponse " + id + " supprimée avec succès"; } @@ -116,9 +121,10 @@ public class ReponseController { @PutMapping("/addReponse/{id}") @ResponseBody + @PreAuthorize("hasRole('ADMIN')") public String addReponse(@PathVariable("id") int id, @RequestBody Map body) { try { - if(body.containsKey("reponse")){ + if (body.containsKey("reponse")) { Reponse rep = rDao.findById(id).get(); String reponse = body.get("reponse"); rep.getReponses().add(reponse); @@ -132,6 +138,7 @@ public class ReponseController { @PutMapping("/removeReponse/{id}") @ResponseBody + @PreAuthorize("hasRole('ADMIN')") public String removeReponses(@PathVariable("id") int id, @RequestBody Map body) { try { Reponse rep = rDao.findById(id).get(); @@ -148,6 +155,7 @@ public class ReponseController { @PutMapping("/addChoix/{id}") @ResponseBody + @PreAuthorize("hasRole('ADMIN')") public String addChoix(@PathVariable("id") int id, @RequestBody Map body) { try { Reponse reponse = rDao.findById(id).get(); @@ -156,17 +164,16 @@ public class ReponseController { ((Choix) reponse).getChoix().add(choix); rDao.save(reponse); return "Choix \"" + choix + "\" ajouté à la question " + id; - } - else return "Erreur : la réponse doit être a choix multiple."; + } else return "Erreur : la réponse doit être a choix multiple."; } catch (Exception ex) { return "Erreur lors de l'ajout du choix : " + ex.toString(); } } - @PutMapping("/removeChoix/{id}") @ResponseBody + @PreAuthorize("hasRole('ADMIN')") public String removeChoix(@PathVariable("id") int id, @RequestBody Map body) { try { Reponse reponse = rDao.findById(id).get(); @@ -175,8 +182,7 @@ public class ReponseController { ((Choix) reponse).getChoix().remove(choix); rDao.save(reponse); return "Choix \"" + choix + "\" supprimé à la question " + id; - } - else return "Erreur : la réponse doit être a choix multiple."; + } else return "Erreur : la réponse doit être a choix multiple."; } catch (Exception ex) { return "Erreur lors de la suppression du choix : " + ex.toString(); diff --git a/src/main/java/sample/data/jpa/web/SessionController.java b/src/main/java/sample/data/jpa/web/SessionController.java index 932655a..09a3ecc 100644 --- a/src/main/java/sample/data/jpa/web/SessionController.java +++ b/src/main/java/sample/data/jpa/web/SessionController.java @@ -4,6 +4,8 @@ import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -24,7 +26,6 @@ import sample.data.jpa.service.UtilisateurDao; @Controller @RequestMapping("/session") public class SessionController { - @Autowired private SessionDao sDao; @Autowired @@ -39,53 +40,51 @@ public class SessionController { Put /session/addQuizz/{id}/{idQ} Put /session/removeQuizz/{id} Put /session/update/{id} param : body Jsp, "theme" - Put /session/addUtilisateur/{id}/{idU} - Put /session/removeUtilisateur/{id}/{idU} + Put /session/join/{sessionId} + Put /session//leave/{sessionId} */ - - @PostMapping("/create") @ResponseBody + @PreAuthorize("hasRole('ADMIN')") public String create(@RequestBody Map body) { String sId = ""; Session q = new Session(); try { - if(body.containsKey("theme")){ + if (body.containsKey("theme")) { q.setTheme(body.get("theme")); - } - else q.setTheme(""); + } else q.setTheme(""); sDao.save(q); sId = String.valueOf(q.getId()); + } catch (Exception ex) { + return "Error creating the Session : " + ex.toString(); } - catch (Exception ex) { - return "Error creating the Session : " + ex.toString(); - } - return "Session \""+q.getTheme()+"\" succesfully created with id = " + sId; + return "Session \"" + q.getTheme() + "\" succesfully created with id = " + sId; } @DeleteMapping("/delete/{id}") @ResponseBody + @PreAuthorize("hasRole('ADMIN')") public String delete(@PathVariable("id") int id) { - + try { Session q = sDao.findById(id).get(); sDao.delete(q); - } - catch (Exception ex) { - return "Error deleting the session " + id + " :" + ex.toString(); + } catch (Exception ex) { + return "Error deleting the session " + id + " :" + ex.toString(); } return "Session " + id + " succesfully deleted!"; } @GetMapping("/getAll") @ResponseBody - public String getAll(){ + @PreAuthorize("hasAnyRole('ADMIN','USER')") + public String getAll() { try { List sessions = sDao.findAll(); String res = ""; - for(Session session : sessions){ - res+="id: " + session.getId() + " , "; - res+="theme: \"" + session.getTheme() + "\" , "; + for (Session session : sessions) { + res += "id: " + session.getId() + " , "; + res += "theme: \"" + session.getTheme() + "\" , "; res += "nbUtilisateur :" + session.getUtilisateurs().size() + "\n"; } @@ -98,6 +97,7 @@ public class SessionController { @PutMapping("/addQuizz/{id}/{qid}") @ResponseBody + @PreAuthorize("hasRole('ADMIN')") public String addQuizz(@PathVariable("id") int id, @PathVariable("qid") int qId) { try { Session s = sDao.findById(id).get(); @@ -111,9 +111,10 @@ public class SessionController { } return "Quizz " + qId + " add in Session " + id; } - + @PutMapping("/removeQuizz/{id}/{qid}") @ResponseBody + @PreAuthorize("hasRole('ADMIN')") public String removeQuizz(@PathVariable("id") int id, @PathVariable("qid") int qId) { try { Session s = sDao.findById(id).get(); @@ -128,57 +129,65 @@ public class SessionController { return "Quizz " + qId + " remove from Session " + id; } - /* * Utiliser un Json pour mettre le String "theme" * l'id se met dans l'url */ @PutMapping("/update/{id}") @ResponseBody + @PreAuthorize("hasRole('ADMIN')") public String updateQuestion(@PathVariable("id") int id, @RequestBody Map body) { Session s; try { s = sDao.findById(id).get(); s.setTheme(body.get("theme")); sDao.save(s); - } - catch (Exception ex) { + } catch (Exception ex) { return "Error updating the Session: " + ex.toString(); } - return "Session "+id+" succesfully updated! : " + s.getTheme(); + return "Session " + id + " succesfully updated! : " + s.getTheme(); } - - @PutMapping("/addUtilisateur/{id}/{idU}") + @PutMapping("/join/{sessionId}") @ResponseBody - public String addSession(@PathVariable("id") int id, @PathVariable("qid") int idU) { + @PreAuthorize("hasRole('USER')") + public String joinSession(@PathVariable("sessionId") int sessionId, JwtAuthenticationToken auth) { try { - Utilisateur u = uDao.findById(idU).get(); - Session s = sDao.findById(id).get(); + String keycloakUserId = auth.getToken().getClaim("sub"); + Utilisateur u = uDao.findByKeycloakId(keycloakUserId); + if (u == null) { + return "User not found in database."; + } + Session s = sDao.findById(sessionId).orElseThrow(() -> new Exception("Session not found")); u.getSessions().add(s); s.getUtilisateurs().add(u); sDao.save(s); uDao.save(u); + + return "User " + u.getName() + " joined session " + sessionId; } catch (Exception ex) { - return "Erreur pendant l'ajout de l'utilisateur dans la session : " + ex.toString(); + return "Erreur pendant l'ajout de l'utilisateur dans la session : " + ex.toString(); } - return "Utilisateur " + id + " ajouté à la Session " + id; } - - @PutMapping("/removeUtilisateur/{id}/{idU}") + + @PutMapping("/leave/{sessionId}") @ResponseBody - public String removeSession(@PathVariable("id") int id, @PathVariable("idU") int idU) { + @PreAuthorize("hasRole('USER')") + public String leaveSession(@PathVariable("sessionId") int sessionId, JwtAuthenticationToken auth) { try { - Utilisateur u = uDao.findById(idU).get(); - Session s = sDao.findById(id).get(); + String keycloakUserId = auth.getToken().getClaim("sub"); + Utilisateur u = uDao.findByKeycloakId(keycloakUserId); + if (u == null) { + return "User not found in database."; + } + Session s = sDao.findById(sessionId).orElseThrow(() -> new Exception("Session not found")); u.getSessions().remove(s); s.getUtilisateurs().remove(u); sDao.save(s); uDao.save(u); + return "User " + u.getName() + " left session " + sessionId; } catch (Exception ex) { - return "Erreur pendant la suppression de l'utilisateur de la session : " + ex.toString(); + return "Erreur pendant la suppression de l'utilisateur de la session : " + ex.toString(); } - return "Utilisateur " + id + " retiré de la Session " + id; } - } \ No newline at end of file diff --git a/src/main/java/sample/data/jpa/web/UserController.java b/src/main/java/sample/data/jpa/web/UserController.java deleted file mode 100644 index 729c584..0000000 --- a/src/main/java/sample/data/jpa/web/UserController.java +++ /dev/null @@ -1,92 +0,0 @@ -package sample.data.jpa.web; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; - -import sample.data.jpa.domain.User; -import sample.data.jpa.service.UserDao; - -@Controller -@RequestMapping("/user") -public class UserController { - - /** - * GET /create --> Create a new user and save it in the database. - */ - @RequestMapping("/create") - @ResponseBody - public String create(String email, String name) { - String userId = ""; - try { - User user = new User(email, name); - userDao.save(user); - userId = String.valueOf(user.getId()); - } - catch (Exception ex) { - return "Error creating the user: " + ex.toString(); - } - return "User succesfully created with id = " + userId; - } - - /** - * GET /delete --> Delete the user having the passed id. - */ - @RequestMapping("/delete") - @ResponseBody - public String delete(long id) { - try { - User user = new User(id); - userDao.delete(user); - } - catch (Exception ex) { - return "Error deleting the user:" + ex.toString(); - } - return "User succesfully deleted!"; - } - - /** - * GET /get-by-email --> Return the id for the user having the passed - * email. - */ - @RequestMapping("/get-by-email/{email}") - @ResponseBody - public String getByEmail(@PathVariable("email") String email) { - String userId = ""; - try { - User user = userDao.findByEmail(email); - userId = String.valueOf(user.getId()); - } - catch (Exception ex) { - return "User not found"; - } - return "The user id is: " + userId; - } - - /** - * GET /update --> Update the email and the name for the user in the - * database having the passed id. - */ - @RequestMapping("/update") - @ResponseBody - public String updateUser(long id, String email, String name) { - try { - User user = userDao.findById(id).get(); - user.setEmail(email); - user.setName(name); - userDao.save(user); - } - catch (Exception ex) { - return "Error updating the user: " + ex.toString(); - } - return "User succesfully updated!"; - } - - // Private fields - - @Autowired - private UserDao userDao; - -} \ No newline at end of file diff --git a/src/main/java/sample/data/jpa/web/UtilisateurController.java b/src/main/java/sample/data/jpa/web/UtilisateurController.java index 618f20d..c11538b 100644 --- a/src/main/java/sample/data/jpa/web/UtilisateurController.java +++ b/src/main/java/sample/data/jpa/web/UtilisateurController.java @@ -1,8 +1,10 @@ package sample.data.jpa.web; + import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -38,9 +40,9 @@ public class UtilisateurController { Put /utilisateur/update/{id} param : body Jsp, "name", "email", "oldpassword, "password" */ - @PostMapping("/create") @ResponseBody + @PreAuthorize("hasRole('ADMIN')") public String create(@RequestBody Map body) { try { if(body.containsKey("name") && body.containsKey("email") && body.containsKey("password")){ @@ -50,40 +52,38 @@ public class UtilisateurController { u.setPassword(body.get("password")); uDao.save(u); String uId = String.valueOf(u.getId()); - return "Utilisateur \""+u.getName()+"\" créé avec succès avec l'id = " + uId; - } - else return "Erreur, besoin de name, email et password dans le JSON"; - } - catch (Exception ex) { - return "Erreur durant la création de l'Utilisateur : " + ex.toString(); + return "Utilisateur \"" + u.getName() + "\" créé avec succès avec l'id = " + uId; + } else return "Erreur, besoin de name, email et password dans le JSON"; + } catch (Exception ex) { + return "Erreur durant la création de l'Utilisateur : " + ex.toString(); } } - @DeleteMapping("/delete/{id}") @ResponseBody + @PreAuthorize("hasRole('ADMIN')") public String delete(@PathVariable("id") int id) { - + try { Utilisateur u = uDao.findById(id).get(); uDao.delete(u); - } - catch (Exception ex) { - return "Erreur pendant la suppression de l'utilisateur " + id + " :" + ex.toString(); + } catch (Exception ex) { + return "Erreur pendant la suppression de l'utilisateur " + id + " :" + ex.toString(); } return "Utilisateur " + id + " supprimé avec succès !"; } @GetMapping("/getAll") @ResponseBody - public String getAll(){ + @PreAuthorize("hasAnyRole('ADMIN','USER')") + public String getAll() { try { List utilisateurs = uDao.findAll(); String res = ""; - for(Utilisateur utilisateur : utilisateurs){ - res+="id: " + utilisateur.getId() + " , "; - res+="name: " + utilisateur.getName() + " , "; - res+="email: \"" + utilisateur.getEmail() + "\"\n"; + for (Utilisateur utilisateur : utilisateurs) { + res += "id: " + utilisateur.getId() + " , "; + res += "name: " + utilisateur.getName() + " , "; + res += "email: \"" + utilisateur.getEmail() + "\"\n"; } return res; @@ -94,6 +94,7 @@ public class UtilisateurController { @GetMapping("/getSessions/{id}") @ResponseBody + @PreAuthorize("hasAnyRole('ADMIN','USER')") public String getSessions(@PathVariable("id") int id){ try { Utilisateur u = uDao.findById(id).get(); @@ -109,6 +110,7 @@ public class UtilisateurController { @PutMapping("/addSession/{id}/{qid}") @ResponseBody + @PreAuthorize("hasRole('ADMIN')") public String addSession(@PathVariable("id") int id, @PathVariable("qid") int sId) { try { Utilisateur u = uDao.findById(id).get(); @@ -126,6 +128,7 @@ public class UtilisateurController { @PutMapping("/removeSession/{id}/{qid}") @ResponseBody + @PreAuthorize("hasRole('ADMIN')") public String removeSession(@PathVariable("id") int id, @PathVariable("qid") int sId) { try { Utilisateur u = uDao.findById(id).get(); @@ -143,20 +146,19 @@ public class UtilisateurController { @PostMapping("/update/{id}") @ResponseBody + @PreAuthorize("hasRole('ADMIN')") public String update(@PathVariable("id") int id, @RequestBody Map body) { try { - if(body.containsKey("name") && body.containsKey("email") && body.containsKey("password")){ + if (body.containsKey("name") && body.containsKey("email") && body.containsKey("password")) { Utilisateur u = uDao.findById(id).get(); u.setName(body.get("name")); u.setEmail(body.get("email")); u.setPassword(body.get("password")); uDao.save(u); - return "Utilisateur \""+u.getName()+"\" mis à jour avec succès"; - } - else return "Erreur, besoin de name, email et password dans le JSON"; - } - catch (Exception ex) { - return "Erreur durant la mise à jour de de l'Utilisateur : " + ex.toString(); + return "Utilisateur \"" + u.getName() + "\" mis à jour avec succès"; + } else return "Erreur, besoin de name, email et password dans le JSON"; + } catch (Exception ex) { + return "Erreur durant la mise à jour de de l'Utilisateur : " + ex.toString(); } } } \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 782bef1..1bae572 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,2 +1,14 @@ -spring.datasource.name=scratchdb -spring.jmx.default-domain=jpa.sample \ No newline at end of file +server.port=8082 + +spring.h2.console.enabled=true +spring.h2.console.path=/h2 +spring.datasource.url=jdbc:h2:mem:testdb +spring.datasource.driver-class-name=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password= +spring.sql.init.platform=h2 +spring.sql.init.mode= always +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect + +spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8080/realms/myspringbootapprealm +spring.security.oauth2.resourceserver.jwt.jwk-set-uri=http://localhost:8080/realms/myspringbootapprealm/protocol/openid-connect/certs diff --git a/src/main/resources/templates/admin.html b/src/main/resources/templates/admin.html new file mode 100644 index 0000000..2a63f37 --- /dev/null +++ b/src/main/resources/templates/admin.html @@ -0,0 +1,14 @@ + + + + + Admin + + +This is the admin page +
+Logged user: +
+logout + + \ No newline at end of file diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html new file mode 100644 index 0000000..b0cc4c7 --- /dev/null +++ b/src/main/resources/templates/index.html @@ -0,0 +1,14 @@ + + + + + Index + + +This is the index page. +
+Logged user: +
+admin +logout + diff --git a/src/main/resources/templates/indexmain.html b/src/main/resources/templates/indexmain.html new file mode 100644 index 0000000..29976ae --- /dev/null +++ b/src/main/resources/templates/indexmain.html @@ -0,0 +1,15 @@ + + + + + Main + + +This is the main page. +
+index +
+admin + + +> \ No newline at end of file diff --git a/src/main/resources/templates/logout.html b/src/main/resources/templates/logout.html new file mode 100644 index 0000000..d0e6dee --- /dev/null +++ b/src/main/resources/templates/logout.html @@ -0,0 +1,14 @@ + + + + + Logout + + +This is the logout page. +
+Logged user: +
+main + + \ No newline at end of file