9 Commits

Author SHA1 Message Date
820757c836 fix: corrected formatter error
All checks were successful
Format / formatting (push) Successful in 7s
CI / build (push) Successful in 11s
2025-02-18 16:59:19 +01:00
730aa5f450 Merge remote-tracking branch 'refs/remotes/origin/back-postgres' into back-postgres
Some checks failed
Format / formatting (push) Failing after 7s
CI / build (push) Successful in 11s
2025-02-18 16:56:26 +01:00
dda3e5fcfd fix: most likely fixed merge conflict 2025-02-18 16:55:08 +01:00
5e8e875a37 feat: added user deletion and custom api call in the frontend
All checks were successful
CI / build (push) Successful in 11s
2025-02-18 16:45:41 +01:00
86e7dc7c75 fix: removed the test file that was causing the linter to fail
All checks were successful
CI / build (push) Successful in 12s
2025-02-18 16:37:55 +01:00
6235fe7e68 feat: separated class definition
Some checks failed
CI / build (push) Failing after 8s
2025-02-18 12:07:07 +01:00
fc73293122 fix: merge
All checks were successful
Format / formatting (push) Successful in 8s
CI / build (push) Successful in 13s
2025-02-12 19:03:39 +01:00
e26f8da662 fix: inserting data in db 2025-02-12 18:51:27 +01:00
249d00177c feat: interraction between the backend and keycloak
Some checks failed
CI / build (push) Failing after 9s
2025-02-11 10:00:11 +01:00
30 changed files with 272 additions and 343 deletions

View File

@ -1,78 +0,0 @@
package enseirb.myinpulse.api;
import enseirb.myinpulse.api.datatypes.Project;
import enseirb.myinpulse.api.datatypes.ProjectDecision;
import enseirb.myinpulse.api.datatypes.Report;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.*;
@SpringBootApplication
@RestController
public class AdminApi {
/**
* TODO
*
* @return a list of all project managed by the current admin user
*/
@GetMapping("/admin/projects")
public void getProjects() {}
/**
* TODO: Why in admin instead of shared ?
*
* @return a list of upcoming appointments for the current user
*/
@GetMapping("/admin/appointments/upcoming")
public void getUpcomingAppointments() {}
/**
* TODO
*
* @return a list of current unvalidated projects, waiting to be accepted
*/
@GetMapping("/admin/projects/pending")
public void getPendingProjects() {}
/**
* TODO
*
* <p>Endpoint used to make a decision about a project.
*
* @return the status code of the request
*/
@PostMapping("/admin/projects/decision")
public void validateProject(@RequestBody ProjectDecision decision) {}
/**
* TODO
*
* <p>Endpoint used to manually add a project by an admin
*
* @return the status code of the request
*/
@PostMapping("/admin/project/add")
public void addNewProject(@RequestBody Project project) {}
/**
* TODO: shouldn't it be an UPDATE request ?
*
* <p>Endpoint used to add a new report to an appointment
*
* @return the status code of the request
*/
@PostMapping("/admin/appoitements/report/{appointmentId}")
public void createAppointmentReport(
@PathVariable String appointmentId, @RequestBody Report report) {}
/**
* TODO: Shouldn't a project be kept in history ? 2 different endpoints ?
*
* <p>Endpoint used to completely remove a project.
*
* @return the status code of the request
*/
@DeleteMapping("/admin/projects/remove/{projectId}")
public void deleteProject(@PathVariable String projectId) {}
}

View File

@ -1,51 +0,0 @@
package enseirb.myinpulse.api;
import enseirb.myinpulse.api.datatypes.LCSection;
import enseirb.myinpulse.api.datatypes.Project;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.*;
@SpringBootApplication
@RestController
public class EntrepreneurApi {
/**
* TODO
*
* <p>Endpoint used to update a LC section.
*
* @return status code
*/
@PutMapping("/entrepreneur/lcsection/modify/{sectionId}")
public void editLCSection(@PathVariable String sectionId, @RequestBody LCSection section) {}
/**
* TODO
*
* <p>Endpoint used to delete a LC section
*
* @return status code
*/
@DeleteMapping("/entrepreneur/lcsection/remove/{sectionId}")
public void removeLCSection(@PathVariable String sectionId) {}
/**
* TODO
*
* <p>Endpoint used to create a new LC section
*
* @return status code
*/
@PostMapping("/entrepreneur/lcsection/add/{sectionId}")
public void addLCSection(@PathVariable String sectionId, @RequestBody LCSection section) {}
/**
* TODO
*
* <p>Endpoint used to request the creation of a new project
*
* @return status code
*/
@PostMapping("/entrepreneur/project/request")
public void requestNewProject(@RequestBody Project project) {}
}

View File

@ -1,20 +1,30 @@
package enseirb.myinpulse.api; package enseirb.myinpulse.api;
import enseirb.myinpulse.postgres_db.controller.ComptesRendusController;
import enseirb.myinpulse.postgres_db.model.ComptesRendus;
import enseirb.myinpulse.postgres_db.repository.ComptesRendusRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.security.Principal;
import javax.management.relation.RoleNotFoundException;
@SpringBootApplication @SpringBootApplication
@RestController @RestController
public class GetUserInfo { public class GetUserInfo {
// TODO: understand how to get data
@GetMapping("/getUserInfo")
public Object user(Principal principal) {
System.out.println("GetUserInfo + " + principal);
System.out.println(SecurityContextHolder.getContext().getAuthentication());
return SecurityContextHolder.getContext().getAuthentication().getPrincipal();
}
@CrossOrigin(methods = {RequestMethod.GET, RequestMethod.OPTIONS})
@GetMapping("/unauth/random") @GetMapping("/unauth/random")
public boolean rand() { public boolean rand(@RequestHeader("Authorization") String token) throws RoleNotFoundException {
System.err.println(token);
return Math.random() > 0.5; return Math.random() > 0.5;
} }
@ -27,11 +37,4 @@ public class GetUserInfo {
public boolean rand3() { public boolean rand3() {
return Math.random() > 0.5; return Math.random() > 0.5;
} }
@Autowired
@GetMapping("/unauth/dev")
public ComptesRendus testApi(ComptesRendusRepository repository) {
ComptesRendusController comptesRendusController = new ComptesRendusController(repository);
return comptesRendusController.getComptesRendusById((long) 1);
}
} }

View File

@ -1,78 +0,0 @@
package enseirb.myinpulse.api;
import enseirb.myinpulse.api.datatypes.Appointment;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.*;
@SpringBootApplication
@RestController
public class SharedApi {
/**
* TODO: It does not looks like a good id to have the title and the date in the url. What even
* TODO: is the title btw ? if this is the LC section, wouldn't it be better to use an ID ?
* TODO: choose return type, cf comment in LCSection
*
* <p>Endpoint used to get the data inside the lean canvas
*
* @return a list of lean canvas sections
*/
@GetMapping("/shared/project/lcsection/{projectId}/{title}/{date}")
public void getLCSection(
@PathVariable("projectId") String projectId,
@PathVariable("title") String title,
@PathVariable("date") String date) {}
/**
* TODO
*
* <p>Endpoint used to get entrepreneurs details
*
* @return a list of all entrepreneurs in a project
*/
@GetMapping("/shared/entrepreneurs/{projectId}")
public void getEntrepreneursByProjectId(@PathVariable int projectId) {}
/**
* TODO: is it really useful for the admin ? We can already get all the project of the current
* administrator.
*
* <p>Endpoint used to get the administrator of a project.
*
* @return a list of all project managed by the current admin user
*/
@GetMapping("/shared/projects/admin/{projectId}")
public void getAdminByProjectId(@PathVariable int projectId) {}
/**
* TODO: Should it really be all appointments? all future appointments ? a flag to choose \\
* TODO: between both ?
*
* <p>Endpoint used to get all appointments of a single project.
*
* @return a list of all appointments.
*/
@GetMapping("/shared/projects/appointments/{projectId}")
public void getAppointmentsByProjectId(@PathVariable int projectId) {}
/**
* TODO: Shouldn't the last two parameters be swapped ?
*
* <p>Endpoint used to generate a PDF report
*
* @return a PDF file? TODO: how does that works ?
*/
@GetMapping("/shared/projects/appointments/report/{appointmentId}")
public void getPDFReport(@PathVariable int appointmentId) {}
/**
* TODO
*
* <p>
*
* @return a list of all project managed by the current admin user
*/
@PostMapping("/shared/appointment/request")
public void createAppointmentRequest(@RequestBody Appointment appointment) {}
}

View File

@ -1,8 +0,0 @@
package enseirb.myinpulse.api.datatypes;
public class Appointment {
int validated;
int[] akserId;
int[] destId;
String date; // TODO: date type ?
}

View File

@ -1,7 +0,0 @@
package enseirb.myinpulse.api.datatypes;
// TODO: is this redundant with the Section class from the database ?
// TODO: In the one hand it represent the same data, and on the other it should be much lighter.
// TODO: btw why does a LC section have an administrator ?
public class LCSection {}

View File

@ -1,7 +0,0 @@
package enseirb.myinpulse.api.datatypes;
public class Project {
int projectId;
String projectName;
String projectDescription;
}

View File

@ -1,7 +0,0 @@
package enseirb.myinpulse.api.datatypes;
public class ProjectDecision {
int projectId;
int adminId;
int isAccepted;
}

View File

@ -1,6 +0,0 @@
package enseirb.myinpulse.api.datatypes;
public class Report {
int projectId;
String reportContent;
}

View File

@ -0,0 +1,7 @@
package enseirb.myinpulse.exceptions;
public class RoleNotFoudException extends RuntimeException {
public RoleNotFoudException(String message) {
super(message);
}
}

View File

@ -0,0 +1,7 @@
package enseirb.myinpulse.exceptions;
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(String message) {
super(message);
}
}

View File

@ -3,6 +3,7 @@ package enseirb.myinpulse.postgres_db.controller;
import enseirb.myinpulse.postgres_db.model.ComptesRendus; import enseirb.myinpulse.postgres_db.model.ComptesRendus;
import enseirb.myinpulse.postgres_db.repository.ComptesRendusRepository; import enseirb.myinpulse.postgres_db.repository.ComptesRendusRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException; import org.springframework.web.server.ResponseStatusException;
@ -12,11 +13,7 @@ import java.util.Optional;
@RestController @RestController
public class ComptesRendusController { public class ComptesRendusController {
private final ComptesRendusRepository comptesRendusRepository; @Autowired ComptesRendusRepository comptesRendusRepository;
public ComptesRendusController(ComptesRendusRepository comptesRendusRepository) {
this.comptesRendusRepository = comptesRendusRepository;
}
@GetMapping("/ComptesRendus") @GetMapping("/ComptesRendus")
@ResponseBody @ResponseBody
@ -47,6 +44,6 @@ public class ComptesRendusController {
if (contenu_compte_rendu != null) { if (contenu_compte_rendu != null) {
compteRendu.get().setContenu_compte_rendu(contenu_compte_rendu); compteRendu.get().setContenu_compte_rendu(contenu_compte_rendu);
} }
return compteRendu.get(); return this.comptesRendusRepository.save(compteRendu.get());
} }
} }

View File

@ -53,6 +53,6 @@ public class EntrepreneursController {
if (status_snee != null) { if (status_snee != null) {
entrepreneur.get().setStatus_snee(status_snee); entrepreneur.get().setStatus_snee(status_snee);
} }
return entrepreneur.get(); return this.entrepreneursRepository.save(entrepreneur.get());
} }
} }

View File

@ -59,6 +59,6 @@ public class ProjetsController {
if (status_projet != null) { if (status_projet != null) {
projet.get().setStatus_projet(status_projet); projet.get().setStatus_projet(status_projet);
} }
return projet.get(); return this.projetsRepository.save(projet.get());
} }
} }

View File

@ -2,16 +2,14 @@ package enseirb.myinpulse.postgres_db.controller;
import enseirb.myinpulse.postgres_db.model.RendezVous; import enseirb.myinpulse.postgres_db.model.RendezVous;
import enseirb.myinpulse.postgres_db.repository.RendezVousRepository; 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.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException; import org.springframework.web.server.ResponseStatusException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Optional;
@RestController @RestController
public class RendezVousController { public class RendezVousController {
@ -41,8 +39,8 @@ public class RendezVousController {
public RendezVous updateRendezVous( public RendezVous updateRendezVous(
@PathVariable Long id, @PathVariable Long id,
LocalDate date_rdv, LocalDate date_rdv,
LocalDateTime heure_rdv, LocalTime heure_rdv,
LocalDateTime duree_rdv, LocalTime duree_rdv,
String lieu_rdv, String lieu_rdv,
String sujet_rdv) { String sujet_rdv) {
Optional<RendezVous> rendezVous = this.rendezVousRepository.findById(id); Optional<RendezVous> rendezVous = this.rendezVousRepository.findById(id);
@ -64,6 +62,6 @@ public class RendezVousController {
if (sujet_rdv != null) { if (sujet_rdv != null) {
rendezVous.get().setSujet_rdv(sujet_rdv); rendezVous.get().setSujet_rdv(sujet_rdv);
} }
return rendezVous.get(); return this.rendezVousRepository.save(rendezVous.get());
} }
} }

View File

@ -55,6 +55,6 @@ public class SectionsController {
if (date_modification != null) { if (date_modification != null) {
section.get().setDate_modification(date_modification); section.get().setDate_modification(date_modification);
} }
return section.get(); return this.sectionsRepository.save(section.get());
} }
} }

View File

@ -62,6 +62,6 @@ public class UtilisateursController {
if (numero_telephone != null) { if (numero_telephone != null) {
utilisateur.get().setNumero_telephone(numero_telephone); utilisateur.get().setNumero_telephone(numero_telephone);
} }
return utilisateur.get(); return this.utilisateursRepository.save(utilisateur.get());
} }
} }

View File

@ -9,7 +9,7 @@ import java.util.List;
@Entity @Entity
@Table(name = "administrateurs") @Table(name = "administrateurs")
@PrimaryKeyJoinColumn(name = "id_administrateur") @PrimaryKeyJoinColumn(name = "id_administrateur", referencedColumnName = "id_utilisateur")
public class Administrateurs extends Utilisateurs { public class Administrateurs extends Utilisateurs {
@ManyToOne(fetch = FetchType.LAZY) @ManyToOne(fetch = FetchType.LAZY)

View File

@ -6,7 +6,7 @@ import jakarta.persistence.Table;
@Entity @Entity
@Table(name = "entrepreneurs") @Table(name = "entrepreneurs")
@PrimaryKeyJoinColumn(name = "id_entrepreneur") @PrimaryKeyJoinColumn(name = "id_entrepreneur", referencedColumnName = "id_utilisateur")
public class Entrepreneurs extends Utilisateurs { public class Entrepreneurs extends Utilisateurs {
@Column(length = 255) @Column(length = 255)

View File

@ -4,7 +4,7 @@ import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -36,8 +36,8 @@ public class RendezVous {
private Long id_rdv; private Long id_rdv;
private LocalDate date_rdv; private LocalDate date_rdv;
private LocalDateTime heure_rdv; private LocalTime heure_rdv;
private LocalDateTime duree_rdv; private LocalTime duree_rdv;
@Column(length = 255) @Column(length = 255)
private String lieu_rdv; private String lieu_rdv;
@ -49,8 +49,8 @@ public class RendezVous {
public RendezVous( public RendezVous(
Long id_rdv, Long id_rdv,
LocalDate date_rdv, LocalDate date_rdv,
LocalDateTime heure_rdv, LocalTime heure_rdv,
LocalDateTime duree_rdv, LocalTime duree_rdv,
String lieu_rdv, String lieu_rdv,
String sujet_rdv) { String sujet_rdv) {
this.id_rdv = id_rdv; this.id_rdv = id_rdv;
@ -77,19 +77,19 @@ public class RendezVous {
this.date_rdv = date_rdv; this.date_rdv = date_rdv;
} }
public LocalDateTime getHeure_rdv() { public LocalTime getHeure_rdv() {
return heure_rdv; return heure_rdv;
} }
public void setHeure_rdv(LocalDateTime heure_rdv) { public void setHeure_rdv(LocalTime heure_rdv) {
this.heure_rdv = heure_rdv; this.heure_rdv = heure_rdv;
} }
public LocalDateTime getDuree_rdv() { public LocalTime getDuree_rdv() {
return duree_rdv; return duree_rdv;
} }
public void setDuree_rdv(LocalDateTime duree_rdv) { public void setDuree_rdv(LocalTime duree_rdv) {
this.duree_rdv = duree_rdv; this.duree_rdv = duree_rdv;
} }

View File

@ -25,7 +25,7 @@ public class Utilisateurs {
@Column(length = 255) @Column(length = 255)
private String mail_secondaire; private String mail_secondaire;
@Column(length = 15) @Column(length = 20)
private String numero_telephone; private String numero_telephone;
public Utilisateurs() {} public Utilisateurs() {}

View File

@ -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; package enseirb.myinpulse.security;
import static java.util.stream.Collectors.toSet; import static java.util.stream.Collectors.toSet;
@ -38,7 +42,7 @@ public class KeycloakJwtRolesConverter implements Converter<Jwt, AbstractAuthent
source, source,
Stream.concat( Stream.concat(
new JwtGrantedAuthoritiesConverter().convert(source).stream(), new JwtGrantedAuthoritiesConverter().convert(source).stream(),
TEMPORARNAME(source).stream()) tokenRolesExtractor(source).stream())
.collect(toSet())); .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 * Extracts the realm and resource level roles from a JWT token distinguishing between them
* using prefixes. * using prefixes.
*/ */
public Collection<GrantedAuthority> TEMPORARNAME(Jwt jwt) { public Collection<GrantedAuthority> tokenRolesExtractor(Jwt jwt) {
// Collection that will hold the extracted roles // Collection that will hold the extracted roles
Collection<GrantedAuthority> grantedAuthorities = new ArrayList<>(); Collection<GrantedAuthority> grantedAuthorities = new ArrayList<>();

View File

@ -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();
}
}

View File

@ -0,0 +1,7 @@
package enseirb.myinpulse.utils.keycloak.datatypes;
public class RoleRepresentation {
public String id;
public String name;
public String description;
}

View File

@ -0,0 +1,6 @@
package enseirb.myinpulse.utils.keycloak.datatypes;
public class UserRepresentation {
public String id;
public String name;
}

View File

@ -1,3 +1,5 @@
TRUNCATE projets, utilisateurs, entrepreneurs, sections, rendez_vous, comptes_rendus CASCADE;
INSERT INTO projets (nom_projet, logo, date_creation, status_projet) INSERT INTO projets (nom_projet, logo, date_creation, status_projet)
VALUES ('Eau du robinet', decode('013d7d16d7ad4fefb61bd95b765c8ceb', 'hex'), TO_DATE('01-OCT-2023', 'DD-MON-YYYY'), VALUES ('Eau du robinet', decode('013d7d16d7ad4fefb61bd95b765c8ceb', 'hex'), TO_DATE('01-OCT-2023', 'DD-MON-YYYY'),
'En cours'), 'En cours'),
@ -7,56 +9,49 @@ VALUES ('Eau du robinet', decode('013d7d16d7ad4fefb61bd95b765c8ceb', 'hex'), TO_
('HDeirbMI', decode('ab548d6c1d595a2975e6476f544d14c55a', 'hex'), TO_DATE('07-DEC-2024', 'DD-MON-YYYY'), ('HDeirbMI', decode('ab548d6c1d595a2975e6476f544d14c55a', 'hex'), TO_DATE('07-DEC-2024', 'DD-MON-YYYY'),
'Lancement'); 'Lancement');
INSERT INTO utilisateurs (nom_utilisateur, prenom_utilisateur, mail_principal, mail_secondaire, numero_telephone) INSERT INTO utilisateurs (nom_utilisateur, prenom_utilisateur, mail_principal, mail_secondaire, numero_telephone) VALUES
VALUES ('Dupont', 'Dupond', 'super@mail.fr', 'super2@mail.fr', '06 45 72 45 98'), ('Dupont', 'Dupond', 'super@mail.fr', 'super2@mail.fr', '06 45 72 45 98'),
('Martin', 'Matin', 'genial@mail.fr', 'genial2@mail.fr', '06 52 14 58 73'), ('Martin', 'Matin', 'genial@mail.fr', 'genial2@mail.fr', '06 52 14 58 73'),
('Charvet', 'Lautre', 'mieux@tmail.fr', 'mieux2@tmail.fr', '07 49 82 16 35'), ('Charvet', 'Lautre', 'mieux@tmail.fr', 'mieux2@tmail.fr', '07 49 82 16 35'),
('Leguez', 'Theo', 'bof@mesmails.fr', 'bof2@mesmails.fr', '+33 6 78 14 25 29'), ('Leguez', 'Theo', 'bof@mesmails.fr', 'bof2@mesmails.fr', '+33 6 78 14 25 29'),
('Kia', 'Bi', 'special@mail.fr', 'special2@mail.fr', '07 65 31 38 95'); ('Kia', 'Bi', 'special@mail.fr', 'special2@mail.fr', '07 65 31 38 95'),
('Ducaillou', 'Pierre', 'maildefou@xyz.fr', 'maildefou2@xyz.fr', '06 54 78 12 62');
INSERT INTO entrepreneurs (ecole, filiere, status_snee)
VALUES ('ENSEIRB-MATMECA', 'INFO', TRUE),
('ENSC', 'Cognitique', TRUE),
('ENSEIRB-MATMECA', 'MATMECA', FALSE),
('SupOptique', 'Classique', TRUE),
('ENSEGID', 'Géoscience', FALSE),
('ENSMAC', 'Matériaux composites - Mécanique', FALSE);
INSERT INTO sections (titre, contenu_section, date_modification) INSERT INTO entrepreneurs (ecole, filiere, status_snee, id_entrepreneur) VALUES
VALUES ("Problème", "les problèmes...", TO_DATE('15-JAN-2025', 'DD-MON-YYYY')), ('ENSEIRB-MATMECA', 'INFO', TRUE, 1),
("Segment de client", "Le segment AB passant le client n°8 est de longueur 32mm. ('ENSC', 'Cognitique', TRUE, 2),
Le segment BC a quant à lui un longueur de 28mm. Quelle la longueur du segment AC ?", ('ENSEIRB-MATMECA', 'MATMECA', FALSE, 3),
TO_DATE('12-OCT-2022', 'DD-MON-YYYY')), ('SupOptique', 'Classique', TRUE, 4),
("Proposition de valeur unique", "'Son prix est de 2594€' 'Ah oui c'est unique en effet'", ('ENSEGID', 'Géoscience', FALSE, 5),
TO_DATE('25-MAY-2024', 'DD-MON-YYYY')), ('ENSMAC', 'Matériaux composites - Mécanique', FALSE, 6);
("Solution", "Un problème ? Une solution", TO_DATE('08-FEB-2024', 'DD-MON-YYYY')),
("Canaux", "Ici nous avons la Seine, là-bas le Rhin, oh et plus loin le canal de Suez",
TO_DATE('19-JUL-2023', 'DD-MON-YYYY')),
("Sources de revenus", "Y'en n'a pas on est pas payé. Enfin y'a du café quoi",
TO_DATE('12-JAN-2025', 'DD-MON-YYYY')),
("Structure des coûts", "'Ah oui là ça va faire au moins 1000€ par mois', Eirbware",
TO_DATE('06-FEB-2025', 'DD-MON-YYYY')),
("Indicateurs clés", "On apprend les clés comme des badges, ça se fait", TO_DATE('05-FEB-2025', 'DD-MON-YYYY')),
("Avantages concurrentiel", "On est meilleur", TO_DATE('23-APR-2024', 'DD-MON-YYYY'));
INSERT INTO rendez_vous (date_rdv, heure_rdv, duree_rdv, lieu_rdv, sujet_rdv) INSERT INTO sections (titre, contenu_section, date_modification) VALUES
VALUES (TO_DATE('24-DEC-2023', 'DD-MON-YYYY'), '00:00:00', '00:37:53', "À la maison", "Ouvrir les cadeaux"), ('Problème', 'les problèmes...', TO_TIMESTAMP('15-JAN-2025 09:30:20', 'DD-MON-YYYY, HH24:MI:SS')),
(TO_DATE('15-AUG-2024', 'DD-MON-YYYY'), '22:35:00', '00:12:36', "Sur les quais ou dans un champ probablement", ('Segment de client', 'Le segment AB passant le client n°8 est de longueur 32mm.
"BOUM BOUM les feux d'artifices (on fête quoi déjà ?)"), Le segment BC a quant à lui un longueur de 28mm. Quelle la longueur du segment AC ?', TO_TIMESTAMP('12-OCT-2022 17:47:38', 'DD-MON-YYYY, HH24:MI:SS')),
(TO_DATE('29-FEB-2023', 'DD-MON-YYYY'), '14:20:00', '00:20:00', "Salle TD 15", ('Proposition de valeur unique', '''Son prix est de 2594€'' ''Ah oui c''est unique en effet', TO_TIMESTAMP('25-MAY-2024 11:12:04', 'DD-MON-YYYY, HH24:MI:SS')),
"Ah mince c'est pas une année bissextile !"), ('Solution', 'Un problème ? Une solution', TO_TIMESTAMP('08-FEB-2024 10:17:53', 'DD-MON-YYYY, HH24:MI:SS')),
(TO_DATE('23-JAN-2024', 'DD-MON-YYYY'), '12:56:27', '11:03:33', "Là où le vent nous porte", ('Canaux', 'Ici nous avons la Seine, là-bas le Rhin, oh et plus loin le canal de Suez', TO_TIMESTAMP('19-JUL-2023 19:22:45', 'DD-MON-YYYY, HH24:MI:SS')),
"Journée la plus importante de l'année"), ('Sources de revenus', 'Y''en n''a pas on est pas payé. Enfin y''a du café quoi', TO_TIMESTAMP('12-JAN-2025 11:40:26', 'DD-MON-YYYY, HH24:MI:SS')),
(TO_DATE('25-AUG-2025', 'DD-MON-YYYY'), '00:09:00', '01:00:00', "Euh c'est par où l'amphi 56 ?", ('Structure des coûts', '''Ah oui là ça va faire au moins 1000€ par mois'', Eirbware', TO_TIMESTAMP('06-FEB-2025 13:04:06', 'DD-MON-YYYY, HH24:MI:SS')),
"Rentrée scolaire (il fait trop froid c'est quoi ça on est en août)"); ('Indicateurs clés', 'On apprend les clés comme des badges, ça se fait', TO_TIMESTAMP('05-FEB-2025 12:42:38', 'DD-MON-YYYY, HH24:MI:SS')),
('Avantages concurrentiel', 'On est meilleur', TO_TIMESTAMP('23-APR-2024 16:24:02', 'DD-MON-YYYY, HH24:MI:SS'));
INSERT INTO comptes_rendus (contenu_compte_rendu) INSERT INTO rendez_vous (date_rdv, heure_rdv, duree_rdv, lieu_rdv, sujet_rdv) VALUES
VALUES ("Ah oui ça c'est super, ah ouais j'aime bien, bien vu de penser à ça"), (TO_DATE('24-DEC-2023', 'DD-MON-YYYY'), '00:00:00', '00:37:53', 'À la maison', 'Ouvrir les cadeaux'),
("Bonne réunion"), (TO_DATE('15-AUG-2024', 'DD-MON-YYYY'), '22:35:00', '00:12:36', 'Sur les quais ou dans un champ probablement', 'BOUM BOUM les feux d''artifices (on fête quoi déjà ?)'),
("Ouais, j'ai rien compris mais niquel on fait comme vous avez dit"), (TO_DATE('28-FEB-2023', 'DD-MON-YYYY'), '14:20:00', '00:20:00', 'Salle TD 15', 'Ah mince c''est pas une année bissextile !'),
("Non non ça va pas du tout ce que tu me proposes, faut tout refaire"), (TO_DATE('23-JAN-2024', 'DD-MON-YYYY'), '12:56:27', '11:03:33', 'Là où le vent nous porte', 'Journée la plus importante de l''année'),
("Réponse de la DSI : non"), (TO_DATE('25-AUG-2025', 'DD-MON-YYYY'), '00:09:00', '01:00:00', 'Euh c''est par où l''amphi 56 ?', 'Rentrée scolaire (il fait trop froid c''est quoi ça on est en août)');
("Trop dommage qu'Apple ait sorti leur logiciel avant nous, on avait la même idée et tout on aurait tellement pu leur faire de la concurrence");
INSERT INTO comptes_rendus (contenu_compte_rendu) VALUES
('Ah oui ça c''est super, ah ouais j''aime bien, bien vu de penser à ça'),
('Bonne réunion'),
('Ouais, j''ai rien compris mais niquel on fait comme vous avez dit'),
('Non non ça va pas du tout ce que tu me proposes, faut tout refaire'),
('Réponse de la DSI : non'),
('Trop dommage qu''Apple ait sorti leur logiciel avant nous, on avait la même idée et tout on aurait tellement pu leur faire de la concurrence');

View File

@ -0,0 +1 @@
DROP TABLE IF EXISTS administrateurs, projets, utilisateurs, entrepreneurs, sections, rendez_vous, comptes_rendus, concerner CASCADE;

View File

@ -25,9 +25,8 @@ CREATE TABLE utilisateurs
prenom_utilisateur VARCHAR(255) , prenom_utilisateur VARCHAR(255) ,
mail_principal VARCHAR(255) , mail_principal VARCHAR(255) ,
mail_secondaire VARCHAR(255) , mail_secondaire VARCHAR(255) ,
numero_telephone VARCHAR(15), numero_telephone VARCHAR(20) ,
CONSTRAINT pk_utilisateur PRIMARY KEY (id_utilisateur) CONSTRAINT pk_utilisateur PRIMARY KEY (id_utilisateur) );
);
CREATE TABLE entrepreneurs CREATE TABLE entrepreneurs
( (

View File

@ -14,7 +14,8 @@ axiosInstance.interceptors.response.use(
async (error) => { async (error) => {
const originalRequest = error.config; const originalRequest = error.config;
if ( if (
error.response.status === 401 && ((error.response && error.response.status === 401) ||
error.code == "ERR_NETWORK") &&
!originalRequest._retry && !originalRequest._retry &&
store.authenticated store.authenticated
) { ) {

View File

@ -1,6 +1,9 @@
<script lang="ts" setup> <script lang="ts" setup>
import { store } from "../main.ts"; import { store } from "../main.ts";
import { callApi } from "@/services/api.ts"; import { callApi } from "@/services/api.ts";
import { ref } from "vue";
const CustomRequest = ref("");
</script> </script>
<template> <template>
@ -50,11 +53,19 @@ import { callApi } from "@/services/api.ts";
<tr> <tr>
<td>Unauth API call</td> <td>Unauth API call</td>
<td> <td>
<button @click="callApi('unauth/dev')">call</button> <button @click="callApi('random3')">call</button>
</td> </td>
<td>res</td> <td>res</td>
<td id="3"></td> <td id="3"></td>
</tr> </tr>
<tr>
<td>
<input v-model="CustomRequest" placeholder="edit me" />
</td>
<td>
<button @click="callApi(CustomRequest)">call</button>
</td>
</tr>
</tbody> </tbody>
</table> </table>
</template> </template>