package fr.titionfire.ffsaf.rest; import fr.titionfire.ffsaf.domain.service.MembreService; import fr.titionfire.ffsaf.rest.data.SimpleMembre; import fr.titionfire.ffsaf.rest.exception.DInternalError; import fr.titionfire.ffsaf.rest.from.ClubMemberForm; import fr.titionfire.ffsaf.rest.from.FullMemberForm; import fr.titionfire.ffsaf.utils.PageResult; import fr.titionfire.ffsaf.utils.SecurityCtx; import fr.titionfire.ffsaf.utils.Utils; import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.unchecked.Unchecked; import jakarta.annotation.security.RolesAllowed; import jakarta.inject.Inject; import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.eclipse.microprofile.openapi.annotations.Operation; import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; import org.eclipse.microprofile.openapi.annotations.tags.Tag; @Tag(name = "Membre club", description = "Gestion des membres (pour les clubs)") @RolesAllowed({"club_president", "club_secretaire", "club_respo_intra"}) @Path("api/member") public class MembreClubEndpoints { @Inject MembreService membreService; @ConfigProperty(name = "upload_dir") String media; @Inject SecurityCtx securityCtx; @GET @Path("/find/club") @Produces(MediaType.APPLICATION_JSON) @Operation(summary = "Recherche des membres par critères", description = "Recherche des membres en " + "fonction de critères tels que le nom, le prénom, etc.") @APIResponses(value = { @APIResponse(responseCode = "200", description = "La liste des membres correspondant aux critères de recherche"), @APIResponse(responseCode = "500", description = "Erreur interne du serveur") }) public Uni> getFindClub( @Parameter(description = "Nombre max de résulta (max 50)") @QueryParam("limit") Integer limit, @Parameter(description = "Page à consulter") @QueryParam("page") Integer page, @Parameter(description = "Text à rechercher") @QueryParam("search") String search) { if (limit == null) limit = 50; if (page == null || page < 1) page = 1; return membreService.search(limit, page - 1, search, securityCtx.getSubject()); } @PUT @Path("club/{id}") @Produces(MediaType.TEXT_PLAIN) @Consumes(MediaType.MULTIPART_FORM_DATA) @Operation(summary = "Met à jour les informations d'un membre en fonction de son identifiant", description = "Met à jour les informations d'un membre en fonction de son identifiant") @APIResponses(value = { @APIResponse(responseCode = "200", description = "Le membre a été mis à jour avec succès"), @APIResponse(responseCode = "403", description = "Accès refusé"), @APIResponse(responseCode = "404", description = "Le membre n'existe pas"), @APIResponse(responseCode = "500", description = "Erreur interne du serveur") }) public Uni setMembre( @Parameter(description = "Identifiant de membre") @PathParam("id") long id, ClubMemberForm input) { return membreService.update(id, input, securityCtx) .invoke(Unchecked.consumer(out -> { if (!out.equals("OK")) throw new InternalError("Fail to update data: " + out); })).chain(() -> { if (input.getPhoto_data().length > 0) return Uni.createFrom().future(Utils.replacePhoto(id, input.getPhoto_data(), media, "ppMembre" )).invoke(Unchecked.consumer(out -> { if (!out.equals("OK")) throw new DInternalError("Impossible de reconnaitre le fichier: " + out); })); else return Uni.createFrom().nullItem(); }); } @POST @Path("club") @Produces(MediaType.TEXT_PLAIN) @Consumes(MediaType.MULTIPART_FORM_DATA) @Operation(summary = "Ajoute un nouveau membre", description = "Ajoute un nouveau membre avec les informations " + "fournies dans le formulaire") @APIResponses(value = { @APIResponse(responseCode = "200", description = "Le membre a été ajouté avec succès"), @APIResponse(responseCode = "400", description = "Les données envoyées sont invalides"), @APIResponse(responseCode = "500", description = "Erreur interne du serveur") }) public Uni addMembre(FullMemberForm input) { return membreService.add(input, securityCtx.getSubject()) .invoke(Unchecked.consumer(id -> { if (id == null) throw new InternalError("Fail to creat member data"); })).call(id -> { if (input.getPhoto_data().length > 0) return Uni.createFrom().future(Utils.replacePhoto(id, input.getPhoto_data(), media, "ppMembre" )); else return Uni.createFrom().nullItem(); }); } @DELETE @Path("club/{id}") @Produces(MediaType.TEXT_PLAIN) @Operation(summary = "Supprime un membre en fonction de son identifiant", description = "Supprime " + "un membre en fonction de son identifiant, ainsi que toutes les informations associées") @APIResponses(value = { @APIResponse(responseCode = "204", description = "Le membre a été supprimé avec succès"), @APIResponse(responseCode = "403", description = "Accès refusé"), @APIResponse(responseCode = "404", description = "Le membre n'existe pas"), @APIResponse(responseCode = "500", description = "Erreur interne du serveur") }) public Uni deleteMembre( @Parameter(description = "Identifiant de membre") @PathParam("id") long id) { return membreService.delete(id, securityCtx); } }