WIP: adding basic sites and ji handling #2

Draft
arthur.wambst wants to merge 30 commits from arthur.wambst/tests into master
44 changed files with 1856 additions and 404 deletions

View File

@ -79,6 +79,11 @@
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkiverse.docker</groupId>
<artifactId>quarkus-docker-client</artifactId>
<version>0.0.5</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>

View File

@ -1,30 +1,32 @@
{ pkgs ? import <nixpkgs> {} }:
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
'';
}

View File

@ -0,0 +1,72 @@
/**package fr.la_banquise.backend.data.model;
Review

Il est commente, il aurait une importance plus tard ou on peut le supprimer ?

Il est commente, il aurait une importance plus tard ou on peut le supprimer ?
Review

Il sert pour le moment a m éviter d aller rechercher les fonctions de docker java api directement dans le repo vu que y a 0 doc, j l enleverai pour la version finale

Il sert pour le moment a m éviter d aller rechercher les fonctions de docker java api directement dans le repo vu que y a 0 doc, j l enleverai pour la version finale
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<Instance> 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;
};
}**/

View File

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

View File

@ -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<User> respos;
public String date;
@ManyToOne
@JoinColumn(name = "site_id") //@JsonIgnore
public Site site;
@OneToMany @JoinColumn(name = "instance_id") public List<Instance> instances;
public Ji(String name, String description, List<User> respos, String date,
Site site) {
this.name = name;
this.description = description;
this.respos = respos;
this.date = date;
this.site = site;
}
}

View File

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

View File

@ -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<Instance> instances;*/
@OneToMany(mappedBy = "site") @JsonIgnore public List<Ji> jiInSite;
public Site(String name, String description, String address) {
this.name = name;
this.description = description;
this.address = address;
this.jiInSite = new ArrayList<Ji>();
}
arthur.wambst marked this conversation as resolved
Review

l'annotation @ToString fait ca pour toi

l'annotation `@ToString` fait ca pour toi
Review

done

done
}

View File

@ -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<User> respos;
public Sujet(String name, String description, String pdfLink,
List<User> respos) {
this.name = name;
this.description = description;
this.pdfLink = pdfLink;
this.respos = respos;
}
}

View File

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

View File

@ -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<RolesAsso> role;
//@JsonManagedReference
@OneToMany(mappedBy = "owner", cascade = CascadeType.ALL)
public List<Instance> instances;
public User(String name, String password, String role, List<Instance> instances) {
this.name = name;
this.password = password;
this.role = role;
this.instances = instances;
@ManyToMany(mappedBy = "respos", cascade = CascadeType.ALL)
public List<Sujet> sujetRespo;
@ManyToMany(mappedBy = "respos", cascade = CascadeType.ALL)
public List<Ji> jiRespo;
// Méthode pour Quarkus Security - conversion simple
@RolesValue
@Roles
public Set<String> 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<>();
}
}

View File

@ -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<Container> {
}*/

View File

@ -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<Ji> {
}

View File

@ -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<Site> {}

View File

@ -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<Tp> {
}
public class SujetRepository implements PanacheRepository<Sujet> {}

View File

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

View File

@ -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
arthur.wambst marked this conversation as resolved Outdated

Il manque un @Authenticated pour que ca marche

Il manque un `@Authenticated` pour que ca marche

done

done
@Path("dashboard")
Review

unused si ligne 31 commentee

Edit: pourquoi la ligne 31 est commentee du coup ?

unused si ligne 31 commentee Edit: pourquoi la ligne 31 est commentee du coup ?
Review

j crois que instance.getAllInstace marchait pas ? j re regarderai ca une autre fois

j crois que instance.getAllInstace marchait pas ? j re regarderai ca une autre fois
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();
}
}

View File

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

View File

@ -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> 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) {
Review

address, description et name_site sont pas deja dans site? Autant utiliser l'id du site du coup. Pareil pour le respo utiliser un id plutot qu'une string

address, description et name_site sont pas deja dans site? Autant utiliser l'id du site du coup. Pareil pour le respo utiliser un id plutot qu'une string
Review

fait en partie, j changerai les string vers id une autre fois

fait en partie, j changerai les string vers id une autre fois
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);
Review

Priviliegier les get by id plutot que by name en regle generale, le front utilisera l'id qui est plus simple pour la db a trouver

Priviliegier les get by id plutot que by name en regle generale, le front utilisera l'id qui est plus simple pour la db a trouver
Review

ok, j changerai + tard

ok, j changerai + tard
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")
arthur.wambst marked this conversation as resolved Outdated

ROOT plutot que root du coup ?

ROOT plutot que root du coup ?

done

done
, @APIResponse(responseCode = "500",
description =
"Internal server error, usually site not found")
})
public Response
deleteJiByName(@QueryParam("name") String name) {
try {
jiService.deleteJi(name);

par id plutot que par name

par id plutot que par name
return Response.ok().build();
} catch (Exception e) {
return Response.status(500)
.entity(Map.of("error", e.getMessage()))
.build();
}
}
}

View File

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

View File

@ -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")
arthur.wambst marked this conversation as resolved Outdated

Si possibilites d'avoir plusieurs sujets (i.e. la liste de tous les sujets dispo), mettre subject au pluriel

Si possibilites d'avoir plusieurs sujets (i.e. la liste de tous les sujets dispo), mettre subject au pluriel

done

done
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,

Camel Case pour les noms de variables ^[a-z][a-zA-Z0-9]*$ (aussi pour les query params)

Camel Case pour les noms de variables ^[a-z][a-zA-Z0-9]*$ (aussi pour les query params)

done en partie, j repasserai dessus une autre fois

done en partie, j repasserai dessus une autre fois
@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)
Review

Quand une des annotation est repetitive @Produces(MediaType.APPLICATION_JSON) par exemple tu peux le mettre au dessus de ta declaration de class et elle sera pour toutes les method a l'interieur de ta classe

Quand une des annotation est repetitive `@Produces(MediaType.APPLICATION_JSON)` par exemple tu peux le mettre au dessus de ta declaration de class et elle sera pour toutes les method a l'interieur de ta classe
Review

euu jsp si elle est vraiment necessaire en fait, j vois pas clairement c qu elle change

euu jsp si elle est vraiment necessaire en fait, j vois pas clairement c qu elle change
@RolesAllowed("ROOT")

des fois ROOT des fois root pour le role

des fois `ROOT` des fois `root` pour le role

j ai fait en sorte que ca cree un user avec le role ROOT a chaque boot sur le profil dev, mais root marchait pas j crois
j ai pas encore change partout mais j y fais petit a petit

j ai fait en sorte que ca cree un user avec le role ROOT a chaque boot sur le profil dev, mais root marchait pas j crois j ai pas encore change partout mais j y fais petit a petit
public Response rmRespoSujet(@QueryParam("nameSujet") String nameSujet,
arthur.wambst marked this conversation as resolved Outdated

Camel Case pour les noms de variables ^[a-z][a-zA-Z0-9]*$ (aussi pour les query params)

Camel Case pour les noms de variables ^[a-z][a-zA-Z0-9]*$ (aussi pour les query params)
@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();
}
}
}

View File

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

View File

@ -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")
Review

Pourquoi il y a deux endpoints differents pour les users ? (et pourquoi celui la il est au singulier?

Pourquoi il y a deux endpoints differents pour les users ? (et pourquoi celui la il est au singulier?
Review

y avait bcp d endpoints deja pour la gestion des users 1 par 1 donc j ai mis les fonctions qui font des operations sur plusieurs users et j ai mis tout ca dans users, mais jsp si c est mieux que d avoir un seul giga fichier

y avait bcp d endpoints deja pour la gestion des users 1 par 1 donc j ai mis les fonctions qui font des operations sur plusieurs users et j ai mis tout ca dans users, mais jsp si c est mieux que d avoir un seul giga fichier
@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));
Review

Pas de logique dans la partie rest, ca devrait etre dans une methode dans le service (avec une annotation transaction sinon ca ne marche pas).

un truc du style:

    @Transactional
    public void updateRole(String role, Long userId) {
        User user = userRepository.findById(userId);
        user.role.add(fromString(role));
    }
Pas de logique dans la partie rest, ca devrait etre dans une methode dans le service (avec une annotation transaction sinon ca ne marche pas). un truc du style: ```java @Transactional public void updateRole(String role, Long userId) { User user = userRepository.findById(userId); user.role.add(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));
Review

pareil qu'au dessus

pareil qu'au dessus
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();
}

View File

@ -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
Review

@RolesAllowed({ "ROOT", "JI" })

`@RolesAllowed({ "ROOT", "JI" })`
Review

nan ca doit etre que les respo de la JI en question donc flm pour le moment

nan ca doit etre que les respo de la JI en question donc flm pour le moment
// 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<String, String> retour = new HashMap<String, String>();
Review

pas de logique ici, que dans la couche des services

pas de logique ici, que dans la couche des services
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();
}
}

View File

@ -0,0 +1,7 @@
package fr.la_banquise.backend.rest.request;
import java.util.List;
public class BulkUserDelRequest {
public List<UserDelRequest> usernames;
}

View File

@ -2,11 +2,7 @@ package fr.la_banquise.backend.rest.request;
import java.util.List;
/**
* UserRequest
*/
public class BulkUserRequest {
public class BulkUserPostRequest {
public List<UserRequest> users;
public String password;
public Long tpId;
public Long jiId;
}

View File

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

View File

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

View File

@ -0,0 +1,5 @@
package fr.la_banquise.backend.rest.request;
public class UserDelRequest {
public String name;
}

View File

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

View File

@ -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<String> success_names;
Review

Camel Case pour les noms de variables ^[a-z][a-zA-Z0-9]*$

Camel Case pour les noms de variables `^[a-z][a-zA-Z0-9]*$`
public List<String> failed_names;
public List<String> failed_reasons;
public BulkUserDelResponse() {
this.success_names = new ArrayList<String>();
this.failed_names = new ArrayList<String>();
this.failed_reasons = new ArrayList<String>();
}
}

View File

@ -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<String> success_names;
Review

Camel Case pour les noms de variables ^[a-z][a-zA-Z0-9]*$

Camel Case pour les noms de variables `^[a-z][a-zA-Z0-9]*$`
public List<String> already_created;
public BulkUserPostResponse() {
this.success_names = new ArrayList<String>();
this.already_created = new ArrayList<String>();
}
}

View File

@ -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<Tp> tps;
public List<Sujet> tps;
public List<Instance> instances;
}

View File

@ -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<String> roles;
public LoggedUserResponse(String username, Set<String> roles) {
this.username = username;
this.roles = roles;
}
}

View File

@ -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<User> 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;
}*/
}

View File

@ -0,0 +1,179 @@
/*package fr.la_banquise.backend.services;
Review

Besoin de ca ou pas si il est commente ?

Besoin de ca ou pas si il est commente ?
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<String, String> 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<Container> 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<Container> containers = dockerClient.listContainersCmd()
.withShowAll(true)
.exec();
json.append("[");
for (int i = 0; i < containers.size(); i++) {
Container container = containers.get(i);
// Ports
List<String> 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();
}
}*/

View File

@ -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<String, String> 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<Container> 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<Container> containers = dockerClient.listContainersCmd()
.withShowAll(true)
.exec();
json.append("[");
for (int i = 0; i < containers.size(); i++) {
Container container = containers.get(i);
// Ports
List<String> 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();
}
}

View File

@ -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<Instance> getAllInstances() {
return instanceRepository.findAll().list();
}
public List<Instance> getAllInstances(String username) {
public List<Instance> 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) {
Review

pourquoi ce qui est lie au container est pas dans le container service ?

pourquoi ce qui est lie au container est pas dans le container service ?
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<String, String> 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<Integer> getUsedPorts() {
Set<Integer> retour = new HashSet<>();
List<Instance> allInstances = getAllInstances();
for (Instance instance : allInstances) {
retour.add(instance.port);
}
return retour;
}
public Set<Integer> getFreePort(int nbPortsNeeded) {
Set<Integer> used = getUsedPorts();
Set<Integer> 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;
}
}

View File

@ -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) {
Review

Camel Case pour les noms de variables ^[a-z][a-zA-Z0-9]*$

Camel Case pour les noms de variables `^[a-z][a-zA-Z0-9]*$`
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<Ji> getAllJiAdmin() { return jiRepository.listAll(); }
public List<Ji> 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) {
Review

Pourquoi c'est la tout ce qui ne parle pas de ji directement ? Et pas directement dans les services respectifs ? (instance, containers etc...)

Pourquoi c'est la tout ce qui ne parle pas de ji directement ? Et pas directement dans les services respectifs ? (instance, containers etc...)
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;
}
}

View File

@ -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<Site> saveAllSites(List<Site> sites) {
sites.forEach(site -> siteRepository.persist(site));
return sites;
}*/
public List<Site> 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;
}
}

View File

@ -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;
Review

On utilise generalement les services des autres fonctionnalite plutot que leur repo, pour avoir une layer d'abstraction en moins. Par exemple, le SujetService peut acceder au SujetRepository mais devrait acceder aux methode du UserRepository a travers les methode de UserService

On utilise generalement les services des autres fonctionnalite plutot que leur repo, pour avoir une layer d'abstraction en moins. Par exemple, le SujetService peut acceder au SujetRepository mais devrait acceder aux methode du UserRepository a travers les methode de UserService
public List<Sujet> getAllSujetsAdmin() { return sujetRepository.listAll(); }
public List<Sujet> getAllSujetsRespo(String username) {
User user = userRepository.findByName(username);
return user.sujetRespo;
}
/*public PracticalResponse getTp(Long id, String username) {
Review

Le code commentee a une utilite ou peut etre supprime ?

Le code commentee a une utilite ou peut etre supprime ?
Review

faut faire les get pour en get qu un seul ou tous ceux dont l user est participant, et j pensais repartir de ca pour aps avoir a rechercher les commandes pour l user

faut faire les get pour en get qu un seul ou tous ceux dont l user est participant, et j pensais repartir de ca pour aps avoir a rechercher les commandes pour l user
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) {
arthur.wambst marked this conversation as resolved Outdated

Camel Case pour les noms de variables ^[a-z][a-zA-Z0-9]*$

Camel Case pour les noms de variables `^[a-z][a-zA-Z0-9]*$`

done

done
User user = userRepository.find("name", nameUser).firstResult();
Sujet sujet = sujetRepository.find("name", nameSujet).firstResult();

une method findByName peut etre implem dans les repository

Edit: Plutot que de faire une recherche sur les noms, autant utiliser l'id de la personne et du sujet. Dans le front on peut faire un auto fill du nom et c'est l'id qui est renvoye, moins couteux pour la creation et plus aligne avec une API

une method `findByName` peut etre implem dans les repository Edit: Plutot que de faire une recherche sur les noms, autant utiliser l'id de la personne et du sujet. Dans le front on peut faire un auto fill du nom et c'est l'id qui est renvoye, moins couteux pour la creation et plus aligne avec une API
if (!sujet.respos.contains(user)) {
Review

Que se passe-t-il si le sujet/user n'existe pas ? Toujours controler l'input de l'utilisateur

Que se passe-t-il si le sujet/user n'existe pas ? Toujours controler l'input de l'utilisateur
Review

ca met une erreur degeue de la db, mais pour le moment j me suis absolument pas interesse a la gestion des erreurs

ca met une erreur degeue de la db, mais pour le moment j me suis absolument pas interesse a la gestion des erreurs
sujet.respos.add(user);
return true;
}
return false;
}
@Transactional
public boolean rmRespo(String nameSujet, String nameUser) {
arthur.wambst marked this conversation as resolved Outdated

Camel Case pour les noms de variables ^[a-z][a-zA-Z0-9]*$

Camel Case pour les noms de variables `^[a-z][a-zA-Z0-9]*$`

done

done
User user = userRepository.find("name", nameUser).firstResult();
Sujet sujet = sujetRepository.find("name", nameSujet).firstResult();
if (sujet.respos.contains(user)) {
Review

Meme problemes qu'au dessus

Meme problemes qu'au dessus
sujet.respos.remove(user);
return true;
}
return false;
}
/*
* TODO: Seuls les respos du sujet et root doivent pouvoir avoir acces
Review

Je sais que c'est commente mais c'est fait au niveau des endpoints les checks d'acces

Je sais que c'est commente mais c'est fait au niveau des endpoints les checks d'acces
Review

aa okeee j changerai ca dans tout plus tard

aa okeee j changerai ca dans tout plus tard
* @Transactional
public Sujet updateSujet(Long id) {
Sujet sujet = sujetRepository.findById(id);
return sujet;
}*/
}

View File

@ -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<Tp> getAllTpsAdmin() {
return tpRepository.listAll();
}
public List<Tp> getAllTps(String username) {
User user = userRepository.findByName(username);
List<Instance> 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;
}
}

View File

@ -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<User> getAllUsers() { return userRepository.listAll(); }
public List<User> 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)

oui, c'etait histoire d'avoir la methode qq part mais ca avait pas ete implem x)

oui, c'etait histoire d'avoir la methode qq part mais ca avait pas ete implem x)

x))) a changer alors

x))) a changer alors
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<User> createJdmiUser(BulkUserRequest usersRequest) {
List<User> 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<User>();
}
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");
};
}
}

View File

@ -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

View File

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