From 94cba5e60c1237c920aacf13b0caa97bf2753b62 Mon Sep 17 00:00:00 2001 From: tuanvu Date: Thu, 8 Jan 2026 08:57:58 +0100 Subject: [PATCH 1/4] add registration --- front_end/src/classes.tsx | 1 + front_end/src/components/login.tsx | 30 ++++++++++++++++----- front_end/src/components/ressourcePanel.tsx | 3 +++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/front_end/src/classes.tsx b/front_end/src/classes.tsx index a22ad88..365dda1 100644 --- a/front_end/src/classes.tsx +++ b/front_end/src/classes.tsx @@ -4,6 +4,7 @@ export type Role = "Admin" | "Athlete" | "Coach"; export class User{ id!: number; nom!: String; + prenom!:String; sessions: Session[] = []; //nb: Admin liaison non symétrique /!\ email!: String; role!: Role; diff --git a/front_end/src/components/login.tsx b/front_end/src/components/login.tsx index 97b4465..aef8447 100644 --- a/front_end/src/components/login.tsx +++ b/front_end/src/components/login.tsx @@ -8,11 +8,31 @@ import { useLocalData } from '../context/useLocalData'; export const Login =() =>{ const {user,setUser} = useLocalData() + const { keycloak } = useKeycloak(); + useEffect(() => { + if (keycloak.authenticated) { + fetch("http://localhost:8080/api/athlete/create", { + method: "POST", + headers: { + Authorization: `Bearer ${keycloak.token}`, + }, + }); + } + }, [keycloak.authenticated]); - - useEffect(() => { //TODO à supprimer - setUser(getUserTest()) - },[]); + useEffect(() => { + if (keycloak.authenticated) { + const tokenParsed = keycloak.tokenParsed; + setUser({ + id: tokenParsed?.id, + email: tokenParsed?.email, + nom: tokenParsed?.family_name, + prenom: tokenParsed?.given_name, + role: "Athlete", + sessions: [] + }); + } + }, [keycloak.authenticated]); function handleLogin(): void { @@ -24,8 +44,6 @@ export const Login =() =>{ keycloak.logout() setUser(new User()); } - - const { keycloak } = useKeycloak() return(
diff --git a/front_end/src/components/ressourcePanel.tsx b/front_end/src/components/ressourcePanel.tsx index 57f8661..00aca71 100644 --- a/front_end/src/components/ressourcePanel.tsx +++ b/front_end/src/components/ressourcePanel.tsx @@ -11,6 +11,9 @@ const [showSessions, setShowSessions] = useState(false); const [showLignes, setShowLignes] = useState(false); console.log("Rôle utilisateur:", user.role); + console.log(user.nom); + console.log(user.prenom); + console.log(user.email); if (user.role === "Athlete") return null; From 068eb7f611e01cd3a6ef014f038ed41a14fc6e5d Mon Sep 17 00:00:00 2001 From: tuanvu Date: Thu, 8 Jan 2026 08:59:52 +0100 Subject: [PATCH 2/4] remove admin previlige in creation --- .../src/main/java/hackathon/FrisbYEE/rest/AthleteResource.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/back_end/src/main/java/hackathon/FrisbYEE/rest/AthleteResource.java b/back_end/src/main/java/hackathon/FrisbYEE/rest/AthleteResource.java index b4372ee..32999dd 100644 --- a/back_end/src/main/java/hackathon/FrisbYEE/rest/AthleteResource.java +++ b/back_end/src/main/java/hackathon/FrisbYEE/rest/AthleteResource.java @@ -32,7 +32,6 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; - @Controller @RequestMapping("/athlete") public class AthleteResource { @@ -45,7 +44,6 @@ public class AthleteResource { @ApiResponse(responseCode = "200", description = "Renvoie l'athlète créé", content = @Content(mediaType = "application/json", schema = @Schema(implementation = AthleteDTO.class))) }) @PostMapping("/create") - @PreAuthorize("hasRole('Admin')") // Only admin can create?? public ResponseEntity create(@RequestBody AthleteDTO dto) { Athlete athlete = mapToEntity(dto); athleteDAO.save(athlete); From e28b12683849de8fa8c17575ad74bc1226860cbb Mon Sep 17 00:00:00 2001 From: tuanvu Date: Thu, 8 Jan 2026 11:27:18 +0100 Subject: [PATCH 3/4] change in athlete and getkeycloak --- .../hackathon/FrisbYEE/jpa/metier/Admin.java | 10 ----- .../FrisbYEE/jpa/metier/Athlete.java | 11 ------ .../hackathon/FrisbYEE/jpa/metier/Coach.java | 10 ----- .../hackathon/FrisbYEE/jpa/metier/User.java | 6 +-- .../FrisbYEE/jpa/service/AthleteDAO.java | 5 ++- .../FrisbYEE/rest/AthleteResource.java | 11 +++++- .../FrisbYEE/rest/CoachResource.java | 4 +- .../src/main/resources/application.properties | 1 - front_end/src/App.tsx | 4 +- front_end/src/classes.tsx | 5 +-- front_end/src/components/login.tsx | 37 +++++++++++++++---- 11 files changed, 50 insertions(+), 54 deletions(-) diff --git a/back_end/src/main/java/hackathon/FrisbYEE/jpa/metier/Admin.java b/back_end/src/main/java/hackathon/FrisbYEE/jpa/metier/Admin.java index 6928f7c..f7d35c1 100644 --- a/back_end/src/main/java/hackathon/FrisbYEE/jpa/metier/Admin.java +++ b/back_end/src/main/java/hackathon/FrisbYEE/jpa/metier/Admin.java @@ -43,16 +43,6 @@ public class Admin extends User{ super.setPrenom(prenom); } - @Override - public String getId_keycloak() { - return super.getId_keycloak(); - } - - @Override - public void setId_keycloak(String id_keycloak) { - super.setId_keycloak(id_keycloak); - } - @Override public Role getRole() { return super.getRole(); diff --git a/back_end/src/main/java/hackathon/FrisbYEE/jpa/metier/Athlete.java b/back_end/src/main/java/hackathon/FrisbYEE/jpa/metier/Athlete.java index a4a4865..c43b77f 100644 --- a/back_end/src/main/java/hackathon/FrisbYEE/jpa/metier/Athlete.java +++ b/back_end/src/main/java/hackathon/FrisbYEE/jpa/metier/Athlete.java @@ -56,17 +56,6 @@ public class Athlete extends User{ public void setPrenom(String prenom) { super.setPrenom(prenom); } - - @Override - public String getId_keycloak() { - return super.getId_keycloak(); - } - - @Override - public void setId_keycloak(String id_keycloak) { - super.setId_keycloak(id_keycloak); - } - @Override public Role getRole() { return super.getRole(); diff --git a/back_end/src/main/java/hackathon/FrisbYEE/jpa/metier/Coach.java b/back_end/src/main/java/hackathon/FrisbYEE/jpa/metier/Coach.java index 77ad6ec..cd2ade7 100644 --- a/back_end/src/main/java/hackathon/FrisbYEE/jpa/metier/Coach.java +++ b/back_end/src/main/java/hackathon/FrisbYEE/jpa/metier/Coach.java @@ -49,16 +49,6 @@ public class Coach extends User{ super.setPrenom(prenom); } - @Override - public String getId_keycloak() { - return super.getId_keycloak(); - } - - @Override - public void setId_keycloak(String id_keycloak) { - super.setId_keycloak(id_keycloak); - } - @Override public Role getRole() { return super.getRole(); diff --git a/back_end/src/main/java/hackathon/FrisbYEE/jpa/metier/User.java b/back_end/src/main/java/hackathon/FrisbYEE/jpa/metier/User.java index 188bd09..2bdf5ce 100644 --- a/back_end/src/main/java/hackathon/FrisbYEE/jpa/metier/User.java +++ b/back_end/src/main/java/hackathon/FrisbYEE/jpa/metier/User.java @@ -26,8 +26,8 @@ public class User implements Serializable { @GeneratedValue @Column(unique = true, nullable = false) private Integer id; - @Column(nullable = false, unique = true) - private String id_keycloak; + @Column(name = "id_keycloak", unique = true, nullable = false) + private String keycloakId; private String name; private String prenom; @@ -38,7 +38,7 @@ public class User implements Serializable { public User(String name, String id_keycloak, String prenom, Role role) { this.name = name; - this.id_keycloak = id_keycloak; + this.keycloakId = id_keycloak; this.prenom = prenom; this.role = role; } diff --git a/back_end/src/main/java/hackathon/FrisbYEE/jpa/service/AthleteDAO.java b/back_end/src/main/java/hackathon/FrisbYEE/jpa/service/AthleteDAO.java index 476acc8..25da7ef 100644 --- a/back_end/src/main/java/hackathon/FrisbYEE/jpa/service/AthleteDAO.java +++ b/back_end/src/main/java/hackathon/FrisbYEE/jpa/service/AthleteDAO.java @@ -1,11 +1,12 @@ package hackathon.FrisbYEE.jpa.service; import hackathon.FrisbYEE.jpa.metier.Athlete; - +import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface AthleteDAO extends JpaRepository { - + boolean existsByKeycloakId(String keycloakId); + Optional findByKeycloakId(String keycloakId); } \ No newline at end of file diff --git a/back_end/src/main/java/hackathon/FrisbYEE/rest/AthleteResource.java b/back_end/src/main/java/hackathon/FrisbYEE/rest/AthleteResource.java index 32999dd..a638c7f 100644 --- a/back_end/src/main/java/hackathon/FrisbYEE/rest/AthleteResource.java +++ b/back_end/src/main/java/hackathon/FrisbYEE/rest/AthleteResource.java @@ -32,7 +32,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; -@Controller +@RestController @RequestMapping("/athlete") public class AthleteResource { @Autowired @@ -124,8 +124,9 @@ public class AthleteResource { private AthleteDTO mapToDTO(Athlete athlete) { AthleteDTO dto = new AthleteDTO(); - dto.setId_keycloak(athlete.getId_keycloak()); + dto.setId_keycloak(athlete.getKeycloakId()); dto.setName(athlete.getName()); + dto.setPrenom(athlete.getPrenom()); dto.setCategorie(athlete.getCategorie()); dto.setNiveau(athlete.getNiveau()); return dto; @@ -133,6 +134,12 @@ public class AthleteResource { private Athlete mapToEntity(AthleteDTO dto) { Athlete athlete = new Athlete(); + athlete.setName(dto.getName()); + athlete.setPrenom(dto.getPrenom()); + athlete.setKeycloakId(dto.getId_keycloak()); + athlete.setCategorie(dto.getCategorie()); + athlete.setNiveau(dto.getNiveau()); + athlete.setRole(hackathon.FrisbYEE.jpa.metier.Role.ATHLETE); return athlete; } diff --git a/back_end/src/main/java/hackathon/FrisbYEE/rest/CoachResource.java b/back_end/src/main/java/hackathon/FrisbYEE/rest/CoachResource.java index 706a777..acd34f1 100644 --- a/back_end/src/main/java/hackathon/FrisbYEE/rest/CoachResource.java +++ b/back_end/src/main/java/hackathon/FrisbYEE/rest/CoachResource.java @@ -70,14 +70,14 @@ public class CoachResource { private CoachDTO mapToDTO(Coach coach) { CoachDTO dto = new CoachDTO(); - dto.setId_keycloak(coach.getId_keycloak()); + dto.setId_keycloak(coach.getKeycloakId()); dto.setName(coach.getName()); return dto; } private Coach mapToEntity(CoachDTO dto) { Coach coach = new Coach(); - coach.setId_keycloak(dto.getId_keycloak()); + coach.setKeycloakId(dto.getId_keycloak()); coach.setName(dto.getName()); return coach; } diff --git a/back_end/src/main/resources/application.properties b/back_end/src/main/resources/application.properties index a0fc7cf..adbc11b 100644 --- a/back_end/src/main/resources/application.properties +++ b/back_end/src/main/resources/application.properties @@ -8,6 +8,5 @@ spring.jpa.show-sql=true spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect server.port=8081 server.servlet.context-path=/api - spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8080/realms/Frisbyee_realm spring.security.oauth2.resourceserver.jwt.jwk-set-uri: http://localhost:8080/realms/Frisbyee_realm/protocol/openid-connect/certs \ No newline at end of file diff --git a/front_end/src/App.tsx b/front_end/src/App.tsx index a4b5b7f..733add2 100644 --- a/front_end/src/App.tsx +++ b/front_end/src/App.tsx @@ -11,7 +11,7 @@ import EdtCoach from './components/edt_coach' import { Coach } from "./classes"; import RessourcePanel from './components/ressourcePanel'; import TestAPI from './components/test_api'; - +import EdtAthlete from './components/edt_athlete'; // Test const testCoach = new Coach(); testCoach.id = 1; @@ -36,7 +36,7 @@ function App() { - +
diff --git a/front_end/src/classes.tsx b/front_end/src/classes.tsx index cf5c7e6..42d638c 100644 --- a/front_end/src/classes.tsx +++ b/front_end/src/classes.tsx @@ -3,6 +3,7 @@ export type Role = "Admin" | "Athlete" | "Coach"; export class User{ id!: number; + keycloakId!: String; nom!: String; prenom!:String; sessions: Session[] = []; //nb: Admin liaison non symétrique /!\ @@ -19,21 +20,17 @@ export class Ligne{ export class Admin extends User{ role!: Role; - } export class Athlete extends User{ nom!: String; groupe!: Groupe; role!: Role; - - } export class Coach extends User{ nom!: String; role!: Role; - } export class Session{ diff --git a/front_end/src/components/login.tsx b/front_end/src/components/login.tsx index aef8447..c02d1b5 100644 --- a/front_end/src/components/login.tsx +++ b/front_end/src/components/login.tsx @@ -3,20 +3,42 @@ import { useEffect } from 'react'; import { getUserTest, User } from '../classes'; import { useLocalData } from '../context/useLocalData'; - - - export const Login =() =>{ const {user,setUser} = useLocalData() const { keycloak } = useKeycloak(); + useEffect(() => { - if (keycloak.authenticated) { - fetch("http://localhost:8080/api/athlete/create", { + const syncUser = async () => { + if (keycloak.authenticated && keycloak.token) { + console.log("Attempting to sync user with backend..."); + try { + const response = await fetch("http://localhost:8081/api/users/sync", { + method: "POST", + headers: { + "Authorization": `Bearer ${keycloak.token}`, + "Content-Type": "application/json" + }, + }); + console.log("Sync status:", response.status); + } catch (error) { + console.error("Sync fetch failed:", error); + } + } + }; + + syncUser(); + }, [keycloak.authenticated, keycloak.token]); + + useEffect(() => { + if (keycloak.authenticated && keycloak.token) { + fetch("http://localhost:8081/api/users/sync", { method: "POST", headers: { Authorization: `Bearer ${keycloak.token}`, }, - }); + }) + .then(res => console.log("Sync response status:", res.status)) + .catch(err => console.error("Sync error:", err));; } }, [keycloak.authenticated]); @@ -24,7 +46,8 @@ export const Login =() =>{ if (keycloak.authenticated) { const tokenParsed = keycloak.tokenParsed; setUser({ - id: tokenParsed?.id, + id: 0, + keycloakId: tokenParsed!.sub!, email: tokenParsed?.email, nom: tokenParsed?.family_name, prenom: tokenParsed?.given_name, From f77b4016282db783ade6695421832bf3910b5309 Mon Sep 17 00:00:00 2001 From: tuanvu Date: Thu, 8 Jan 2026 11:34:13 +0100 Subject: [PATCH 4/4] athlete test --- .../main/java/hackathon/FrisbYEE/config/WebSecurityConfig.java | 2 +- .../src/main/java/hackathon/FrisbYEE/rest/AthleteResource.java | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/back_end/src/main/java/hackathon/FrisbYEE/config/WebSecurityConfig.java b/back_end/src/main/java/hackathon/FrisbYEE/config/WebSecurityConfig.java index c96ab6c..e054c00 100644 --- a/back_end/src/main/java/hackathon/FrisbYEE/config/WebSecurityConfig.java +++ b/back_end/src/main/java/hackathon/FrisbYEE/config/WebSecurityConfig.java @@ -26,7 +26,7 @@ public class WebSecurityConfig { .cors(cors -> cors.configurationSource(corsConfigurationSource())) .csrf(csrf -> csrf.disable()) .authorizeHttpRequests(auth -> auth - .requestMatchers(HttpMethod.OPTIONS, "/", "/public", "/coach/**").permitAll() // allow coach endpoints + .requestMatchers(HttpMethod.OPTIONS, "/", "/public", "/coach/**","/athlete/**").permitAll() // allow coach endpoints .requestMatchers("/admin/**").hasRole("admin") .requestMatchers("/user/**").hasRole("user") .anyRequest().authenticated()) diff --git a/back_end/src/main/java/hackathon/FrisbYEE/rest/AthleteResource.java b/back_end/src/main/java/hackathon/FrisbYEE/rest/AthleteResource.java index a638c7f..56c46d3 100644 --- a/back_end/src/main/java/hackathon/FrisbYEE/rest/AthleteResource.java +++ b/back_end/src/main/java/hackathon/FrisbYEE/rest/AthleteResource.java @@ -34,6 +34,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; @RestController @RequestMapping("/athlete") +@CrossOrigin(origins = "http://localhost:3000") public class AthleteResource { @Autowired private AthleteDAO athleteDAO; @@ -44,6 +45,7 @@ public class AthleteResource { @ApiResponse(responseCode = "200", description = "Renvoie l'athlète créé", content = @Content(mediaType = "application/json", schema = @Schema(implementation = AthleteDTO.class))) }) @PostMapping("/create") + @PreAuthorize("hasRole('Admin') or hasRole('Coach') or hasRole('Athlete')") public ResponseEntity create(@RequestBody AthleteDTO dto) { Athlete athlete = mapToEntity(dto); athleteDAO.save(athlete);