feat: merged Keycloak / postgres
This commit is contained in:
@ -6,15 +6,18 @@ import enseirb.myinpulse.postgres_db.repository.ComptesRendusRepository;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.management.relation.RoleNotFoundException;
|
||||
|
||||
@SpringBootApplication
|
||||
@RestController
|
||||
public class GetUserInfo {
|
||||
|
||||
@GetMapping("/unauth/random")
|
||||
public boolean rand() {
|
||||
public boolean rand(@RequestHeader("Authorization") String token) throws RoleNotFoundException {
|
||||
System.err.println(token);
|
||||
return Math.random() > 0.5;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,7 @@
|
||||
package enseirb.myinpulse.exceptions;
|
||||
|
||||
public class RoleNotFoudException extends RuntimeException {
|
||||
public RoleNotFoudException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package enseirb.myinpulse.exceptions;
|
||||
|
||||
public class UserNotFoundException extends RuntimeException {
|
||||
public UserNotFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@ -47,6 +47,6 @@ public class ComptesRendusController {
|
||||
if (contenu_compte_rendu != null) {
|
||||
compteRendu.get().setContenu_compte_rendu(contenu_compte_rendu);
|
||||
}
|
||||
return compteRendu.get();
|
||||
return this.comptesRendusRepository.save(compteRendu.get());
|
||||
}
|
||||
}
|
||||
|
@ -53,6 +53,6 @@ public class EntrepreneursController {
|
||||
if (status_snee != null) {
|
||||
entrepreneur.get().setStatus_snee(status_snee);
|
||||
}
|
||||
return entrepreneur.get();
|
||||
return this.entrepreneursRepository.save(entrepreneur.get());
|
||||
}
|
||||
}
|
||||
|
@ -59,6 +59,6 @@ public class ProjetsController {
|
||||
if (status_projet != null) {
|
||||
projet.get().setStatus_projet(status_projet);
|
||||
}
|
||||
return projet.get();
|
||||
return this.projetsRepository.save(projet.get());
|
||||
}
|
||||
}
|
||||
|
@ -2,16 +2,14 @@ package enseirb.myinpulse.postgres_db.controller;
|
||||
|
||||
import enseirb.myinpulse.postgres_db.model.RendezVous;
|
||||
import enseirb.myinpulse.postgres_db.repository.RendezVousRepository;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.util.Optional;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Optional;
|
||||
|
||||
@RestController
|
||||
public class RendezVousController {
|
||||
|
||||
@ -41,8 +39,8 @@ public class RendezVousController {
|
||||
public RendezVous updateRendezVous(
|
||||
@PathVariable Long id,
|
||||
LocalDate date_rdv,
|
||||
LocalDateTime heure_rdv,
|
||||
LocalDateTime duree_rdv,
|
||||
LocalTime heure_rdv,
|
||||
LocalTime duree_rdv,
|
||||
String lieu_rdv,
|
||||
String sujet_rdv) {
|
||||
Optional<RendezVous> rendezVous = this.rendezVousRepository.findById(id);
|
||||
@ -64,6 +62,6 @@ public class RendezVousController {
|
||||
if (sujet_rdv != null) {
|
||||
rendezVous.get().setSujet_rdv(sujet_rdv);
|
||||
}
|
||||
return rendezVous.get();
|
||||
return this.rendezVousRepository.save(rendezVous.get());
|
||||
}
|
||||
}
|
||||
|
@ -55,6 +55,6 @@ public class SectionsController {
|
||||
if (date_modification != null) {
|
||||
section.get().setDate_modification(date_modification);
|
||||
}
|
||||
return section.get();
|
||||
return this.sectionsRepository.save(section.get());
|
||||
}
|
||||
}
|
||||
|
@ -62,6 +62,6 @@ public class UtilisateursController {
|
||||
if (numero_telephone != null) {
|
||||
utilisateur.get().setNumero_telephone(numero_telephone);
|
||||
}
|
||||
return utilisateur.get();
|
||||
return this.utilisateursRepository.save(utilisateur.get());
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name = "administrateurs")
|
||||
@PrimaryKeyJoinColumn(name = "id_administrateur")
|
||||
@PrimaryKeyJoinColumn(name = "id_administrateur", referencedColumnName = "id_utilisateur")
|
||||
public class Administrateurs extends Utilisateurs {
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
|
@ -6,7 +6,7 @@ import jakarta.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "entrepreneurs")
|
||||
@PrimaryKeyJoinColumn(name = "id_entrepreneur")
|
||||
@PrimaryKeyJoinColumn(name = "id_entrepreneur", referencedColumnName = "id_utilisateur")
|
||||
public class Entrepreneurs extends Utilisateurs {
|
||||
|
||||
@Column(length = 255)
|
||||
|
@ -4,7 +4,7 @@ import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ -36,8 +36,8 @@ public class RendezVous {
|
||||
private Long id_rdv;
|
||||
|
||||
private LocalDate date_rdv;
|
||||
private LocalDateTime heure_rdv;
|
||||
private LocalDateTime duree_rdv;
|
||||
private LocalTime heure_rdv;
|
||||
private LocalTime duree_rdv;
|
||||
|
||||
@Column(length = 255)
|
||||
private String lieu_rdv;
|
||||
@ -49,8 +49,8 @@ public class RendezVous {
|
||||
public RendezVous(
|
||||
Long id_rdv,
|
||||
LocalDate date_rdv,
|
||||
LocalDateTime heure_rdv,
|
||||
LocalDateTime duree_rdv,
|
||||
LocalTime heure_rdv,
|
||||
LocalTime duree_rdv,
|
||||
String lieu_rdv,
|
||||
String sujet_rdv) {
|
||||
this.id_rdv = id_rdv;
|
||||
@ -77,19 +77,19 @@ public class RendezVous {
|
||||
this.date_rdv = date_rdv;
|
||||
}
|
||||
|
||||
public LocalDateTime getHeure_rdv() {
|
||||
public LocalTime getHeure_rdv() {
|
||||
return heure_rdv;
|
||||
}
|
||||
|
||||
public void setHeure_rdv(LocalDateTime heure_rdv) {
|
||||
public void setHeure_rdv(LocalTime heure_rdv) {
|
||||
this.heure_rdv = heure_rdv;
|
||||
}
|
||||
|
||||
public LocalDateTime getDuree_rdv() {
|
||||
public LocalTime getDuree_rdv() {
|
||||
return duree_rdv;
|
||||
}
|
||||
|
||||
public void setDuree_rdv(LocalDateTime duree_rdv) {
|
||||
public void setDuree_rdv(LocalTime duree_rdv) {
|
||||
this.duree_rdv = duree_rdv;
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ public class Utilisateurs {
|
||||
@Column(length = 255)
|
||||
private String mail_secondaire;
|
||||
|
||||
@Column(length = 15)
|
||||
@Column(length = 20)
|
||||
private String numero_telephone;
|
||||
|
||||
public Utilisateurs() {}
|
||||
|
@ -1,3 +1,7 @@
|
||||
/*
|
||||
* Source: https://github.com/ChristianHuff-DEV/secure-spring-rest-api-using-keycloak/blob/main/src/main/java/io/betweendata/RestApi/security/oauth2/KeycloakJwtRolesConverter.java
|
||||
* edited by Pierre Tellier
|
||||
*/
|
||||
package enseirb.myinpulse.security;
|
||||
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
@ -38,7 +42,7 @@ public class KeycloakJwtRolesConverter implements Converter<Jwt, AbstractAuthent
|
||||
source,
|
||||
Stream.concat(
|
||||
new JwtGrantedAuthoritiesConverter().convert(source).stream(),
|
||||
TEMPORARNAME(source).stream())
|
||||
tokenRolesExtractor(source).stream())
|
||||
.collect(toSet()));
|
||||
}
|
||||
|
||||
@ -46,7 +50,7 @@ public class KeycloakJwtRolesConverter implements Converter<Jwt, AbstractAuthent
|
||||
* Extracts the realm and resource level roles from a JWT token distinguishing between them
|
||||
* using prefixes.
|
||||
*/
|
||||
public Collection<GrantedAuthority> TEMPORARNAME(Jwt jwt) {
|
||||
public Collection<GrantedAuthority> tokenRolesExtractor(Jwt jwt) {
|
||||
// Collection that will hold the extracted roles
|
||||
Collection<GrantedAuthority> grantedAuthorities = new ArrayList<>();
|
||||
|
||||
|
@ -0,0 +1,135 @@
|
||||
package enseirb.myinpulse.utils.keycloak;
|
||||
|
||||
import static org.springframework.http.MediaType.APPLICATION_JSON;
|
||||
|
||||
import enseirb.myinpulse.exceptions.UserNotFoundException;
|
||||
import enseirb.myinpulse.utils.keycloak.datatypes.RoleRepresentation;
|
||||
import enseirb.myinpulse.utils.keycloak.datatypes.UserRepresentation;
|
||||
|
||||
import org.springframework.web.client.RestClient;
|
||||
|
||||
import javax.management.relation.RoleNotFoundException;
|
||||
|
||||
public class KeycloakApi {
|
||||
|
||||
static final String keycloakUrl;
|
||||
static final String realmName;
|
||||
|
||||
static {
|
||||
if (System.getenv("VITE_KEYCLOAK_URL") == null) {
|
||||
System.exit(-1);
|
||||
}
|
||||
keycloakUrl = System.getenv("VITE_KEYCLOAK_URL");
|
||||
}
|
||||
|
||||
static {
|
||||
if (System.getenv("VITE_KEYCLOAK_REALM") == null) {
|
||||
System.exit(-1);
|
||||
}
|
||||
realmName = System.getenv("VITE_KEYCLOAK_REALM");
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses Keycloak API to retrieve a role representation of a role by its name
|
||||
*
|
||||
* @param roleName name of the role
|
||||
* @param bearer authorization header used by the client to authenticate to keycloak
|
||||
*/
|
||||
public static RoleRepresentation getRoleRepresentationByName(String roleName, String bearer)
|
||||
throws RoleNotFoundException {
|
||||
RoleRepresentation[] response =
|
||||
RestClient.builder()
|
||||
.baseUrl(keycloakUrl)
|
||||
.defaultHeader("Authorization", bearer)
|
||||
.build()
|
||||
.get()
|
||||
.uri("/admin/realms/{realmName}/roles/{roleName}", realmName, roleName)
|
||||
.retrieve()
|
||||
.body(RoleRepresentation[].class);
|
||||
|
||||
if (response == null || response.length == 0) {
|
||||
throw new RoleNotFoundException("Role not found");
|
||||
}
|
||||
return response[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Use keycloak API to to retreive a userID via his name or email.
|
||||
*
|
||||
* @param username username or mail of the user
|
||||
* @param bearer bearer of the user, allowing access to database
|
||||
* @return the userid, as a String
|
||||
* @throws UserNotFoundException
|
||||
*/
|
||||
public static String getUserIdByName(String username, String bearer)
|
||||
throws UserNotFoundException {
|
||||
UserRepresentation[] response =
|
||||
RestClient.builder()
|
||||
.baseUrl(keycloakUrl)
|
||||
.defaultHeader("Authorization", bearer)
|
||||
.build()
|
||||
.get()
|
||||
.uri(
|
||||
"/admin/realms/{realmName}/users?username={username}",
|
||||
realmName,
|
||||
username)
|
||||
.retrieve()
|
||||
.body(UserRepresentation[].class);
|
||||
|
||||
if (response == null || response.length == 0) {
|
||||
throw new UserNotFoundException("User not found");
|
||||
}
|
||||
return response[0].id;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: check for error
|
||||
*
|
||||
* <p>Set a keycloak role to a keycloak user.
|
||||
*
|
||||
* <p>Usual roles should be `MyINPulse-admin` and `MyINPulse-entrepreneur`
|
||||
*
|
||||
* @param username
|
||||
* @param roleName
|
||||
* @param bearer
|
||||
* @throws RoleNotFoundException
|
||||
* @throws UserNotFoundException
|
||||
*/
|
||||
public static void setRoleToUser(String username, String roleName, String bearer)
|
||||
throws RoleNotFoundException, UserNotFoundException {
|
||||
RoleRepresentation roleRepresentation = getRoleRepresentationByName(roleName, bearer);
|
||||
String userId = getUserIdByName(username, bearer);
|
||||
|
||||
RestClient.builder()
|
||||
.baseUrl(keycloakUrl)
|
||||
.defaultHeader("Authorization", bearer)
|
||||
.build()
|
||||
.post()
|
||||
.uri(
|
||||
"/admin/realms/${realmName}/users/${userId}/role-mappings/realm",
|
||||
realmName,
|
||||
userId)
|
||||
.body(roleRepresentation)
|
||||
.contentType(APPLICATION_JSON)
|
||||
.retrieve();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a user from Keycloak database. TODO: check the bearer permission.
|
||||
*
|
||||
* @param username
|
||||
* @param bearer
|
||||
* @throws UserNotFoundException
|
||||
*/
|
||||
public static void deleteUser(String username, String bearer) throws UserNotFoundException {
|
||||
String userId = getUserIdByName(username, bearer);
|
||||
|
||||
RestClient.builder()
|
||||
.baseUrl(keycloakUrl)
|
||||
.defaultHeader("Authorization", bearer)
|
||||
.build()
|
||||
.delete()
|
||||
.uri("/admin/realms/${realmName}/users/${userId}", realmName, userId)
|
||||
.retrieve();
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package enseirb.myinpulse.utils.keycloak.datatypes;
|
||||
|
||||
public class RoleRepresentation {
|
||||
public String id;
|
||||
public String name;
|
||||
public String description;
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
package enseirb.myinpulse.utils.keycloak.datatypes;
|
||||
|
||||
public class UserRepresentation {
|
||||
public String id;
|
||||
public String name;
|
||||
}
|
Reference in New Issue
Block a user