package fr.titionfire.ffsaf.rest; import fr.titionfire.ffsaf.data.model.MembreModel; import fr.titionfire.ffsaf.domain.service.MembreService; import fr.titionfire.ffsaf.rest.data.SimpleMembre; import fr.titionfire.ffsaf.rest.from.ClubMemberForm; import fr.titionfire.ffsaf.rest.from.FullMemberForm; import fr.titionfire.ffsaf.utils.GroupeUtils; import fr.titionfire.ffsaf.utils.PageResult; import fr.titionfire.ffsaf.utils.Utils; import io.quarkus.oidc.IdToken; import io.quarkus.security.Authenticated; import io.quarkus.security.identity.SecurityIdentity; 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 jakarta.ws.rs.core.Response; import jodd.net.MimeTypes; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.eclipse.microprofile.jwt.JsonWebToken; import java.io.*; import java.net.URISyntaxException; import java.net.URLConnection; import java.nio.file.Files; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Future; import java.util.function.Consumer; @Authenticated @Path("api/member") public class CombEndpoints { @Inject MembreService membreService; @ConfigProperty(name = "upload_dir") String media; @Inject @IdToken JsonWebToken idToken; @Inject SecurityIdentity securityIdentity; Consumer checkPerm = Unchecked.consumer(membreModel -> { if (!securityIdentity.getRoles().contains("federation_admin") && !GroupeUtils.isInClubGroup( membreModel.getClub().getId(), idToken)) throw new ForbiddenException(); }); @GET @Path("/find/admin") @RolesAllowed({"federation_admin"}) @Produces(MediaType.APPLICATION_JSON) public Uni> getFindAdmin(@QueryParam("limit") Integer limit, @QueryParam("page") Integer page, @QueryParam("search") String search, @QueryParam("club") String club) { if (limit == null) limit = 50; if (page == null || page < 1) page = 1; return membreService.searchAdmin(limit, page - 1, search, club); } @GET @Path("/find/similar") @RolesAllowed({"federation_admin"}) @Produces(MediaType.APPLICATION_JSON) public Uni> getSimilar(@QueryParam("fname") String fname, @QueryParam("lname") String lname) { return membreService.getSimilar(fname, lname); } @GET @Path("/find/club") @RolesAllowed({"club_president", "club_secretaire", "club_respo_intra"}) @Produces(MediaType.APPLICATION_JSON) public Uni> getFindClub(@QueryParam("limit") Integer limit, @QueryParam("page") Integer page, @QueryParam("search") String search) { if (limit == null) limit = 50; if (page == null || page < 1) page = 1; return membreService.search(limit, page - 1, search, idToken.getSubject()); } @GET @Path("{id}") @RolesAllowed({"federation_admin", "club_president", "club_secretaire", "club_respo_intra"}) @Produces(MediaType.APPLICATION_JSON) public Uni getById(@PathParam("id") long id) { return membreService.getById(id).onItem().invoke(checkPerm).map(SimpleMembre::fromModel); } @GET @Path("/find/licence") @RolesAllowed({"federation_admin", "club_president", "club_secretaire", "club_respo_intra"}) @Produces(MediaType.APPLICATION_JSON) public Uni getByLicence(@QueryParam("id") long id) { return membreService.getByLicence(id).onItem().invoke(checkPerm).map(SimpleMembre::fromModel); } @PUT @Path("{id}") @RolesAllowed({"federation_admin"}) @Produces(MediaType.TEXT_PLAIN) @Consumes(MediaType.MULTIPART_FORM_DATA) public Uni setAdminMembre(@PathParam("id") long id, FullMemberForm input) { return membreService.update(id, input) .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 InternalError("Fail to get MimeType " + out); })); else return Uni.createFrom().nullItem(); }); } @POST @RolesAllowed({"federation_admin"}) @Produces(MediaType.TEXT_PLAIN) @Consumes(MediaType.MULTIPART_FORM_DATA) public Uni addAdminMembre(FullMemberForm input) { return membreService.add(input) .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("{id}") @RolesAllowed({"federation_admin"}) @Produces(MediaType.TEXT_PLAIN) public Uni deleteAdminMembre(@PathParam("id") long id) { return membreService.delete(id); } @PUT @Path("club/{id}") @RolesAllowed({"club_president", "club_secretaire", "club_respo_intra"}) @Produces(MediaType.TEXT_PLAIN) @Consumes(MediaType.MULTIPART_FORM_DATA) public Uni setMembre(@PathParam("id") long id, ClubMemberForm input) { return membreService.update(id, input, idToken, securityIdentity) .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 InternalError("Fail to get MimeType " + out); })); else return Uni.createFrom().nullItem(); }); } @POST @Path("club") @RolesAllowed({"club_president", "club_secretaire", "club_respo_intra"}) @Produces(MediaType.TEXT_PLAIN) @Consumes(MediaType.MULTIPART_FORM_DATA) public Uni addMembre(FullMemberForm input) { return membreService.add(input, idToken.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}") @RolesAllowed({"club_president", "club_secretaire", "club_respo_intra"}) @Produces(MediaType.TEXT_PLAIN) public Uni deleteMembre(@PathParam("id") long id) { return membreService.delete(id, idToken); } @GET @Path("{id}/photo") @RolesAllowed({"federation_admin", "club_president", "club_secretaire", "club_respo_intra"}) public Uni getPhoto(@PathParam("id") long id) throws URISyntaxException { return Utils.getMediaFile(id, media, "ppMembre", membreService.getById(id).onItem().invoke(checkPerm)); } }