package fr.titionfire.ffsaf.rest; import fr.titionfire.ffsaf.domain.service.KeycloakService; import fr.titionfire.ffsaf.rest.exception.DForbiddenException; import fr.titionfire.ffsaf.rest.from.MemberPermForm; import fr.titionfire.ffsaf.utils.GroupeUtils; import fr.titionfire.ffsaf.utils.Pair; import io.quarkus.security.identity.SecurityIdentity; import io.smallrye.mutiny.Uni; import io.vertx.mutiny.core.Vertx; import jakarta.annotation.security.RolesAllowed; import jakarta.inject.Inject; import jakarta.ws.rs.GET; import jakarta.ws.rs.PUT; import jakarta.ws.rs.Path; import jakarta.ws.rs.PathParam; import org.eclipse.microprofile.jwt.JsonWebToken; import org.eclipse.microprofile.openapi.annotations.Operation; import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; import org.eclipse.microprofile.openapi.annotations.tags.Tag; import org.keycloak.representations.idm.GroupRepresentation; import java.util.ArrayList; import java.util.List; @Tag(name = "Compte", description = "Gestion des comptes utilisateurs") @Path("api/compte") public class CompteEndpoints { @Inject KeycloakService service; @Inject JsonWebToken idToken; @Inject SecurityIdentity securityIdentity; @Inject Vertx vertx; @GET @Path("{id}") @RolesAllowed({"federation_admin", "club_president", "club_secretaire", "club_respo_intra"}) @Operation(summary = "Renvoie les informations d'un compte utilisateur", description = "Renvoie les informations d'un" + " compte utilisateur en fonction de son identifiant long (UUID)") @APIResponses(value = { @APIResponse(responseCode = "200", description = "Les informations du compte utilisateur"), @APIResponse(responseCode = "403", description = "Accès refusé"), @APIResponse(responseCode = "404", description = "Le compte utilisateur n'existe pas"), @APIResponse(responseCode = "500", description = "Erreur interne du serveur") }) public Uni getCompte(@PathParam("id") String id) { return service.fetchCompte(id).call(pair -> vertx.getOrCreateContext().executeBlocking(() -> { if (!securityIdentity.getRoles().contains("federation_admin") && pair.getKey().groups().stream() .map(GroupRepresentation::getPath) .noneMatch(s -> s.startsWith("/club/") && GroupeUtils.contains(s, idToken))) throw new DForbiddenException(); return pair; })).map(Pair::getValue); } @PUT @Path("{id}/init") @RolesAllowed("federation_admin") @Operation(summary = "Initialise un compte utilisateur", description = "Initialise un compte utilisateur en fonction" + " de son identifiant") @APIResponses(value = { @APIResponse(responseCode = "204", description = "Le compte utilisateur a été initialisé 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 initCompte(@PathParam("id") long id) { return service.initCompte(id); } @PUT @Path("{id}/setUUID/{nid}") @RolesAllowed("federation_admin") @Operation(hidden = true) public Uni initCompte(@PathParam("id") long id, @PathParam("nid") String nid) { return service.setId(id, nid); } @GET @Path("{id}/roles") @RolesAllowed("federation_admin") @Operation(summary = "Renvoie les rôles d'un compte utilisateur", description = "Renvoie les rôles d'un compte" + " utilisateur en fonction de son identifiant") @APIResponses(value = { @APIResponse(responseCode = "200", description = "Les rôles du compte utilisateur"), @APIResponse(responseCode = "403", description = "Accès refusé"), @APIResponse(responseCode = "404", description = "Le compte utilisateur n'existe pas"), @APIResponse(responseCode = "500", description = "Erreur interne du serveur") }) public Uni> getRole(@PathParam("id") String id) { return service.fetchRole(id); } @PUT @Path("{id}/roles") @RolesAllowed("federation_admin") @Operation(summary = "Met à jour les rôles d'un compte utilisateur", description = "Met à jour les rôles d'un compte" + " utilisateur en fonction de son identifiant et des rôles fournis dans le formulaire") @APIResponses(value = { @APIResponse(responseCode = "204", description = "Les rôles du compte utilisateur ont été mis à jour avec succès"), @APIResponse(responseCode = "403", description = "Accès refusé"), @APIResponse(responseCode = "404", description = "Le compte utilisateur n'existe pas"), @APIResponse(responseCode = "500", description = "Erreur interne du serveur") }) public Uni updateRole(@PathParam("id") String id, MemberPermForm form) { List toAdd = new ArrayList<>(); List toRemove = new ArrayList<>(); if (form.isFederation_admin()) toAdd.add("federation_admin"); else toRemove.add("federation_admin"); if (form.isSafca_super_admin()) toAdd.add("safca_super_admin"); else toRemove.add("safca_super_admin"); if (form.isSafca_user()) toAdd.add("safca_user"); else toRemove.add("safca_user"); if (form.isSafca_create_compet()) toAdd.add("safca_create_compet"); else toRemove.add("safca_create_compet"); return service.updateRole(id, toAdd, toRemove); } }