diff --git a/src/main/java/fr/titionfire/ffsaf/domain/service/ClubService.java b/src/main/java/fr/titionfire/ffsaf/domain/service/ClubService.java index 5e2274a..82ff6d9 100644 --- a/src/main/java/fr/titionfire/ffsaf/domain/service/ClubService.java +++ b/src/main/java/fr/titionfire/ffsaf/domain/service/ClubService.java @@ -31,16 +31,10 @@ import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.unchecked.Unchecked; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; -import jakarta.ws.rs.core.HttpHeaders; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.hibernate.reactive.mutiny.Mutiny; -import org.jboss.logging.Logger; -import java.io.*; import java.util.*; -import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import static fr.titionfire.ffsaf.net2.Client_Thread.MAPPER; @@ -48,7 +42,6 @@ import static fr.titionfire.ffsaf.net2.Client_Thread.MAPPER; @WithSession @ApplicationScoped public class ClubService { - private static final Logger LOGGER = Logger.getLogger(ClubService.class); @Inject ClubRepository repository; @@ -68,12 +61,6 @@ public class ClubService { @Inject LoggerService ls; - @ConfigProperty(name = "pdf-maker.jar-path") - String pdfMakerJarPath; - - @ConfigProperty(name = "pdf-maker.sign-file") - String sign_file; - public SimpleClubModel findByIdOptionalClub(long id) throws Throwable { return VertxContextSupport.subscribeAndAwait( () -> Panache.withTransaction(() -> repository.findById(id).map(SimpleClubModel::fromModel))); @@ -346,120 +333,4 @@ public class ClubService { return data; }).collect().asList(); } - - public Uni getAffiliationPdf(String subject) { - return getAffiliationPdf( - combRepository.find("userId = ?1", subject).firstResult() - .invoke(Unchecked.consumer(m -> { - if (m == null || m.getClub() == null) - throw new DNotFoundException("Club non trouvé"); - })) - .map(MembreModel::getClub) - .call(m -> Mutiny.fetch(m.getAffiliations()))); - } - - public Uni getAffiliationPdf(long id) { - return getAffiliationPdf( - repository.findById(id) - .invoke(Unchecked.consumer(m -> { - if (m == null) - throw new DNotFoundException("Club non trouvé"); - })) - .call(m -> Mutiny.fetch(m.getAffiliations()))); - } - - - private Uni getAffiliationPdf(Uni uniBase) { - return uniBase - .map(Unchecked.function(m -> { - if (m.getAffiliations().stream() - .noneMatch(licenceModel -> licenceModel.getSaison() == Utils.getSaison())) - throw new DNotFoundException("Pas d'affiliation pour la saison en cours"); - - try { - byte[] buff = make_pdf(m); - if (buff == null) - throw new IOException("Error making pdf"); - - String mimeType = "application/pdf"; - - Response.ResponseBuilder resp = Response.ok(buff); - resp.type(MediaType.APPLICATION_OCTET_STREAM); - resp.header(HttpHeaders.CONTENT_LENGTH, buff.length); - resp.header(HttpHeaders.CONTENT_TYPE, mimeType); - resp.header(HttpHeaders.CONTENT_DISPOSITION, - "inline; " + "filename=\"Attestation d'affiliation " + Utils.getSaison() + "-" + - (Utils.getSaison() + 1) + " de " + m.getName() + ".pdf\""); - return resp.build(); - } catch (Exception e) { - throw new IOException(e); - } - })); - } - - private byte[] make_pdf(ClubModel m) throws IOException, InterruptedException { - List cmd = new ArrayList<>(); - cmd.add("java"); - cmd.add("-jar"); - cmd.add(pdfMakerJarPath); - - UUID uuid = UUID.randomUUID(); - - cmd.add("/tmp/" + uuid + ".pdf"); - cmd.add("club"); - cmd.add(m.getName()); - cmd.add(Utils.getSaison() + ""); - cmd.add(m.getNo_affiliation() + ""); - cmd.add(new File(sign_file).getAbsolutePath()); - - return getPdf(cmd, uuid, LOGGER); - } - - static byte[] getPdf(List cmd, UUID uuid, Logger logger) throws IOException, InterruptedException { - ProcessBuilder processBuilder = new ProcessBuilder(cmd); - processBuilder.redirectErrorStream(true); - Process process = processBuilder.start(); - - BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); - - StringBuilder builder = new StringBuilder(); - Thread t = new Thread(() -> { - try { - String line; - while ((line = reader.readLine()) != null) - builder.append(line).append("\n"); - } catch (Exception ignored) { - } - }); - t.start(); - - int code = -1; - if (!process.waitFor(30, TimeUnit.SECONDS)) { - process.destroy(); - builder.append("Timeout..."); - } else { - code = process.exitValue(); - } - - if (t.isAlive()) - t.interrupt(); - - logger.debug("PDF maker: " + builder); - - if (code != 0) { - throw new IOException("Error code: " + code); - } else { - File file = new File("/tmp/" + uuid + ".pdf"); - try (FileInputStream fis = new FileInputStream(file)) { - byte[] buff = fis.readAllBytes(); - //noinspection ResultOfMethodCallIgnored - file.delete(); - return buff; - } catch (IOException e) { - //noinspection ResultOfMethodCallIgnored - file.delete(); - } - return null; - } - } } diff --git a/src/main/java/fr/titionfire/ffsaf/domain/service/MembreService.java b/src/main/java/fr/titionfire/ffsaf/domain/service/MembreService.java index 6e6e58e..be34bb1 100644 --- a/src/main/java/fr/titionfire/ffsaf/domain/service/MembreService.java +++ b/src/main/java/fr/titionfire/ffsaf/domain/service/MembreService.java @@ -13,7 +13,6 @@ import fr.titionfire.ffsaf.rest.data.SimpleMembre; import fr.titionfire.ffsaf.rest.data.SimpleMembreInOutData; import fr.titionfire.ffsaf.rest.exception.DBadRequestException; import fr.titionfire.ffsaf.rest.exception.DForbiddenException; -import fr.titionfire.ffsaf.rest.exception.DNotFoundException; import fr.titionfire.ffsaf.rest.from.FullMemberForm; import fr.titionfire.ffsaf.utils.*; import io.quarkus.hibernate.reactive.panache.Panache; @@ -27,22 +26,13 @@ import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.unchecked.Unchecked; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; -import jakarta.ws.rs.core.HttpHeaders; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.hibernate.reactive.mutiny.Mutiny; import org.jboss.logging.Logger; -import java.io.File; -import java.io.FilenameFilter; -import java.io.IOException; -import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.atomic.AtomicReference; -import static fr.titionfire.ffsaf.domain.service.ClubService.getPdf; - @WithSession @ApplicationScoped @@ -67,8 +57,6 @@ public class MembreService { @ConfigProperty(name = "upload_dir") String media; - @ConfigProperty(name = "pdf-maker.jar-path") - String pdfMakerJarPath; @Inject RegisterRepository registerRepository; @@ -167,9 +155,10 @@ public class MembreService { clubModel.set(membreModel.getClub()); if (data2.stream().noneMatch(d -> d.getLicence() != null)) return Uni.createFrom().item(new ArrayList()); - return repository.list("licence IN ?1 OR LOWER(lname || ' ' || fname) IN ?2", + return repository.list("licence IN ?1 OR LOWER(lname || ' ' || fname) IN ?2 OR email IN ?3", data2.stream().map(SimpleMembreInOutData::getLicence).filter(Objects::nonNull).toList(), - data2.stream().map(o -> (o.getNom() + " " + o.getPrenom()).toLowerCase()).toList()); + data2.stream().map(o -> (o.getNom() + " " + o.getPrenom()).toLowerCase()).toList(), + data2.stream().map(SimpleMembreInOutData::getEmail).filter(Objects::nonNull).toList()); }) .call(Unchecked.function(membres -> { for (MembreModel membreModel : membres) { @@ -181,7 +170,8 @@ public class MembreService { for (SimpleMembreInOutData dataIn : data2) { MembreModel model = membres.stream() .filter(m -> Objects.equals(m.getLicence(), dataIn.getLicence()) || m.getLname() - .equals(dataIn.getNom()) && m.getFname().equals(dataIn.getPrenom())).findFirst() + .equals(dataIn.getNom()) && m.getFname().equals(dataIn.getPrenom()) || + Objects.equals(m.getFname(), dataIn.getEmail())).findFirst() .orElseGet(() -> { MembreModel mm = new MembreModel(); mm.setClub(clubModel.get()); @@ -190,6 +180,18 @@ public class MembreService { return mm; }); + if (model.getEmail() != null) { + if (model.getLicence() != null && !model.getLicence().equals(dataIn.getLicence())) { + throw new DBadRequestException("Email déja utiliser"); + } + + if (StringSimilarity.similarity(model.getLname().toUpperCase(), + dataIn.getNom().toUpperCase()) > 3 || StringSimilarity.similarity( + model.getFname().toUpperCase(), dataIn.getPrenom().toUpperCase()) > 3) { + throw new DBadRequestException("Email déja utiliser"); + } + } + boolean add = model.getId() == null; if ((!add && StringSimilarity.similarity(model.getLname().toUpperCase(), @@ -477,70 +479,4 @@ public class MembreService { .map(__ -> null); } - public Uni getLicencePdf(String subject) { - return getLicencePdf(repository.find("userId = ?1", subject).firstResult() - .call(m -> Mutiny.fetch(m.getLicences()))); - } - - public Uni getLicencePdf(Uni uniBase) { - return uniBase - .map(Unchecked.function(m -> { - LicenceModel licence = m.getLicences().stream() - .filter(licenceModel -> licenceModel.getSaison() == Utils.getSaison() && licenceModel.isValidate()) - .findFirst() - .orElseThrow(() -> new DNotFoundException("Pas de licence pour la saison en cours")); - - try { - byte[] buff = make_pdf(m, licence); - if (buff == null) - throw new IOException("Error making pdf"); - - String mimeType = "application/pdf"; - - Response.ResponseBuilder resp = Response.ok(buff); - resp.type(MediaType.APPLICATION_OCTET_STREAM); - resp.header(HttpHeaders.CONTENT_LENGTH, buff.length); - resp.header(HttpHeaders.CONTENT_TYPE, mimeType); - resp.header(HttpHeaders.CONTENT_DISPOSITION, - "inline; " + "filename=\"Attestation d'adhésion " + Utils.getSaison() + "-" + - (Utils.getSaison() + 1) + " de " + m.getLname() + " " + m.getFname() + ".pdf\""); - return resp.build(); - } catch (Exception e) { - throw new IOException(e); - } - })); - } - - private byte[] make_pdf(MembreModel m, LicenceModel licence) throws IOException, InterruptedException { - List cmd = new ArrayList<>(); - cmd.add("java"); - cmd.add("-jar"); - cmd.add(pdfMakerJarPath); - - UUID uuid = UUID.randomUUID(); - - cmd.add("/tmp/" + uuid + ".pdf"); - cmd.add("membre"); - cmd.add(m.getFname()); - cmd.add(m.getLname()); - cmd.add(m.getGenre().str); - cmd.add(m.getCategorie().getName()); - cmd.add(licence.getCertificate() == null ? "" : licence.getCertificate()); - cmd.add(Utils.getSaison() + ""); - cmd.add(m.getLicence() + ""); - cmd.add(m.getClub().getName()); - cmd.add(m.getClub().getNo_affiliation() + ""); - cmd.add(m.getBirth_date() == null ? "--" : new SimpleDateFormat("dd/MM/yyyy").format(m.getBirth_date())); - - FilenameFilter filter = (directory, filename) -> filename.startsWith(m.getId() + "."); - File[] files = new File(media, "ppMembre").listFiles(filter); - if (files != null && files.length > 0) { - File file = files[0]; - cmd.add(file.getAbsolutePath()); - } else { - cmd.add("/dev/null"); - } - - return getPdf(cmd, uuid, LOGGER); - } } diff --git a/src/main/java/fr/titionfire/ffsaf/domain/service/PDFService.java b/src/main/java/fr/titionfire/ffsaf/domain/service/PDFService.java new file mode 100644 index 0000000..e95bb8a --- /dev/null +++ b/src/main/java/fr/titionfire/ffsaf/domain/service/PDFService.java @@ -0,0 +1,232 @@ +package fr.titionfire.ffsaf.domain.service; + +import fr.titionfire.ffsaf.data.model.ClubModel; +import fr.titionfire.ffsaf.data.model.LicenceModel; +import fr.titionfire.ffsaf.data.model.MembreModel; +import fr.titionfire.ffsaf.data.repository.ClubRepository; +import fr.titionfire.ffsaf.data.repository.CombRepository; +import fr.titionfire.ffsaf.rest.exception.DNotFoundException; +import fr.titionfire.ffsaf.utils.Utils; +import io.quarkus.hibernate.reactive.panache.common.WithSession; +import io.smallrye.mutiny.Uni; +import io.smallrye.mutiny.unchecked.Unchecked; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.hibernate.reactive.mutiny.Mutiny; +import org.jboss.logging.Logger; + +import java.io.*; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +@WithSession +@ApplicationScoped +public class PDFService { + private static final Logger LOGGER = Logger.getLogger(PDFService.class); + + @Inject + CombRepository combRepository; + + @Inject + ClubRepository clubRepository; + + @ConfigProperty(name = "upload_dir") + String media; + + @ConfigProperty(name = "pdf-maker.jar-path") + String pdfMakerJarPath; + + @ConfigProperty(name = "pdf-maker.sign-file") + String sign_file; + + + public Uni getLicencePdf(String subject) { + return getLicencePdf(combRepository.find("userId = ?1", subject).firstResult() + .call(m -> Mutiny.fetch(m.getLicences()))); + } + + public Uni getLicencePdf(Uni uniBase) { + return uniBase + .map(Unchecked.function(m -> { + LicenceModel licence = m.getLicences().stream() + .filter(licenceModel -> licenceModel.getSaison() == Utils.getSaison() && licenceModel.isValidate()) + .findFirst() + .orElseThrow(() -> new DNotFoundException("Pas de licence pour la saison en cours")); + + try { + byte[] buff = make_pdf(m, licence); + if (buff == null) + throw new IOException("Error making pdf"); + + String mimeType = "application/pdf"; + + Response.ResponseBuilder resp = Response.ok(buff); + resp.type(MediaType.APPLICATION_OCTET_STREAM); + resp.header(HttpHeaders.CONTENT_LENGTH, buff.length); + resp.header(HttpHeaders.CONTENT_TYPE, mimeType); + resp.header(HttpHeaders.CONTENT_DISPOSITION, + "inline; " + "filename=\"Attestation d'adhésion " + Utils.getSaison() + "-" + + (Utils.getSaison() + 1) + " de " + m.getLname() + " " + m.getFname() + ".pdf\""); + return resp.build(); + } catch (Exception e) { + throw new IOException(e); + } + })); + } + + private byte[] make_pdf(MembreModel m, LicenceModel licence) throws IOException, InterruptedException { + List cmd = new ArrayList<>(); + cmd.add("java"); + cmd.add("-jar"); + cmd.add(pdfMakerJarPath); + + UUID uuid = UUID.randomUUID(); + + cmd.add("/tmp/" + uuid + ".pdf"); + cmd.add("membre"); + cmd.add(m.getFname()); + cmd.add(m.getLname()); + cmd.add(m.getGenre().str); + cmd.add(m.getCategorie().getName()); + cmd.add(licence.getCertificate() == null ? "" : licence.getCertificate()); + cmd.add(Utils.getSaison() + ""); + cmd.add(m.getLicence() + ""); + cmd.add(m.getClub().getName()); + cmd.add(m.getClub().getNo_affiliation() + ""); + cmd.add(m.getBirth_date() == null ? "--" : new SimpleDateFormat("dd/MM/yyyy").format(m.getBirth_date())); + + FilenameFilter filter = (directory, filename) -> filename.startsWith(m.getId() + "."); + File[] files = new File(media, "ppMembre").listFiles(filter); + if (files != null && files.length > 0) { + File file = files[0]; + cmd.add(file.getAbsolutePath()); + } else { + cmd.add("/dev/null"); + } + + return getPdf(cmd, uuid); + } + + public Uni getAffiliationPdf(String subject) { + return getAffiliationPdf( + combRepository.find("userId = ?1", subject).firstResult() + .invoke(Unchecked.consumer(m -> { + if (m == null || m.getClub() == null) + throw new DNotFoundException("Club non trouvé"); + })) + .map(MembreModel::getClub) + .call(m -> Mutiny.fetch(m.getAffiliations()))); + } + + public Uni getAffiliationPdf(long id) { + return getAffiliationPdf( + clubRepository.findById(id) + .invoke(Unchecked.consumer(m -> { + if (m == null) + throw new DNotFoundException("Club non trouvé"); + })) + .call(m -> Mutiny.fetch(m.getAffiliations()))); + } + + + private Uni getAffiliationPdf(Uni uniBase) { + return uniBase + .map(Unchecked.function(m -> { + if (m.getAffiliations().stream() + .noneMatch(licenceModel -> licenceModel.getSaison() == Utils.getSaison())) + throw new DNotFoundException("Pas d'affiliation pour la saison en cours"); + + try { + byte[] buff = make_pdf(m); + if (buff == null) + throw new IOException("Error making pdf"); + + String mimeType = "application/pdf"; + + Response.ResponseBuilder resp = Response.ok(buff); + resp.type(MediaType.APPLICATION_OCTET_STREAM); + resp.header(HttpHeaders.CONTENT_LENGTH, buff.length); + resp.header(HttpHeaders.CONTENT_TYPE, mimeType); + resp.header(HttpHeaders.CONTENT_DISPOSITION, + "inline; " + "filename=\"Attestation d'affiliation " + Utils.getSaison() + "-" + + (Utils.getSaison() + 1) + " de " + m.getName() + ".pdf\""); + return resp.build(); + } catch (Exception e) { + throw new IOException(e); + } + })); + } + + private byte[] make_pdf(ClubModel m) throws IOException, InterruptedException { + List cmd = new ArrayList<>(); + cmd.add("java"); + cmd.add("-jar"); + cmd.add(pdfMakerJarPath); + + UUID uuid = UUID.randomUUID(); + + cmd.add("/tmp/" + uuid + ".pdf"); + cmd.add("club"); + cmd.add(m.getName()); + cmd.add(Utils.getSaison() + ""); + cmd.add(m.getNo_affiliation() + ""); + cmd.add(new File(sign_file).getAbsolutePath()); + + return getPdf(cmd, uuid); + } + + static byte[] getPdf(List cmd, UUID uuid) throws IOException, InterruptedException { + ProcessBuilder processBuilder = new ProcessBuilder(cmd); + processBuilder.redirectErrorStream(true); + Process process = processBuilder.start(); + + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + + StringBuilder builder = new StringBuilder(); + Thread t = new Thread(() -> { + try { + String line; + while ((line = reader.readLine()) != null) + builder.append(line).append("\n"); + } catch (Exception ignored) { + } + }); + t.start(); + + int code = -1; + if (!process.waitFor(30, TimeUnit.SECONDS)) { + process.destroy(); + builder.append("Timeout..."); + } else { + code = process.exitValue(); + } + + if (t.isAlive()) + t.interrupt(); + + PDFService.LOGGER.debug("PDF maker: " + builder); + + if (code != 0) { + throw new IOException("Error code: " + code); + } else { + File file = new File("/tmp/" + uuid + ".pdf"); + try (FileInputStream fis = new FileInputStream(file)) { + byte[] buff = fis.readAllBytes(); + //noinspection ResultOfMethodCallIgnored + file.delete(); + return buff; + } catch (IOException e) { + //noinspection ResultOfMethodCallIgnored + file.delete(); + } + return null; + } + } +} diff --git a/src/main/java/fr/titionfire/ffsaf/rest/ClubEndpoints.java b/src/main/java/fr/titionfire/ffsaf/rest/ClubEndpoints.java index a9e7657..1b3a2c2 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/ClubEndpoints.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/ClubEndpoints.java @@ -2,6 +2,7 @@ package fr.titionfire.ffsaf.rest; import fr.titionfire.ffsaf.data.model.ClubModel; import fr.titionfire.ffsaf.domain.service.ClubService; +import fr.titionfire.ffsaf.domain.service.PDFService; import fr.titionfire.ffsaf.net2.data.SimpleClubModel; import fr.titionfire.ffsaf.rest.data.*; import fr.titionfire.ffsaf.rest.exception.DForbiddenException; @@ -39,6 +40,9 @@ public class ClubEndpoints { @Inject ClubService clubService; + @Inject + PDFService pdfService; + @Inject SecurityCtx securityCtx; @@ -219,7 +223,7 @@ public class ClubEndpoints { @APIResponse(responseCode = "500", description = "Erreur interne du serveur") }) public Uni getAffiliation(@Parameter(description = "Identifiant de club") @PathParam("id") long id) { - return clubService.getAffiliationPdf(id); + return pdfService.getAffiliationPdf(id); } @GET @@ -268,7 +272,7 @@ public class ClubEndpoints { @APIResponse(responseCode = "500", description = "Erreur interne du serveur") }) public Uni getMeAffiliation() { - return clubService.getAffiliationPdf(securityCtx.getSubject()); + return pdfService.getAffiliationPdf(securityCtx.getSubject()); } @GET diff --git a/src/main/java/fr/titionfire/ffsaf/rest/MembreEndpoints.java b/src/main/java/fr/titionfire/ffsaf/rest/MembreEndpoints.java index 1227bd7..cc0794b 100644 --- a/src/main/java/fr/titionfire/ffsaf/rest/MembreEndpoints.java +++ b/src/main/java/fr/titionfire/ffsaf/rest/MembreEndpoints.java @@ -2,6 +2,7 @@ package fr.titionfire.ffsaf.rest; import fr.titionfire.ffsaf.data.model.MembreModel; import fr.titionfire.ffsaf.domain.service.MembreService; +import fr.titionfire.ffsaf.domain.service.PDFService; import fr.titionfire.ffsaf.rest.data.MeData; import fr.titionfire.ffsaf.rest.data.SimpleMembre; import fr.titionfire.ffsaf.rest.exception.DForbiddenException; @@ -34,6 +35,9 @@ public class MembreEndpoints { @Inject MembreService membreService; + @Inject + PDFService pdfService; + @ConfigProperty(name = "upload_dir") String media; @@ -106,7 +110,7 @@ public class MembreEndpoints { @APIResponse(responseCode = "500", description = "Erreur interne du serveur") }) public Uni getMeLicence() { - return membreService.getLicencePdf(securityCtx.getSubject()); + return pdfService.getLicencePdf(securityCtx.getSubject()); } @GET @@ -151,6 +155,6 @@ public class MembreEndpoints { @APIResponse(responseCode = "500", description = "Erreur interne du serveur") }) public Uni getLicencePDF(@PathParam("id") long id) { - return membreService.getLicencePdf(membreService.getByIdWithLicence(id).onItem().invoke(checkPerm)); + return pdfService.getLicencePdf(membreService.getByIdWithLicence(id).onItem().invoke(checkPerm)); } }