From e18c86e483b196ca9ee4e69cd89bdfeebc46a7fc Mon Sep 17 00:00:00 2001 From: Malopieds Date: Thu, 24 Jul 2025 10:58:59 +0200 Subject: [PATCH 01/28] feat: docker basis --- pom.xml | 5 +++ .../backend/rest/ContainerResource.java | 40 ++++++++++++++++++ .../backend/services/DockerService.java | 41 +++++++++++++++++++ src/main/resources/application.properties | 2 + 4 files changed, 88 insertions(+) create mode 100644 src/main/java/fr/la_banquise/backend/rest/ContainerResource.java create mode 100644 src/main/java/fr/la_banquise/backend/services/DockerService.java diff --git a/pom.xml b/pom.xml index 1492269..9fdd9e2 100644 --- a/pom.xml +++ b/pom.xml @@ -79,6 +79,11 @@ rest-assured test + + io.quarkiverse.docker + quarkus-docker-client + 0.0.5 + org.projectlombok lombok diff --git a/src/main/java/fr/la_banquise/backend/rest/ContainerResource.java b/src/main/java/fr/la_banquise/backend/rest/ContainerResource.java new file mode 100644 index 0000000..a16e287 --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/rest/ContainerResource.java @@ -0,0 +1,40 @@ +package fr.la_banquise.backend.rest; + +import fr.la_banquise.backend.services.DockerService; +import jakarta.inject.Inject; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; + +import java.util.Map; + +@Path("/containers") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +public class ContainerResource { + + @Inject + DockerService dockerService; + + @POST + @Path("/nginx") + public Response launchNginx() { + try { + String id = dockerService.createAndStartNginx(); + return Response.ok(Map.of("containerId", id, "status", "running")).build(); + } catch (Exception e) { + return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } + } + + @DELETE + @Path("/{id}") + public Response remove(@PathParam("id") String id) { + try { + dockerService.stopAndRemove(id); + return Response.ok(Map.of("containerId", id, "status", "removed")).build(); + } catch (Exception e) { + return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } + } +} \ No newline at end of file diff --git a/src/main/java/fr/la_banquise/backend/services/DockerService.java b/src/main/java/fr/la_banquise/backend/services/DockerService.java new file mode 100644 index 0000000..add12d4 --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/services/DockerService.java @@ -0,0 +1,41 @@ +package fr.la_banquise.backend.services; + +import com.github.dockerjava.api.DockerClient; +import com.github.dockerjava.api.command.CreateContainerResponse; +import com.github.dockerjava.api.model.ExposedPort; +import com.github.dockerjava.api.model.HostConfig; +import com.github.dockerjava.api.model.PortBinding; +import com.github.dockerjava.api.model.Ports; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +@ApplicationScoped +public class DockerService { + + @Inject + DockerClient dockerClient; + + public String createAndStartNginx() { + ExposedPort tcp80 = ExposedPort.tcp(80); + + Ports portBindings = new Ports(); + portBindings.bind(tcp80, Ports.Binding.bindPort(8081)); + + HostConfig hostConfig = HostConfig.newHostConfig() + .withPortBindings(portBindings); + + CreateContainerResponse container = dockerClient.createContainerCmd("nginx:latest") + .withName("my-nginx") + .withExposedPorts(tcp80) + .withHostConfig(hostConfig) + .exec(); + + dockerClient.startContainerCmd(container.getId()).exec(); + return container.getId(); + } + + public void stopAndRemove(String containerId) { + dockerClient.stopContainerCmd(containerId).exec(); + dockerClient.removeContainerCmd(containerId).exec(); + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index e95de2b..e7fb8cc 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -36,3 +36,5 @@ quarkus.hibernate-orm.database.generation=update quarkus.quinoa.dev-server.port=5173 quarkus.quinoa.enable-spa-routing=true + +quarkus.docker.docker-host=unix:///var/run/docker.sock -- 2.47.2 From 4c0ce1f2bfe7a5facc6cb7d3eb5209952e789953 Mon Sep 17 00:00:00 2001 From: Arthur Wambst Date: Thu, 24 Jul 2025 16:17:56 +0200 Subject: [PATCH 02/28] fix: added docker in nix shell --- shell.nix | 31 ++++++++++--------- .../backend/rest/UserEndpoints.java | 1 - src/main/resources/application.properties | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/shell.nix b/shell.nix index 1bc0e59..2b0bf22 100644 --- a/shell.nix +++ b/shell.nix @@ -1,30 +1,31 @@ { pkgs ? import {} }: - pkgs.mkShell { buildInputs = with pkgs; [ - # Java Development Kit openjdk21 - - # Maven maven - nodejs_24 - - # Utilitaires optionnels mais utiles + docker + docker-compose + postgresql_16 git curl - which + jq + pgcli ]; - # Variables d'environnement JAVA_HOME = "${pkgs.openjdk21}/lib/openjdk"; - MAVEN_OPTS = "-Xmx2048m -Xms512m"; + DOCKER_BUILDKIT = "1"; - # Message d'accueil shellHook = '' - echo "Environnement de développement Java/Maven activé !" - echo "Java version: $(java -version 2>&1 | head -n 1)" - echo "Maven version: $(mvn -version | head -n 1)" - echo "JAVA_HOME: $JAVA_HOME" + echo "Quarkus dev environment ready!" + echo "Java: $(java -version 2>&1 | head -n 1)" + export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock + dockerd-rootless + # Fix Docker socket + if [ ! -S /var/run/docker.sock ]; then + echo "⚠️ Docker not started. Run:" + echo " sudo systemctl start docker" + echo " sudo usermod -aG docker $USER" + fi ''; } diff --git a/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java index f8cd258..33775b7 100644 --- a/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java +++ b/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java @@ -50,7 +50,6 @@ public class UserEndpoints { } @POST - @RolesAllowed("root") public Response createUser(UserRequest user) { return Response.ok(userService.createUser(user)).build(); } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index e95de2b..6858101 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -28,7 +28,7 @@ quarkus.security.ldap.identity-mapping.attribute-mappings."0".filter-base-dn=ou= quarkus.datasource.db-kind = postgresql quarkus.datasource.username = postgres quarkus.datasource.password = secret -quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:5432/quarkus +#quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:5432/quarkus # drop and create the database at startup (use `update` to only update the schema)drop-and-create quarkus.hibernate-orm.database.generation=update -- 2.47.2 From 53a49f9befea844489758fcd6cdaeae09bd35b16 Mon Sep 17 00:00:00 2001 From: Arthur Wambst Date: Sun, 27 Jul 2025 00:31:30 +0200 Subject: [PATCH 03/28] des trucs a droite a gauche --- shell.nix | 2 +- .../fr/la_banquise/backend/data/model/Ji.java | 36 +++++ .../la_banquise/backend/data/model/Site.java | 31 ++++ .../la_banquise/backend/data/model/Sites.java | 31 ++++ .../data/repository/SitesRepository.java | 9 ++ .../backend/rest/ContainerResource.java | 53 ++++++- .../backend/services/DockerService.java | 150 +++++++++++++++++- .../backend/services/TpService.java | 3 +- src/main/resources/application.properties | 4 +- 9 files changed, 308 insertions(+), 11 deletions(-) create mode 100644 src/main/java/fr/la_banquise/backend/data/model/Ji.java create mode 100644 src/main/java/fr/la_banquise/backend/data/model/Site.java create mode 100644 src/main/java/fr/la_banquise/backend/data/model/Sites.java create mode 100644 src/main/java/fr/la_banquise/backend/data/repository/SitesRepository.java diff --git a/shell.nix b/shell.nix index 2b0bf22..842ab5d 100644 --- a/shell.nix +++ b/shell.nix @@ -20,7 +20,7 @@ pkgs.mkShell { echo "Quarkus dev environment ready!" echo "Java: $(java -version 2>&1 | head -n 1)" export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock - dockerd-rootless + dockerd-rootless & # Fix Docker socket if [ ! -S /var/run/docker.sock ]; then echo "⚠️ Docker not started. Run:" diff --git a/src/main/java/fr/la_banquise/backend/data/model/Ji.java b/src/main/java/fr/la_banquise/backend/data/model/Ji.java new file mode 100644 index 0000000..40c6764 --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/data/model/Ji.java @@ -0,0 +1,36 @@ +package fr.la_banquise.backend.data.model; + +import io.quarkus.hibernate.orm.panache.PanacheEntity; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; + +/** + * Tp + */ +@Entity +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "ji") +public class Ji { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @SequenceGenerator(name = "JiSeq", sequenceName = "ji_id_seq", allocationSize = 1, initialValue = 1) + public Long id; + public String name; + public String description; + public String respo; + public String date; + + public Tp(String name, String description, String respo, String date) { + this.name = name; + this.description = description; + this.respo = respo; + this.date = date; + } +} diff --git a/src/main/java/fr/la_banquise/backend/data/model/Site.java b/src/main/java/fr/la_banquise/backend/data/model/Site.java new file mode 100644 index 0000000..6230d59 --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/data/model/Site.java @@ -0,0 +1,31 @@ +package fr.la_banquise.backend.data.model; + +import io.quarkus.hibernate.orm.panache.PanacheEntity; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; + +@Entity +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "site") +public class Site { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @SequenceGenerator(name = "SiteSeq", sequenceName = "site_id_seq", allocationSize = 1, initialValue = 1) + public Long id; + public String name; + public String description; + public String address; + + public Site(String name, String description, String address) { + this.name = name; + this.description = description; + this.address = address; + } +} diff --git a/src/main/java/fr/la_banquise/backend/data/model/Sites.java b/src/main/java/fr/la_banquise/backend/data/model/Sites.java new file mode 100644 index 0000000..79dfc28 --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/data/model/Sites.java @@ -0,0 +1,31 @@ +package fr.la_banquise.backend.data.model; + +import io.quarkus.hibernate.orm.panache.PanacheEntity; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import java.util.List; + + +@Entity +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "Sites") +public class Sites { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @SequenceGenerator(name = "SitesSeq", sequenceName = "sites_id_seq", allocationSize = 1, initialValue = 1) + public Long id; + public List sites; + + public Sites(List sites) { + this.sites = sites; + } +} + + diff --git a/src/main/java/fr/la_banquise/backend/data/repository/SitesRepository.java b/src/main/java/fr/la_banquise/backend/data/repository/SitesRepository.java new file mode 100644 index 0000000..599d124 --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/data/repository/SitesRepository.java @@ -0,0 +1,9 @@ +package fr.la_banquise.backend.data.repository; + +import fr.la_banquise.backend.data.model.Sites; +import io.quarkus.hibernate.orm.panache.PanacheRepository; +import jakarta.enterprise.context.ApplicationScoped; + +@ApplicationScoped +public class SitesRepository implements PanacheRepository { +} diff --git a/src/main/java/fr/la_banquise/backend/rest/ContainerResource.java b/src/main/java/fr/la_banquise/backend/rest/ContainerResource.java index a16e287..3f90be4 100644 --- a/src/main/java/fr/la_banquise/backend/rest/ContainerResource.java +++ b/src/main/java/fr/la_banquise/backend/rest/ContainerResource.java @@ -27,14 +27,57 @@ public class ContainerResource { } } - @DELETE - @Path("/{id}") - public Response remove(@PathParam("id") String id) { + @POST + @Path("/create") + public Response createContainer(@QueryParam("name") String name, @QueryParam("port") int port) { try { - dockerService.stopAndRemove(id); + String id = dockerService.createContainer(name, port); + return Response.ok(Map.of("containerId", id)).build(); + } catch (Exception e) { + return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } + } + + @GET + @Path("/all") + public Response listContainers() { + try { + String id = dockerService.listAllContainers(); + return Response.ok(id).build(); + } catch (Exception e) { + return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } + } + + @POST + @Path("/start") + public Response start(@QueryParam("id") String id) { + try { + dockerService.start(id); + return Response.ok(Map.of("containerId", id, "status", "Running")).build(); + } catch (Exception e) { + return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } + } + + @POST + @Path("/stop") + public Response stop(@QueryParam("id") String id) { + try { + dockerService.stop(id); return Response.ok(Map.of("containerId", id, "status", "removed")).build(); } catch (Exception e) { return Response.status(500).entity(Map.of("error", e.getMessage())).build(); } } -} \ No newline at end of file + @DELETE + @Path("/remove") + public Response remove(@QueryParam("id") String id) { + try { + dockerService.remove(id); + return Response.ok(Map.of("containerId", id, "status", "removed")).build(); + } catch (Exception e) { + return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } + } +} diff --git a/src/main/java/fr/la_banquise/backend/services/DockerService.java b/src/main/java/fr/la_banquise/backend/services/DockerService.java index add12d4..4e53bee 100644 --- a/src/main/java/fr/la_banquise/backend/services/DockerService.java +++ b/src/main/java/fr/la_banquise/backend/services/DockerService.java @@ -8,6 +8,12 @@ import com.github.dockerjava.api.model.PortBinding; import com.github.dockerjava.api.model.Ports; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; +import java.util.List; +import java.util.Map; +import java.util.HashMap; +import com.github.dockerjava.api.model.Container; +import com.github.dockerjava.api.model.ContainerPort; +import com.github.dockerjava.api.command.InspectContainerResponse; @ApplicationScoped public class DockerService { @@ -23,9 +29,15 @@ public class DockerService { HostConfig hostConfig = HostConfig.newHostConfig() .withPortBindings(portBindings); + Map labels = new HashMap<>(); + labels.put("test", "banquise"); + labels.put("environment", "development"); + labels.put("version", "1.0"); + labels.put("created-by", "java-docker-api"); CreateContainerResponse container = dockerClient.createContainerCmd("nginx:latest") .withName("my-nginx") + .withLabels(labels) .withExposedPorts(tcp80) .withHostConfig(hostConfig) .exec(); @@ -34,8 +46,144 @@ public class DockerService { return container.getId(); } - public void stopAndRemove(String containerId) { + public String createContainer(String containerName, int port) { + StringBuilder result = new StringBuilder(); + ExposedPort tcpSsh = ExposedPort.tcp(80); + + Ports portBindings = new Ports(); + portBindings.bind(tcpSsh, Ports.Binding.bindPort(port)); + + HostConfig hostConfig = HostConfig.newHostConfig() + .withPortBindings(portBindings); + + CreateContainerResponse container = dockerClient.createContainerCmd("nginx:latest") + .withName(containerName) + .withExposedPorts(tcpSsh) + .withHostConfig(hostConfig) + .exec(); + + //dockerClient.startContainerCmd(container.getId()).exec(); + return container.getId(); + } +/* + public String listAllContainers() { + StringBuilder json = new StringBuilder(); + List containers = dockerClient.listContainersCmd() + .withShowAll(true) + .exec(); + + json.append("["); + + for (int i = 0; i < containers.size(); i++) { + Container container = containers.get(i); + + json.append("{"); + json.append("\"name\":\"").append(container.getNames()[0].substring(1)).append("\","); + json.append("\"id\":\"").append(container.getId()).append("\","); + json.append("\"image\":\"").append(container.getImage()).append("\","); + json.append("\"status\":\"").append(container.getStatus()).append("\","); + + // Ports + InspectContainerResponse inspectResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); + json.append("\"ports\":["); +if (container.getPorts() != null && container.getPorts().length > 0) { + for (int j = 0; j < .length; j+=2) { + ContainerPort port = container.getPorts()[j]; + json.append("[\""); + json.append(port.getPrivatePort()).append("->").append(port.getPublicPort()).append("/"+port.getType()+"\",\""); +json.append(port.getIp()).append(",").append((container.getPorts()[j+1]).getIp()); +if (port.getType() != null) { + json.append("/").append(port.getType()); + } + if (port.getPublicPort() != null) { + json.append("->").append(port.getPublicPort()); + }* + json.append("\"]"); + if (j < container.getPorts().length - 2) { + json.append(","); + } + } + } + json.append("]"); + + // Ports + String ports = "[]"; + try { + InspectContainerResponse inspectResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); + if (inspectResponse.getConfig().getExposedPorts() != null) { + ports = inspectResponse.getConfig().getExposedPorts().toString(); + } + } catch (Exception e) { + // Fallback vers les ports runtime si inspect échoue + if (container.getPorts() != null && container.getPorts().length > 0) { + ports = java.util.Arrays.toString(container.getPorts()); + } + } + json.append("\"ports\":\"").append(ports).append("\""); + json.append("}"); + if (i < containers.size() - 1) { + json.append(","); + } + + json.append("}"); + + if (i < containers.size() - 1) { + json.append(","); + } + } + + json.append("]"); + return json.toString(); +} */ + public String listAllContainers() { + StringBuilder json = new StringBuilder(); + List containers = dockerClient.listContainersCmd() + .withShowAll(true) + .exec(); + json.append("["); + for (int i = 0; i < containers.size(); i++) { + Container container = containers.get(i); + // Ports + List portsList = new ArrayList<>(); + try { + var inspectResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); + if (inspectResponse.getConfig().getExposedPorts() != null) { + var exposedPorts = inspectResponse.getConfig().getExposedPorts(); + int count = 0; + for (var port : exposedPorts) { + if (count > 0) portsList.append(","); + portsList.append(String.format("\"%s\"", port.toString())); + count = 1; + } + portsList.append("]"); + ports = portsList.toString(); + } + } catch (Exception e) { + // Fallback vers les ports runtime si inspect échoue + if (container.getPorts() != null && container.getPorts().length > 0) { + ports = java.util.Arrays.toString(container.getPorts()); + } + } + + //json.append(containerJson); + + if (i < containers.size() - 1) { + json.append(","); + } + } + json.append("]"); + return json.toString(); +} + + public void start(String containerId) { + dockerClient.startContainerCmd(containerId).exec(); + } + + public void stop(String containerId) { dockerClient.stopContainerCmd(containerId).exec(); + } + + public void remove(String containerId) { dockerClient.removeContainerCmd(containerId).exec(); } } diff --git a/src/main/java/fr/la_banquise/backend/services/TpService.java b/src/main/java/fr/la_banquise/backend/services/TpService.java index decb756..64a46c3 100644 --- a/src/main/java/fr/la_banquise/backend/services/TpService.java +++ b/src/main/java/fr/la_banquise/backend/services/TpService.java @@ -64,8 +64,7 @@ public class TpService { @Transactional public Tp createTp(TpRequest requestTp) { - Tp tp = new Tp(requestTp.title, requestTp.description, requestTp.pdf, security.getUserPrincipal().getName(), - requestTp.date); + Tp tp = new Tp(requestTp.title, requestTp.description, requestTp.pdf, security.getUserPrincipal().getName(), requestTp.date); tpRepository.persist(tp); return tp; } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index f562095..ee245e3 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -32,9 +32,9 @@ quarkus.datasource.password = secret # drop and create the database at startup (use `update` to only update the schema)drop-and-create quarkus.hibernate-orm.database.generation=update -# quarkus.hibernate-orm.database.generation=drop-and-create +#quarkus.hibernate-orm.database.generation=drop-and-create quarkus.quinoa.dev-server.port=5173 quarkus.quinoa.enable-spa-routing=true -quarkus.docker.docker-host=unix:///var/run/docker.sock +quarkus.docker.docker-host=unix:///run/user/1000/docker.sock -- 2.47.2 From 62a685fafbf7795a6a02cc48c7fd26571e171f89 Mon Sep 17 00:00:00 2001 From: Arthur Wambst Date: Mon, 28 Jul 2025 03:52:56 +0200 Subject: [PATCH 04/28] encore trop de trucs, demain je commit + souvent promis --- .../fr/la_banquise/backend/data/model/Ji.java | 8 +- .../la_banquise/backend/data/model/Site.java | 19 ++- .../la_banquise/backend/data/model/Sites.java | 31 ----- ...SitesRepository.java => JiRepository.java} | 4 +- .../data/repository/SiteRepository.java | 9 ++ .../la_banquise/backend/rest/JiResource.java | 118 ++++++++++++++++ .../backend/rest/SiteEndpoints.java | 129 ++++++++++++++++++ .../backend/services/DockerService.java | 5 +- .../backend/services/JiService.java | 59 ++++++++ .../backend/services/SiteService.java | 72 ++++++++++ src/main/resources/application.properties | 10 +- 11 files changed, 419 insertions(+), 45 deletions(-) delete mode 100644 src/main/java/fr/la_banquise/backend/data/model/Sites.java rename src/main/java/fr/la_banquise/backend/data/repository/{SitesRepository.java => JiRepository.java} (61%) create mode 100644 src/main/java/fr/la_banquise/backend/data/repository/SiteRepository.java create mode 100644 src/main/java/fr/la_banquise/backend/rest/JiResource.java create mode 100644 src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java create mode 100644 src/main/java/fr/la_banquise/backend/services/JiService.java create mode 100644 src/main/java/fr/la_banquise/backend/services/SiteService.java diff --git a/src/main/java/fr/la_banquise/backend/data/model/Ji.java b/src/main/java/fr/la_banquise/backend/data/model/Ji.java index 40c6764..95d9151 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/Ji.java +++ b/src/main/java/fr/la_banquise/backend/data/model/Ji.java @@ -9,10 +9,8 @@ import jakarta.persistence.SequenceGenerator; import jakarta.persistence.Table; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; +import java.util.List; -/** - * Tp - */ @Entity @NoArgsConstructor @AllArgsConstructor @@ -26,11 +24,13 @@ public class Ji { public String description; public String respo; public String date; + public Long siteId; - public Tp(String name, String description, String respo, String date) { + public Ji(String name, String description, String respo, String date, Long siteId) { this.name = name; this.description = description; this.respo = respo; this.date = date; + this.siteId = siteId; } } diff --git a/src/main/java/fr/la_banquise/backend/data/model/Site.java b/src/main/java/fr/la_banquise/backend/data/model/Site.java index 6230d59..db3fc61 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/Site.java +++ b/src/main/java/fr/la_banquise/backend/data/model/Site.java @@ -1,31 +1,48 @@ package fr.la_banquise.backend.data.model; import io.quarkus.hibernate.orm.panache.PanacheEntity; + +import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.SequenceGenerator; import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; +import java.util.Set; +import java.util.HashSet; @Entity @NoArgsConstructor @AllArgsConstructor -@Table(name = "site") +@Table(name = "site", uniqueConstraints = { + @UniqueConstraint(columnNames = "name") +}) public class Site { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @SequenceGenerator(name = "SiteSeq", sequenceName = "site_id_seq", allocationSize = 1, initialValue = 1) public Long id; + + @Column(unique = true, nullable = false) public String name; public String description; public String address; + public Set jiInSite; public Site(String name, String description, String address) { this.name = name; this.description = description; this.address = address; + this.jiInSite = new HashSet(); + } + + + @Override + public String toString() { + return "Site{id=" + id + ", name='" + name + "', description='" + description + "', address='" + address + "'}"; } } diff --git a/src/main/java/fr/la_banquise/backend/data/model/Sites.java b/src/main/java/fr/la_banquise/backend/data/model/Sites.java deleted file mode 100644 index 79dfc28..0000000 --- a/src/main/java/fr/la_banquise/backend/data/model/Sites.java +++ /dev/null @@ -1,31 +0,0 @@ -package fr.la_banquise.backend.data.model; - -import io.quarkus.hibernate.orm.panache.PanacheEntity; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.SequenceGenerator; -import jakarta.persistence.Table; -import lombok.AllArgsConstructor; -import lombok.NoArgsConstructor; -import java.util.List; - - -@Entity -@NoArgsConstructor -@AllArgsConstructor -@Table(name = "Sites") -public class Sites { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @SequenceGenerator(name = "SitesSeq", sequenceName = "sites_id_seq", allocationSize = 1, initialValue = 1) - public Long id; - public List sites; - - public Sites(List sites) { - this.sites = sites; - } -} - - diff --git a/src/main/java/fr/la_banquise/backend/data/repository/SitesRepository.java b/src/main/java/fr/la_banquise/backend/data/repository/JiRepository.java similarity index 61% rename from src/main/java/fr/la_banquise/backend/data/repository/SitesRepository.java rename to src/main/java/fr/la_banquise/backend/data/repository/JiRepository.java index 599d124..c2025c5 100644 --- a/src/main/java/fr/la_banquise/backend/data/repository/SitesRepository.java +++ b/src/main/java/fr/la_banquise/backend/data/repository/JiRepository.java @@ -1,9 +1,9 @@ package fr.la_banquise.backend.data.repository; -import fr.la_banquise.backend.data.model.Sites; +import fr.la_banquise.backend.data.model.Ji; import io.quarkus.hibernate.orm.panache.PanacheRepository; import jakarta.enterprise.context.ApplicationScoped; @ApplicationScoped -public class SitesRepository implements PanacheRepository { +public class JiRepository implements PanacheRepository { } diff --git a/src/main/java/fr/la_banquise/backend/data/repository/SiteRepository.java b/src/main/java/fr/la_banquise/backend/data/repository/SiteRepository.java new file mode 100644 index 0000000..18e5aa0 --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/data/repository/SiteRepository.java @@ -0,0 +1,9 @@ +package fr.la_banquise.backend.data.repository; + +import fr.la_banquise.backend.data.model.Site; +import io.quarkus.hibernate.orm.panache.PanacheRepository; +import jakarta.enterprise.context.ApplicationScoped; + +@ApplicationScoped +public class SiteRepository implements PanacheRepository { +} diff --git a/src/main/java/fr/la_banquise/backend/rest/JiResource.java b/src/main/java/fr/la_banquise/backend/rest/JiResource.java new file mode 100644 index 0000000..2934cde --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/rest/JiResource.java @@ -0,0 +1,118 @@ +package fr.la_banquise.backend.rest; + +import fr.la_banquise.backend.data.model.Ji; +import fr.la_banquise.backend.services.JiService; +import jakarta.inject.Inject; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import java.util.List; +import java.util.stream.Collectors; + +import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; + +import java.util.Map; + +@Path("/ji") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +public class JiResource { + + @Inject + JiService jiService; + + + @GET + @Path("/listall") + @Produces(MediaType.APPLICATION_JSON) + public Response listall() { + try { + List ji = jiService.getAllJi(); + return Response.ok(ji).build(); + } catch (Exception e) { + return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } + } + + @POST + @Path("/create") + public Response createJi(@QueryParam("name") String name, @QueryParam("desc") String desc, @QueryParam("address") String address, @QueryParam("respo") String respo, @QueryParam("site") String name_site) { + try { + Ji jsp = jiService.createJi(name, desc, address, respo, name_site); + return Response.ok(Map.of("created", jsp)).build(); + } catch (Exception e) { + return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } + } + + @GET + @Path("/getbyname") + @Produces(MediaType.APPLICATION_JSON) + public Response getJiByName(@QueryParam("name") String name) { + try { + Ji ji = jiService.getJiByName(name); + return Response.ok(ji.toString()).build(); + } catch (Exception e) { + return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } + } + + @DELETE + @Path("/del") + @APIResponses({ + @APIResponse(responseCode = "200", description = "Successfully deleted"), + @APIResponse(responseCode = "500", description = "Internal server error, usually site not found") +}) + public Response deleteJiByName(@QueryParam("name") String name) { + try { + jiService.deleteJiByName(name); + return Response.ok().build(); + } catch (Exception e) { + return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } + } +/* + @GET + @Path("/all") + public Response listContainers() { + try { + String id = dockerService.listAllContainers(); + return Response.ok(id).build(); + } catch (Exception e) { + return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } + } + + @POST + @Path("/start") + public Response start(@QueryParam("id") String id) { + try { + dockerService.start(id); + return Response.ok(Map.of("containerId", id, "status", "Running")).build(); + } catch (Exception e) { + return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } + } + + @POST + @Path("/stop") + public Response stop(@QueryParam("id") String id) { + try { + dockerService.stop(id); + return Response.ok(Map.of("containerId", id, "status", "removed")).build(); + } catch (Exception e) { + return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } + } + @DELETE + @Path("/remove") + public Response remove(@QueryParam("id") String id) { + try { + dockerService.remove(id); + return Response.ok(Map.of("containerId", id, "status", "removed")).build(); + } catch (Exception e) { + return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } + }*/ +} diff --git a/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java new file mode 100644 index 0000000..3b23052 --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java @@ -0,0 +1,129 @@ +package fr.la_banquise.backend.rest; + +import fr.la_banquise.backend.data.model.Site; +import fr.la_banquise.backend.services.SiteService; +import jakarta.inject.Inject; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import java.util.List; +import java.util.stream.Collectors; + +import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; +import org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; + +import java.util.Map; + +@Path("/sites") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +public class SiteEndpoints { + + @Inject + SiteService siteService; + + @GET + @Path("/listall") + @Produces(MediaType.APPLICATION_JSON) + public Response listall() { + try { + List sites = siteService.getAllSites(); + return Response.ok(sites).build(); + } + catch (Exception e) { + return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } + } + + @POST + @Path("/create") + public Response createSite(@QueryParam("name") String name, @QueryParam("desc") String desc, @QueryParam("address") String address) { + try { + String jsp = siteService.createSite(name, desc, address).toString(); + return Response.ok(Map.of("created", jsp)).build(); + } + catch (Exception e) { + return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } + } + + + + @GET + @Path("/getbyname") + @Produces(MediaType.APPLICATION_JSON) + public Response getSiteByName(@QueryParam("name") String name) { + try { + Site site = siteService.getSiteByName(name); + return Response.ok(site.toString()).build(); + } + catch (Exception e) { + return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } + } + + + + @DELETE + @Path("/del") + @Operation(summary = "Deletes a site", description = "Permanently removes a site if no Ji are associated to it.") + @APIResponses({ + @APIResponse(responseCode = "200", description = "Successfully deleted"), + @APIResponse(responseCode = "409", description = "Cannot delete site, it has associated JI records"), + @APIResponse(responseCode = "500", description = "Internal server error, usually site not found")}) + public Response deleteSiteByName(@QueryParam("name") String name) { + try { + boolean retour = siteService.deleteSiteByName(name); + if (retour) { return Response.ok().build(); } + return Response.status(409).entity(Map.of("Cannot delete site", "it has associated JI records")).build(); + } + catch (Exception e) { + return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } + } +/* + @GET + @Path("/all") + public Response listContainers() { + try { + String id = dockerService.listAllContainers(); + return Response.ok(id).build(); + } catch (Exception e) { + return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } + } + + @POST + @Path("/start") + public Response start(@QueryParam("id") String id) { + try { + dockerService.start(id); + return Response.ok(Map.of("containerId", id, "status", "Running")).build(); + } catch (Exception e) { + return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } + } + + @POST + @Path("/stop") + public Response stop(@QueryParam("id") String id) { + try { + dockerService.stop(id); + return Response.ok(Map.of("containerId", id, "status", "removed")).build(); + } catch (Exception e) { + return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } + } + @DELETE + @Path("/remove") + public Response remove(@QueryParam("id") String id) { + try { + dockerService.remove(id); + return Response.ok(Map.of("containerId", id, "status", "removed")).build(); + } catch (Exception e) { + return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } + }*/ +} diff --git a/src/main/java/fr/la_banquise/backend/services/DockerService.java b/src/main/java/fr/la_banquise/backend/services/DockerService.java index 4e53bee..426f5ed 100644 --- a/src/main/java/fr/la_banquise/backend/services/DockerService.java +++ b/src/main/java/fr/la_banquise/backend/services/DockerService.java @@ -134,7 +134,7 @@ if (port.getType() != null) { json.append("]"); return json.toString(); -} */ +} public String listAllContainers() { StringBuilder json = new StringBuilder(); List containers = dockerClient.listContainersCmd() @@ -173,7 +173,8 @@ if (port.getType() != null) { } json.append("]"); return json.toString(); -} +}*/ + public String listAllContainers() { return ""; } public void start(String containerId) { dockerClient.startContainerCmd(containerId).exec(); diff --git a/src/main/java/fr/la_banquise/backend/services/JiService.java b/src/main/java/fr/la_banquise/backend/services/JiService.java new file mode 100644 index 0000000..03b1e4c --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/services/JiService.java @@ -0,0 +1,59 @@ +package fr.la_banquise.backend.services; + +import fr.la_banquise.backend.data.model.Ji; +import fr.la_banquise.backend.data.model.Site; +import fr.la_banquise.backend.data.repository.JiRepository; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.transaction.Transactional; +import java.util.List; + +@ApplicationScoped +public class JiService { + + @Inject + JiRepository jiRepository; + + @Inject + SiteService siteService; + + @Transactional + public Ji createJi(String name, String description, String address, String respo, String site_name) { + Site site = siteService.getSiteByName(site_name); + Ji ji = new Ji(name, description, address, respo, site.id); + jiRepository.persist(ji); + siteService.addJi(site, ji.id); + return ji; + } + + /*@Transactional + public List saveAllSites(List sites) { + sites.forEach(site -> siteRepository.persist(site)); + return sites; + }*/ + + public List getAllJi() { + return jiRepository.listAll(); + } + + public Ji getJiByName(String name) { + return jiRepository.find("name", name).firstResult(); + } + + public Ji getJiById(Long id) { + return jiRepository.findById(id); + } + + @Transactional + public void deleteJiById(Long id) { + siteService.removeJi(siteService.getSiteById(getJiById(id).siteId), id); + jiRepository.deleteById(id); + } + + @Transactional + public void deleteJiByName(String name) { + Ji ji = getJiByName(name); + siteService.removeJi(siteService.getSiteById(ji.siteId), ji.id); + jiRepository.delete(ji); + } +} diff --git a/src/main/java/fr/la_banquise/backend/services/SiteService.java b/src/main/java/fr/la_banquise/backend/services/SiteService.java new file mode 100644 index 0000000..2ea1743 --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/services/SiteService.java @@ -0,0 +1,72 @@ +package fr.la_banquise.backend.services; + +import fr.la_banquise.backend.data.model.Site; +import fr.la_banquise.backend.data.repository.SiteRepository; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.transaction.Transactional; +import java.util.List; + +@ApplicationScoped +public class SiteService { + + @Inject + SiteRepository siteRepository; + + @Transactional + public Site createSite(String name, String description, String address) { + Site site = new Site(name, description, address); + siteRepository.persist(site); + return site; + } + + /*@Transactional + public List saveAllSites(List sites) { + sites.forEach(site -> siteRepository.persist(site)); + return sites; + }*/ + + public List getAllSites() { + return siteRepository.listAll(); + } + + public Site getSiteByName(String name) { + return siteRepository.find("name", name).firstResult(); + } + + public Site getSiteById(Long id) { + return siteRepository.findById(id); + } + + @Transactional + public void addJi(Site site, Long id){ + site.jiInSite.add(id); + } + + @Transactional + public void removeJi(Site site, Long id){ + site.jiInSite.remove(id); + } + + @Transactional + public boolean deleteSiteById(Long id) { + if (getSiteById(id).jiInSite.isEmpty()) + { + siteRepository.deleteById(id); + return true; + } + return false; + + } + + @Transactional + public boolean deleteSiteByName(String name) { + Site site = getSiteByName(name); + if (site.jiInSite.isEmpty()) + { + siteRepository.delete(site); + return true; + } + return false; + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index ee245e3..9922da7 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -26,13 +26,13 @@ quarkus.security.ldap.identity-mapping.attribute-mappings."0".filter-base-dn=ou= # database quarkus.datasource.db-kind = postgresql -quarkus.datasource.username = postgres -quarkus.datasource.password = secret -#quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:5432/quarkus +quarkus.datasource.username = banq +quarkus.datasource.password = test +quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:5432/quarkus # drop and create the database at startup (use `update` to only update the schema)drop-and-create -quarkus.hibernate-orm.database.generation=update -#quarkus.hibernate-orm.database.generation=drop-and-create +#quarkus.hibernate-orm.database.generation=update +quarkus.hibernate-orm.database.generation=drop-and-create quarkus.quinoa.dev-server.port=5173 quarkus.quinoa.enable-spa-routing=true -- 2.47.2 From 6ac45b39a279e16a752ca49d509d927f5f63d3be Mon Sep 17 00:00:00 2001 From: Arthur Wambst Date: Tue, 29 Jul 2025 18:10:22 +0200 Subject: [PATCH 05/28] feat: removed auth for dev --- src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java | 1 + src/main/resources/application.properties | 1 + 2 files changed, 2 insertions(+) diff --git a/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java index 3b23052..f6391a1 100644 --- a/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java +++ b/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java @@ -39,6 +39,7 @@ public class SiteEndpoints { @POST @Path("/create") + @RolesAllowed("root") public Response createSite(@QueryParam("name") String name, @QueryParam("desc") String desc, @QueryParam("address") String address) { try { String jsp = siteService.createSite(name, desc, address).toString(); diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 9922da7..798cdc6 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -38,3 +38,4 @@ quarkus.quinoa.dev-server.port=5173 quarkus.quinoa.enable-spa-routing=true quarkus.docker.docker-host=unix:///run/user/1000/docker.sock +%dev.quarkus.security.auth.enabled=false -- 2.47.2 From 2279f23ac49f8444f1808dbbe1bf7c10b82c6017 Mon Sep 17 00:00:00 2001 From: Arthur Wambst Date: Tue, 29 Jul 2025 18:11:29 +0200 Subject: [PATCH 06/28] feat: added roles requirement for critical site operations --- src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java index f6391a1..9652644 100644 --- a/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java +++ b/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java @@ -69,6 +69,7 @@ public class SiteEndpoints { @DELETE @Path("/del") + @RolesAllowed("root") @Operation(summary = "Deletes a site", description = "Permanently removes a site if no Ji are associated to it.") @APIResponses({ @APIResponse(responseCode = "200", description = "Successfully deleted"), -- 2.47.2 From 9039e3d3f65466181fa61e251955424ed48f28b8 Mon Sep 17 00:00:00 2001 From: Arthur Wambst Date: Tue, 29 Jul 2025 18:12:02 +0200 Subject: [PATCH 07/28] feat: added roles requirement for critical ji operations --- src/main/java/fr/la_banquise/backend/rest/JiResource.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/fr/la_banquise/backend/rest/JiResource.java b/src/main/java/fr/la_banquise/backend/rest/JiResource.java index 2934cde..4de930a 100644 --- a/src/main/java/fr/la_banquise/backend/rest/JiResource.java +++ b/src/main/java/fr/la_banquise/backend/rest/JiResource.java @@ -37,6 +37,7 @@ public class JiResource { @POST @Path("/create") + @RolesAllowed("root") public Response createJi(@QueryParam("name") String name, @QueryParam("desc") String desc, @QueryParam("address") String address, @QueryParam("respo") String respo, @QueryParam("site") String name_site) { try { Ji jsp = jiService.createJi(name, desc, address, respo, name_site); @@ -60,9 +61,10 @@ public class JiResource { @DELETE @Path("/del") + @RolesAllowed("root") @APIResponses({ - @APIResponse(responseCode = "200", description = "Successfully deleted"), - @APIResponse(responseCode = "500", description = "Internal server error, usually site not found") + @APIResponse(responseCode = "200", description = "Successfully deleted"), + @APIResponse(responseCode = "500", description = "Internal server error, usually site not found") }) public Response deleteJiByName(@QueryParam("name") String name) { try { -- 2.47.2 From 6aa4b5f0c4bcc0a90a2e4b85c98ada00b79edaa3 Mon Sep 17 00:00:00 2001 From: Arthur Wambst Date: Tue, 29 Jul 2025 18:16:29 +0200 Subject: [PATCH 08/28] fix: added missing import for RolesAllowed --- src/main/java/fr/la_banquise/backend/rest/JiResource.java | 5 +++++ src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/main/java/fr/la_banquise/backend/rest/JiResource.java b/src/main/java/fr/la_banquise/backend/rest/JiResource.java index 4de930a..13a409d 100644 --- a/src/main/java/fr/la_banquise/backend/rest/JiResource.java +++ b/src/main/java/fr/la_banquise/backend/rest/JiResource.java @@ -8,6 +8,8 @@ import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import java.util.List; import java.util.stream.Collectors; +import io.quarkus.security.identity.SecurityIdentity; +import jakarta.annotation.security.RolesAllowed; import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; @@ -19,6 +21,9 @@ import java.util.Map; @Consumes(MediaType.APPLICATION_JSON) public class JiResource { + @Inject + SecurityIdentity identity; + @Inject JiService jiService; diff --git a/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java index 9652644..551b7a6 100644 --- a/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java +++ b/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java @@ -8,6 +8,8 @@ import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import java.util.List; import java.util.stream.Collectors; +import io.quarkus.security.identity.SecurityIdentity; +import jakarta.annotation.security.RolesAllowed; import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; @@ -21,6 +23,9 @@ import java.util.Map; @Consumes(MediaType.APPLICATION_JSON) public class SiteEndpoints { + @Inject + SecurityIdentity identity; + @Inject SiteService siteService; -- 2.47.2 From 637a934b81c44939ada5e6f6c086f4e42e664f3b Mon Sep 17 00:00:00 2001 From: Arthur Wambst Date: Tue, 29 Jul 2025 18:23:09 +0200 Subject: [PATCH 09/28] fix: really disabled auth in dev mode --- src/main/resources/application.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 798cdc6..03c87e8 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -38,4 +38,4 @@ quarkus.quinoa.dev-server.port=5173 quarkus.quinoa.enable-spa-routing=true quarkus.docker.docker-host=unix:///run/user/1000/docker.sock -%dev.quarkus.security.auth.enabled=false +quarkus.security.auth.enabled-in-dev-mode=false -- 2.47.2 From 5496bee4e66573f419076d53e0adb74b09254b59 Mon Sep 17 00:00:00 2001 From: Arthur Wambst Date: Tue, 29 Jul 2025 18:27:47 +0200 Subject: [PATCH 10/28] fix: added back a removed RolesAllowed for user creation --- src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java index 33775b7..f8cd258 100644 --- a/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java +++ b/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java @@ -50,6 +50,7 @@ public class UserEndpoints { } @POST + @RolesAllowed("root") public Response createUser(UserRequest user) { return Response.ok(userService.createUser(user)).build(); } -- 2.47.2 From 7a984cb7d2afffac5182895b850754d0a97b7439 Mon Sep 17 00:00:00 2001 From: Arthur Wambst Date: Wed, 30 Jul 2025 03:45:15 +0200 Subject: [PATCH 11/28] fix: ji and site now reference each other directly instead of ids --- .../fr/la_banquise/backend/data/model/Instance.java | 2 +- .../java/fr/la_banquise/backend/data/model/Ji.java | 11 ++++++++--- .../fr/la_banquise/backend/data/model/Site.java | 9 +++++++-- .../fr/la_banquise/backend/rest/JiResource.java | 2 +- .../fr/la_banquise/backend/services/JiService.java | 13 +++++++------ .../la_banquise/backend/services/SiteService.java | 9 +++++---- 6 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/main/java/fr/la_banquise/backend/data/model/Instance.java b/src/main/java/fr/la_banquise/backend/data/model/Instance.java index 42da592..aab3b06 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/Instance.java +++ b/src/main/java/fr/la_banquise/backend/data/model/Instance.java @@ -34,7 +34,7 @@ public class Instance { public User user; @ManyToOne - @JoinColumn(name = "practical_id") + @JoinColumn(name = "practical_id", nullable = false) public Tp tp; public Instance(String name, String ssh, String pwd, Long port, User user, Tp tp) { diff --git a/src/main/java/fr/la_banquise/backend/data/model/Ji.java b/src/main/java/fr/la_banquise/backend/data/model/Ji.java index 95d9151..987761b 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/Ji.java +++ b/src/main/java/fr/la_banquise/backend/data/model/Ji.java @@ -10,6 +10,8 @@ import jakarta.persistence.Table; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; import java.util.List; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.JoinColumn; @Entity @NoArgsConstructor @@ -24,13 +26,16 @@ public class Ji { public String description; public String respo; public String date; - public Long siteId; - public Ji(String name, String description, String respo, String date, Long siteId) { + @ManyToOne + @JoinColumn(name = "site_id") + public Site site; + + public Ji(String name, String description, String respo, String date, Site site) { this.name = name; this.description = description; this.respo = respo; this.date = date; - this.siteId = siteId; + this.site = site; } } diff --git a/src/main/java/fr/la_banquise/backend/data/model/Site.java b/src/main/java/fr/la_banquise/backend/data/model/Site.java index db3fc61..d832eef 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/Site.java +++ b/src/main/java/fr/la_banquise/backend/data/model/Site.java @@ -14,6 +14,9 @@ import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; import java.util.Set; import java.util.HashSet; +import jakarta.persistence.OneToMany; +import java.util.List; +import java.util.ArrayList; @Entity @NoArgsConstructor @@ -31,13 +34,15 @@ public class Site { public String name; public String description; public String address; - public Set jiInSite; + + @OneToMany(mappedBy = "site") + public List jiInSite; public Site(String name, String description, String address) { this.name = name; this.description = description; this.address = address; - this.jiInSite = new HashSet(); + this.jiInSite = new ArrayList(); } diff --git a/src/main/java/fr/la_banquise/backend/rest/JiResource.java b/src/main/java/fr/la_banquise/backend/rest/JiResource.java index 13a409d..9c81679 100644 --- a/src/main/java/fr/la_banquise/backend/rest/JiResource.java +++ b/src/main/java/fr/la_banquise/backend/rest/JiResource.java @@ -73,7 +73,7 @@ public class JiResource { }) public Response deleteJiByName(@QueryParam("name") String name) { try { - jiService.deleteJiByName(name); + jiService.deleteJi(name); return Response.ok().build(); } catch (Exception e) { return Response.status(500).entity(Map.of("error", e.getMessage())).build(); diff --git a/src/main/java/fr/la_banquise/backend/services/JiService.java b/src/main/java/fr/la_banquise/backend/services/JiService.java index 03b1e4c..a956d29 100644 --- a/src/main/java/fr/la_banquise/backend/services/JiService.java +++ b/src/main/java/fr/la_banquise/backend/services/JiService.java @@ -20,9 +20,9 @@ public class JiService { @Transactional public Ji createJi(String name, String description, String address, String respo, String site_name) { Site site = siteService.getSiteByName(site_name); - Ji ji = new Ji(name, description, address, respo, site.id); + Ji ji = new Ji(name, description, address, respo, site); jiRepository.persist(ji); - siteService.addJi(site, ji.id); + siteService.addJi(site, ji); return ji; } @@ -45,15 +45,16 @@ public class JiService { } @Transactional - public void deleteJiById(Long id) { - siteService.removeJi(siteService.getSiteById(getJiById(id).siteId), id); + public void deleteJi(Long id) { + Ji ji = getJiById(id); + siteService.removeJi(ji.site, ji); jiRepository.deleteById(id); } @Transactional - public void deleteJiByName(String name) { + public void deleteJi(String name) { Ji ji = getJiByName(name); - siteService.removeJi(siteService.getSiteById(ji.siteId), ji.id); + siteService.removeJi(ji.site, ji); jiRepository.delete(ji); } } diff --git a/src/main/java/fr/la_banquise/backend/services/SiteService.java b/src/main/java/fr/la_banquise/backend/services/SiteService.java index 2ea1743..0086770 100644 --- a/src/main/java/fr/la_banquise/backend/services/SiteService.java +++ b/src/main/java/fr/la_banquise/backend/services/SiteService.java @@ -1,6 +1,7 @@ package fr.la_banquise.backend.services; import fr.la_banquise.backend.data.model.Site; +import fr.la_banquise.backend.data.model.Ji; import fr.la_banquise.backend.data.repository.SiteRepository; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @@ -39,13 +40,13 @@ public class SiteService { } @Transactional - public void addJi(Site site, Long id){ - site.jiInSite.add(id); + public void addJi(Site site, Ji ji){ + site.jiInSite.add(ji); } @Transactional - public void removeJi(Site site, Long id){ - site.jiInSite.remove(id); + public void removeJi(Site site, Ji ji){ + site.jiInSite.remove(ji); } @Transactional -- 2.47.2 From 887090bf4901927001012c745fbc7e4f34751ad7 Mon Sep 17 00:00:00 2001 From: Arthur Wambst Date: Sat, 2 Aug 2025 03:06:12 +0200 Subject: [PATCH 12/28] refactor: experiencing with clang format --- .../backend/data/model/Instance.java | 7 +- .../fr/la_banquise/backend/data/model/Ji.java | 16 +- .../la_banquise/backend/data/model/Site.java | 28 +- .../fr/la_banquise/backend/data/model/Tp.java | 7 +- .../la_banquise/backend/data/model/User.java | 20 +- .../data/repository/SiteRepository.java | 3 +- .../backend/data/repository/TpRepository.java | 3 +- .../backend/rest/ContainerResource.java | 43 ++- .../la_banquise/backend/rest/JiResource.java | 128 ++++----- .../backend/rest/SiteEndpoints.java | 160 +++++------ .../backend/rest/UserEndpoints.java | 9 +- .../backend/services/DockerService.java | 248 +++++++++--------- .../backend/services/JiService.java | 25 +- .../backend/services/SiteService.java | 26 +- .../backend/services/UserService.java | 33 +-- 15 files changed, 380 insertions(+), 376 deletions(-) diff --git a/src/main/java/fr/la_banquise/backend/data/model/Instance.java b/src/main/java/fr/la_banquise/backend/data/model/Instance.java index aab3b06..bf5b135 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/Instance.java +++ b/src/main/java/fr/la_banquise/backend/data/model/Instance.java @@ -1,7 +1,6 @@ package fr.la_banquise.backend.data.model; import com.fasterxml.jackson.annotation.JsonBackReference; - import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; @@ -21,7 +20,8 @@ import lombok.NoArgsConstructor; public class Instance { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @SequenceGenerator(name = "InstanceSeq", sequenceName = "instance_id_seq", allocationSize = 1, initialValue = 1) + @SequenceGenerator(name = "InstanceSeq", sequenceName = "instance_id_seq", + allocationSize = 1, initialValue = 1) public Long id; public String name; public String ssh; @@ -37,7 +37,8 @@ public class Instance { @JoinColumn(name = "practical_id", nullable = false) public Tp tp; - public Instance(String name, String ssh, String pwd, Long port, User user, Tp tp) { + public Instance(String name, String ssh, String pwd, Long port, User user, + Tp tp) { this.name = name; this.ssh = ssh; this.pwd = pwd; diff --git a/src/main/java/fr/la_banquise/backend/data/model/Ji.java b/src/main/java/fr/la_banquise/backend/data/model/Ji.java index 987761b..ac075d8 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/Ji.java +++ b/src/main/java/fr/la_banquise/backend/data/model/Ji.java @@ -5,13 +5,13 @@ import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; import jakarta.persistence.SequenceGenerator; import jakarta.persistence.Table; +import java.util.List; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; -import java.util.List; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.JoinColumn; @Entity @NoArgsConstructor @@ -20,18 +20,18 @@ import jakarta.persistence.JoinColumn; public class Ji { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @SequenceGenerator(name = "JiSeq", sequenceName = "ji_id_seq", allocationSize = 1, initialValue = 1) + @SequenceGenerator(name = "JiSeq", sequenceName = "ji_id_seq", + allocationSize = 1, initialValue = 1) public Long id; public String name; public String description; public String respo; public String date; - @ManyToOne - @JoinColumn(name = "site_id") - public Site site; + @ManyToOne @JoinColumn(name = "site_id") public Site site; - public Ji(String name, String description, String respo, String date, Site site) { + public Ji(String name, String description, String respo, String date, + Site site) { this.name = name; this.description = description; this.respo = respo; diff --git a/src/main/java/fr/la_banquise/backend/data/model/Site.java b/src/main/java/fr/la_banquise/backend/data/model/Site.java index d832eef..f7e5543 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/Site.java +++ b/src/main/java/fr/la_banquise/backend/data/model/Site.java @@ -1,42 +1,36 @@ package fr.la_banquise.backend.data.model; -import io.quarkus.hibernate.orm.panache.PanacheEntity; - import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; import jakarta.persistence.SequenceGenerator; import jakarta.persistence.Table; import jakarta.persistence.UniqueConstraint; +import java.util.ArrayList; +import java.util.List; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; -import java.util.Set; -import java.util.HashSet; -import jakarta.persistence.OneToMany; -import java.util.List; -import java.util.ArrayList; @Entity @NoArgsConstructor @AllArgsConstructor -@Table(name = "site", uniqueConstraints = { - @UniqueConstraint(columnNames = "name") -}) +@Table(name = "site", + uniqueConstraints = { @UniqueConstraint(columnNames = "name") }) public class Site { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @SequenceGenerator(name = "SiteSeq", sequenceName = "site_id_seq", allocationSize = 1, initialValue = 1) + @SequenceGenerator(name = "SiteSeq", sequenceName = "site_id_seq", + allocationSize = 1, initialValue = 1) public Long id; - @Column(unique = true, nullable = false) - public String name; + @Column(unique = true, nullable = false) public String name; public String description; public String address; - @OneToMany(mappedBy = "site") - public List jiInSite; + @OneToMany(mappedBy = "site") public List jiInSite; public Site(String name, String description, String address) { this.name = name; @@ -45,9 +39,9 @@ public class Site { this.jiInSite = new ArrayList(); } - @Override public String toString() { - return "Site{id=" + id + ", name='" + name + "', description='" + description + "', address='" + address + "'}"; + return "Site{id=" + id + ", name='" + name + "', description='" + + description + "', address='" + address + "'}"; } } diff --git a/src/main/java/fr/la_banquise/backend/data/model/Tp.java b/src/main/java/fr/la_banquise/backend/data/model/Tp.java index 8eeb3b6..370a23c 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/Tp.java +++ b/src/main/java/fr/la_banquise/backend/data/model/Tp.java @@ -1,6 +1,5 @@ package fr.la_banquise.backend.data.model; -import io.quarkus.hibernate.orm.panache.PanacheEntity; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; @@ -20,7 +19,8 @@ import lombok.NoArgsConstructor; public class Tp { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @SequenceGenerator(name = "TpSeq", sequenceName = "tp_id_seq", allocationSize = 1, initialValue = 1) + @SequenceGenerator(name = "TpSeq", sequenceName = "tp_id_seq", + allocationSize = 1, initialValue = 1) public Long id; public String name; public String description; @@ -28,7 +28,8 @@ public class Tp { public String respo; public String date; - public Tp(String name, String description, String pdfLink, String respo, String date) { + public Tp(String name, String description, String pdfLink, String respo, + String date) { this.name = name; this.description = description; this.pdfLink = pdfLink; diff --git a/src/main/java/fr/la_banquise/backend/data/model/User.java b/src/main/java/fr/la_banquise/backend/data/model/User.java index 325e749..7c7caa1 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/User.java +++ b/src/main/java/fr/la_banquise/backend/data/model/User.java @@ -1,9 +1,6 @@ package fr.la_banquise.backend.data.model; -import java.util.List; - import com.fasterxml.jackson.annotation.JsonManagedReference; - import io.quarkus.security.jpa.Password; import io.quarkus.security.jpa.Roles; import io.quarkus.security.jpa.UserDefinition; @@ -16,6 +13,7 @@ import jakarta.persistence.Id; import jakarta.persistence.OneToMany; import jakarta.persistence.SequenceGenerator; import jakarta.persistence.Table; +import java.util.List; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @@ -34,24 +32,22 @@ import lombok.Setter; public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @SequenceGenerator(name = "UserSeq", sequenceName = "user_id_seq", allocationSize = 1, initialValue = 1) + @SequenceGenerator(name = "UserSeq", sequenceName = "user_id_seq", + allocationSize = 1, initialValue = 1) public Long id; - @Username - public String name; - @Password - public String password; - @Roles - public String role; + @Username public String name; + @Password public String password; + @Roles public String role; @JsonManagedReference @OneToMany(mappedBy = "user", cascade = CascadeType.ALL) public List instances; - public User(String name, String password, String role, List instances) { + public User(String name, String password, String role, + List instances) { this.name = name; this.password = password; this.role = role; this.instances = instances; } - } diff --git a/src/main/java/fr/la_banquise/backend/data/repository/SiteRepository.java b/src/main/java/fr/la_banquise/backend/data/repository/SiteRepository.java index 18e5aa0..0dc3a52 100644 --- a/src/main/java/fr/la_banquise/backend/data/repository/SiteRepository.java +++ b/src/main/java/fr/la_banquise/backend/data/repository/SiteRepository.java @@ -5,5 +5,4 @@ import io.quarkus.hibernate.orm.panache.PanacheRepository; import jakarta.enterprise.context.ApplicationScoped; @ApplicationScoped -public class SiteRepository implements PanacheRepository { -} +public class SiteRepository implements PanacheRepository {} diff --git a/src/main/java/fr/la_banquise/backend/data/repository/TpRepository.java b/src/main/java/fr/la_banquise/backend/data/repository/TpRepository.java index c395dfc..8751766 100644 --- a/src/main/java/fr/la_banquise/backend/data/repository/TpRepository.java +++ b/src/main/java/fr/la_banquise/backend/data/repository/TpRepository.java @@ -8,5 +8,4 @@ import jakarta.enterprise.context.ApplicationScoped; * TpRepository */ @ApplicationScoped -public class TpRepository implements PanacheRepository { -} +public class TpRepository implements PanacheRepository {} diff --git a/src/main/java/fr/la_banquise/backend/rest/ContainerResource.java b/src/main/java/fr/la_banquise/backend/rest/ContainerResource.java index 3f90be4..0a5bd48 100644 --- a/src/main/java/fr/la_banquise/backend/rest/ContainerResource.java +++ b/src/main/java/fr/la_banquise/backend/rest/ContainerResource.java @@ -5,7 +5,6 @@ import jakarta.inject.Inject; import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; - import java.util.Map; @Path("/containers") @@ -13,28 +12,33 @@ import java.util.Map; @Consumes(MediaType.APPLICATION_JSON) public class ContainerResource { - @Inject - DockerService dockerService; + @Inject DockerService dockerService; @POST @Path("/nginx") public Response launchNginx() { try { String id = dockerService.createAndStartNginx(); - return Response.ok(Map.of("containerId", id, "status", "running")).build(); + return Response.ok(Map.of("containerId", id, "status", "running")) + .build(); } catch (Exception e) { - return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + return Response.status(500) + .entity(Map.of("error", e.getMessage())) + .build(); } } @POST @Path("/create") - public Response createContainer(@QueryParam("name") String name, @QueryParam("port") int port) { + public Response createContainer(@QueryParam("name") String name, + @QueryParam("port") int port) { try { String id = dockerService.createContainer(name, port); return Response.ok(Map.of("containerId", id)).build(); } catch (Exception e) { - return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + return Response.status(500) + .entity(Map.of("error", e.getMessage())) + .build(); } } @@ -45,7 +49,9 @@ public class ContainerResource { String id = dockerService.listAllContainers(); return Response.ok(id).build(); } catch (Exception e) { - return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + return Response.status(500) + .entity(Map.of("error", e.getMessage())) + .build(); } } @@ -54,9 +60,12 @@ public class ContainerResource { public Response start(@QueryParam("id") String id) { try { dockerService.start(id); - return Response.ok(Map.of("containerId", id, "status", "Running")).build(); + return Response.ok(Map.of("containerId", id, "status", "Running")) + .build(); } catch (Exception e) { - return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + return Response.status(500) + .entity(Map.of("error", e.getMessage())) + .build(); } } @@ -65,9 +74,12 @@ public class ContainerResource { public Response stop(@QueryParam("id") String id) { try { dockerService.stop(id); - return Response.ok(Map.of("containerId", id, "status", "removed")).build(); + return Response.ok(Map.of("containerId", id, "status", "removed")) + .build(); } catch (Exception e) { - return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + return Response.status(500) + .entity(Map.of("error", e.getMessage())) + .build(); } } @DELETE @@ -75,9 +87,12 @@ public class ContainerResource { public Response remove(@QueryParam("id") String id) { try { dockerService.remove(id); - return Response.ok(Map.of("containerId", id, "status", "removed")).build(); + return Response.ok(Map.of("containerId", id, "status", "removed")) + .build(); } catch (Exception e) { - return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + return Response.status(500) + .entity(Map.of("error", e.getMessage())) + .build(); } } } diff --git a/src/main/java/fr/la_banquise/backend/rest/JiResource.java b/src/main/java/fr/la_banquise/backend/rest/JiResource.java index 9c81679..b0357d8 100644 --- a/src/main/java/fr/la_banquise/backend/rest/JiResource.java +++ b/src/main/java/fr/la_banquise/backend/rest/JiResource.java @@ -2,31 +2,25 @@ package fr.la_banquise.backend.rest; import fr.la_banquise.backend.data.model.Ji; import fr.la_banquise.backend.services.JiService; +import io.quarkus.security.identity.SecurityIdentity; +import jakarta.annotation.security.RolesAllowed; import jakarta.inject.Inject; import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import java.util.List; -import java.util.stream.Collectors; -import io.quarkus.security.identity.SecurityIdentity; -import jakarta.annotation.security.RolesAllowed; - -import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; -import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; - import java.util.Map; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; @Path("/ji") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public class JiResource { - @Inject - SecurityIdentity identity; + @Inject SecurityIdentity identity; - @Inject - JiService jiService; - + @Inject JiService jiService; @GET @Path("/listall") @@ -36,19 +30,27 @@ public class JiResource { List ji = jiService.getAllJi(); return Response.ok(ji).build(); } catch (Exception e) { - return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + return Response.status(500) + .entity(Map.of("error", e.getMessage())) + .build(); } } @POST @Path("/create") @RolesAllowed("root") - public Response createJi(@QueryParam("name") String name, @QueryParam("desc") String desc, @QueryParam("address") String address, @QueryParam("respo") String respo, @QueryParam("site") String name_site) { + public Response createJi(@QueryParam("name") String name, + @QueryParam("desc") String desc, + @QueryParam("address") String address, + @QueryParam("respo") String respo, + @QueryParam("site") String name_site) { try { Ji jsp = jiService.createJi(name, desc, address, respo, name_site); return Response.ok(Map.of("created", jsp)).build(); } catch (Exception e) { - return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + return Response.status(500) + .entity(Map.of("error", e.getMessage())) + .build(); } } @@ -60,7 +62,9 @@ public class JiResource { Ji ji = jiService.getJiByName(name); return Response.ok(ji.toString()).build(); } catch (Exception e) { - return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + return Response.status(500) + .entity(Map.of("error", e.getMessage())) + .build(); } } @@ -68,58 +72,64 @@ public class JiResource { @Path("/del") @RolesAllowed("root") @APIResponses({ - @APIResponse(responseCode = "200", description = "Successfully deleted"), - @APIResponse(responseCode = "500", description = "Internal server error, usually site not found") -}) - public Response deleteJiByName(@QueryParam("name") String name) { + @APIResponse(responseCode = "200", description = "Successfully deleted") + , @APIResponse(responseCode = "500", + description = + "Internal server error, usually site not found") + }) + public Response + deleteJiByName(@QueryParam("name") String name) { try { jiService.deleteJi(name); return Response.ok().build(); } catch (Exception e) { - return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + return Response.status(500) + .entity(Map.of("error", e.getMessage())) + .build(); } } -/* - @GET - @Path("/all") - public Response listContainers() { - try { - String id = dockerService.listAllContainers(); - return Response.ok(id).build(); - } catch (Exception e) { - return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + /* + @GET + @Path("/all") + public Response listContainers() { + try { + String id = dockerService.listAllContainers(); + return Response.ok(id).build(); + } catch (Exception e) { + return Response.status(500).entity(Map.of("error", + e.getMessage())).build(); + } } - } - @POST - @Path("/start") - public Response start(@QueryParam("id") String id) { - try { - dockerService.start(id); - return Response.ok(Map.of("containerId", id, "status", "Running")).build(); - } catch (Exception e) { - return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + @POST + @Path("/start") + public Response start(@QueryParam("id") String id) { + try { + dockerService.start(id); + return Response.ok(Map.of("containerId", id, "status", + "Running")).build(); } catch (Exception e) { return + Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } } - } - @POST - @Path("/stop") - public Response stop(@QueryParam("id") String id) { - try { - dockerService.stop(id); - return Response.ok(Map.of("containerId", id, "status", "removed")).build(); - } catch (Exception e) { - return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + @POST + @Path("/stop") + public Response stop(@QueryParam("id") String id) { + try { + dockerService.stop(id); + return Response.ok(Map.of("containerId", id, "status", + "removed")).build(); } catch (Exception e) { return + Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } } - } - @DELETE - @Path("/remove") - public Response remove(@QueryParam("id") String id) { - try { - dockerService.remove(id); - return Response.ok(Map.of("containerId", id, "status", "removed")).build(); - } catch (Exception e) { - return Response.status(500).entity(Map.of("error", e.getMessage())).build(); - } - }*/ + @DELETE + @Path("/remove") + public Response remove(@QueryParam("id") String id) { + try { + dockerService.remove(id); + return Response.ok(Map.of("containerId", id, "status", + "removed")).build(); } catch (Exception e) { return + Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } + }*/ } diff --git a/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java index 551b7a6..6995685 100644 --- a/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java +++ b/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java @@ -2,32 +2,28 @@ package fr.la_banquise.backend.rest; import fr.la_banquise.backend.data.model.Site; import fr.la_banquise.backend.services.SiteService; +import io.quarkus.security.identity.SecurityIdentity; +import jakarta.annotation.security.RolesAllowed; import jakarta.inject.Inject; import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; -import io.quarkus.security.identity.SecurityIdentity; -import jakarta.annotation.security.RolesAllowed; - -import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; -import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; import org.eclipse.microprofile.openapi.annotations.Operation; import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; - -import java.util.Map; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; @Path("/sites") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public class SiteEndpoints { - @Inject - SecurityIdentity identity; + @Inject SecurityIdentity identity; - @Inject - SiteService siteService; + @Inject SiteService siteService; @GET @Path("/listall") @@ -36,27 +32,29 @@ public class SiteEndpoints { try { List sites = siteService.getAllSites(); return Response.ok(sites).build(); - } - catch (Exception e) { - return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } catch (Exception e) { + return Response.status(500) + .entity(Map.of("error", e.getMessage())) + .build(); } } @POST @Path("/create") @RolesAllowed("root") - public Response createSite(@QueryParam("name") String name, @QueryParam("desc") String desc, @QueryParam("address") String address) { + public Response createSite(@QueryParam("name") String name, + @QueryParam("desc") String desc, + @QueryParam("address") String address) { try { String jsp = siteService.createSite(name, desc, address).toString(); return Response.ok(Map.of("created", jsp)).build(); - } - catch (Exception e) { - return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } catch (Exception e) { + return Response.status(500) + .entity(Map.of("error", e.getMessage())) + .build(); } } - - @GET @Path("/getbyname") @Produces(MediaType.APPLICATION_JSON) @@ -64,73 +62,89 @@ public class SiteEndpoints { try { Site site = siteService.getSiteByName(name); return Response.ok(site.toString()).build(); - } - catch (Exception e) { - return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } catch (Exception e) { + return Response.status(500) + .entity(Map.of("error", e.getMessage())) + .build(); } } - - @DELETE @Path("/del") @RolesAllowed("root") - @Operation(summary = "Deletes a site", description = "Permanently removes a site if no Ji are associated to it.") + @Operation(summary = "Deletes a site", + description = + "Permanently removes a site if no Ji are associated to it.") @APIResponses({ - @APIResponse(responseCode = "200", description = "Successfully deleted"), - @APIResponse(responseCode = "409", description = "Cannot delete site, it has associated JI records"), - @APIResponse(responseCode = "500", description = "Internal server error, usually site not found")}) - public Response deleteSiteByName(@QueryParam("name") String name) { + @APIResponse(responseCode = "200", description = "Successfully deleted") + , + @APIResponse(responseCode = "409", + description = + "Cannot delete site, it has associated JI records") + , + @APIResponse(responseCode = "500", + description = + "Internal server error, usually site not found") + }) + public Response + deleteSiteByName(@QueryParam("name") String name) { try { boolean retour = siteService.deleteSiteByName(name); - if (retour) { return Response.ok().build(); } - return Response.status(409).entity(Map.of("Cannot delete site", "it has associated JI records")).build(); - } - catch (Exception e) { - return Response.status(500).entity(Map.of("error", e.getMessage())).build(); - } - } -/* - @GET - @Path("/all") - public Response listContainers() { - try { - String id = dockerService.listAllContainers(); - return Response.ok(id).build(); + if (retour) { + return Response.ok().build(); + } + return Response.status(409) + .entity(Map.of("Cannot delete site", + "it has associated JI records")) + .build(); } catch (Exception e) { - return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + return Response.status(500) + .entity(Map.of("error", e.getMessage())) + .build(); } } + /* + @GET + @Path("/all") + public Response listContainers() { + try { + String id = dockerService.listAllContainers(); + return Response.ok(id).build(); + } catch (Exception e) { + return Response.status(500).entity(Map.of("error", + e.getMessage())).build(); + } + } - @POST - @Path("/start") - public Response start(@QueryParam("id") String id) { - try { - dockerService.start(id); - return Response.ok(Map.of("containerId", id, "status", "Running")).build(); - } catch (Exception e) { - return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + @POST + @Path("/start") + public Response start(@QueryParam("id") String id) { + try { + dockerService.start(id); + return Response.ok(Map.of("containerId", id, "status", + "Running")).build(); } catch (Exception e) { return + Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } } - } - @POST - @Path("/stop") - public Response stop(@QueryParam("id") String id) { - try { - dockerService.stop(id); - return Response.ok(Map.of("containerId", id, "status", "removed")).build(); - } catch (Exception e) { - return Response.status(500).entity(Map.of("error", e.getMessage())).build(); + @POST + @Path("/stop") + public Response stop(@QueryParam("id") String id) { + try { + dockerService.stop(id); + return Response.ok(Map.of("containerId", id, "status", + "removed")).build(); } catch (Exception e) { return + Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } } - } - @DELETE - @Path("/remove") - public Response remove(@QueryParam("id") String id) { - try { - dockerService.remove(id); - return Response.ok(Map.of("containerId", id, "status", "removed")).build(); - } catch (Exception e) { - return Response.status(500).entity(Map.of("error", e.getMessage())).build(); - } - }*/ + @DELETE + @Path("/remove") + public Response remove(@QueryParam("id") String id) { + try { + dockerService.remove(id); + return Response.ok(Map.of("containerId", id, "status", + "removed")).build(); } catch (Exception e) { return + Response.status(500).entity(Map.of("error", e.getMessage())).build(); + } + }*/ } diff --git a/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java index f8cd258..076d591 100644 --- a/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java +++ b/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java @@ -23,16 +23,15 @@ import jakarta.ws.rs.core.Response; @Produces(MediaType.APPLICATION_JSON) public class UserEndpoints { - @Inject - SecurityIdentity identity; + @Inject SecurityIdentity identity; - @Inject - UserService userService; + @Inject UserService userService; @GET @Path("/me") public Response getCurrentUser() { - LoggedUserResponse user = new LoggedUserResponse(identity.getPrincipal().getName(), identity.getRoles()); + LoggedUserResponse user = new LoggedUserResponse( + identity.getPrincipal().getName(), identity.getRoles()); return Response.ok(user).build(); } diff --git a/src/main/java/fr/la_banquise/backend/services/DockerService.java b/src/main/java/fr/la_banquise/backend/services/DockerService.java index 426f5ed..7456d54 100644 --- a/src/main/java/fr/la_banquise/backend/services/DockerService.java +++ b/src/main/java/fr/la_banquise/backend/services/DockerService.java @@ -2,24 +2,23 @@ package fr.la_banquise.backend.services; import com.github.dockerjava.api.DockerClient; import com.github.dockerjava.api.command.CreateContainerResponse; +import com.github.dockerjava.api.command.InspectContainerResponse; +import com.github.dockerjava.api.model.Container; +import com.github.dockerjava.api.model.ContainerPort; import com.github.dockerjava.api.model.ExposedPort; import com.github.dockerjava.api.model.HostConfig; import com.github.dockerjava.api.model.PortBinding; import com.github.dockerjava.api.model.Ports; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; +import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.HashMap; -import com.github.dockerjava.api.model.Container; -import com.github.dockerjava.api.model.ContainerPort; -import com.github.dockerjava.api.command.InspectContainerResponse; @ApplicationScoped public class DockerService { - @Inject - DockerClient dockerClient; + @Inject DockerClient dockerClient; public String createAndStartNginx() { ExposedPort tcp80 = ExposedPort.tcp(80); @@ -27,15 +26,16 @@ public class DockerService { Ports portBindings = new Ports(); portBindings.bind(tcp80, Ports.Binding.bindPort(8081)); - HostConfig hostConfig = HostConfig.newHostConfig() - .withPortBindings(portBindings); + HostConfig hostConfig = + HostConfig.newHostConfig().withPortBindings(portBindings); Map labels = new HashMap<>(); - labels.put("test", "banquise"); - labels.put("environment", "development"); - labels.put("version", "1.0"); - labels.put("created-by", "java-docker-api"); + labels.put("test", "banquise"); + labels.put("environment", "development"); + labels.put("version", "1.0"); + labels.put("created-by", "java-docker-api"); - CreateContainerResponse container = dockerClient.createContainerCmd("nginx:latest") + CreateContainerResponse container = + dockerClient.createContainerCmd("nginx:latest") .withName("my-nginx") .withLabels(labels) .withExposedPorts(tcp80) @@ -47,139 +47,141 @@ public class DockerService { } public String createContainer(String containerName, int port) { - StringBuilder result = new StringBuilder(); + StringBuilder result = new StringBuilder(); ExposedPort tcpSsh = ExposedPort.tcp(80); Ports portBindings = new Ports(); portBindings.bind(tcpSsh, Ports.Binding.bindPort(port)); - HostConfig hostConfig = HostConfig.newHostConfig() - .withPortBindings(portBindings); + HostConfig hostConfig = + HostConfig.newHostConfig().withPortBindings(portBindings); - CreateContainerResponse container = dockerClient.createContainerCmd("nginx:latest") + CreateContainerResponse container = + dockerClient.createContainerCmd("nginx:latest") .withName(containerName) .withExposedPorts(tcpSsh) .withHostConfig(hostConfig) .exec(); - //dockerClient.startContainerCmd(container.getId()).exec(); + // dockerClient.startContainerCmd(container.getId()).exec(); return container.getId(); } -/* - public String listAllContainers() { - StringBuilder json = new StringBuilder(); - List containers = dockerClient.listContainersCmd() - .withShowAll(true) - .exec(); - - json.append("["); - - for (int i = 0; i < containers.size(); i++) { - Container container = containers.get(i); - - json.append("{"); - json.append("\"name\":\"").append(container.getNames()[0].substring(1)).append("\","); - json.append("\"id\":\"").append(container.getId()).append("\","); - json.append("\"image\":\"").append(container.getImage()).append("\","); - json.append("\"status\":\"").append(container.getStatus()).append("\","); - - // Ports - InspectContainerResponse inspectResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); - json.append("\"ports\":["); -if (container.getPorts() != null && container.getPorts().length > 0) { - for (int j = 0; j < .length; j+=2) { - ContainerPort port = container.getPorts()[j]; - json.append("[\""); - json.append(port.getPrivatePort()).append("->").append(port.getPublicPort()).append("/"+port.getType()+"\",\""); -json.append(port.getIp()).append(",").append((container.getPorts()[j+1]).getIp()); -if (port.getType() != null) { - json.append("/").append(port.getType()); + /* + public String listAllContainers() { + StringBuilder json = new StringBuilder(); + List containers = dockerClient.listContainersCmd() + .withShowAll(true) + .exec(); + + json.append("["); + + for (int i = 0; i < containers.size(); i++) { + Container container = containers.get(i); + + json.append("{"); + json.append("\"name\":\"").append(container.getNames()[0].substring(1)).append("\","); + json.append("\"id\":\"").append(container.getId()).append("\","); + json.append("\"image\":\"").append(container.getImage()).append("\","); + json.append("\"status\":\"").append(container.getStatus()).append("\","); + + // Ports + InspectContainerResponse inspectResponse = + dockerClient.inspectContainerCmd(container.getId()).exec(); + json.append("\"ports\":["); + if (container.getPorts() != null && container.getPorts().length > 0) { + for (int j = 0; j < .length; j+=2) { + ContainerPort port = container.getPorts()[j]; + json.append("[\""); + json.append(port.getPrivatePort()).append("->").append(port.getPublicPort()).append("/"+port.getType()+"\",\""); + json.append(port.getIp()).append(",").append((container.getPorts()[j+1]).getIp()); + if (port.getType() != null) { + json.append("/").append(port.getType()); + } + if (port.getPublicPort() != null) { + json.append("->").append(port.getPublicPort()); + }* + json.append("\"]"); + if (j < container.getPorts().length - 2) { + json.append(","); + } } - if (port.getPublicPort() != null) { - json.append("->").append(port.getPublicPort()); - }* - json.append("\"]"); - if (j < container.getPorts().length - 2) { - json.append(","); + } + json.append("]"); + + // Ports + String ports = "[]"; + try { + InspectContainerResponse inspectResponse = + dockerClient.inspectContainerCmd(container.getId()).exec(); if + (inspectResponse.getConfig().getExposedPorts() != null) { ports = + inspectResponse.getConfig().getExposedPorts().toString(); } + } catch (Exception e) { + // Fallback vers les ports runtime si inspect échoue + if (container.getPorts() != null && container.getPorts().length + > 0) { ports = java.util.Arrays.toString(container.getPorts()); + } + } + json.append("\"ports\":\"").append(ports).append("\""); + json.append("}"); + if (i < containers.size() - 1) { + json.append(","); + } + + json.append("}"); + + if (i < containers.size() - 1) { + json.append(","); + } + } + + json.append("]"); + return json.toString(); + } + public String listAllContainers() { + StringBuilder json = new StringBuilder(); + List containers = dockerClient.listContainersCmd() + .withShowAll(true) + .exec(); + json.append("["); + for (int i = 0; i < containers.size(); i++) { + Container container = containers.get(i); + // Ports + List portsList = new ArrayList<>(); + try { + var inspectResponse = + dockerClient.inspectContainerCmd(container.getId()).exec(); if + (inspectResponse.getConfig().getExposedPorts() != null) { var exposedPorts = + inspectResponse.getConfig().getExposedPorts(); int count = 0; for (var port + : exposedPorts) { if (count > 0) portsList.append(","); + portsList.append(String.format("\"%s\"", + port.toString())); count = 1; + } + portsList.append("]"); + ports = portsList.toString(); + } + } catch (Exception e) { + // Fallback vers les ports runtime si inspect échoue + if (container.getPorts() != null && container.getPorts().length + > 0) { ports = java.util.Arrays.toString(container.getPorts()); + } + } + + //json.append(containerJson); + + if (i < containers.size() - 1) { + json.append(","); } } json.append("]"); - - // Ports - String ports = "[]"; - try { - InspectContainerResponse inspectResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); - if (inspectResponse.getConfig().getExposedPorts() != null) { - ports = inspectResponse.getConfig().getExposedPorts().toString(); - } - } catch (Exception e) { - // Fallback vers les ports runtime si inspect échoue - if (container.getPorts() != null && container.getPorts().length > 0) { - ports = java.util.Arrays.toString(container.getPorts()); - } - } - json.append("\"ports\":\"").append(ports).append("\""); - json.append("}"); - if (i < containers.size() - 1) { - json.append(","); - } - - json.append("}"); - - if (i < containers.size() - 1) { - json.append(","); - } - } - - json.append("]"); - return json.toString(); -} - public String listAllContainers() { - StringBuilder json = new StringBuilder(); - List containers = dockerClient.listContainersCmd() - .withShowAll(true) - .exec(); - json.append("["); - for (int i = 0; i < containers.size(); i++) { - Container container = containers.get(i); - // Ports - List portsList = new ArrayList<>(); - try { - var inspectResponse = dockerClient.inspectContainerCmd(container.getId()).exec(); - if (inspectResponse.getConfig().getExposedPorts() != null) { - var exposedPorts = inspectResponse.getConfig().getExposedPorts(); - int count = 0; - for (var port : exposedPorts) { - if (count > 0) portsList.append(","); - portsList.append(String.format("\"%s\"", port.toString())); - count = 1; - } - portsList.append("]"); - ports = portsList.toString(); - } - } catch (Exception e) { - // Fallback vers les ports runtime si inspect échoue - if (container.getPorts() != null && container.getPorts().length > 0) { - ports = java.util.Arrays.toString(container.getPorts()); - } - } - - //json.append(containerJson); - - if (i < containers.size() - 1) { - json.append(","); - } - } - json.append("]"); - return json.toString(); -}*/ + return json.toString(); + }*/ public String listAllContainers() { return ""; } public void start(String containerId) { dockerClient.startContainerCmd(containerId).exec(); } - + public void stop(String containerId) { dockerClient.stopContainerCmd(containerId).exec(); } diff --git a/src/main/java/fr/la_banquise/backend/services/JiService.java b/src/main/java/fr/la_banquise/backend/services/JiService.java index a956d29..9186ca4 100644 --- a/src/main/java/fr/la_banquise/backend/services/JiService.java +++ b/src/main/java/fr/la_banquise/backend/services/JiService.java @@ -10,15 +10,14 @@ import java.util.List; @ApplicationScoped public class JiService { - - @Inject - JiRepository jiRepository; - @Inject - SiteService siteService; + @Inject JiRepository jiRepository; + + @Inject SiteService siteService; @Transactional - public Ji createJi(String name, String description, String address, String respo, String site_name) { + public Ji createJi(String name, String description, String address, + String respo, String site_name) { Site site = siteService.getSiteByName(site_name); Ji ji = new Ji(name, description, address, respo, site); jiRepository.persist(ji); @@ -26,23 +25,13 @@ public class JiService { return ji; } - /*@Transactional - public List saveAllSites(List sites) { - sites.forEach(site -> siteRepository.persist(site)); - return sites; - }*/ - - public List getAllJi() { - return jiRepository.listAll(); - } + public List getAllJi() { return jiRepository.listAll(); } public Ji getJiByName(String name) { return jiRepository.find("name", name).firstResult(); } - public Ji getJiById(Long id) { - return jiRepository.findById(id); - } + public Ji getJiById(Long id) { return jiRepository.findById(id); } @Transactional public void deleteJi(Long id) { diff --git a/src/main/java/fr/la_banquise/backend/services/SiteService.java b/src/main/java/fr/la_banquise/backend/services/SiteService.java index 0086770..816d277 100644 --- a/src/main/java/fr/la_banquise/backend/services/SiteService.java +++ b/src/main/java/fr/la_banquise/backend/services/SiteService.java @@ -1,7 +1,7 @@ package fr.la_banquise.backend.services; -import fr.la_banquise.backend.data.model.Site; import fr.la_banquise.backend.data.model.Ji; +import fr.la_banquise.backend.data.model.Site; import fr.la_banquise.backend.data.repository.SiteRepository; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @@ -10,9 +10,8 @@ import java.util.List; @ApplicationScoped public class SiteService { - - @Inject - SiteRepository siteRepository; + + @Inject SiteRepository siteRepository; @Transactional public Site createSite(String name, String description, String address) { @@ -27,44 +26,37 @@ public class SiteService { return sites; }*/ - public List getAllSites() { - return siteRepository.listAll(); - } + public List getAllSites() { return siteRepository.listAll(); } public Site getSiteByName(String name) { return siteRepository.find("name", name).firstResult(); } - public Site getSiteById(Long id) { - return siteRepository.findById(id); - } + public Site getSiteById(Long id) { return siteRepository.findById(id); } @Transactional - public void addJi(Site site, Ji ji){ + public void addJi(Site site, Ji ji) { site.jiInSite.add(ji); } @Transactional - public void removeJi(Site site, Ji ji){ + public void removeJi(Site site, Ji ji) { site.jiInSite.remove(ji); } @Transactional public boolean deleteSiteById(Long id) { - if (getSiteById(id).jiInSite.isEmpty()) - { + if (getSiteById(id).jiInSite.isEmpty()) { siteRepository.deleteById(id); return true; } return false; - } @Transactional public boolean deleteSiteByName(String name) { Site site = getSiteByName(name); - if (site.jiInSite.isEmpty()) - { + if (site.jiInSite.isEmpty()) { siteRepository.delete(site); return true; } diff --git a/src/main/java/fr/la_banquise/backend/services/UserService.java b/src/main/java/fr/la_banquise/backend/services/UserService.java index a71e013..10b1f86 100644 --- a/src/main/java/fr/la_banquise/backend/services/UserService.java +++ b/src/main/java/fr/la_banquise/backend/services/UserService.java @@ -1,10 +1,5 @@ package fr.la_banquise.backend.services; -import java.util.ArrayList; -import java.util.List; - -import org.hibernate.annotations.TypeRegistration; - import fr.la_banquise.backend.data.model.Instance; import fr.la_banquise.backend.data.model.User; import fr.la_banquise.backend.data.repository.UserRepository; @@ -14,6 +9,9 @@ import io.quarkus.elytron.security.common.BcryptUtil; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.transaction.Transactional; +import java.util.ArrayList; +import java.util.List; +import org.hibernate.annotations.TypeRegistration; /** * UserService @@ -21,23 +19,19 @@ import jakarta.transaction.Transactional; @ApplicationScoped public class UserService { - @Inject - UserRepository userRepository; + @Inject UserRepository userRepository; - @Inject - InstanceService instanceService; + @Inject InstanceService instanceService; - public List getAllUsers() { - return userRepository.listAll(); - } + public List getAllUsers() { return userRepository.listAll(); } - public User getUser(Long id) { - return userRepository.findById(id); - } + public User getUser(Long id) { return userRepository.findById(id); } @Transactional public User createUser(UserRequest request) { - User user = new User(request.name, BcryptUtil.bcryptHash(request.password), "pingouin", new ArrayList<>()); + User user = + new User(request.name, BcryptUtil.bcryptHash(request.password), + "pingouin", new ArrayList<>()); userRepository.persist(user); return user; } @@ -74,11 +68,10 @@ public class UserService { for (UserRequest user : usersRequest.users) { User newUser = createUser(user); users.add(newUser); - instanceService.createInstance(user.instance_name, user.instance_ssh, user.instance_pwd, user.instance_port, - user.name, - usersRequest.tpId); + instanceService.createInstance( + user.instance_name, user.instance_ssh, user.instance_pwd, + user.instance_port, user.name, usersRequest.tpId); } return new ArrayList(); } - } -- 2.47.2 From 101e5a5ddb65396d925b715ca66ded75f9299224 Mon Sep 17 00:00:00 2001 From: Arthur Wambst Date: Fri, 15 Aug 2025 21:45:59 +0200 Subject: [PATCH 13/28] pleins de trucs --- .../backend/data/model/Instance.java | 2 ++ .../fr/la_banquise/backend/data/model/Ji.java | 7 +++-- .../la_banquise/backend/data/model/Site.java | 5 +++- .../fr/la_banquise/backend/data/model/Tp.java | 2 ++ .../la_banquise/backend/data/model/User.java | 2 ++ .../rest/response/PracticalResponse.java | 30 +++++++++++++------ .../backend/services/TpService.java | 10 +++---- src/main/resources/application.properties | 2 +- 8 files changed, 41 insertions(+), 19 deletions(-) diff --git a/src/main/java/fr/la_banquise/backend/data/model/Instance.java b/src/main/java/fr/la_banquise/backend/data/model/Instance.java index bf5b135..d8fec85 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/Instance.java +++ b/src/main/java/fr/la_banquise/backend/data/model/Instance.java @@ -46,4 +46,6 @@ public class Instance { this.user = user; this.tp = tp; } + + public Instance() {} } diff --git a/src/main/java/fr/la_banquise/backend/data/model/Ji.java b/src/main/java/fr/la_banquise/backend/data/model/Ji.java index ac075d8..a9c71d2 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/Ji.java +++ b/src/main/java/fr/la_banquise/backend/data/model/Ji.java @@ -1,6 +1,6 @@ package fr.la_banquise.backend.data.model; -import io.quarkus.hibernate.orm.panache.PanacheEntity; +import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; @@ -9,7 +9,6 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.SequenceGenerator; import jakarta.persistence.Table; -import java.util.List; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; @@ -28,7 +27,7 @@ public class Ji { public String respo; public String date; - @ManyToOne @JoinColumn(name = "site_id") public Site site; + @ManyToOne @JoinColumn(name = "site_id") @JsonIgnore public Site site; public Ji(String name, String description, String respo, String date, Site site) { @@ -38,4 +37,6 @@ public class Ji { this.date = date; this.site = site; } + + public Ji() {} } diff --git a/src/main/java/fr/la_banquise/backend/data/model/Site.java b/src/main/java/fr/la_banquise/backend/data/model/Site.java index f7e5543..0fe3304 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/Site.java +++ b/src/main/java/fr/la_banquise/backend/data/model/Site.java @@ -1,5 +1,6 @@ package fr.la_banquise.backend.data.model; +import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; @@ -30,7 +31,7 @@ public class Site { public String description; public String address; - @OneToMany(mappedBy = "site") public List jiInSite; + @OneToMany(mappedBy = "site") @JsonIgnore public List jiInSite; public Site(String name, String description, String address) { this.name = name; @@ -44,4 +45,6 @@ public class Site { return "Site{id=" + id + ", name='" + name + "', description='" + description + "', address='" + address + "'}"; } + + public Site() {} } diff --git a/src/main/java/fr/la_banquise/backend/data/model/Tp.java b/src/main/java/fr/la_banquise/backend/data/model/Tp.java index 370a23c..f5d4074 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/Tp.java +++ b/src/main/java/fr/la_banquise/backend/data/model/Tp.java @@ -36,4 +36,6 @@ public class Tp { this.respo = respo; this.date = date; } + + public Tp() {} } diff --git a/src/main/java/fr/la_banquise/backend/data/model/User.java b/src/main/java/fr/la_banquise/backend/data/model/User.java index 7c7caa1..0809923 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/User.java +++ b/src/main/java/fr/la_banquise/backend/data/model/User.java @@ -50,4 +50,6 @@ public class User { this.role = role; this.instances = instances; } + + public User() {} } diff --git a/src/main/java/fr/la_banquise/backend/rest/response/PracticalResponse.java b/src/main/java/fr/la_banquise/backend/rest/response/PracticalResponse.java index 762535c..cc2fb67 100644 --- a/src/main/java/fr/la_banquise/backend/rest/response/PracticalResponse.java +++ b/src/main/java/fr/la_banquise/backend/rest/response/PracticalResponse.java @@ -7,7 +7,7 @@ import lombok.AllArgsConstructor; /** * PracticalResponse */ -@AllArgsConstructor +//@AllArgsConstructor @RegisterForReflection public class PracticalResponse { public String name; @@ -16,12 +16,24 @@ public class PracticalResponse { public String respo; public String endDate; - @Nullable - public String instanceName; - @Nullable - public String pwd; - @Nullable - public String ssh; - @Nullable - public Long port; + @Nullable public String instanceName; + @Nullable public String pwd; + @Nullable public String ssh; + @Nullable public Long port; + + public PracticalResponse(String name, String description, String pdfLink, + String respo, String date, + @Nullable String InstanceName, + @Nullable String pwd, @Nullable String ssh, + @Nullable Long port) { + this.name = name; + this.endDate = date; + this.description = description; + this.pdfLink = pdfLink; + this.respo = respo; + this.instanceName = InstanceName; + this.port = port; + this.ssh = ssh; + this.pwd = pwd; + } } diff --git a/src/main/java/fr/la_banquise/backend/services/TpService.java b/src/main/java/fr/la_banquise/backend/services/TpService.java index 64a46c3..6fadefc 100644 --- a/src/main/java/fr/la_banquise/backend/services/TpService.java +++ b/src/main/java/fr/la_banquise/backend/services/TpService.java @@ -55,19 +55,19 @@ public class TpService { return res; } - public PracticalResponse getTpAdmin(Long id) { + /* public PracticalResponse getTpAdmin(Long id) { Tp tp = tpRepository.findById(id); - return new PracticalResponse(tp.name, tp.description, tp.pdfLink, tp.respo, tp.date, + return new PracticalResponse(tp.name, tp.description, tp.pdfLink, tp.respo, "", "", "", 0L); - } + }*/ - @Transactional + /*@Transactional public Tp createTp(TpRequest requestTp) { Tp tp = new Tp(requestTp.title, requestTp.description, requestTp.pdf, security.getUserPrincipal().getName(), requestTp.date); tpRepository.persist(tp); return tp; - } + }*/ @Transactional public void deleteTp(Long id) { diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 03c87e8..8136c5b 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -28,7 +28,7 @@ quarkus.security.ldap.identity-mapping.attribute-mappings."0".filter-base-dn=ou= quarkus.datasource.db-kind = postgresql quarkus.datasource.username = banq quarkus.datasource.password = test -quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:5432/quarkus +#quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:5432/quarkus # drop and create the database at startup (use `update` to only update the schema)drop-and-create #quarkus.hibernate-orm.database.generation=update -- 2.47.2 From 97ee77a8a676172c189b841c253dac3d29139483 Mon Sep 17 00:00:00 2001 From: Arthur Wambst Date: Sat, 16 Aug 2025 04:52:22 +0200 Subject: [PATCH 14/28] nix shell: source ~/.bashrc --- shell.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/shell.nix b/shell.nix index 842ab5d..15a8a5b 100644 --- a/shell.nix +++ b/shell.nix @@ -17,6 +17,7 @@ pkgs.mkShell { DOCKER_BUILDKIT = "1"; shellHook = '' + source ~/.bashrc echo "Quarkus dev environment ready!" echo "Java: $(java -version 2>&1 | head -n 1)" export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock -- 2.47.2 From 31cb26e54cb416407900c9747c17dd2a8a95ec82 Mon Sep 17 00:00:00 2001 From: Arthur Wambst Date: Tue, 19 Aug 2025 00:46:22 +0200 Subject: [PATCH 15/28] a lot of changes again --- .../backend/data/model/Container.java | 72 +++++++ .../backend/data/model/Instance.java | 19 +- .../fr/la_banquise/backend/data/model/Ji.java | 18 +- .../la_banquise/backend/data/model/Site.java | 2 +- .../data/model/{Tp.java => Sujet.java} | 29 +-- .../la_banquise/backend/data/model/User.java | 11 +- .../data/repository/ContainerRepository.java | 12 ++ ...TpRepository.java => SujetRepository.java} | 4 +- .../la_banquise/backend/rest/Endpoints.java | 8 +- .../la_banquise/backend/rest/JiResource.java | 4 +- .../backend/rest/SujetEndpoints.java | 45 +++++ .../la_banquise/backend/rest/TpEndpoints.java | 56 ------ .../backend/rest/UserEndpoints.java | 4 +- .../{TpRequest.java => SujetRequest.java} | 2 +- .../rest/response/DashboardResponse.java | 4 +- .../rest/response/LoggedUserResponse.java | 3 +- .../rest/response/PracticalResponse.java | 11 +- .../backend/services/ContainerService.java | 181 ++++++++++++++++++ .../backend/services/InstanceService.java | 30 ++- .../backend/services/JiService.java | 20 +- .../backend/services/SujetService.java | 81 ++++++++ .../backend/services/TpService.java | 82 -------- .../backend/services/UserService.java | 2 +- src/main/resources/application.properties | 2 +- 24 files changed, 491 insertions(+), 211 deletions(-) create mode 100644 src/main/java/fr/la_banquise/backend/data/model/Container.java rename src/main/java/fr/la_banquise/backend/data/model/{Tp.java => Sujet.java} (52%) create mode 100644 src/main/java/fr/la_banquise/backend/data/repository/ContainerRepository.java rename src/main/java/fr/la_banquise/backend/data/repository/{TpRepository.java => SujetRepository.java} (63%) create mode 100644 src/main/java/fr/la_banquise/backend/rest/SujetEndpoints.java delete mode 100644 src/main/java/fr/la_banquise/backend/rest/TpEndpoints.java rename src/main/java/fr/la_banquise/backend/rest/request/{TpRequest.java => SujetRequest.java} (90%) create mode 100644 src/main/java/fr/la_banquise/backend/services/ContainerService.java create mode 100644 src/main/java/fr/la_banquise/backend/services/SujetService.java delete mode 100644 src/main/java/fr/la_banquise/backend/services/TpService.java diff --git a/src/main/java/fr/la_banquise/backend/data/model/Container.java b/src/main/java/fr/la_banquise/backend/data/model/Container.java new file mode 100644 index 0000000..b84dbb0 --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/data/model/Container.java @@ -0,0 +1,72 @@ +/**package fr.la_banquise.backend.data.model; + +import com.fasterxml.jackson.annotation.JsonBackReference; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.github.dockerjava.api.DockerClient; +import com.github.dockerjava.api.command.CreateContainerResponse; +import com.github.dockerjava.api.command.InspectContainerResponse.ContainerState; +import com.github.dockerjava.api.model.ExposedPort; +import com.github.dockerjava.api.model.HostConfig; +import com.github.dockerjava.api.model.Ports; +import jakarta.inject.Inject; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; +import java.util.List; +import lombok.NoArgsConstructor; + +/** + * Instances + +@Entity +@NoArgsConstructor +@Table(name = "dockerfile") +public class Dockerfile { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @SequenceGenerator(name = "DockerfileSeq", + sequenceName = "dockerfile_id_seq", allocationSize = 1, + initialValue = 1) + public Long id; + @Column(unique = true) public String name; + public String text; + + @JsonIgnore + public List instances; + + public Dockerfile(String name, String text) { + this.name = name; + this.text = text; + } + + public Dockerfile() {} + + public boolean isCreated() { return containerId != null && status != null; } + + public boolean createContainer(String containerName, int port) { + ExposedPort tcpSsh = ExposedPort.tcp(80); + + Ports portBindings = new Ports(); + portBindings.bind(tcpSsh, Ports.Binding.bindPort(port)); + + HostConfig hostConfig = + HostConfig.newHostConfig().withPortBindings(portBindings); + + CreateContainerResponse container = + dockerClient.createContainerCmd("nginx:latest") + .withName(containerName) + .withExposedPorts(tcpSsh) + .withHostConfig(hostConfig) + .exec(); + + this.containerId = container.getId(); + + return true; + }; +}**/ diff --git a/src/main/java/fr/la_banquise/backend/data/model/Instance.java b/src/main/java/fr/la_banquise/backend/data/model/Instance.java index d8fec85..47a49ae 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/Instance.java +++ b/src/main/java/fr/la_banquise/backend/data/model/Instance.java @@ -1,6 +1,7 @@ package fr.la_banquise.backend.data.model; import com.fasterxml.jackson.annotation.JsonBackReference; +import com.github.dockerjava.api.model.Container; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; @@ -24,28 +25,22 @@ public class Instance { allocationSize = 1, initialValue = 1) public Long id; public String name; - public String ssh; public Long port; - public String pwd; + public Container container; @JsonBackReference @ManyToOne @JoinColumn(name = "user_id", nullable = false) - public User user; + public User owner; @ManyToOne @JoinColumn(name = "practical_id", nullable = false) - public Tp tp; + public Sujet sujet; - public Instance(String name, String ssh, String pwd, Long port, User user, - Tp tp) { + public Instance(String name, Long port, User user, Sujet sujet) { this.name = name; - this.ssh = ssh; - this.pwd = pwd; this.port = port; - this.user = user; - this.tp = tp; + this.owner = user; + this.sujet = sujet; } - - public Instance() {} } diff --git a/src/main/java/fr/la_banquise/backend/data/model/Ji.java b/src/main/java/fr/la_banquise/backend/data/model/Ji.java index a9c71d2..b296feb 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/Ji.java +++ b/src/main/java/fr/la_banquise/backend/data/model/Ji.java @@ -6,9 +6,12 @@ import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; import jakarta.persistence.ManyToOne; import jakarta.persistence.SequenceGenerator; import jakarta.persistence.Table; +import java.util.List; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; @@ -24,19 +27,24 @@ public class Ji { public Long id; public String name; public String description; - public String respo; + + @ManyToMany + @JoinTable( + name = "ji_user", // Table de liaison + joinColumns = @JoinColumn(name = "ji_id"), + inverseJoinColumns = @JoinColumn(name = "user_id") + ) + public List respos; public String date; @ManyToOne @JoinColumn(name = "site_id") @JsonIgnore public Site site; - public Ji(String name, String description, String respo, String date, + public Ji(String name, String description, List respos, String date, Site site) { this.name = name; this.description = description; - this.respo = respo; + this.respos = respos; this.date = date; this.site = site; } - - public Ji() {} } diff --git a/src/main/java/fr/la_banquise/backend/data/model/Site.java b/src/main/java/fr/la_banquise/backend/data/model/Site.java index 0fe3304..fcb5a8b 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/Site.java +++ b/src/main/java/fr/la_banquise/backend/data/model/Site.java @@ -46,5 +46,5 @@ public class Site { description + "', address='" + address + "'}"; } - public Site() {} + //public Site() {} } diff --git a/src/main/java/fr/la_banquise/backend/data/model/Tp.java b/src/main/java/fr/la_banquise/backend/data/model/Sujet.java similarity index 52% rename from src/main/java/fr/la_banquise/backend/data/model/Tp.java rename to src/main/java/fr/la_banquise/backend/data/model/Sujet.java index f5d4074..be94854 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/Tp.java +++ b/src/main/java/fr/la_banquise/backend/data/model/Sujet.java @@ -1,11 +1,16 @@ package fr.la_banquise.backend.data.model; +import jakarta.persistence.CascadeType; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; import jakarta.persistence.SequenceGenerator; import jakarta.persistence.Table; +import java.util.List; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; @@ -15,27 +20,29 @@ import lombok.NoArgsConstructor; @Entity @NoArgsConstructor @AllArgsConstructor -@Table(name = "tp") -public class Tp { +@Table(name = "Sujet") +public class Sujet { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @SequenceGenerator(name = "TpSeq", sequenceName = "tp_id_seq", + @SequenceGenerator(name = "SujetSeq", sequenceName = "sujet_id_seq", allocationSize = 1, initialValue = 1) public Long id; public String name; public String description; public String pdfLink; - public String respo; - public String date; + @ManyToMany + @JoinTable( + name = "sujet_user", // Table de liaison + joinColumns = @JoinColumn(name = "sujet_id"), + inverseJoinColumns = @JoinColumn(name = "user_id") + ) + public List respos; - public Tp(String name, String description, String pdfLink, String respo, - String date) { + public Sujet(String name, String description, String pdfLink, + List respos) { this.name = name; this.description = description; this.pdfLink = pdfLink; - this.respo = respo; - this.date = date; + this.respos = respos; } - - public Tp() {} } diff --git a/src/main/java/fr/la_banquise/backend/data/model/User.java b/src/main/java/fr/la_banquise/backend/data/model/User.java index 0809923..72aa4af 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/User.java +++ b/src/main/java/fr/la_banquise/backend/data/model/User.java @@ -10,6 +10,7 @@ import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import jakarta.persistence.ManyToMany; import jakarta.persistence.OneToMany; import jakarta.persistence.SequenceGenerator; import jakarta.persistence.Table; @@ -40,9 +41,15 @@ public class User { @Roles public String role; @JsonManagedReference - @OneToMany(mappedBy = "user", cascade = CascadeType.ALL) + @OneToMany(mappedBy = "owner", cascade = CascadeType.ALL) public List instances; + @ManyToMany(mappedBy = "respos", cascade = CascadeType.ALL) + public List sujetRespo; + + @ManyToMany(mappedBy = "respos", cascade = CascadeType.ALL) + public List jiRespo; + public User(String name, String password, String role, List instances) { this.name = name; @@ -51,5 +58,5 @@ public class User { this.instances = instances; } - public User() {} + //public User() {} } diff --git a/src/main/java/fr/la_banquise/backend/data/repository/ContainerRepository.java b/src/main/java/fr/la_banquise/backend/data/repository/ContainerRepository.java new file mode 100644 index 0000000..114fe18 --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/data/repository/ContainerRepository.java @@ -0,0 +1,12 @@ +/**package fr.la_banquise.backend.data.repository; + +import fr.la_banquise.backend.data.model.Container; +import io.quarkus.hibernate.orm.panache.PanacheRepository; +import jakarta.enterprise.context.ApplicationScoped; + +/** + * InstanceRepository + +@ApplicationScoped +public class ContainerRepository implements PanacheRepository { +}*/ diff --git a/src/main/java/fr/la_banquise/backend/data/repository/TpRepository.java b/src/main/java/fr/la_banquise/backend/data/repository/SujetRepository.java similarity index 63% rename from src/main/java/fr/la_banquise/backend/data/repository/TpRepository.java rename to src/main/java/fr/la_banquise/backend/data/repository/SujetRepository.java index 8751766..85aa285 100644 --- a/src/main/java/fr/la_banquise/backend/data/repository/TpRepository.java +++ b/src/main/java/fr/la_banquise/backend/data/repository/SujetRepository.java @@ -1,6 +1,6 @@ package fr.la_banquise.backend.data.repository; -import fr.la_banquise.backend.data.model.Tp; +import fr.la_banquise.backend.data.model.Sujet; import io.quarkus.hibernate.orm.panache.PanacheRepository; import jakarta.enterprise.context.ApplicationScoped; @@ -8,4 +8,4 @@ import jakarta.enterprise.context.ApplicationScoped; * TpRepository */ @ApplicationScoped -public class TpRepository implements PanacheRepository {} +public class SujetRepository implements PanacheRepository {} diff --git a/src/main/java/fr/la_banquise/backend/rest/Endpoints.java b/src/main/java/fr/la_banquise/backend/rest/Endpoints.java index ce4da5f..5107ed9 100644 --- a/src/main/java/fr/la_banquise/backend/rest/Endpoints.java +++ b/src/main/java/fr/la_banquise/backend/rest/Endpoints.java @@ -2,7 +2,7 @@ package fr.la_banquise.backend.rest; import fr.la_banquise.backend.rest.response.DashboardResponse; import fr.la_banquise.backend.services.InstanceService; -import fr.la_banquise.backend.services.TpService; +import fr.la_banquise.backend.services.SujetService; import io.quarkus.security.identity.SecurityIdentity; import jakarta.inject.Inject; import jakarta.ws.rs.GET; @@ -22,7 +22,7 @@ public class Endpoints { InstanceService instanceService; @Inject - TpService tpService; + SujetService sujetService; @GET @Path("dashboard") @@ -30,10 +30,10 @@ public class Endpoints { String username = identity.getPrincipal().getName(); DashboardResponse dashboard = new DashboardResponse(); if (identity.getRoles().contains("root")) { - dashboard.tps = tpService.getAllTpsAdmin(); + dashboard.tps = sujetService.getAllSujetsAdmin(); } else { - dashboard.tps = tpService.getAllTps(identity.getPrincipal().getName()); + dashboard.tps = sujetService.getAllSujetsRespo(identity.getPrincipal().getName()); } dashboard.instances = instanceService.getAllInstances(username); return Response.ok(dashboard).build(); diff --git a/src/main/java/fr/la_banquise/backend/rest/JiResource.java b/src/main/java/fr/la_banquise/backend/rest/JiResource.java index b0357d8..39aba73 100644 --- a/src/main/java/fr/la_banquise/backend/rest/JiResource.java +++ b/src/main/java/fr/la_banquise/backend/rest/JiResource.java @@ -27,7 +27,7 @@ public class JiResource { @Produces(MediaType.APPLICATION_JSON) public Response listall() { try { - List ji = jiService.getAllJi(); + List ji = jiService.getAllJiAdmin(); return Response.ok(ji).build(); } catch (Exception e) { return Response.status(500) @@ -45,7 +45,7 @@ public class JiResource { @QueryParam("respo") String respo, @QueryParam("site") String name_site) { try { - Ji jsp = jiService.createJi(name, desc, address, respo, name_site); + Ji jsp = jiService.createJi(name, desc, address, name_site); return Response.ok(Map.of("created", jsp)).build(); } catch (Exception e) { return Response.status(500) diff --git a/src/main/java/fr/la_banquise/backend/rest/SujetEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/SujetEndpoints.java new file mode 100644 index 0000000..65ffeaa --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/rest/SujetEndpoints.java @@ -0,0 +1,45 @@ +package fr.la_banquise.backend.rest; + +import fr.la_banquise.backend.rest.request.SujetRequest; +import fr.la_banquise.backend.services.SujetService; +import io.quarkus.security.identity.SecurityIdentity; +import jakarta.annotation.security.RolesAllowed; +import jakarta.inject.Inject; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; + +/** + * TpEndpoints + */ +@Path("/api/subject") +public class SujetEndpoints { + + @Inject SecurityIdentity identity; + + @Inject SujetService sujetService; + + @GET + @Produces(MediaType.APPLICATION_JSON) + public Response getAllSujetsRespo() { + if (identity.getRoles().contains("root")) { + return Response.ok(sujetService.getAllSujetsAdmin()).build(); + } + return Response + .ok(sujetService.getAllSujetsRespo( + identity.getPrincipal().getName())) + .build(); + } + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @RolesAllowed("root") + public Response createSujet(SujetRequest sujet) { + return Response.ok(sujetService.createSujet(sujet)).build(); + } +} diff --git a/src/main/java/fr/la_banquise/backend/rest/TpEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/TpEndpoints.java deleted file mode 100644 index edd058f..0000000 --- a/src/main/java/fr/la_banquise/backend/rest/TpEndpoints.java +++ /dev/null @@ -1,56 +0,0 @@ -package fr.la_banquise.backend.rest; - -import fr.la_banquise.backend.services.TpService; -import io.quarkus.security.identity.SecurityIdentity; -import fr.la_banquise.backend.rest.request.TpRequest; -import jakarta.annotation.security.RolesAllowed; -import jakarta.inject.Inject; -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; - -/** - * TpEndpoints - */ -@Path("/api/tps") -public class TpEndpoints { - - @Inject - SecurityIdentity identity; - - @Inject - TpService tpService; - - @GET - @Produces(MediaType.APPLICATION_JSON) - public Response getAllTps() { - if (identity.getRoles().contains("root")) { - return Response.ok(tpService.getAllTpsAdmin()).build(); - } - return Response.ok(tpService.getAllTps(identity.getPrincipal().getName())).build(); - } - - @GET - @Produces(MediaType.APPLICATION_JSON) - @Path("{id}") - public Response getTp(@PathParam("id") Long id) { - if (identity.getRoles().contains("root")) { - return Response.ok(tpService.getTpAdmin(id)).build(); - } - return Response.ok(tpService.getTp(id, identity.getPrincipal().getName())).build(); - } - - @POST - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - @RolesAllowed("root") - public Response createTp(TpRequest tp) { - System.out.println(tp.date); - return Response.ok(tpService.createTp(tp)).build(); - } -} diff --git a/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java index 076d591..b02f2dc 100644 --- a/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java +++ b/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java @@ -36,7 +36,7 @@ public class UserEndpoints { } @GET - @RolesAllowed("root") + //@RolesAllowed("root") public Response getAllUsers() { return Response.ok(userService.getAllUsers()).build(); } @@ -49,7 +49,7 @@ public class UserEndpoints { } @POST - @RolesAllowed("root") + //@RolesAllowed("root") public Response createUser(UserRequest user) { return Response.ok(userService.createUser(user)).build(); } diff --git a/src/main/java/fr/la_banquise/backend/rest/request/TpRequest.java b/src/main/java/fr/la_banquise/backend/rest/request/SujetRequest.java similarity index 90% rename from src/main/java/fr/la_banquise/backend/rest/request/TpRequest.java rename to src/main/java/fr/la_banquise/backend/rest/request/SujetRequest.java index e886261..5353f9d 100644 --- a/src/main/java/fr/la_banquise/backend/rest/request/TpRequest.java +++ b/src/main/java/fr/la_banquise/backend/rest/request/SujetRequest.java @@ -3,7 +3,7 @@ package fr.la_banquise.backend.rest.request; /** * TpRequest */ -public class TpRequest { +public class SujetRequest { public String title; public String description; public String pdf; diff --git a/src/main/java/fr/la_banquise/backend/rest/response/DashboardResponse.java b/src/main/java/fr/la_banquise/backend/rest/response/DashboardResponse.java index 23c500b..fcc3fde 100644 --- a/src/main/java/fr/la_banquise/backend/rest/response/DashboardResponse.java +++ b/src/main/java/fr/la_banquise/backend/rest/response/DashboardResponse.java @@ -3,7 +3,7 @@ package fr.la_banquise.backend.rest.response; import java.util.List; import fr.la_banquise.backend.data.model.Instance; -import fr.la_banquise.backend.data.model.Tp; +import fr.la_banquise.backend.data.model.Sujet; import io.quarkus.runtime.annotations.RegisterForReflection; import lombok.AllArgsConstructor; @@ -12,6 +12,6 @@ import lombok.AllArgsConstructor; */ @RegisterForReflection public class DashboardResponse { - public List tps; + public List tps; public List instances; } diff --git a/src/main/java/fr/la_banquise/backend/rest/response/LoggedUserResponse.java b/src/main/java/fr/la_banquise/backend/rest/response/LoggedUserResponse.java index cccf399..71e8297 100644 --- a/src/main/java/fr/la_banquise/backend/rest/response/LoggedUserResponse.java +++ b/src/main/java/fr/la_banquise/backend/rest/response/LoggedUserResponse.java @@ -1,8 +1,7 @@ package fr.la_banquise.backend.rest.response; -import java.util.Set; - import io.quarkus.runtime.annotations.RegisterForReflection; +import java.util.Set; import lombok.AllArgsConstructor; /** diff --git a/src/main/java/fr/la_banquise/backend/rest/response/PracticalResponse.java b/src/main/java/fr/la_banquise/backend/rest/response/PracticalResponse.java index cc2fb67..766804f 100644 --- a/src/main/java/fr/la_banquise/backend/rest/response/PracticalResponse.java +++ b/src/main/java/fr/la_banquise/backend/rest/response/PracticalResponse.java @@ -1,27 +1,28 @@ package fr.la_banquise.backend.rest.response; +import fr.la_banquise.backend.data.model.User; import io.quarkus.runtime.annotations.RegisterForReflection; import io.smallrye.common.constraint.Nullable; +import java.util.List; import lombok.AllArgsConstructor; /** * PracticalResponse */ -//@AllArgsConstructor +@AllArgsConstructor @RegisterForReflection public class PracticalResponse { public String name; public String description; public String pdfLink; - public String respo; - public String endDate; + public List respos; @Nullable public String instanceName; @Nullable public String pwd; @Nullable public String ssh; @Nullable public Long port; - public PracticalResponse(String name, String description, String pdfLink, + /*public PracticalResponse(String name, String description, String pdfLink, String respo, String date, @Nullable String InstanceName, @Nullable String pwd, @Nullable String ssh, @@ -35,5 +36,5 @@ public class PracticalResponse { this.port = port; this.ssh = ssh; this.pwd = pwd; - } + }*/ } diff --git a/src/main/java/fr/la_banquise/backend/services/ContainerService.java b/src/main/java/fr/la_banquise/backend/services/ContainerService.java new file mode 100644 index 0000000..fe98b4c --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/services/ContainerService.java @@ -0,0 +1,181 @@ +/**package fr.la_banquise.backend.services; + +import com.github.dockerjava.api.DockerClient; +import com.github.dockerjava.api.command.CreateContainerResponse; +import com.github.dockerjava.api.command.InspectContainerResponse; +// import com.github.dockerjava.api.model.Container; +import com.github.dockerjava.api.model.ContainerPort; +import com.github.dockerjava.api.model.ExposedPort; +import com.github.dockerjava.api.model.HostConfig; +import com.github.dockerjava.api.model.PortBinding; +import com.github.dockerjava.api.model.Ports; +import fr.la_banquise.backend.data.model.Container; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@ApplicationScoped +public class ContainerService { + + @Inject DockerClient dockerClient; + + public String createAndStartNginx() { + ExposedPort tcp80 = ExposedPort.tcp(80); + + Ports portBindings = new Ports(); + portBindings.bind(tcp80, Ports.Binding.bindPort(8081)); + + HostConfig hostConfig = + HostConfig.newHostConfig().withPortBindings(portBindings); + Map labels = new HashMap<>(); + labels.put("test", "banquise"); + labels.put("environment", "development"); + labels.put("version", "1.0"); + labels.put("created-by", "java-docker-api"); + + CreateContainerResponse container = + dockerClient.createContainerCmd("nginx:latest") + .withName("my-nginx") + .withLabels(labels) + .withExposedPorts(tcp80) + .withHostConfig(hostConfig) + .exec(); + + dockerClient.startContainerCmd(container.getId()).exec(); + return container.getId(); + } + + public Container createContainer() { + Container container = + dockerClient + .createContainerCmd("nginx:latest") + + // dockerClient.startContainerCmd(container.getId()).exec(); + return container.createContainer(); + } + /* + public String listAllContainers() { + StringBuilder json = new StringBuilder(); + List containers = dockerClient.listContainersCmd() + .withShowAll(true) + .exec(); + + json.append("["); + + for (int i = 0; i < containers.size(); i++) { + Container container = containers.get(i); + + json.append("{"); + json.append("\"name\":\"").append(container.getNames()[0].substring(1)).append("\","); + json.append("\"id\":\"").append(container.getId()).append("\","); + json.append("\"image\":\"").append(container.getImage()).append("\","); + json.append("\"status\":\"").append(container.getStatus()).append("\","); + + // Ports + InspectContainerResponse inspectResponse = + dockerClient.inspectContainerCmd(container.getId()).exec(); + json.append("\"ports\":["); + if (container.getPorts() != null && container.getPorts().length > 0) { + for (int j = 0; j < .length; j+=2) { + ContainerPort port = container.getPorts()[j]; + json.append("[\""); + json.append(port.getPrivatePort()).append("->").append(port.getPublicPort()).append("/"+port.getType()+"\",\""); + json.append(port.getIp()).append(",").append((container.getPorts()[j+1]).getIp()); + if (port.getType() != null) { + json.append("/").append(port.getType()); + } + if (port.getPublicPort() != null) { + json.append("->").append(port.getPublicPort()); + }* + json.append("\"]"); + if (j < container.getPorts().length - 2) { + json.append(","); + } + } + } + json.append("]"); + + // Ports + String ports = "[]"; + try { + InspectContainerResponse inspectResponse = + dockerClient.inspectContainerCmd(container.getId()).exec(); if + (inspectResponse.getConfig().getExposedPorts() != null) { ports = + inspectResponse.getConfig().getExposedPorts().toString(); + } + } catch (Exception e) { + // Fallback vers les ports runtime si inspect échoue + if (container.getPorts() != null && container.getPorts().length + > 0) { ports = java.util.Arrays.toString(container.getPorts()); + } + } + json.append("\"ports\":\"").append(ports).append("\""); + json.append("}"); + if (i < containers.size() - 1) { + json.append(","); + } + + json.append("}"); + + if (i < containers.size() - 1) { + json.append(","); + } + } + + json.append("]"); + return json.toString(); + } + public String listAllContainers() { + StringBuilder json = new StringBuilder(); + List containers = dockerClient.listContainersCmd() + .withShowAll(true) + .exec(); + json.append("["); + for (int i = 0; i < containers.size(); i++) { + Container container = containers.get(i); + // Ports + List portsList = new ArrayList<>(); + try { + var inspectResponse = + dockerClient.inspectContainerCmd(container.getId()).exec(); if + (inspectResponse.getConfig().getExposedPorts() != null) { var exposedPorts = + inspectResponse.getConfig().getExposedPorts(); int count = 0; for (var port + : exposedPorts) { if (count > 0) portsList.append(","); + portsList.append(String.format("\"%s\"", + port.toString())); count = 1; + } + portsList.append("]"); + ports = portsList.toString(); + } + } catch (Exception e) { + // Fallback vers les ports runtime si inspect échoue + if (container.getPorts() != null && container.getPorts().length + > 0) { ports = java.util.Arrays.toString(container.getPorts()); + } + } + + //json.append(containerJson); + + if (i < containers.size() - 1) { + json.append(","); + } + } + json.append("]"); + return json.toString(); + }/ + public String listAllContainers() { return ""; } + + public void start(String containerId) { + dockerClient.startContainerCmd(containerId).exec(); + } + + public void stop(String containerId) { + dockerClient.stopContainerCmd(containerId).exec(); + } + + public void remove(String containerId) { + dockerClient.removeContainerCmd(containerId).exec(); + } +}*/ diff --git a/src/main/java/fr/la_banquise/backend/services/InstanceService.java b/src/main/java/fr/la_banquise/backend/services/InstanceService.java index 25a123f..bf31bcf 100644 --- a/src/main/java/fr/la_banquise/backend/services/InstanceService.java +++ b/src/main/java/fr/la_banquise/backend/services/InstanceService.java @@ -1,16 +1,15 @@ package fr.la_banquise.backend.services; -import java.util.List; - import fr.la_banquise.backend.data.model.Instance; -import fr.la_banquise.backend.data.model.Tp; +import fr.la_banquise.backend.data.model.Sujet; import fr.la_banquise.backend.data.model.User; import fr.la_banquise.backend.data.repository.InstanceRepository; -import fr.la_banquise.backend.data.repository.TpRepository; +import fr.la_banquise.backend.data.repository.SujetRepository; import fr.la_banquise.backend.data.repository.UserRepository; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.transaction.Transactional; +import java.util.List; /** * InstanceService @@ -18,14 +17,11 @@ import jakarta.transaction.Transactional; @ApplicationScoped public class InstanceService { - @Inject - InstanceRepository instanceRepository; + @Inject InstanceRepository instanceRepository; - @Inject - UserRepository userRepository; + @Inject UserRepository userRepository; - @Inject - TpRepository tpRepository; + @Inject SujetRepository sujetRepository; public List getAllInstances() { return instanceRepository.findAll().list(); @@ -41,18 +37,20 @@ public class InstanceService { } @Transactional - public Instance createInstance(String name, String ssh, String pwd, Long port, String username, Long tpId) { + public Instance createInstance(String name, String ssh, String pwd, + Long port, String username, Long sujetId) { User user = userRepository.findByName(username); - Tp tp = tpRepository.findById(tpId); - Instance instance = new Instance(name, ssh, pwd, port, user, tp); + Sujet sujet = sujetRepository.findById(sujetId); + Instance instance = new Instance(name, port, user, sujet); instanceRepository.persist(instance); return instance; } @Transactional - public Instance createInstance(String name, String ssh, String pwd, Long port, User user, Long tpId) { - Tp tp = tpRepository.findById(tpId); - Instance instance = new Instance(name, ssh, pwd, port, user, tp); + public Instance createInstance(String name, String ssh, String pwd, + Long port, User user, Long sujetId) { + Sujet sujet = sujetRepository.findById(sujetId); + Instance instance = new Instance(name, port, user, sujet); instanceRepository.persist(instance); return instance; } diff --git a/src/main/java/fr/la_banquise/backend/services/JiService.java b/src/main/java/fr/la_banquise/backend/services/JiService.java index 9186ca4..cb690e7 100644 --- a/src/main/java/fr/la_banquise/backend/services/JiService.java +++ b/src/main/java/fr/la_banquise/backend/services/JiService.java @@ -2,30 +2,42 @@ package fr.la_banquise.backend.services; import fr.la_banquise.backend.data.model.Ji; import fr.la_banquise.backend.data.model.Site; +import fr.la_banquise.backend.data.model.User; import fr.la_banquise.backend.data.repository.JiRepository; +import fr.la_banquise.backend.data.repository.UserRepository; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.transaction.Transactional; +import jakarta.ws.rs.core.SecurityContext; + import java.util.List; @ApplicationScoped public class JiService { @Inject JiRepository jiRepository; - + @Inject UserRepository userRepository; @Inject SiteService siteService; + @Inject SecurityContext security; @Transactional public Ji createJi(String name, String description, String address, - String respo, String site_name) { + String site_name) { Site site = siteService.getSiteByName(site_name); - Ji ji = new Ji(name, description, address, respo, site); + User currentUser = + userRepository.findByName(security.getUserPrincipal().getName()); + Ji ji = new Ji(name, description, List.of(currentUser), "date", site); jiRepository.persist(ji); siteService.addJi(site, ji); return ji; } - public List getAllJi() { return jiRepository.listAll(); } + public List getAllJiAdmin() { return jiRepository.listAll(); } + + public List getAllJiRespo(String username) { + User user = userRepository.findByName(username); + return user.jiRespo; + } public Ji getJiByName(String name) { return jiRepository.find("name", name).firstResult(); diff --git a/src/main/java/fr/la_banquise/backend/services/SujetService.java b/src/main/java/fr/la_banquise/backend/services/SujetService.java new file mode 100644 index 0000000..f5f5ffb --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/services/SujetService.java @@ -0,0 +1,81 @@ +package fr.la_banquise.backend.services; + +import fr.la_banquise.backend.data.model.Instance; +import fr.la_banquise.backend.data.model.Sujet; +import fr.la_banquise.backend.data.model.User; +import fr.la_banquise.backend.data.repository.InstanceRepository; +import fr.la_banquise.backend.data.repository.SujetRepository; +import fr.la_banquise.backend.data.repository.UserRepository; +import fr.la_banquise.backend.rest.request.SujetRequest; +import fr.la_banquise.backend.rest.response.PracticalResponse; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.transaction.Transactional; +import jakarta.ws.rs.core.SecurityContext; +import java.text.Collator; +import java.util.List; +import java.util.stream.Collectors; + +/** + * TpService + */ +@ApplicationScoped +public class SujetService { + + @Inject SecurityContext security; + + @Inject SujetRepository sujetRepository; + + @Inject UserRepository userRepository; + + @Inject InstanceRepository instanceRepository; + + public List getAllSujetsAdmin() { return sujetRepository.listAll(); } + + public List getAllSujetsRespo(String username) { + User user = userRepository.findByName(username); + return user.sujetRespo; + } + + /*public PracticalResponse getTp(Long id, String username) { + User user = userRepository.findByName(username); + Sujet sujet = sujetRepository.findById(id); + Instance instance = + instanceRepository.find("user = ?1 AND tp = ?2", user, sujet) + .firstResult(); + PracticalResponse res = new PracticalResponse( + sujet.name, sujet.description, sujet.pdfLink, sujet.respos, + instance.name, instance.pwd, instance.ssh, instance.port); + return res; + } + + /*public PracticalResponse getTpAdmin(Long id) { + Sujet sujet = sujetRepository.findById(id); + return new PracticalResponse(sujet.name, sujet.description, + sujet.pdfLink, sujet.respos, "", "", "", + 0L); + }*/ + + @Transactional + public Sujet createSujet(SujetRequest requestSujet) { + User currentUser = + userRepository.findByName(security.getUserPrincipal().getName()); + Sujet sujet = new Sujet(requestSujet.title, requestSujet.description, + requestSujet.pdf, List.of(currentUser)); + sujetRepository.persist(sujet); + return sujet; + } + + @Transactional + public void deleteSujet(Long id) { + sujetRepository.deleteById(id); + } + + /* + * TODO: Seuls les respos du sujet et root doivent pouvoir avoir acces + * @Transactional + public Sujet updateSujet(Long id) { + Sujet sujet = sujetRepository.findById(id); + return sujet; + }*/ +} diff --git a/src/main/java/fr/la_banquise/backend/services/TpService.java b/src/main/java/fr/la_banquise/backend/services/TpService.java deleted file mode 100644 index 6fadefc..0000000 --- a/src/main/java/fr/la_banquise/backend/services/TpService.java +++ /dev/null @@ -1,82 +0,0 @@ -package fr.la_banquise.backend.services; - -import java.text.Collator; -import java.util.List; -import java.util.stream.Collectors; - -import fr.la_banquise.backend.data.model.Instance; -import fr.la_banquise.backend.data.model.Tp; -import fr.la_banquise.backend.data.model.User; -import fr.la_banquise.backend.data.repository.InstanceRepository; -import fr.la_banquise.backend.data.repository.TpRepository; -import fr.la_banquise.backend.data.repository.UserRepository; -import fr.la_banquise.backend.rest.request.TpRequest; -import fr.la_banquise.backend.rest.response.PracticalResponse; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; -import jakarta.transaction.Transactional; -import jakarta.ws.rs.core.SecurityContext; - -/** - * TpService - */ -@ApplicationScoped -public class TpService { - - @Inject - SecurityContext security; - - @Inject - TpRepository tpRepository; - - @Inject - UserRepository userRepository; - - @Inject - InstanceRepository instanceRepository; - - public List getAllTpsAdmin() { - return tpRepository.listAll(); - } - - public List getAllTps(String username) { - User user = userRepository.findByName(username); - List instances = instanceRepository.find("user = ?1 AND tp IS NOT NULL", user).list(); - return tpRepository.find("id in ?1", instances.stream().map(i -> i.tp.id).collect(Collectors.toList())).list(); - } - - public PracticalResponse getTp(Long id, String username) { - User user = userRepository.findByName(username); - Tp tp = tpRepository.findById(id); - Instance instance = instanceRepository.find("user = ?1 AND tp = ?2", user, tp).firstResult(); - PracticalResponse res = new PracticalResponse(tp.name, tp.description, tp.pdfLink, tp.respo, tp.date, - instance.name, - instance.pwd, instance.ssh, instance.port); - return res; - } - - /* public PracticalResponse getTpAdmin(Long id) { - Tp tp = tpRepository.findById(id); - return new PracticalResponse(tp.name, tp.description, tp.pdfLink, tp.respo, - "", - "", "", 0L); - }*/ - - /*@Transactional - public Tp createTp(TpRequest requestTp) { - Tp tp = new Tp(requestTp.title, requestTp.description, requestTp.pdf, security.getUserPrincipal().getName(), requestTp.date); - tpRepository.persist(tp); - return tp; - }*/ - - @Transactional - public void deleteTp(Long id) { - tpRepository.deleteById(id); - } - - @Transactional - public Tp updateTp(Long id) { - Tp tp = tpRepository.findById(id); - return tp; - } -} diff --git a/src/main/java/fr/la_banquise/backend/services/UserService.java b/src/main/java/fr/la_banquise/backend/services/UserService.java index 10b1f86..cda51e1 100644 --- a/src/main/java/fr/la_banquise/backend/services/UserService.java +++ b/src/main/java/fr/la_banquise/backend/services/UserService.java @@ -58,7 +58,7 @@ public class UserService { public void deleteJDMI() { for (Instance instance : instanceService.getAllInstances()) { instanceService.deleteInstance(instance.id); - userRepository.deleteById(instance.user.id); + userRepository.deleteById(instance.owner.id); } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 8136c5b..9a7b0bb 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -38,4 +38,4 @@ quarkus.quinoa.dev-server.port=5173 quarkus.quinoa.enable-spa-routing=true quarkus.docker.docker-host=unix:///run/user/1000/docker.sock -quarkus.security.auth.enabled-in-dev-mode=false +#quarkus.security.auth.enabled-in-dev-mode=false -- 2.47.2 From af57fa5ac7fe26cb892bfff92aab09f1b28b2757 Mon Sep 17 00:00:00 2001 From: Arthur Wambst Date: Tue, 19 Aug 2025 22:39:27 +0200 Subject: [PATCH 16/28] auth + cleaning --- .../backend/rest/SiteEndpoints.java | 47 ++----------------- .../backend/rest/SujetEndpoints.java | 2 + .../backend/rest/UserEndpoints.java | 16 +++++-- .../rest/response/LoggedUserResponse.java | 7 ++- .../backend/services/UserService.java | 4 +- src/main/resources/application.properties | 2 + src/main/resources/import-dev.sql | 2 + 7 files changed, 29 insertions(+), 51 deletions(-) create mode 100644 src/main/resources/import-dev.sql diff --git a/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java index 6995685..0f9ed58 100644 --- a/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java +++ b/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java @@ -2,6 +2,7 @@ package fr.la_banquise.backend.rest; import fr.la_banquise.backend.data.model.Site; import fr.la_banquise.backend.services.SiteService; +import io.quarkus.security.Authenticated; import io.quarkus.security.identity.SecurityIdentity; import jakarta.annotation.security.RolesAllowed; import jakarta.inject.Inject; @@ -28,6 +29,7 @@ public class SiteEndpoints { @GET @Path("/listall") @Produces(MediaType.APPLICATION_JSON) + @RolesAllowed("root") public Response listall() { try { List sites = siteService.getAllSites(); @@ -58,6 +60,7 @@ public class SiteEndpoints { @GET @Path("/getbyname") @Produces(MediaType.APPLICATION_JSON) + @Authenticated public Response getSiteByName(@QueryParam("name") String name) { try { Site site = siteService.getSiteByName(name); @@ -103,48 +106,4 @@ public class SiteEndpoints { .build(); } } - /* - @GET - @Path("/all") - public Response listContainers() { - try { - String id = dockerService.listAllContainers(); - return Response.ok(id).build(); - } catch (Exception e) { - return Response.status(500).entity(Map.of("error", - e.getMessage())).build(); - } - } - - @POST - @Path("/start") - public Response start(@QueryParam("id") String id) { - try { - dockerService.start(id); - return Response.ok(Map.of("containerId", id, "status", - "Running")).build(); } catch (Exception e) { return - Response.status(500).entity(Map.of("error", e.getMessage())).build(); - } - } - - @POST - @Path("/stop") - public Response stop(@QueryParam("id") String id) { - try { - dockerService.stop(id); - return Response.ok(Map.of("containerId", id, "status", - "removed")).build(); } catch (Exception e) { return - Response.status(500).entity(Map.of("error", e.getMessage())).build(); - } - } - @DELETE - @Path("/remove") - public Response remove(@QueryParam("id") String id) { - try { - dockerService.remove(id); - return Response.ok(Map.of("containerId", id, "status", - "removed")).build(); } catch (Exception e) { return - Response.status(500).entity(Map.of("error", e.getMessage())).build(); - } - }*/ } diff --git a/src/main/java/fr/la_banquise/backend/rest/SujetEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/SujetEndpoints.java index 65ffeaa..910d310 100644 --- a/src/main/java/fr/la_banquise/backend/rest/SujetEndpoints.java +++ b/src/main/java/fr/la_banquise/backend/rest/SujetEndpoints.java @@ -2,6 +2,7 @@ package fr.la_banquise.backend.rest; import fr.la_banquise.backend.rest.request.SujetRequest; import fr.la_banquise.backend.services.SujetService; +import io.quarkus.security.Authenticated; import io.quarkus.security.identity.SecurityIdentity; import jakarta.annotation.security.RolesAllowed; import jakarta.inject.Inject; @@ -25,6 +26,7 @@ public class SujetEndpoints { @GET @Produces(MediaType.APPLICATION_JSON) + @Authenticated public Response getAllSujetsRespo() { if (identity.getRoles().contains("root")) { return Response.ok(sujetService.getAllSujetsAdmin()).build(); diff --git a/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java index b02f2dc..d24f810 100644 --- a/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java +++ b/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java @@ -4,6 +4,7 @@ import fr.la_banquise.backend.rest.request.BulkUserRequest; import fr.la_banquise.backend.rest.request.UserRequest; import fr.la_banquise.backend.rest.response.LoggedUserResponse; import fr.la_banquise.backend.services.UserService; +import io.quarkus.security.Authenticated; import io.quarkus.security.identity.SecurityIdentity; import jakarta.annotation.security.RolesAllowed; import jakarta.inject.Inject; @@ -29,14 +30,21 @@ public class UserEndpoints { @GET @Path("/me") + @Authenticated public Response getCurrentUser() { + System.out.println("=== DEBUG /me endpoint ==="); + System.out.println("Identity: " + identity); + System.out.println("Principal: " + identity.getPrincipal()); + System.out.println("Principal name: " + + identity.getPrincipal().getName()); + System.out.println("Roles: " + identity.getRoles()); LoggedUserResponse user = new LoggedUserResponse( identity.getPrincipal().getName(), identity.getRoles()); return Response.ok(user).build(); } @GET - //@RolesAllowed("root") + @RolesAllowed("root") public Response getAllUsers() { return Response.ok(userService.getAllUsers()).build(); } @@ -49,12 +57,12 @@ public class UserEndpoints { } @POST - //@RolesAllowed("root") + @RolesAllowed("root") public Response createUser(UserRequest user) { return Response.ok(userService.createUser(user)).build(); } - @POST + /*@POST @RolesAllowed("root") @Path("/jdmi") public Response createJdmiUsers(BulkUserRequest users) { @@ -67,7 +75,7 @@ public class UserEndpoints { public Response deleteJDMI() { userService.deleteJDMI(); return Response.ok().build(); - } + }*/ @DELETE @RolesAllowed("root") diff --git a/src/main/java/fr/la_banquise/backend/rest/response/LoggedUserResponse.java b/src/main/java/fr/la_banquise/backend/rest/response/LoggedUserResponse.java index 71e8297..aad3ee9 100644 --- a/src/main/java/fr/la_banquise/backend/rest/response/LoggedUserResponse.java +++ b/src/main/java/fr/la_banquise/backend/rest/response/LoggedUserResponse.java @@ -7,9 +7,14 @@ import lombok.AllArgsConstructor; /** * LoggedUserResponse */ -@AllArgsConstructor +//@AllArgsConstructor @RegisterForReflection public class LoggedUserResponse { public String username; public Set roles; + + public LoggedUserResponse(String username, Set roles) { + this.username = username; + this.roles = roles; + } } diff --git a/src/main/java/fr/la_banquise/backend/services/UserService.java b/src/main/java/fr/la_banquise/backend/services/UserService.java index cda51e1..ea40357 100644 --- a/src/main/java/fr/la_banquise/backend/services/UserService.java +++ b/src/main/java/fr/la_banquise/backend/services/UserService.java @@ -54,7 +54,7 @@ public class UserService { } } - @Transactional + /*@Transactional public void deleteJDMI() { for (Instance instance : instanceService.getAllInstances()) { instanceService.deleteInstance(instance.id); @@ -73,5 +73,5 @@ public class UserService { user.instance_port, user.name, usersRequest.tpId); } return new ArrayList(); - } + }*/ } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 9a7b0bb..f908816 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -39,3 +39,5 @@ quarkus.quinoa.enable-spa-routing=true quarkus.docker.docker-host=unix:///run/user/1000/docker.sock #quarkus.security.auth.enabled-in-dev-mode=false + +quarkus.hibernate-orm.sql-load-script=import-dev.sql diff --git a/src/main/resources/import-dev.sql b/src/main/resources/import-dev.sql new file mode 100644 index 0000000..cbe1bb8 --- /dev/null +++ b/src/main/resources/import-dev.sql @@ -0,0 +1,2 @@ +-- Ce fichier est exécuté automatiquement en mode dev +INSERT INTO penguin (name, password, role) VALUES ('root', '$2a$10$lzKAv4aj6s0jtneg0Ikx/eEBb6p.6N6yo7ZF.myqYxEA9MWbMwvNu', 'root'); -- 2.47.2 From f651f417c14e3a22da1d3653db5e15ee2e8919de Mon Sep 17 00:00:00 2001 From: Arthur Wambst Date: Tue, 19 Aug 2025 23:22:46 +0200 Subject: [PATCH 17/28] hints for site --- .../la_banquise/backend/rest/JiResource.java | 1 + .../backend/rest/SiteEndpoints.java | 36 ++++++++++++++++--- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/main/java/fr/la_banquise/backend/rest/JiResource.java b/src/main/java/fr/la_banquise/backend/rest/JiResource.java index 39aba73..3fbb282 100644 --- a/src/main/java/fr/la_banquise/backend/rest/JiResource.java +++ b/src/main/java/fr/la_banquise/backend/rest/JiResource.java @@ -25,6 +25,7 @@ public class JiResource { @GET @Path("/listall") @Produces(MediaType.APPLICATION_JSON) + @RolesAllowed("root") public Response listall() { try { List ji = jiService.getAllJiAdmin(); diff --git a/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java index 0f9ed58..505b397 100644 --- a/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java +++ b/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java @@ -30,7 +30,15 @@ public class SiteEndpoints { @Path("/listall") @Produces(MediaType.APPLICATION_JSON) @RolesAllowed("root") - public Response listall() { + @Operation(summary = "Lists all existing sites", + description = "Lists all sites. Root role required.") + @APIResponses({ + @APIResponse(responseCode = "200", description = "Successfull") + , @APIResponse(responseCode = "500", + description = "Internal server error") + }) + public Response + listall() { try { List sites = siteService.getAllSites(); return Response.ok(sites).build(); @@ -44,9 +52,18 @@ public class SiteEndpoints { @POST @Path("/create") @RolesAllowed("root") - public Response createSite(@QueryParam("name") String name, - @QueryParam("desc") String desc, - @QueryParam("address") String address) { + @Operation(summary = "Creates a site", + description = "Creates a site if no name is not a duplicate.") + @APIResponses({ + @APIResponse(responseCode = "200", description = "Successfully created") + , @APIResponse( + responseCode = "500", + description = + "Internal server error, usually site name already taken") + }) + public Response + createSite(@QueryParam("name") String name, @QueryParam("desc") String desc, + @QueryParam("address") String address) { try { String jsp = siteService.createSite(name, desc, address).toString(); return Response.ok(Map.of("created", jsp)).build(); @@ -61,7 +78,16 @@ public class SiteEndpoints { @Path("/getbyname") @Produces(MediaType.APPLICATION_JSON) @Authenticated - public Response getSiteByName(@QueryParam("name") String name) { + @Operation(summary = "Gets a site with its name", description = "") + @APIResponses({ + @APIResponse(responseCode = "200", description = "Site found") + , @APIResponse(responseCode = "500", + description = + "Internal server error, usually site not found") + }) + + public Response + getSiteByName(@QueryParam("name") String name) { try { Site site = siteService.getSiteByName(name); return Response.ok(site.toString()).build(); -- 2.47.2 From d629357af5a389df2096f9cc75fe3d2aefd7243d Mon Sep 17 00:00:00 2001 From: Arthur Wambst Date: Fri, 22 Aug 2025 00:23:47 +0200 Subject: [PATCH 18/28] fix: wrong field search when searching for owner of an instance --- .../java/fr/la_banquise/backend/rest/UserEndpoints.java | 6 ------ .../fr/la_banquise/backend/services/InstanceService.java | 2 +- .../java/fr/la_banquise/backend/services/UserService.java | 2 +- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java index d24f810..8971d53 100644 --- a/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java +++ b/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java @@ -32,12 +32,6 @@ public class UserEndpoints { @Path("/me") @Authenticated public Response getCurrentUser() { - System.out.println("=== DEBUG /me endpoint ==="); - System.out.println("Identity: " + identity); - System.out.println("Principal: " + identity.getPrincipal()); - System.out.println("Principal name: " + - identity.getPrincipal().getName()); - System.out.println("Roles: " + identity.getRoles()); LoggedUserResponse user = new LoggedUserResponse( identity.getPrincipal().getName(), identity.getRoles()); return Response.ok(user).build(); diff --git a/src/main/java/fr/la_banquise/backend/services/InstanceService.java b/src/main/java/fr/la_banquise/backend/services/InstanceService.java index bf31bcf..608ec15 100644 --- a/src/main/java/fr/la_banquise/backend/services/InstanceService.java +++ b/src/main/java/fr/la_banquise/backend/services/InstanceService.java @@ -29,7 +29,7 @@ public class InstanceService { public List getAllInstances(String username) { User user = userRepository.findByName(username); - return instanceRepository.find("user", user).list(); + return instanceRepository.find("owner", user).list(); } public Instance getInstance(Long id) { diff --git a/src/main/java/fr/la_banquise/backend/services/UserService.java b/src/main/java/fr/la_banquise/backend/services/UserService.java index ea40357..866c5cb 100644 --- a/src/main/java/fr/la_banquise/backend/services/UserService.java +++ b/src/main/java/fr/la_banquise/backend/services/UserService.java @@ -41,7 +41,7 @@ public class UserService { userRepository.deleteById(id); } - @Transactional + @Transactional // wtf ? this is get user no ? public User updateUser(Long id) { User user = userRepository.findById(id); return user; -- 2.47.2 From 1457c58bb456244c57df8188dcbd00b13f3d9880 Mon Sep 17 00:00:00 2001 From: Arthur Wambst Date: Fri, 22 Aug 2025 00:33:02 +0200 Subject: [PATCH 19/28] simplified subjects creation json --- .../fr/la_banquise/backend/rest/request/SujetRequest.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/fr/la_banquise/backend/rest/request/SujetRequest.java b/src/main/java/fr/la_banquise/backend/rest/request/SujetRequest.java index 5353f9d..5de582a 100644 --- a/src/main/java/fr/la_banquise/backend/rest/request/SujetRequest.java +++ b/src/main/java/fr/la_banquise/backend/rest/request/SujetRequest.java @@ -7,8 +7,4 @@ public class SujetRequest { public String title; public String description; public String pdf; - public Long duration; - public String tools; - public String difficulty; - public String date; } -- 2.47.2 From f135ef17ab8a0c3aa5c0806202fbdbf210753375 Mon Sep 17 00:00:00 2001 From: Arthur Wambst Date: Fri, 22 Aug 2025 01:42:08 +0200 Subject: [PATCH 20/28] fix: user --- src/main/java/fr/la_banquise/backend/data/model/Instance.java | 2 +- src/main/java/fr/la_banquise/backend/data/model/Sujet.java | 4 ++++ src/main/java/fr/la_banquise/backend/data/model/User.java | 4 +--- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/fr/la_banquise/backend/data/model/Instance.java b/src/main/java/fr/la_banquise/backend/data/model/Instance.java index 47a49ae..bc15fe5 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/Instance.java +++ b/src/main/java/fr/la_banquise/backend/data/model/Instance.java @@ -28,7 +28,7 @@ public class Instance { public Long port; public Container container; - @JsonBackReference + //@JsonBackReference @ManyToOne @JoinColumn(name = "user_id", nullable = false) public User owner; diff --git a/src/main/java/fr/la_banquise/backend/data/model/Sujet.java b/src/main/java/fr/la_banquise/backend/data/model/Sujet.java index be94854..d12f7f9 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/Sujet.java +++ b/src/main/java/fr/la_banquise/backend/data/model/Sujet.java @@ -11,6 +11,9 @@ import jakarta.persistence.ManyToMany; import jakarta.persistence.SequenceGenerator; import jakarta.persistence.Table; import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnore; + import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; @@ -36,6 +39,7 @@ public class Sujet { joinColumns = @JoinColumn(name = "sujet_id"), inverseJoinColumns = @JoinColumn(name = "user_id") ) + @JsonIgnore public List respos; public Sujet(String name, String description, String pdfLink, diff --git a/src/main/java/fr/la_banquise/backend/data/model/User.java b/src/main/java/fr/la_banquise/backend/data/model/User.java index 72aa4af..7cb82db 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/User.java +++ b/src/main/java/fr/la_banquise/backend/data/model/User.java @@ -40,7 +40,7 @@ public class User { @Password public String password; @Roles public String role; - @JsonManagedReference + //@JsonManagedReference @OneToMany(mappedBy = "owner", cascade = CascadeType.ALL) public List instances; @@ -57,6 +57,4 @@ public class User { this.role = role; this.instances = instances; } - - //public User() {} } -- 2.47.2 From fb80b381f6a3cb184468599418778ee53b877c9a Mon Sep 17 00:00:00 2001 From: Arthur Wambst Date: Fri, 22 Aug 2025 07:25:13 +0200 Subject: [PATCH 21/28] feat: add and removal of respo on subjects --- .../backend/rest/SujetEndpoints.java | 44 +++++++++++++++++++ .../backend/services/SujetService.java | 25 +++++++++-- 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/src/main/java/fr/la_banquise/backend/rest/SujetEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/SujetEndpoints.java index 910d310..7909288 100644 --- a/src/main/java/fr/la_banquise/backend/rest/SujetEndpoints.java +++ b/src/main/java/fr/la_banquise/backend/rest/SujetEndpoints.java @@ -7,12 +7,15 @@ import io.quarkus.security.identity.SecurityIdentity; import jakarta.annotation.security.RolesAllowed; import jakarta.inject.Inject; import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.DELETE; import jakarta.ws.rs.GET; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; +import java.util.Map; /** * TpEndpoints @@ -25,6 +28,7 @@ public class SujetEndpoints { @Inject SujetService sujetService; @GET + @Path("/all") @Produces(MediaType.APPLICATION_JSON) @Authenticated public Response getAllSujetsRespo() { @@ -44,4 +48,44 @@ public class SujetEndpoints { public Response createSujet(SujetRequest sujet) { return Response.ok(sujetService.createSujet(sujet)).build(); } + + @POST + @Path("/respo") + @Produces(MediaType.APPLICATION_JSON) + @RolesAllowed("root") + public Response addRespoSujet(@QueryParam("name_sujet") String name_sujet, + @QueryParam("name_user") String name_user) { + try { + if (sujetService.addRespo(name_sujet, name_user)) { + return Response.ok("Respo added sucessfully.").build(); + } + return Response.status(404) + .entity("Already respo of this subject") + .build(); + } catch (Exception e) { + return Response.status(500) + .entity(Map.of("error", e.getMessage())) + .build(); + } + } + + @DELETE + @Path("/respo") + @Produces(MediaType.APPLICATION_JSON) + @RolesAllowed("root") + public Response rmRespoSujet(@QueryParam("name_sujet") String name_sujet, + @QueryParam("name_user") String name_user) { + try { + if (sujetService.rmRespo(name_sujet, name_user)) { + return Response.ok("Respo removed sucessfully.").build(); + } + return Response.status(404) + .entity("No corresponding respo not found (already removed ?)") + .build(); + } catch (Exception e) { + return Response.status(500) + .entity(Map.of("error", e.getMessage())) + .build(); + } + } } diff --git a/src/main/java/fr/la_banquise/backend/services/SujetService.java b/src/main/java/fr/la_banquise/backend/services/SujetService.java index f5f5ffb..40324a0 100644 --- a/src/main/java/fr/la_banquise/backend/services/SujetService.java +++ b/src/main/java/fr/la_banquise/backend/services/SujetService.java @@ -1,20 +1,16 @@ package fr.la_banquise.backend.services; -import fr.la_banquise.backend.data.model.Instance; import fr.la_banquise.backend.data.model.Sujet; import fr.la_banquise.backend.data.model.User; import fr.la_banquise.backend.data.repository.InstanceRepository; import fr.la_banquise.backend.data.repository.SujetRepository; import fr.la_banquise.backend.data.repository.UserRepository; import fr.la_banquise.backend.rest.request.SujetRequest; -import fr.la_banquise.backend.rest.response.PracticalResponse; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.transaction.Transactional; import jakarta.ws.rs.core.SecurityContext; -import java.text.Collator; import java.util.List; -import java.util.stream.Collectors; /** * TpService @@ -71,6 +67,27 @@ public class SujetService { sujetRepository.deleteById(id); } + @Transactional + public boolean addRespo(String name_sujet, String name_user) { + User user = userRepository.find("name", name_user).firstResult(); + Sujet sujet = sujetRepository.find("name", name_sujet).firstResult(); + if (!sujet.respos.contains(user)) { + sujet.respos.add(user); + return true; + } + return false; + } + + @Transactional + public boolean rmRespo(String name_sujet, String name_user) { + User user = userRepository.find("name", name_user).firstResult(); + Sujet sujet = sujetRepository.find("name", name_sujet).firstResult(); + if (sujet.respos.contains(user)) { + sujet.respos.remove(user); + return true; + } + return false; + } /* * TODO: Seuls les respos du sujet et root doivent pouvoir avoir acces * @Transactional -- 2.47.2 From de92fbe778ce40866ac886821309c64fbd513fa8 Mon Sep 17 00:00:00 2001 From: Arthur Wambst Date: Fri, 22 Aug 2025 08:24:53 +0200 Subject: [PATCH 22/28] simplified dashboard --- .../fr/la_banquise/backend/rest/Endpoints.java | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/main/java/fr/la_banquise/backend/rest/Endpoints.java b/src/main/java/fr/la_banquise/backend/rest/Endpoints.java index 5107ed9..c6f9a75 100644 --- a/src/main/java/fr/la_banquise/backend/rest/Endpoints.java +++ b/src/main/java/fr/la_banquise/backend/rest/Endpoints.java @@ -15,26 +15,19 @@ import jakarta.ws.rs.core.Response; @Path("api") public class Endpoints { - @Inject - SecurityIdentity identity; + @Inject SecurityIdentity identity; - @Inject - InstanceService instanceService; + @Inject InstanceService instanceService; - @Inject - SujetService sujetService; + @Inject SujetService sujetService; @GET @Path("dashboard") public Response getDashboard() { String username = identity.getPrincipal().getName(); DashboardResponse dashboard = new DashboardResponse(); - if (identity.getRoles().contains("root")) { - dashboard.tps = sujetService.getAllSujetsAdmin(); - } else { - - dashboard.tps = sujetService.getAllSujetsRespo(identity.getPrincipal().getName()); - } + dashboard.tps = + sujetService.getAllSujetsRespo(identity.getPrincipal().getName()); dashboard.instances = instanceService.getAllInstances(username); return Response.ok(dashboard).build(); } -- 2.47.2 From 798a83234132fbbc3083b9d6b934807dc607df94 Mon Sep 17 00:00:00 2001 From: Arthur Wambst Date: Fri, 22 Aug 2025 09:39:33 +0200 Subject: [PATCH 23/28] refactor: path adjustments --- .../backend/rest/SiteEndpoints.java | 11 +++------- .../backend/rest/SujetEndpoints.java | 1 - .../backend/rest/UserEndpoints.java | 21 ++++++++++--------- 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java index 505b397..9e56ce3 100644 --- a/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java +++ b/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java @@ -11,13 +11,11 @@ import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; import org.eclipse.microprofile.openapi.annotations.Operation; -import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; -@Path("/sites") +@Path("/api/sites") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public class SiteEndpoints { @@ -27,7 +25,6 @@ public class SiteEndpoints { @Inject SiteService siteService; @GET - @Path("/listall") @Produces(MediaType.APPLICATION_JSON) @RolesAllowed("root") @Operation(summary = "Lists all existing sites", @@ -50,7 +47,6 @@ public class SiteEndpoints { } @POST - @Path("/create") @RolesAllowed("root") @Operation(summary = "Creates a site", description = "Creates a site if no name is not a duplicate.") @@ -75,7 +71,7 @@ public class SiteEndpoints { } @GET - @Path("/getbyname") + @Path("/{name}") @Produces(MediaType.APPLICATION_JSON) @Authenticated @Operation(summary = "Gets a site with its name", description = "") @@ -87,7 +83,7 @@ public class SiteEndpoints { }) public Response - getSiteByName(@QueryParam("name") String name) { + getSiteByName(@PathParam("name") String name) { try { Site site = siteService.getSiteByName(name); return Response.ok(site.toString()).build(); @@ -99,7 +95,6 @@ public class SiteEndpoints { } @DELETE - @Path("/del") @RolesAllowed("root") @Operation(summary = "Deletes a site", description = diff --git a/src/main/java/fr/la_banquise/backend/rest/SujetEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/SujetEndpoints.java index 7909288..726c2e9 100644 --- a/src/main/java/fr/la_banquise/backend/rest/SujetEndpoints.java +++ b/src/main/java/fr/la_banquise/backend/rest/SujetEndpoints.java @@ -28,7 +28,6 @@ public class SujetEndpoints { @Inject SujetService sujetService; @GET - @Path("/all") @Produces(MediaType.APPLICATION_JSON) @Authenticated public Response getAllSujetsRespo() { diff --git a/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java index 8971d53..39a7050 100644 --- a/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java +++ b/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java @@ -14,6 +14,7 @@ import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; import jakarta.ws.rs.PathParam; import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; @@ -56,25 +57,25 @@ public class UserEndpoints { return Response.ok(userService.createUser(user)).build(); } - /*@POST - @RolesAllowed("root") - @Path("/jdmi") - public Response createJdmiUsers(BulkUserRequest users) { - userService.createJdmiUser(users); + @POST + @RolesAllowed("root") // TODO: respos JI doivent aussi pouvoir faire ca + @Path("/bulk") + public Response createUsersBulk(BulkUserRequest users) { + userService.createUsers(users); return Response.ok().build(); } @DELETE @RolesAllowed("root") - public Response deleteJDMI() { - userService.deleteJDMI(); + @Path("/bulk") + public Response deleteUserBulk() { + userService.deleteUsers(); return Response.ok().build(); - }*/ + } @DELETE @RolesAllowed("root") - @Path("/{id}") - public Response deleteUser(@PathParam("id") Long id) { + public Response deleteUser(@QueryParam("id") Long id) { userService.deleteUser(id); return Response.ok().build(); } -- 2.47.2 From b831d9b66e45af2ab07095d3d69fa465343d6652 Mon Sep 17 00:00:00 2001 From: Arthur Wambst Date: Fri, 22 Aug 2025 11:57:41 +0200 Subject: [PATCH 24/28] bulk user handling basics --- .../backend/rest/UserEndpoints.java | 15 +++-- .../rest/request/BulkUserDelRequest.java | 7 +++ ...rRequest.java => BulkUserPostRequest.java} | 8 +-- .../backend/rest/request/UserDelRequest.java | 5 ++ .../backend/rest/request/UserRequest.java | 7 --- .../rest/response/BulkUserDelResponse.java | 12 ++++ .../rest/response/BulkUserPostResponse.java | 11 ++++ .../backend/services/UserService.java | 58 +++++++++++++------ 8 files changed, 86 insertions(+), 37 deletions(-) create mode 100644 src/main/java/fr/la_banquise/backend/rest/request/BulkUserDelRequest.java rename src/main/java/fr/la_banquise/backend/rest/request/{BulkUserRequest.java => BulkUserPostRequest.java} (50%) create mode 100644 src/main/java/fr/la_banquise/backend/rest/request/UserDelRequest.java create mode 100644 src/main/java/fr/la_banquise/backend/rest/response/BulkUserDelResponse.java create mode 100644 src/main/java/fr/la_banquise/backend/rest/response/BulkUserPostResponse.java diff --git a/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java index 39a7050..2ca6405 100644 --- a/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java +++ b/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java @@ -1,6 +1,7 @@ package fr.la_banquise.backend.rest; -import fr.la_banquise.backend.rest.request.BulkUserRequest; +import fr.la_banquise.backend.rest.request.BulkUserDelRequest; +import fr.la_banquise.backend.rest.request.BulkUserPostRequest; import fr.la_banquise.backend.rest.request.UserRequest; import fr.la_banquise.backend.rest.response.LoggedUserResponse; import fr.la_banquise.backend.services.UserService; @@ -60,16 +61,20 @@ public class UserEndpoints { @POST @RolesAllowed("root") // TODO: respos JI doivent aussi pouvoir faire ca @Path("/bulk") - public Response createUsersBulk(BulkUserRequest users) { - userService.createUsers(users); + // INFO: if response is empty => required associated jiId was not found in + // existing JIs + public Response createUsersBulk(BulkUserPostRequest users) { + userService.createUsers( + users); // TODO: adapter en fonction de la reponse return Response.ok().build(); } @DELETE @RolesAllowed("root") @Path("/bulk") - public Response deleteUserBulk() { - userService.deleteUsers(); + public Response deleteUserBulk(BulkUserDelRequest users) { + userService.deleteUsers( + users); // TODO: adapter en focntion de la reponse return Response.ok().build(); } diff --git a/src/main/java/fr/la_banquise/backend/rest/request/BulkUserDelRequest.java b/src/main/java/fr/la_banquise/backend/rest/request/BulkUserDelRequest.java new file mode 100644 index 0000000..e247b79 --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/rest/request/BulkUserDelRequest.java @@ -0,0 +1,7 @@ +package fr.la_banquise.backend.rest.request; + +import java.util.List; + +public class BulkUserDelRequest { + public List usernames; +} diff --git a/src/main/java/fr/la_banquise/backend/rest/request/BulkUserRequest.java b/src/main/java/fr/la_banquise/backend/rest/request/BulkUserPostRequest.java similarity index 50% rename from src/main/java/fr/la_banquise/backend/rest/request/BulkUserRequest.java rename to src/main/java/fr/la_banquise/backend/rest/request/BulkUserPostRequest.java index cef006b..b179b27 100644 --- a/src/main/java/fr/la_banquise/backend/rest/request/BulkUserRequest.java +++ b/src/main/java/fr/la_banquise/backend/rest/request/BulkUserPostRequest.java @@ -2,11 +2,7 @@ package fr.la_banquise.backend.rest.request; import java.util.List; -/** - * UserRequest - */ -public class BulkUserRequest { +public class BulkUserPostRequest { public List users; - public String password; - public Long tpId; + public Long jiId; } diff --git a/src/main/java/fr/la_banquise/backend/rest/request/UserDelRequest.java b/src/main/java/fr/la_banquise/backend/rest/request/UserDelRequest.java new file mode 100644 index 0000000..e1223b3 --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/rest/request/UserDelRequest.java @@ -0,0 +1,5 @@ +package fr.la_banquise.backend.rest.request; + +public class UserDelRequest { + public String name; +} diff --git a/src/main/java/fr/la_banquise/backend/rest/request/UserRequest.java b/src/main/java/fr/la_banquise/backend/rest/request/UserRequest.java index f73a23e..9c2e690 100644 --- a/src/main/java/fr/la_banquise/backend/rest/request/UserRequest.java +++ b/src/main/java/fr/la_banquise/backend/rest/request/UserRequest.java @@ -1,14 +1,7 @@ package fr.la_banquise.backend.rest.request; -/** - * UserRequest - */ public class UserRequest { public String name; public String email; public String password; - public String instance_name; - public String instance_ssh; - public Long instance_port; - public String instance_pwd; } diff --git a/src/main/java/fr/la_banquise/backend/rest/response/BulkUserDelResponse.java b/src/main/java/fr/la_banquise/backend/rest/response/BulkUserDelResponse.java new file mode 100644 index 0000000..97491f6 --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/rest/response/BulkUserDelResponse.java @@ -0,0 +1,12 @@ +package fr.la_banquise.backend.rest.response; + +import java.util.List; + +import io.quarkus.runtime.annotations.RegisterForReflection; + +@RegisterForReflection +public class BulkUserDelResponse { + public List success_names; + public List failed_names; + public List failed_reasons; +} diff --git a/src/main/java/fr/la_banquise/backend/rest/response/BulkUserPostResponse.java b/src/main/java/fr/la_banquise/backend/rest/response/BulkUserPostResponse.java new file mode 100644 index 0000000..2dda8ec --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/rest/response/BulkUserPostResponse.java @@ -0,0 +1,11 @@ +package fr.la_banquise.backend.rest.response; + +import java.util.List; + +import io.quarkus.runtime.annotations.RegisterForReflection; + +@RegisterForReflection +public class BulkUserPostResponse { + public List success_names; + public List already_created; +} diff --git a/src/main/java/fr/la_banquise/backend/services/UserService.java b/src/main/java/fr/la_banquise/backend/services/UserService.java index 866c5cb..f1aec56 100644 --- a/src/main/java/fr/la_banquise/backend/services/UserService.java +++ b/src/main/java/fr/la_banquise/backend/services/UserService.java @@ -1,17 +1,20 @@ package fr.la_banquise.backend.services; -import fr.la_banquise.backend.data.model.Instance; import fr.la_banquise.backend.data.model.User; +import fr.la_banquise.backend.data.repository.JiRepository; import fr.la_banquise.backend.data.repository.UserRepository; -import fr.la_banquise.backend.rest.request.BulkUserRequest; +import fr.la_banquise.backend.rest.request.BulkUserDelRequest; +import fr.la_banquise.backend.rest.request.BulkUserPostRequest; +import fr.la_banquise.backend.rest.request.UserDelRequest; import fr.la_banquise.backend.rest.request.UserRequest; +import fr.la_banquise.backend.rest.response.BulkUserDelResponse; +import fr.la_banquise.backend.rest.response.BulkUserPostResponse; import io.quarkus.elytron.security.common.BcryptUtil; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.transaction.Transactional; import java.util.ArrayList; import java.util.List; -import org.hibernate.annotations.TypeRegistration; /** * UserService @@ -20,8 +23,8 @@ import org.hibernate.annotations.TypeRegistration; public class UserService { @Inject UserRepository userRepository; - @Inject InstanceService instanceService; + @Inject JiRepository jiRepository; public List getAllUsers() { return userRepository.listAll(); } @@ -54,24 +57,41 @@ public class UserService { } } - /*@Transactional - public void deleteJDMI() { - for (Instance instance : instanceService.getAllInstances()) { - instanceService.deleteInstance(instance.id); - userRepository.deleteById(instance.owner.id); + @Transactional + public BulkUserDelResponse deleteUsers(BulkUserDelRequest request) { + BulkUserDelResponse response = new BulkUserDelResponse(); + User userToDel; + + for (UserDelRequest requestName : request.usernames) { + try { + userToDel = + userRepository.find("name", requestName.name).firstResult(); + userRepository.delete(userToDel); + response.success_names.add(requestName.name); + } catch (Exception e) { + response.failed_names.add(requestName.name); + response.failed_reasons.add(e.toString()); + } } + + return response; } @Transactional - public List createJdmiUser(BulkUserRequest usersRequest) { - List users = new ArrayList<>(); - for (UserRequest user : usersRequest.users) { - User newUser = createUser(user); - users.add(newUser); - instanceService.createInstance( - user.instance_name, user.instance_ssh, user.instance_pwd, - user.instance_port, user.name, usersRequest.tpId); + public BulkUserPostResponse createUsers(BulkUserPostRequest usersRequest) { + BulkUserPostResponse response = new BulkUserPostResponse(); + + if (jiRepository.findById(usersRequest.jiId) != null) { + for (UserRequest user : usersRequest.users) { + try { + createUser(user); + response.success_names.add(user.name); + } catch (Exception e) { + response.already_created.add(user.name); + } + } } - return new ArrayList(); - }*/ + + return response; + } } -- 2.47.2 From 391c43a569a12356fd0ee5a0eb104ad69a3d2028 Mon Sep 17 00:00:00 2001 From: Arthur Wambst Date: Fri, 22 Aug 2025 12:29:52 +0200 Subject: [PATCH 25/28] fix: bulk user missing constructors --- .../backend/rest/response/BulkUserDelResponse.java | 11 +++++++++-- .../backend/rest/response/BulkUserPostResponse.java | 6 ++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/main/java/fr/la_banquise/backend/rest/response/BulkUserDelResponse.java b/src/main/java/fr/la_banquise/backend/rest/response/BulkUserDelResponse.java index 97491f6..cf74ffe 100644 --- a/src/main/java/fr/la_banquise/backend/rest/response/BulkUserDelResponse.java +++ b/src/main/java/fr/la_banquise/backend/rest/response/BulkUserDelResponse.java @@ -1,12 +1,19 @@ package fr.la_banquise.backend.rest.response; -import java.util.List; - import io.quarkus.runtime.annotations.RegisterForReflection; +import java.util.ArrayList; +import java.util.List; + @RegisterForReflection public class BulkUserDelResponse { public List success_names; public List failed_names; public List failed_reasons; + + public BulkUserDelResponse() { + this.success_names = new ArrayList(); + this.failed_names = new ArrayList(); + this.failed_reasons = new ArrayList(); + } } diff --git a/src/main/java/fr/la_banquise/backend/rest/response/BulkUserPostResponse.java b/src/main/java/fr/la_banquise/backend/rest/response/BulkUserPostResponse.java index 2dda8ec..8e02599 100644 --- a/src/main/java/fr/la_banquise/backend/rest/response/BulkUserPostResponse.java +++ b/src/main/java/fr/la_banquise/backend/rest/response/BulkUserPostResponse.java @@ -1,5 +1,6 @@ package fr.la_banquise.backend.rest.response; +import java.util.ArrayList; import java.util.List; import io.quarkus.runtime.annotations.RegisterForReflection; @@ -8,4 +9,9 @@ import io.quarkus.runtime.annotations.RegisterForReflection; public class BulkUserPostResponse { public List success_names; public List already_created; + + public BulkUserPostResponse() { + this.success_names = new ArrayList(); + this.already_created = new ArrayList(); + } } -- 2.47.2 From e290b9314c2cf06c81f4d66bb47ff7fd741c19d7 Mon Sep 17 00:00:00 2001 From: Arthur Wambst Date: Sat, 23 Aug 2025 06:25:55 +0200 Subject: [PATCH 26/28] feat: role operations --- .../backend/data/model/Instance.java | 1 - .../backend/data/model/RolesAsso.java | 20 +++++ .../la_banquise/backend/data/model/User.java | 34 +++++++- .../backend/rest/UserEndpoints.java | 87 ++++++++++++------- .../backend/rest/UsersEndpoints.java | 74 ++++++++++++++++ .../backend/services/ContainerService.java | 6 +- .../backend/services/InstanceService.java | 6 +- .../backend/services/UserService.java | 14 ++- src/main/resources/import-dev.sql | 3 +- 9 files changed, 201 insertions(+), 44 deletions(-) create mode 100644 src/main/java/fr/la_banquise/backend/data/model/RolesAsso.java create mode 100644 src/main/java/fr/la_banquise/backend/rest/UsersEndpoints.java diff --git a/src/main/java/fr/la_banquise/backend/data/model/Instance.java b/src/main/java/fr/la_banquise/backend/data/model/Instance.java index bc15fe5..437a62c 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/Instance.java +++ b/src/main/java/fr/la_banquise/backend/data/model/Instance.java @@ -1,6 +1,5 @@ package fr.la_banquise.backend.data.model; -import com.fasterxml.jackson.annotation.JsonBackReference; import com.github.dockerjava.api.model.Container; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; diff --git a/src/main/java/fr/la_banquise/backend/data/model/RolesAsso.java b/src/main/java/fr/la_banquise/backend/data/model/RolesAsso.java new file mode 100644 index 0000000..ee4d0ac --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/data/model/RolesAsso.java @@ -0,0 +1,20 @@ +package fr.la_banquise.backend.data.model; + +public enum RolesAsso { + ROOT("ROOT"), // ROOT should always be the first + MODO("MODO"), + PINGOUIN("PINGOUIN"), + JI("JI"), + NONE("NONE"); + + private final String roleName; + + RolesAsso(String roleName) { this.roleName = roleName; } + + public String getRoleName() { return roleName; } + + @Override + public String toString() { + return roleName; + } +} diff --git a/src/main/java/fr/la_banquise/backend/data/model/User.java b/src/main/java/fr/la_banquise/backend/data/model/User.java index 7cb82db..03af65a 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/User.java +++ b/src/main/java/fr/la_banquise/backend/data/model/User.java @@ -1,12 +1,17 @@ package fr.la_banquise.backend.data.model; -import com.fasterxml.jackson.annotation.JsonManagedReference; import io.quarkus.security.jpa.Password; import io.quarkus.security.jpa.Roles; +import io.quarkus.security.jpa.RolesValue; import io.quarkus.security.jpa.UserDefinition; import io.quarkus.security.jpa.Username; import jakarta.persistence.CascadeType; +import jakarta.persistence.CollectionTable; +import jakarta.persistence.ElementCollection; import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; @@ -14,7 +19,11 @@ import jakarta.persistence.ManyToMany; import jakarta.persistence.OneToMany; import jakarta.persistence.SequenceGenerator; import jakarta.persistence.Table; +import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @@ -38,7 +47,11 @@ public class User { public Long id; @Username public String name; @Password public String password; - @Roles public String role; + + @Enumerated(EnumType.STRING) + @ElementCollection(fetch = FetchType.EAGER) + @CollectionTable(name = "user_roles") + public Set role; //@JsonManagedReference @OneToMany(mappedBy = "owner", cascade = CascadeType.ALL) @@ -50,11 +63,24 @@ public class User { @ManyToMany(mappedBy = "respos", cascade = CascadeType.ALL) public List jiRespo; - public User(String name, String password, String role, + // Méthode pour Quarkus Security - conversion simple + @RolesValue + @Roles + public Set getRoles() { + return role.stream() + .filter(r -> r != RolesAsso.NONE) + .map(Enum::name) + .collect(Collectors.toSet()); + } + + public User(String name, String password, RolesAsso role, List instances) { this.name = name; this.password = password; - this.role = role; + if (role == RolesAsso.NONE) + this.role = new HashSet<>(); + else + this.role = new HashSet<>(Arrays.asList(role)); this.instances = instances; } } diff --git a/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java index 2ca6405..d9c2d94 100644 --- a/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java +++ b/src/main/java/fr/la_banquise/backend/rest/UserEndpoints.java @@ -1,8 +1,12 @@ package fr.la_banquise.backend.rest; +import fr.la_banquise.backend.data.model.RolesAsso; +import fr.la_banquise.backend.data.model.User; import fr.la_banquise.backend.rest.request.BulkUserDelRequest; import fr.la_banquise.backend.rest.request.BulkUserPostRequest; import fr.la_banquise.backend.rest.request.UserRequest; +import fr.la_banquise.backend.rest.response.BulkUserDelResponse; +import fr.la_banquise.backend.rest.response.BulkUserPostResponse; import fr.la_banquise.backend.rest.response.LoggedUserResponse; import fr.la_banquise.backend.services.UserService; import io.quarkus.security.Authenticated; @@ -18,11 +22,13 @@ import jakarta.ws.rs.Produces; import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; +import java.util.HashMap; +import java.util.Map; /** * UserEndpoints */ -@Path("/api/users") +@Path("/api/user") @Produces(MediaType.APPLICATION_JSON) public class UserEndpoints { @@ -40,46 +46,67 @@ public class UserEndpoints { } @GET - @RolesAllowed("root") - public Response getAllUsers() { - return Response.ok(userService.getAllUsers()).build(); - } - - @GET - @RolesAllowed("root") + @RolesAllowed("ROOT") @Path("{id}") public Response getUser(@PathParam("id") Long id) { return Response.ok(userService.getUser(id)).build(); } + @GET + @RolesAllowed("ROOT") + @Path("{id}/roles") + public Response getRoles(@PathParam("id") Long userId) { + try { + User user = userService.getUser(userId); + return Response.ok(user.role).build(); + } catch (Exception e) { + return Response.status(404) + .entity(Map.of("User or Role not found", e)) + .build(); + } + } + @POST - @RolesAllowed("root") + @RolesAllowed("ROOT") + @Path("{id}/roles") + public Response addRole(@PathParam("id") Long userId, + @QueryParam("role") String role) { + try { + User user = userService.getUser(userId); + user.role.add(userService.fromString(role)); + return Response.ok(user.role).build(); + } catch (Exception e) { + return Response.status(404) + .entity(Map.of("User or Role not found", e)) + .build(); + } + } + + @DELETE + @RolesAllowed("ROOT") + @Path("{id}/roles") + public Response removeRole(@PathParam("id") Long userId, + @QueryParam("role") String role) { + try { + User user = userService.getUser(userId); + user.role.remove(userService.fromString(role)); + return Response.ok(user.role).build(); + } catch (Exception e) { + return Response.status(404) + .entity(Map.of("User or Role not found", e)) + .build(); + } + } + + + @POST + @RolesAllowed("ROOT") public Response createUser(UserRequest user) { return Response.ok(userService.createUser(user)).build(); } - @POST - @RolesAllowed("root") // TODO: respos JI doivent aussi pouvoir faire ca - @Path("/bulk") - // INFO: if response is empty => required associated jiId was not found in - // existing JIs - public Response createUsersBulk(BulkUserPostRequest users) { - userService.createUsers( - users); // TODO: adapter en fonction de la reponse - return Response.ok().build(); - } - @DELETE - @RolesAllowed("root") - @Path("/bulk") - public Response deleteUserBulk(BulkUserDelRequest users) { - userService.deleteUsers( - users); // TODO: adapter en focntion de la reponse - return Response.ok().build(); - } - - @DELETE - @RolesAllowed("root") + @RolesAllowed("ROOT") public Response deleteUser(@QueryParam("id") Long id) { userService.deleteUser(id); return Response.ok().build(); diff --git a/src/main/java/fr/la_banquise/backend/rest/UsersEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/UsersEndpoints.java new file mode 100644 index 0000000..e6fa0f2 --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/rest/UsersEndpoints.java @@ -0,0 +1,74 @@ +package fr.la_banquise.backend.rest; + +import fr.la_banquise.backend.data.model.RolesAsso; +import fr.la_banquise.backend.data.model.User; +import fr.la_banquise.backend.rest.request.BulkUserDelRequest; +import fr.la_banquise.backend.rest.request.BulkUserPostRequest; +import fr.la_banquise.backend.rest.request.UserRequest; +import fr.la_banquise.backend.rest.response.BulkUserDelResponse; +import fr.la_banquise.backend.rest.response.BulkUserPostResponse; +import fr.la_banquise.backend.rest.response.LoggedUserResponse; +import fr.la_banquise.backend.services.UserService; +import io.quarkus.security.Authenticated; +import io.quarkus.security.identity.SecurityIdentity; +import jakarta.annotation.security.RolesAllowed; +import jakarta.inject.Inject; +import jakarta.ws.rs.DELETE; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import java.util.HashMap; +import java.util.Map; + +/** + * UserEndpoints + */ +@Path("/api/users") +@Produces(MediaType.APPLICATION_JSON) +public class UsersEndpoints { + + @Inject SecurityIdentity identity; + + @Inject UserService userService; + + @GET + @RolesAllowed("ROOT") + public Response getAllUsers() { + return Response.ok(userService.getAllUsers()).build(); + } + + @POST + @RolesAllowed("ROOT") // TODO: respos JI doivent aussi pouvoir faire ca + // INFO: if response is empty => required associated jiId was not found in + // existing JIs + public Response createUsersBulk(BulkUserPostRequest users) { + BulkUserPostResponse response = userService.createUsers( + users); + if (response.success_names.size() == users.users.size()) + return Response.ok().build(); + return Response.status(202) + .entity(Map.of("These users were already created : ", + response.already_created)) + .build(); + } + + @DELETE + @RolesAllowed("ROOT") + public Response deleteUserBulk(BulkUserDelRequest users) { + BulkUserDelResponse response = userService.deleteUsers(users); + if (response.success_names.size() == users.usernames.size()) + return Response.ok().build(); + + Map retour = new HashMap(); + for (int id = 0; id < response.failed_names.size(); id++) { + retour.put(response.failed_names.get(id), + response.failed_reasons.get(id)); + } + return Response.status(202).entity(retour).build(); + } +} diff --git a/src/main/java/fr/la_banquise/backend/services/ContainerService.java b/src/main/java/fr/la_banquise/backend/services/ContainerService.java index fe98b4c..3c2565d 100644 --- a/src/main/java/fr/la_banquise/backend/services/ContainerService.java +++ b/src/main/java/fr/la_banquise/backend/services/ContainerService.java @@ -1,15 +1,13 @@ -/**package fr.la_banquise.backend.services; +/*package fr.la_banquise.backend.services; import com.github.dockerjava.api.DockerClient; import com.github.dockerjava.api.command.CreateContainerResponse; import com.github.dockerjava.api.command.InspectContainerResponse; -// import com.github.dockerjava.api.model.Container; import com.github.dockerjava.api.model.ContainerPort; import com.github.dockerjava.api.model.ExposedPort; import com.github.dockerjava.api.model.HostConfig; import com.github.dockerjava.api.model.PortBinding; import com.github.dockerjava.api.model.Ports; -import fr.la_banquise.backend.data.model.Container; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import java.util.HashMap; @@ -47,7 +45,7 @@ public class ContainerService { return container.getId(); } - public Container createContainer() { + /*public Container createContainer() { Container container = dockerClient .createContainerCmd("nginx:latest") diff --git a/src/main/java/fr/la_banquise/backend/services/InstanceService.java b/src/main/java/fr/la_banquise/backend/services/InstanceService.java index 608ec15..7b8cf37 100644 --- a/src/main/java/fr/la_banquise/backend/services/InstanceService.java +++ b/src/main/java/fr/la_banquise/backend/services/InstanceService.java @@ -27,7 +27,7 @@ public class InstanceService { return instanceRepository.findAll().list(); } - public List getAllInstances(String username) { + public List getInstancesByOwner(String username) { User user = userRepository.findByName(username); return instanceRepository.find("owner", user).list(); } @@ -37,8 +37,8 @@ public class InstanceService { } @Transactional - public Instance createInstance(String name, String ssh, String pwd, - Long port, String username, Long sujetId) { + public Instance createInstance(String name, Long port, String username, + Long sujetId) { User user = userRepository.findByName(username); Sujet sujet = sujetRepository.findById(sujetId); Instance instance = new Instance(name, port, user, sujet); diff --git a/src/main/java/fr/la_banquise/backend/services/UserService.java b/src/main/java/fr/la_banquise/backend/services/UserService.java index f1aec56..5da50f1 100644 --- a/src/main/java/fr/la_banquise/backend/services/UserService.java +++ b/src/main/java/fr/la_banquise/backend/services/UserService.java @@ -1,5 +1,6 @@ package fr.la_banquise.backend.services; +import fr.la_banquise.backend.data.model.RolesAsso; import fr.la_banquise.backend.data.model.User; import fr.la_banquise.backend.data.repository.JiRepository; import fr.la_banquise.backend.data.repository.UserRepository; @@ -34,7 +35,7 @@ public class UserService { public User createUser(UserRequest request) { User user = new User(request.name, BcryptUtil.bcryptHash(request.password), - "pingouin", new ArrayList<>()); + RolesAsso.NONE, new ArrayList<>()); userRepository.persist(user); return user; } @@ -93,5 +94,16 @@ public class UserService { } return response; + } + + + public RolesAsso fromString(String role_str) { + return switch (role_str) { + case "ROOT" -> RolesAsso.ROOT; + case "MODO" -> RolesAsso.MODO; + case "PINGOUIN" -> RolesAsso.PINGOUIN; + case "JI" -> RolesAsso.JI; + default -> throw new Error("Wrong role str"); + }; } } diff --git a/src/main/resources/import-dev.sql b/src/main/resources/import-dev.sql index cbe1bb8..ace0c48 100644 --- a/src/main/resources/import-dev.sql +++ b/src/main/resources/import-dev.sql @@ -1,2 +1,3 @@ -- Ce fichier est exécuté automatiquement en mode dev -INSERT INTO penguin (name, password, role) VALUES ('root', '$2a$10$lzKAv4aj6s0jtneg0Ikx/eEBb6p.6N6yo7ZF.myqYxEA9MWbMwvNu', 'root'); +INSERT INTO penguin (name, password) VALUES ('root', '$2a$10$lzKAv4aj6s0jtneg0Ikx/eEBb6p.6N6yo7ZF.myqYxEA9MWbMwvNu'); +INSERT INTO user_roles (User_id, role) VALUES (1, 'ROOT'); -- 2.47.2 From 27332ff809feb3bd98fd7b24ab4f0892e598c15e Mon Sep 17 00:00:00 2001 From: Arthur Wambst Date: Sun, 31 Aug 2025 14:30:49 +0200 Subject: [PATCH 27/28] preparation for docker containers handling --- .../backend/data/model/Instance.java | 26 ++-- .../fr/la_banquise/backend/data/model/Ji.java | 16 ++- .../la_banquise/backend/data/model/Site.java | 6 +- .../la_banquise/backend/data/model/User.java | 6 +- .../la_banquise/backend/rest/Endpoints.java | 2 +- .../backend/rest/InstanceEndpoints.java | 39 ++++-- .../la_banquise/backend/rest/JiResource.java | 9 +- .../backend/rest/SiteEndpoints.java | 4 +- .../backend/rest/SujetEndpoints.java | 4 +- .../backend/rest/request/InstanceRequest.java | 9 +- .../backend/services/InstanceService.java | 132 ++++++++++++++---- .../backend/services/JiService.java | 43 +++++- .../backend/services/UserService.java | 2 +- src/main/resources/application.properties | 2 +- src/main/resources/import-dev.sql | 3 + 15 files changed, 223 insertions(+), 80 deletions(-) diff --git a/src/main/java/fr/la_banquise/backend/data/model/Instance.java b/src/main/java/fr/la_banquise/backend/data/model/Instance.java index 437a62c..18fbb92 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/Instance.java +++ b/src/main/java/fr/la_banquise/backend/data/model/Instance.java @@ -1,6 +1,9 @@ package fr.la_banquise.backend.data.model; -import com.github.dockerjava.api.model.Container; +import java.util.Set; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; @@ -9,6 +12,7 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.SequenceGenerator; import jakarta.persistence.Table; +import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; /** @@ -16,6 +20,7 @@ import lombok.NoArgsConstructor; */ @Entity @NoArgsConstructor +@AllArgsConstructor @Table(name = "instance") public class Instance { @Id @@ -23,23 +28,26 @@ public class Instance { @SequenceGenerator(name = "InstanceSeq", sequenceName = "instance_id_seq", allocationSize = 1, initialValue = 1) public Long id; - public String name; - public Long port; - public Container container; + + @Column(unique = true, nullable = false) + public String name; + // So people cant have more than one + // container per JI because name will be login-jiId + + public int port; //@JsonBackReference + @JsonIgnore @ManyToOne @JoinColumn(name = "user_id", nullable = false) public User owner; - @ManyToOne - @JoinColumn(name = "practical_id", nullable = false) - public Sujet sujet; + //@ManyToOne @JoinColumn(name = "ji_id", nullable = false) public Ji ji; - public Instance(String name, Long port, User user, Sujet sujet) { + public Instance(String name, int port, User user ) {//, Ji ji) { this.name = name; this.port = port; this.owner = user; - this.sujet = sujet; + //this.ji = ji; } } diff --git a/src/main/java/fr/la_banquise/backend/data/model/Ji.java b/src/main/java/fr/la_banquise/backend/data/model/Ji.java index b296feb..852ca12 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/Ji.java +++ b/src/main/java/fr/la_banquise/backend/data/model/Ji.java @@ -9,6 +9,7 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.JoinTable; import jakarta.persistence.ManyToMany; import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; import jakarta.persistence.SequenceGenerator; import jakarta.persistence.Table; import java.util.List; @@ -28,16 +29,19 @@ public class Ji { public String name; public String description; + @JsonIgnore @ManyToMany - @JoinTable( - name = "ji_user", // Table de liaison - joinColumns = @JoinColumn(name = "ji_id"), - inverseJoinColumns = @JoinColumn(name = "user_id") - ) + @JoinTable(name = "ji_respos", // Table de liaison + joinColumns = @JoinColumn(name = "ji_id"), + inverseJoinColumns = @JoinColumn(name = "user_id")) public List respos; public String date; - @ManyToOne @JoinColumn(name = "site_id") @JsonIgnore public Site site; + @ManyToOne + @JoinColumn(name = "site_id") //@JsonIgnore + public Site site; + + @OneToMany @JoinColumn(name = "instance_id") public List instances; public Ji(String name, String description, List respos, String date, Site site) { diff --git a/src/main/java/fr/la_banquise/backend/data/model/Site.java b/src/main/java/fr/la_banquise/backend/data/model/Site.java index fcb5a8b..1e07e46 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/Site.java +++ b/src/main/java/fr/la_banquise/backend/data/model/Site.java @@ -1,6 +1,7 @@ package fr.la_banquise.backend.data.model; import com.fasterxml.jackson.annotation.JsonIgnore; +import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; @@ -31,6 +32,9 @@ public class Site { public String description; public String address; + /*@OneToMany(mappedBy = "ji", cascade = CascadeType.ALL) + public List instances;*/ + @OneToMany(mappedBy = "site") @JsonIgnore public List jiInSite; public Site(String name, String description, String address) { @@ -46,5 +50,5 @@ public class Site { description + "', address='" + address + "'}"; } - //public Site() {} + // public Site() {} } diff --git a/src/main/java/fr/la_banquise/backend/data/model/User.java b/src/main/java/fr/la_banquise/backend/data/model/User.java index 03af65a..3bd8f5e 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/User.java +++ b/src/main/java/fr/la_banquise/backend/data/model/User.java @@ -19,6 +19,7 @@ import jakarta.persistence.ManyToMany; import jakarta.persistence.OneToMany; import jakarta.persistence.SequenceGenerator; import jakarta.persistence.Table; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; @@ -73,14 +74,13 @@ public class User { .collect(Collectors.toSet()); } - public User(String name, String password, RolesAsso role, - List instances) { + public User(String name, String password, RolesAsso role) { this.name = name; this.password = password; if (role == RolesAsso.NONE) this.role = new HashSet<>(); else this.role = new HashSet<>(Arrays.asList(role)); - this.instances = instances; + this.instances = new ArrayList<>(); } } diff --git a/src/main/java/fr/la_banquise/backend/rest/Endpoints.java b/src/main/java/fr/la_banquise/backend/rest/Endpoints.java index c6f9a75..21c90aa 100644 --- a/src/main/java/fr/la_banquise/backend/rest/Endpoints.java +++ b/src/main/java/fr/la_banquise/backend/rest/Endpoints.java @@ -28,7 +28,7 @@ public class Endpoints { DashboardResponse dashboard = new DashboardResponse(); dashboard.tps = sujetService.getAllSujetsRespo(identity.getPrincipal().getName()); - dashboard.instances = instanceService.getAllInstances(username); + //dashboard.instances = instanceService.getAllInstances(username); return Response.ok(dashboard).build(); } } diff --git a/src/main/java/fr/la_banquise/backend/rest/InstanceEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/InstanceEndpoints.java index 39b7d7b..23c7339 100644 --- a/src/main/java/fr/la_banquise/backend/rest/InstanceEndpoints.java +++ b/src/main/java/fr/la_banquise/backend/rest/InstanceEndpoints.java @@ -1,38 +1,57 @@ package fr.la_banquise.backend.rest; -import fr.la_banquise.backend.rest.request.InstanceRequest; import fr.la_banquise.backend.services.InstanceService; +import fr.la_banquise.backend.services.JiService; import io.quarkus.security.identity.SecurityIdentity; +import jakarta.annotation.security.RolesAllowed; import jakarta.inject.Inject; import jakarta.ws.rs.GET; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; /** * InstanceEndpoints */ -@Path("/api/instances") +@Path("/api/ji/") @Produces(MediaType.APPLICATION_JSON) public class InstanceEndpoints { - @Inject - SecurityIdentity identity; + @Inject SecurityIdentity identity; - @Inject - InstanceService instanceService; + @Inject JiService jiService; + @Inject InstanceService instanceService; @GET + @RolesAllowed("ROOT") + @Path("/instances") public Response getAllInstances() { - String username = identity.getPrincipal().getName(); - return Response.ok(instanceService.getAllInstances(username)).build(); + return Response.ok(instanceService.getAllInstances()).build(); } @POST - public Response createInstance(InstanceRequest request) { - instanceService.createInstance(request.name, request.ssh, request.pwd, request.port, request.username, request.tpId); + @Path("/{id}/instance") + public Response createInstance(@PathParam("id") Long jiId, + @QueryParam("username") String username) { + jiService.createInstance(jiId, username); return Response.ok().build(); } + + @POST + @Path("/{id}/instance/container") + public Response createContainer(@PathParam("id") Long jiId, + @QueryParam("username") String username) { + return Response.ok(jiService.createContainer(jiId, username)).build(); + } + + @GET + @Path("/{id}/instance/container") + public Response getStatusContainer(@PathParam("id") Long jiId, + @QueryParam("username") String username) { + return Response.ok(jiService.getStatusContainer(jiId, username)).build(); + } } diff --git a/src/main/java/fr/la_banquise/backend/rest/JiResource.java b/src/main/java/fr/la_banquise/backend/rest/JiResource.java index 3fbb282..3a9bc31 100644 --- a/src/main/java/fr/la_banquise/backend/rest/JiResource.java +++ b/src/main/java/fr/la_banquise/backend/rest/JiResource.java @@ -13,7 +13,7 @@ import java.util.Map; import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; -@Path("/ji") +@Path("/api/ji") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public class JiResource { @@ -25,7 +25,7 @@ public class JiResource { @GET @Path("/listall") @Produces(MediaType.APPLICATION_JSON) - @RolesAllowed("root") + @RolesAllowed("ROOT") public Response listall() { try { List ji = jiService.getAllJiAdmin(); @@ -39,9 +39,10 @@ public class JiResource { @POST @Path("/create") - @RolesAllowed("root") + @RolesAllowed("ROOT") public Response createJi(@QueryParam("name") String name, - @QueryParam("desc") String desc, + @QueryParam("desc") String desc, // TODO : change + // desc to date @QueryParam("address") String address, @QueryParam("respo") String respo, @QueryParam("site") String name_site) { diff --git a/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java index 9e56ce3..2a11467 100644 --- a/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java +++ b/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java @@ -26,7 +26,7 @@ public class SiteEndpoints { @GET @Produces(MediaType.APPLICATION_JSON) - @RolesAllowed("root") + @RolesAllowed("ROOT") @Operation(summary = "Lists all existing sites", description = "Lists all sites. Root role required.") @APIResponses({ @@ -47,7 +47,7 @@ public class SiteEndpoints { } @POST - @RolesAllowed("root") + @RolesAllowed("ROOT") @Operation(summary = "Creates a site", description = "Creates a site if no name is not a duplicate.") @APIResponses({ diff --git a/src/main/java/fr/la_banquise/backend/rest/SujetEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/SujetEndpoints.java index 726c2e9..8a670dc 100644 --- a/src/main/java/fr/la_banquise/backend/rest/SujetEndpoints.java +++ b/src/main/java/fr/la_banquise/backend/rest/SujetEndpoints.java @@ -43,7 +43,7 @@ public class SujetEndpoints { @POST @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) - @RolesAllowed("root") + @RolesAllowed("ROOT") public Response createSujet(SujetRequest sujet) { return Response.ok(sujetService.createSujet(sujet)).build(); } @@ -51,7 +51,7 @@ public class SujetEndpoints { @POST @Path("/respo") @Produces(MediaType.APPLICATION_JSON) - @RolesAllowed("root") + @RolesAllowed("ROOT") public Response addRespoSujet(@QueryParam("name_sujet") String name_sujet, @QueryParam("name_user") String name_user) { try { diff --git a/src/main/java/fr/la_banquise/backend/rest/request/InstanceRequest.java b/src/main/java/fr/la_banquise/backend/rest/request/InstanceRequest.java index a157c97..a3e6b62 100644 --- a/src/main/java/fr/la_banquise/backend/rest/request/InstanceRequest.java +++ b/src/main/java/fr/la_banquise/backend/rest/request/InstanceRequest.java @@ -1,16 +1,9 @@ package fr.la_banquise.backend.rest.request; -import io.smallrye.common.constraint.Nullable; - /** * InstanceRequest */ public class InstanceRequest { - public String name; - public String ssh; - public String pwd; public String username; - public Long port; - @Nullable - public Long tpId; + public Long jiId; } diff --git a/src/main/java/fr/la_banquise/backend/services/InstanceService.java b/src/main/java/fr/la_banquise/backend/services/InstanceService.java index 7b8cf37..b02d6a2 100644 --- a/src/main/java/fr/la_banquise/backend/services/InstanceService.java +++ b/src/main/java/fr/la_banquise/backend/services/InstanceService.java @@ -1,15 +1,27 @@ package fr.la_banquise.backend.services; +import com.github.dockerjava.api.DockerClient; +import com.github.dockerjava.api.command.CreateContainerResponse; +import com.github.dockerjava.api.command.InspectContainerResponse; +import com.github.dockerjava.api.model.ExposedPort; +import com.github.dockerjava.api.model.HostConfig; +import com.github.dockerjava.api.model.Ports; + import fr.la_banquise.backend.data.model.Instance; -import fr.la_banquise.backend.data.model.Sujet; +import fr.la_banquise.backend.data.model.Ji; import fr.la_banquise.backend.data.model.User; import fr.la_banquise.backend.data.repository.InstanceRepository; -import fr.la_banquise.backend.data.repository.SujetRepository; +import fr.la_banquise.backend.data.repository.JiRepository; import fr.la_banquise.backend.data.repository.UserRepository; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.transaction.Transactional; + +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; /** * InstanceService @@ -21,7 +33,9 @@ public class InstanceService { @Inject UserRepository userRepository; - @Inject SujetRepository sujetRepository; + @Inject JiRepository jiRepository; + + @Inject DockerClient dockerClient; public List getAllInstances() { return instanceRepository.findAll().list(); @@ -36,44 +50,100 @@ public class InstanceService { return instanceRepository.findById(id); } + public InspectContainerResponse.ContainerState getStatusContainer(Long id) { + Instance instance = instanceRepository.findById(id); + InspectContainerResponse container = + dockerClient.inspectContainerCmd(instance.name).exec(); + return container.getState(); + } + @Transactional - public Instance createInstance(String name, Long port, String username, - Long sujetId) { + public Instance createInstance(String username, Ji ji) { User user = userRepository.findByName(username); - Sujet sujet = sujetRepository.findById(sujetId); - Instance instance = new Instance(name, port, user, sujet); + String name = username + "-" + ji.id; + int port = getFreePort(1).iterator().next(); + Instance instance = new Instance(name, port, user); instanceRepository.persist(instance); return instance; } - @Transactional - public Instance createInstance(String name, String ssh, String pwd, - Long port, User user, Long sujetId) { - Sujet sujet = sujetRepository.findById(sujetId); - Instance instance = new Instance(name, port, user, sujet); - instanceRepository.persist(instance); - return instance; + public String createContainer(Long instanceId) { + Instance instance = instanceRepository.findById(instanceId); + + ExposedPort tcpSsh = ExposedPort.tcp(22); + + Ports portBindings = new Ports(); + portBindings.bind(tcpSsh, Ports.Binding.bindPort(instance.port)); + + HostConfig hostConfig = + HostConfig.newHostConfig().withPortBindings(portBindings); + Map labels = new HashMap<>(); + labels.put("test", "banquise"); + labels.put("environment", "development"); + labels.put("version", "1.0"); + labels.put("created-by", "java-docker-api"); + + CreateContainerResponse container = + dockerClient.createContainerCmd("nginx:latest") + .withName(instance.name) + .withLabels(labels) + .withExposedPorts(tcpSsh) + .withHostConfig(hostConfig) + .exec(); + + return container.getId(); + } + + public boolean deleteContainer(String containerName) { + try { + dockerClient.removeContainerCmd(containerName).exec(); + return true; + } catch (Exception e) { + return false; + } } @Transactional public boolean deleteInstance(Long id) { - return instanceRepository.deleteById(id); - } - - @Transactional - public boolean deleteAllInstances() { - instanceRepository.deleteAll(); - return true; - } - - @Transactional - public void deleteJDMIInstances() { - instanceRepository.deleteAll(); - } - - @Transactional - public Instance updateInstance(Long id) { Instance instance = instanceRepository.findById(id); - return instance; + if (!containerExists(instance.name)) + return instanceRepository.deleteById(id); + return false; + } + + public boolean containerExists(String containerName) { + try { + dockerClient.inspectContainerCmd(containerName).exec(); + return true; + } catch (Exception e) { + return false; + } + } + + public Set getUsedPorts() { + Set retour = new HashSet<>(); + List allInstances = getAllInstances(); + for (Instance instance : allInstances) { + retour.add(instance.port); + } + + return retour; + } + + public Set getFreePort(int nbPortsNeeded) { + Set used = getUsedPorts(); + Set retour = new HashSet<>(); + + int port = 40000; + + // max 1000 ports used at a same time + while (retour.size() < nbPortsNeeded && port < 41000) { + if (!used.contains(port)) { + retour.add(port); + } + port++; + } + + return retour; } } diff --git a/src/main/java/fr/la_banquise/backend/services/JiService.java b/src/main/java/fr/la_banquise/backend/services/JiService.java index cb690e7..536e85e 100644 --- a/src/main/java/fr/la_banquise/backend/services/JiService.java +++ b/src/main/java/fr/la_banquise/backend/services/JiService.java @@ -1,5 +1,6 @@ package fr.la_banquise.backend.services; +import fr.la_banquise.backend.data.model.Instance; import fr.la_banquise.backend.data.model.Ji; import fr.la_banquise.backend.data.model.Site; import fr.la_banquise.backend.data.model.User; @@ -9,7 +10,6 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.transaction.Transactional; import jakarta.ws.rs.core.SecurityContext; - import java.util.List; @ApplicationScoped @@ -18,6 +18,7 @@ public class JiService { @Inject JiRepository jiRepository; @Inject UserRepository userRepository; @Inject SiteService siteService; + @Inject InstanceService instanceService; @Inject SecurityContext security; @Transactional @@ -58,4 +59,44 @@ public class JiService { siteService.removeJi(ji.site, ji); jiRepository.delete(ji); } + + @Transactional + public Instance createInstance(Long id, String username) { + Ji ji = jiRepository.findById(id); + Instance instance = instanceService.createInstance(username, ji); + ji.instances.add(instance); + return instance; + } + + @Transactional + public String createContainer(Long id, String username) { + Ji ji = jiRepository.findById(id); + String retour = ""; + for (Instance instance : ji.instances) { + + if (instance.name.equals(username + "-" + id)) { + retour = instanceService.createContainer(instance.id); + break; + } + } + if (retour == "") + throw new Error("instance or container not found"); + + return retour; + } + + public String getStatusContainer(Long id, String username) { + Ji ji = jiRepository.findById(id); + String retour = ""; + for (Instance instance : ji.instances) { + if (instance.name.equals(username + "-" + id)) { + retour = + instanceService.getStatusContainer(instance.id).toString(); + break; + } + } + if (retour == "") + throw new Error("instance or container not found"); + return retour; + } } diff --git a/src/main/java/fr/la_banquise/backend/services/UserService.java b/src/main/java/fr/la_banquise/backend/services/UserService.java index 5da50f1..12300f5 100644 --- a/src/main/java/fr/la_banquise/backend/services/UserService.java +++ b/src/main/java/fr/la_banquise/backend/services/UserService.java @@ -35,7 +35,7 @@ public class UserService { public User createUser(UserRequest request) { User user = new User(request.name, BcryptUtil.bcryptHash(request.password), - RolesAsso.NONE, new ArrayList<>()); + RolesAsso.NONE); userRepository.persist(user); return user; } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index f908816..46f7133 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -37,7 +37,7 @@ quarkus.hibernate-orm.database.generation=drop-and-create quarkus.quinoa.dev-server.port=5173 quarkus.quinoa.enable-spa-routing=true -quarkus.docker.docker-host=unix:///run/user/1000/docker.sock +quarkus.docker.docker-host=unix:///run/user/1001/docker.sock #quarkus.security.auth.enabled-in-dev-mode=false quarkus.hibernate-orm.sql-load-script=import-dev.sql diff --git a/src/main/resources/import-dev.sql b/src/main/resources/import-dev.sql index ace0c48..dc81df7 100644 --- a/src/main/resources/import-dev.sql +++ b/src/main/resources/import-dev.sql @@ -1,3 +1,6 @@ -- Ce fichier est exécuté automatiquement en mode dev INSERT INTO penguin (name, password) VALUES ('root', '$2a$10$lzKAv4aj6s0jtneg0Ikx/eEBb6p.6N6yo7ZF.myqYxEA9MWbMwvNu'); INSERT INTO user_roles (User_id, role) VALUES (1, 'ROOT'); +INSERT INTO site (name, description, address) VALUES ('test', 'test', 'test'); +INSERT INTO ji (name, description, date, site_id) VALUES ('ji', 'test', 'date', 1); +INSERT INTO ji_respos (ji_id, User_id) VALUES (1, 1); -- 2.47.2 From a82677b3bbd8583cee28e68e130d9d031783fed8 Mon Sep 17 00:00:00 2001 From: Arthur Wambst Date: Mon, 8 Sep 2025 23:43:16 +0200 Subject: [PATCH 28/28] started changes required by review --- .../la_banquise/backend/data/model/Site.java | 10 +--- .../la_banquise/backend/rest/Endpoints.java | 4 +- .../la_banquise/backend/rest/JiResource.java | 52 ++----------------- .../backend/rest/SujetEndpoints.java | 16 +++--- .../backend/services/SujetService.java | 12 ++--- .../backend/services/UserService.java | 2 +- 6 files changed, 23 insertions(+), 73 deletions(-) diff --git a/src/main/java/fr/la_banquise/backend/data/model/Site.java b/src/main/java/fr/la_banquise/backend/data/model/Site.java index 1e07e46..8dc60e9 100644 --- a/src/main/java/fr/la_banquise/backend/data/model/Site.java +++ b/src/main/java/fr/la_banquise/backend/data/model/Site.java @@ -15,10 +15,12 @@ import java.util.ArrayList; import java.util.List; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; +import lombok.ToString; @Entity @NoArgsConstructor @AllArgsConstructor +@ToString @Table(name = "site", uniqueConstraints = { @UniqueConstraint(columnNames = "name") }) public class Site { @@ -43,12 +45,4 @@ public class Site { this.address = address; this.jiInSite = new ArrayList(); } - - @Override - public String toString() { - return "Site{id=" + id + ", name='" + name + "', description='" + - description + "', address='" + address + "'}"; - } - - // public Site() {} } diff --git a/src/main/java/fr/la_banquise/backend/rest/Endpoints.java b/src/main/java/fr/la_banquise/backend/rest/Endpoints.java index 21c90aa..3918dec 100644 --- a/src/main/java/fr/la_banquise/backend/rest/Endpoints.java +++ b/src/main/java/fr/la_banquise/backend/rest/Endpoints.java @@ -3,6 +3,7 @@ package fr.la_banquise.backend.rest; import fr.la_banquise.backend.rest.response.DashboardResponse; import fr.la_banquise.backend.services.InstanceService; import fr.la_banquise.backend.services.SujetService; +import io.quarkus.security.Authenticated; import io.quarkus.security.identity.SecurityIdentity; import jakarta.inject.Inject; import jakarta.ws.rs.GET; @@ -22,13 +23,14 @@ public class Endpoints { @Inject SujetService sujetService; @GET + @Authenticated @Path("dashboard") public Response getDashboard() { String username = identity.getPrincipal().getName(); DashboardResponse dashboard = new DashboardResponse(); dashboard.tps = sujetService.getAllSujetsRespo(identity.getPrincipal().getName()); - //dashboard.instances = instanceService.getAllInstances(username); + // dashboard.instances = instanceService.getAllInstances(username); return Response.ok(dashboard).build(); } } diff --git a/src/main/java/fr/la_banquise/backend/rest/JiResource.java b/src/main/java/fr/la_banquise/backend/rest/JiResource.java index 3a9bc31..6cf75b0 100644 --- a/src/main/java/fr/la_banquise/backend/rest/JiResource.java +++ b/src/main/java/fr/la_banquise/backend/rest/JiResource.java @@ -41,13 +41,11 @@ public class JiResource { @Path("/create") @RolesAllowed("ROOT") public Response createJi(@QueryParam("name") String name, - @QueryParam("desc") String desc, // TODO : change - // desc to date - @QueryParam("address") String address, + @QueryParam("date") String date, @QueryParam("respo") String respo, @QueryParam("site") String name_site) { try { - Ji jsp = jiService.createJi(name, desc, address, name_site); + Ji jsp = jiService.createJi(name, date, respo, name_site); return Response.ok(Map.of("created", jsp)).build(); } catch (Exception e) { return Response.status(500) @@ -72,7 +70,7 @@ public class JiResource { @DELETE @Path("/del") - @RolesAllowed("root") + @RolesAllowed("ROOT") @APIResponses({ @APIResponse(responseCode = "200", description = "Successfully deleted") , @APIResponse(responseCode = "500", @@ -90,48 +88,4 @@ public class JiResource { .build(); } } - /* - @GET - @Path("/all") - public Response listContainers() { - try { - String id = dockerService.listAllContainers(); - return Response.ok(id).build(); - } catch (Exception e) { - return Response.status(500).entity(Map.of("error", - e.getMessage())).build(); - } - } - - @POST - @Path("/start") - public Response start(@QueryParam("id") String id) { - try { - dockerService.start(id); - return Response.ok(Map.of("containerId", id, "status", - "Running")).build(); } catch (Exception e) { return - Response.status(500).entity(Map.of("error", e.getMessage())).build(); - } - } - - @POST - @Path("/stop") - public Response stop(@QueryParam("id") String id) { - try { - dockerService.stop(id); - return Response.ok(Map.of("containerId", id, "status", - "removed")).build(); } catch (Exception e) { return - Response.status(500).entity(Map.of("error", e.getMessage())).build(); - } - } - @DELETE - @Path("/remove") - public Response remove(@QueryParam("id") String id) { - try { - dockerService.remove(id); - return Response.ok(Map.of("containerId", id, "status", - "removed")).build(); } catch (Exception e) { return - Response.status(500).entity(Map.of("error", e.getMessage())).build(); - } - }*/ } diff --git a/src/main/java/fr/la_banquise/backend/rest/SujetEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/SujetEndpoints.java index 8a670dc..ce0e71b 100644 --- a/src/main/java/fr/la_banquise/backend/rest/SujetEndpoints.java +++ b/src/main/java/fr/la_banquise/backend/rest/SujetEndpoints.java @@ -20,7 +20,7 @@ import java.util.Map; /** * TpEndpoints */ -@Path("/api/subject") +@Path("/api/subjects") public class SujetEndpoints { @Inject SecurityIdentity identity; @@ -52,10 +52,10 @@ public class SujetEndpoints { @Path("/respo") @Produces(MediaType.APPLICATION_JSON) @RolesAllowed("ROOT") - public Response addRespoSujet(@QueryParam("name_sujet") String name_sujet, - @QueryParam("name_user") String name_user) { + public Response addRespoSujet(@QueryParam("nameSujet") String nameSujet, + @QueryParam("nameUser") String nameUser) { try { - if (sujetService.addRespo(name_sujet, name_user)) { + if (sujetService.addRespo(nameSujet, nameUser)) { return Response.ok("Respo added sucessfully.").build(); } return Response.status(404) @@ -71,11 +71,11 @@ public class SujetEndpoints { @DELETE @Path("/respo") @Produces(MediaType.APPLICATION_JSON) - @RolesAllowed("root") - public Response rmRespoSujet(@QueryParam("name_sujet") String name_sujet, - @QueryParam("name_user") String name_user) { + @RolesAllowed("ROOT") + public Response rmRespoSujet(@QueryParam("nameSujet") String nameSujet, + @QueryParam("nameUser") String nameUser) { try { - if (sujetService.rmRespo(name_sujet, name_user)) { + if (sujetService.rmRespo(nameSujet, nameUser)) { return Response.ok("Respo removed sucessfully.").build(); } return Response.status(404) diff --git a/src/main/java/fr/la_banquise/backend/services/SujetService.java b/src/main/java/fr/la_banquise/backend/services/SujetService.java index 40324a0..42e7f1f 100644 --- a/src/main/java/fr/la_banquise/backend/services/SujetService.java +++ b/src/main/java/fr/la_banquise/backend/services/SujetService.java @@ -68,9 +68,9 @@ public class SujetService { } @Transactional - public boolean addRespo(String name_sujet, String name_user) { - User user = userRepository.find("name", name_user).firstResult(); - Sujet sujet = sujetRepository.find("name", name_sujet).firstResult(); + public boolean addRespo(String nameSujet, String nameUser) { + User user = userRepository.find("name", nameUser).firstResult(); + Sujet sujet = sujetRepository.find("name", nameSujet).firstResult(); if (!sujet.respos.contains(user)) { sujet.respos.add(user); return true; @@ -79,9 +79,9 @@ public class SujetService { } @Transactional - public boolean rmRespo(String name_sujet, String name_user) { - User user = userRepository.find("name", name_user).firstResult(); - Sujet sujet = sujetRepository.find("name", name_sujet).firstResult(); + public boolean rmRespo(String nameSujet, String nameUser) { + User user = userRepository.find("name", nameUser).firstResult(); + Sujet sujet = sujetRepository.find("name", nameSujet).firstResult(); if (sujet.respos.contains(user)) { sujet.respos.remove(user); return true; diff --git a/src/main/java/fr/la_banquise/backend/services/UserService.java b/src/main/java/fr/la_banquise/backend/services/UserService.java index 12300f5..c22ae1b 100644 --- a/src/main/java/fr/la_banquise/backend/services/UserService.java +++ b/src/main/java/fr/la_banquise/backend/services/UserService.java @@ -45,7 +45,7 @@ public class UserService { userRepository.deleteById(id); } - @Transactional // wtf ? this is get user no ? + @Transactional // wtf ? this is get user no ? EDIT : this is x) public User updateUser(Long id) { User user = userRepository.findById(id); return user; -- 2.47.2