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/shell.nix b/shell.nix index 1bc0e59..15a8a5b 100644 --- a/shell.nix +++ b/shell.nix @@ -1,30 +1,32 @@ { 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" + 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 + 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/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 42da592..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,7 +1,9 @@ package fr.la_banquise.backend.data.model; -import com.fasterxml.jackson.annotation.JsonBackReference; +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; @@ -10,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; /** @@ -17,32 +20,34 @@ import lombok.NoArgsConstructor; */ @Entity @NoArgsConstructor +@AllArgsConstructor @Table(name = "instance") 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; - public Long port; - public String pwd; - @JsonBackReference + @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 user; + public User owner; - @ManyToOne - @JoinColumn(name = "practical_id") - public Tp tp; + //@ManyToOne @JoinColumn(name = "ji_id", nullable = false) public Ji ji; - public Instance(String name, String ssh, String pwd, Long port, User user, Tp tp) { + public Instance(String name, int port, User user ) {//, Ji ji) { this.name = name; - this.ssh = ssh; - this.pwd = pwd; this.port = port; - this.user = user; - this.tp = tp; + this.owner = user; + //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 new file mode 100644 index 0000000..852ca12 --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/data/model/Ji.java @@ -0,0 +1,54 @@ +package fr.la_banquise.backend.data.model; + +import com.fasterxml.jackson.annotation.JsonIgnore; +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.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.SequenceGenerator; +import jakarta.persistence.Table; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; + +@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; + + @JsonIgnore + @ManyToMany + @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; + + @OneToMany @JoinColumn(name = "instance_id") public List instances; + + public Ji(String name, String description, List respos, String date, + Site site) { + this.name = name; + this.description = description; + this.respos = respos; + this.date = date; + this.site = site; + } +} 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/Site.java b/src/main/java/fr/la_banquise/backend/data/model/Site.java new file mode 100644 index 0000000..8dc60e9 --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/data/model/Site.java @@ -0,0 +1,48 @@ +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; +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 lombok.ToString; + +@Entity +@NoArgsConstructor +@AllArgsConstructor +@ToString +@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; + + /*@OneToMany(mappedBy = "ji", cascade = CascadeType.ALL) + public List instances;*/ + + @OneToMany(mappedBy = "site") @JsonIgnore public List jiInSite; + + public Site(String name, String description, String address) { + this.name = name; + this.description = description; + this.address = address; + this.jiInSite = new ArrayList(); + } +} 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 new file mode 100644 index 0000000..d12f7f9 --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/data/model/Sujet.java @@ -0,0 +1,52 @@ +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 com.fasterxml.jackson.annotation.JsonIgnore; + +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; + +/** + * Tp + */ +@Entity +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "Sujet") +public class Sujet { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @SequenceGenerator(name = "SujetSeq", sequenceName = "sujet_id_seq", + allocationSize = 1, initialValue = 1) + public Long id; + public String name; + public String description; + public String pdfLink; + @ManyToMany + @JoinTable( + name = "sujet_user", // Table de liaison + joinColumns = @JoinColumn(name = "sujet_id"), + inverseJoinColumns = @JoinColumn(name = "user_id") + ) + @JsonIgnore + public List respos; + + public Sujet(String name, String description, String pdfLink, + List respos) { + this.name = name; + this.description = description; + this.pdfLink = pdfLink; + this.respos = respos; + } +} 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 deleted file mode 100644 index 8eeb3b6..0000000 --- a/src/main/java/fr/la_banquise/backend/data/model/Tp.java +++ /dev/null @@ -1,38 +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; - -/** - * Tp - */ -@Entity -@NoArgsConstructor -@AllArgsConstructor -@Table(name = "tp") -public class Tp { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @SequenceGenerator(name = "TpSeq", sequenceName = "tp_id_seq", allocationSize = 1, initialValue = 1) - public Long id; - public String name; - public String description; - public String pdfLink; - public String respo; - public String date; - - public Tp(String name, String description, String pdfLink, String respo, String date) { - this.name = name; - this.description = description; - this.pdfLink = pdfLink; - this.respo = respo; - this.date = date; - } -} 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..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 @@ -1,21 +1,30 @@ 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.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; +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; +import java.util.Set; +import java.util.stream.Collectors; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @@ -34,24 +43,44 @@ 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; - @JsonManagedReference - @OneToMany(mappedBy = "user", cascade = CascadeType.ALL) + @Enumerated(EnumType.STRING) + @ElementCollection(fetch = FetchType.EAGER) + @CollectionTable(name = "user_roles") + public Set role; + + //@JsonManagedReference + @OneToMany(mappedBy = "owner", cascade = CascadeType.ALL) public List instances; - public User(String name, String password, String role, List instances) { - this.name = name; - this.password = password; - this.role = role; - this.instances = instances; + @ManyToMany(mappedBy = "respos", cascade = CascadeType.ALL) + public List sujetRespo; + + @ManyToMany(mappedBy = "respos", cascade = CascadeType.ALL) + public List jiRespo; + + // 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) { + this.name = name; + this.password = password; + if (role == RolesAsso.NONE) + this.role = new HashSet<>(); + else + this.role = new HashSet<>(Arrays.asList(role)); + this.instances = new ArrayList<>(); + } } 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/JiRepository.java b/src/main/java/fr/la_banquise/backend/data/repository/JiRepository.java new file mode 100644 index 0000000..c2025c5 --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/data/repository/JiRepository.java @@ -0,0 +1,9 @@ +package fr.la_banquise.backend.data.repository; + +import fr.la_banquise.backend.data.model.Ji; +import io.quarkus.hibernate.orm.panache.PanacheRepository; +import jakarta.enterprise.context.ApplicationScoped; + +@ApplicationScoped +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..0dc3a52 --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/data/repository/SiteRepository.java @@ -0,0 +1,8 @@ +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/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 c395dfc..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,5 +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/ContainerResource.java b/src/main/java/fr/la_banquise/backend/rest/ContainerResource.java new file mode 100644 index 0000000..0a5bd48 --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/rest/ContainerResource.java @@ -0,0 +1,98 @@ +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(); + } + } + + @POST + @Path("/create") + 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(); + } + } + + @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/Endpoints.java b/src/main/java/fr/la_banquise/backend/rest/Endpoints.java index ce4da5f..3918dec 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,8 @@ 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.Authenticated; import io.quarkus.security.identity.SecurityIdentity; import jakarta.inject.Inject; import jakarta.ws.rs.GET; @@ -15,27 +16,21 @@ import jakarta.ws.rs.core.Response; @Path("api") public class Endpoints { - @Inject - SecurityIdentity identity; + @Inject SecurityIdentity identity; - @Inject - InstanceService instanceService; + @Inject InstanceService instanceService; - @Inject - TpService tpService; + @Inject SujetService sujetService; @GET + @Authenticated @Path("dashboard") public Response getDashboard() { String username = identity.getPrincipal().getName(); DashboardResponse dashboard = new DashboardResponse(); - if (identity.getRoles().contains("root")) { - dashboard.tps = tpService.getAllTpsAdmin(); - } else { - - dashboard.tps = tpService.getAllTps(identity.getPrincipal().getName()); - } - dashboard.instances = instanceService.getAllInstances(username); + 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/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 new file mode 100644 index 0000000..6cf75b0 --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/rest/JiResource.java @@ -0,0 +1,91 @@ +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.Map; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; + +@Path("/api/ji") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +public class JiResource { + + @Inject SecurityIdentity identity; + + @Inject JiService jiService; + + @GET + @Path("/listall") + @Produces(MediaType.APPLICATION_JSON) + @RolesAllowed("ROOT") + public Response listall() { + try { + List ji = jiService.getAllJiAdmin(); + return Response.ok(ji).build(); + } catch (Exception e) { + return Response.status(500) + .entity(Map.of("error", e.getMessage())) + .build(); + } + } + + @POST + @Path("/create") + @RolesAllowed("ROOT") + public Response createJi(@QueryParam("name") String name, + @QueryParam("date") String date, + @QueryParam("respo") String respo, + @QueryParam("site") String name_site) { + try { + Ji jsp = jiService.createJi(name, date, 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") + @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) { + try { + 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/rest/SiteEndpoints.java b/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java new file mode 100644 index 0000000..2a11467 --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/rest/SiteEndpoints.java @@ -0,0 +1,130 @@ +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; +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 org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; + +@Path("/api/sites") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +public class SiteEndpoints { + + @Inject SecurityIdentity identity; + + @Inject SiteService siteService; + + @GET + @Produces(MediaType.APPLICATION_JSON) + @RolesAllowed("ROOT") + @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(); + } catch (Exception e) { + return Response.status(500) + .entity(Map.of("error", e.getMessage())) + .build(); + } + } + + @POST + @RolesAllowed("ROOT") + @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(); + } catch (Exception e) { + return Response.status(500) + .entity(Map.of("error", e.getMessage())) + .build(); + } + } + + @GET + @Path("/{name}") + @Produces(MediaType.APPLICATION_JSON) + @Authenticated + @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(@PathParam("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 + @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") + , + @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(); + } + } +} 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..ce0e71b --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/rest/SujetEndpoints.java @@ -0,0 +1,90 @@ +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; +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 + */ +@Path("/api/subjects") +public class SujetEndpoints { + + @Inject SecurityIdentity identity; + + @Inject SujetService sujetService; + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Authenticated + 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(); + } + + @POST + @Path("/respo") + @Produces(MediaType.APPLICATION_JSON) + @RolesAllowed("ROOT") + public Response addRespoSujet(@QueryParam("nameSujet") String nameSujet, + @QueryParam("nameUser") String nameUser) { + try { + if (sujetService.addRespo(nameSujet, nameUser)) { + 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("nameSujet") String nameSujet, + @QueryParam("nameUser") String nameUser) { + try { + if (sujetService.rmRespo(nameSujet, nameUser)) { + 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/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 f8cd258..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,9 +1,15 @@ package fr.la_banquise.backend.rest; -import fr.la_banquise.backend.rest.request.BulkUserRequest; +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; @@ -13,67 +19,95 @@ 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") +@Path("/api/user") @Produces(MediaType.APPLICATION_JSON) public class UserEndpoints { - @Inject - SecurityIdentity identity; + @Inject SecurityIdentity identity; - @Inject - UserService userService; + @Inject UserService userService; @GET @Path("/me") + @Authenticated 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(); } @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") - @Path("/jdmi") - public Response createJdmiUsers(BulkUserRequest users) { - userService.createJdmiUser(users); - return Response.ok().build(); - } - @DELETE - @RolesAllowed("root") - public Response deleteJDMI() { - userService.deleteJDMI(); - return Response.ok().build(); - } - - @DELETE - @RolesAllowed("root") - @Path("/{id}") - public Response deleteUser(@PathParam("id") Long id) { + @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/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/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/rest/request/TpRequest.java b/src/main/java/fr/la_banquise/backend/rest/request/SujetRequest.java similarity index 53% 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..5de582a 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,12 +3,8 @@ package fr.la_banquise.backend.rest.request; /** * TpRequest */ -public class TpRequest { +public class SujetRequest { public String title; public String description; public String pdf; - public Long duration; - public String tools; - public String difficulty; - public String date; } 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..cf74ffe --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/rest/response/BulkUserDelResponse.java @@ -0,0 +1,19 @@ +package fr.la_banquise.backend.rest.response; + +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 new file mode 100644 index 0000000..8e02599 --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/rest/response/BulkUserPostResponse.java @@ -0,0 +1,17 @@ +package fr.la_banquise.backend.rest.response; + +import java.util.ArrayList; +import java.util.List; + +import io.quarkus.runtime.annotations.RegisterForReflection; + +@RegisterForReflection +public class BulkUserPostResponse { + public List success_names; + public List already_created; + + public BulkUserPostResponse() { + this.success_names = new ArrayList(); + this.already_created = new ArrayList(); + } +} 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..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 @@ -1,16 +1,20 @@ package fr.la_banquise.backend.rest.response; -import java.util.Set; - import io.quarkus.runtime.annotations.RegisterForReflection; +import java.util.Set; 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/rest/response/PracticalResponse.java b/src/main/java/fr/la_banquise/backend/rest/response/PracticalResponse.java index 762535c..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,7 +1,9 @@ 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; /** @@ -13,15 +15,26 @@ 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; + @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/ContainerService.java b/src/main/java/fr/la_banquise/backend/services/ContainerService.java new file mode 100644 index 0000000..3c2565d --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/services/ContainerService.java @@ -0,0 +1,179 @@ +/*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.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; + +@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/DockerService.java b/src/main/java/fr/la_banquise/backend/services/DockerService.java new file mode 100644 index 0000000..7456d54 --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/services/DockerService.java @@ -0,0 +1,192 @@ +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; + +@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); + 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 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 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..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,81 +1,149 @@ package fr.la_banquise.backend.services; -import java.util.List; +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.Tp; +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.TpRepository; +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 */ @ApplicationScoped public class InstanceService { - @Inject - InstanceRepository instanceRepository; + @Inject InstanceRepository instanceRepository; - @Inject - UserRepository userRepository; + @Inject UserRepository userRepository; - @Inject - TpRepository tpRepository; + @Inject JiRepository jiRepository; + + @Inject DockerClient dockerClient; public List getAllInstances() { return instanceRepository.findAll().list(); } - public List getAllInstances(String username) { + public List getInstancesByOwner(String username) { User user = userRepository.findByName(username); - return instanceRepository.find("user", user).list(); + return instanceRepository.find("owner", user).list(); } public Instance getInstance(Long id) { 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, String ssh, String pwd, Long port, String username, Long tpId) { + public Instance createInstance(String username, Ji ji) { User user = userRepository.findByName(username); - Tp tp = tpRepository.findById(tpId); - Instance instance = new Instance(name, ssh, pwd, port, user, tp); + 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 tpId) { - Tp tp = tpRepository.findById(tpId); - Instance instance = new Instance(name, ssh, pwd, port, user, tp); - 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 new file mode 100644 index 0000000..536e85e --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/services/JiService.java @@ -0,0 +1,102 @@ +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; +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 InstanceService instanceService; + @Inject SecurityContext security; + + @Transactional + public Ji createJi(String name, String description, String address, + String site_name) { + Site site = siteService.getSiteByName(site_name); + 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 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(); + } + + public Ji getJiById(Long id) { return jiRepository.findById(id); } + + @Transactional + public void deleteJi(Long id) { + Ji ji = getJiById(id); + siteService.removeJi(ji.site, ji); + jiRepository.deleteById(id); + } + + @Transactional + public void deleteJi(String name) { + Ji ji = getJiByName(name); + 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/SiteService.java b/src/main/java/fr/la_banquise/backend/services/SiteService.java new file mode 100644 index 0000000..816d277 --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/services/SiteService.java @@ -0,0 +1,65 @@ +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.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, Ji ji) { + site.jiInSite.add(ji); + } + + @Transactional + public void removeJi(Site site, Ji ji) { + site.jiInSite.remove(ji); + } + + @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/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..42e7f1f --- /dev/null +++ b/src/main/java/fr/la_banquise/backend/services/SujetService.java @@ -0,0 +1,98 @@ +package fr.la_banquise.backend.services; + +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 jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.transaction.Transactional; +import jakarta.ws.rs.core.SecurityContext; +import java.util.List; + +/** + * 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); + } + + @Transactional + 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; + } + return false; + } + + @Transactional + 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; + } + return false; + } + /* + * 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 decb756..0000000 --- a/src/main/java/fr/la_banquise/backend/services/TpService.java +++ /dev/null @@ -1,83 +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, tp.date, - "", - "", "", 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 a71e013..c22ae1b 100644 --- a/src/main/java/fr/la_banquise/backend/services/UserService.java +++ b/src/main/java/fr/la_banquise/backend/services/UserService.java @@ -1,19 +1,21 @@ 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.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; -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; /** * UserService @@ -21,23 +23,19 @@ import jakarta.transaction.Transactional; @ApplicationScoped public class UserService { - @Inject - UserRepository userRepository; + @Inject UserRepository userRepository; + @Inject InstanceService instanceService; + @Inject JiRepository jiRepository; - @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), + RolesAsso.NONE); userRepository.persist(user); return user; } @@ -47,7 +45,7 @@ public class UserService { userRepository.deleteById(id); } - @Transactional + @Transactional // wtf ? this is get user no ? EDIT : this is x) public User updateUser(Long id) { User user = userRepository.findById(id); return user; @@ -61,24 +59,51 @@ public class UserService { } @Transactional - public void deleteJDMI() { - for (Instance instance : instanceService.getAllInstances()) { - instanceService.deleteInstance(instance.id); - userRepository.deleteById(instance.user.id); + 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); - } - return new ArrayList(); - } + 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 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/application.properties b/src/main/resources/application.properties index e95de2b..46f7133 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -26,13 +26,18 @@ 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 + +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 new file mode 100644 index 0000000..dc81df7 --- /dev/null +++ b/src/main/resources/import-dev.sql @@ -0,0 +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);