feat: club remove
This commit is contained in:
@@ -55,15 +55,29 @@ public class AffiliationService {
|
||||
|
||||
public Uni<String> save(AffiliationRequestForm form) {
|
||||
AffiliationRequestModel affModel = form.toModel();
|
||||
affModel.setSaison(Utils.getSaison());
|
||||
int currentSaison = Utils.getSaison();
|
||||
|
||||
// noinspection ResultOfMethodCallIgnored
|
||||
return repositoryRequest.count("siret = ?1 and saison = ?2", affModel.getSiret(), affModel.getSaison())
|
||||
return Uni.createFrom().item(affModel)
|
||||
.invoke(Unchecked.consumer(model -> {
|
||||
if (model.getSaison() != currentSaison && model.getSaison() != currentSaison + 1) {
|
||||
throw new IllegalArgumentException("Saison not valid");
|
||||
}
|
||||
}))
|
||||
.chain(() -> repositoryRequest.count("siret = ?1 and saison = ?2", affModel.getSiret(),
|
||||
affModel.getSaison()))
|
||||
.onItem().invoke(Unchecked.consumer(count -> {
|
||||
if (count != 0) {
|
||||
throw new IllegalArgumentException("Affiliation request already exists");
|
||||
}
|
||||
}))
|
||||
.chain(() -> clubRepository.find("SIRET = ?1", affModel.getSiret()).firstResult().chain(club ->
|
||||
repository.count("club = ?1 and saison = ?2", club, affModel.getSaison())))
|
||||
.onItem().invoke(Unchecked.consumer(count -> {
|
||||
if (count != 0) {
|
||||
throw new IllegalArgumentException("Affiliation already exists");
|
||||
}
|
||||
}))
|
||||
.map(o -> affModel)
|
||||
.call(model -> ((model.getM1_lincence() != -1) ? combRepository.find("licence",
|
||||
model.getM1_lincence()).count().invoke(count -> {
|
||||
@@ -289,7 +303,12 @@ public class AffiliationService {
|
||||
|
||||
public Uni<SimpleAffiliation> setAffiliation(long id, int saison) {
|
||||
return clubRepository.findById(id)
|
||||
.onItem().ifNull().failWith(new NotFoundException("Affiliation request not found"))
|
||||
.onItem().ifNull().failWith(new NotFoundException("Club non trouver"))
|
||||
.invoke(Unchecked.consumer(club -> {
|
||||
if (club.getAffiliations().stream().anyMatch(affiliation -> affiliation.getSaison() == saison)) {
|
||||
throw new IllegalArgumentException("Affiliation deja existante");
|
||||
}
|
||||
}))
|
||||
.chain(club ->
|
||||
Panache.withTransaction(() -> repository.persist(new AffiliationModel(null, club, saison))))
|
||||
.map(SimpleAffiliation::fromModel);
|
||||
|
||||
@@ -4,12 +4,15 @@ import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import fr.titionfire.ffsaf.data.model.ClubModel;
|
||||
import fr.titionfire.ffsaf.data.repository.ClubRepository;
|
||||
import fr.titionfire.ffsaf.data.repository.CombRepository;
|
||||
import fr.titionfire.ffsaf.net2.ServerCustom;
|
||||
import fr.titionfire.ffsaf.net2.data.SimpleClubModel;
|
||||
import fr.titionfire.ffsaf.net2.request.SReqClub;
|
||||
import fr.titionfire.ffsaf.rest.from.FullClubForm;
|
||||
import fr.titionfire.ffsaf.utils.Contact;
|
||||
import fr.titionfire.ffsaf.utils.PageResult;
|
||||
import fr.titionfire.ffsaf.utils.RoleAsso;
|
||||
import fr.titionfire.ffsaf.utils.Utils;
|
||||
import io.quarkus.hibernate.reactive.panache.Panache;
|
||||
import io.quarkus.hibernate.reactive.panache.PanacheQuery;
|
||||
import io.quarkus.hibernate.reactive.panache.common.WithSession;
|
||||
@@ -21,6 +24,7 @@ import io.smallrye.mutiny.unchecked.Unchecked;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.BadRequestException;
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
import org.hibernate.reactive.mutiny.Mutiny;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -39,6 +43,15 @@ public class ClubService {
|
||||
@Inject
|
||||
ServerCustom serverCustom;
|
||||
|
||||
@Inject
|
||||
CombRepository combRepository;
|
||||
|
||||
@Inject
|
||||
KeycloakService keycloakService;
|
||||
|
||||
@ConfigProperty(name = "upload_dir")
|
||||
String media;
|
||||
|
||||
public SimpleClubModel findByIdOptionalClub(long id) throws Throwable {
|
||||
return VertxContextSupport.subscribeAndAwait(
|
||||
() -> Panache.withTransaction(() -> repository.findById(id).map(SimpleClubModel::fromModel)));
|
||||
@@ -115,6 +128,7 @@ public class ClubService {
|
||||
m.setContact_intern(input.getContact_intern());
|
||||
m.setRNA(input.getRna());
|
||||
m.setSIRET(input.getSiret());
|
||||
m.setAddress(input.getAddress());
|
||||
|
||||
try {
|
||||
m.setContact(MAPPER.readValue(input.getContact(), typeRef));
|
||||
@@ -134,6 +148,22 @@ public class ClubService {
|
||||
}
|
||||
|
||||
public Uni<?> delete(long id) {
|
||||
return Uni.createFrom().nullItem();
|
||||
return repository.findById(id)
|
||||
.chain(club -> combRepository.list("club = ?1", club)
|
||||
.map(combModels -> combModels.stream().peek(combModel -> {
|
||||
combModel.setClub(null);
|
||||
combModel.setRole(RoleAsso.MEMBRE);
|
||||
}).toList())
|
||||
.call(list -> Uni.join().all(list.stream().filter(m -> m.getUserId() != null)
|
||||
.map(m -> keycloakService.clearUser(m.getUserId())).toList()).andCollectFailures())
|
||||
.chain(list -> Panache.withTransaction(() -> combRepository.persist(list)))
|
||||
.map(o -> club)
|
||||
)
|
||||
.call(clubModel -> (clubModel.getClubId() == null) ? Uni.createFrom()
|
||||
.voidItem() : keycloakService.removeClubGroup(clubModel.getClubId()))
|
||||
.invoke(membreModel -> SReqClub.sendRmIfNeed(serverCustom.clients, id))
|
||||
.chain(clubModel -> Panache.withTransaction(() -> repository.delete(clubModel)))
|
||||
.call(__ -> Utils.deleteMedia(id, media, "ppClub"))
|
||||
.call(__ -> Utils.deleteMedia(id, media, "clubStatus"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,21 +49,26 @@ public class KeycloakService {
|
||||
return vertx.getOrCreateContext().executeBlocking(() -> {
|
||||
GroupRepresentation clubGroup =
|
||||
keycloak.realm(realm).groups().groups().stream().filter(g -> g.getName().equals("club"))
|
||||
.findAny().orElseThrow(() -> new KeycloakException("Fail to fetch group %s".formatted("club")));
|
||||
.findAny()
|
||||
.orElseThrow(() -> new KeycloakException("Fail to fetch group %s".formatted("club")));
|
||||
|
||||
GroupRepresentation groupRepresentation = new GroupRepresentation();
|
||||
groupRepresentation.setName(club.getId() + "-" + club.getName());
|
||||
|
||||
try (Response response =
|
||||
keycloak.realm(realm).groups().group(clubGroup.getId()).subGroup(groupRepresentation)) {
|
||||
if (!response.getStatusInfo().equals(Response.Status.CREATED) && !response.getStatusInfo().equals(Response.Status.CONFLICT))
|
||||
throw new KeycloakException("Fail to set group parent for club: %s (reason=%s)".formatted(club.getName(),
|
||||
response.getStatusInfo().getReasonPhrase()));
|
||||
if (!response.getStatusInfo().equals(Response.Status.CREATED) && !response.getStatusInfo()
|
||||
.equals(Response.Status.CONFLICT))
|
||||
throw new KeycloakException(
|
||||
"Fail to set group parent for club: %s (reason=%s)".formatted(club.getName(),
|
||||
response.getStatusInfo().getReasonPhrase()));
|
||||
}
|
||||
|
||||
return keycloak.realm(realm).groups().group(clubGroup.getId()).getSubGroups(0, 1000, true).stream()
|
||||
.filter(g -> g.getName().startsWith(club.getId() + "-")).findAny().map(GroupRepresentation::getId)
|
||||
.orElseThrow(() -> new KeycloakException("Fail to fetch group %s*".formatted(club.getId() + "-")));
|
||||
.filter(g -> g.getName().startsWith(club.getId() + "-")).findAny()
|
||||
.map(GroupRepresentation::getId)
|
||||
.orElseThrow(
|
||||
() -> new KeycloakException("Fail to fetch group %s*".formatted(club.getId() + "-")));
|
||||
}
|
||||
).call(id -> clubService.setClubId(club.getId(), id));
|
||||
}
|
||||
@@ -72,21 +77,24 @@ public class KeycloakService {
|
||||
|
||||
public Uni<String> getUserFromMember(MembreModel membreModel) {
|
||||
if (membreModel.getUserId() == null) {
|
||||
return Uni.createFrom().failure(new NullPointerException("No keycloak user linked to the user id=" + membreModel.getId()));
|
||||
return Uni.createFrom()
|
||||
.failure(new NullPointerException("No keycloak user linked to the user id=" + membreModel.getId()));
|
||||
}
|
||||
return Uni.createFrom().item(membreModel::getUserId);
|
||||
}
|
||||
|
||||
public Uni<String> setClubGroupMembre(MembreModel membreModel, ClubModel club) {
|
||||
return getGroupFromClub(club).chain(
|
||||
clubId -> getUserFromMember(membreModel).chain(userId -> vertx.getOrCreateContext().executeBlocking(() -> {
|
||||
UserResource user = keycloak.realm(realm).users().get(userId);
|
||||
user.groups().stream().filter(g -> g.getPath().startsWith("/club")).forEach(g -> user.leaveGroup(g.getId()));
|
||||
user.joinGroup(clubId);
|
||||
LOGGER.infof("Set club \"%s\" to user %s (%s)", club.getName(), userId,
|
||||
user.toRepresentation().getUsername());
|
||||
return "OK";
|
||||
})));
|
||||
clubId -> getUserFromMember(membreModel).chain(
|
||||
userId -> vertx.getOrCreateContext().executeBlocking(() -> {
|
||||
UserResource user = keycloak.realm(realm).users().get(userId);
|
||||
user.groups().stream().filter(g -> g.getPath().startsWith("/club"))
|
||||
.forEach(g -> user.leaveGroup(g.getId()));
|
||||
user.joinGroup(clubId);
|
||||
LOGGER.infof("Set club \"%s\" to user %s (%s)", club.getName(), userId,
|
||||
user.toRepresentation().getUsername());
|
||||
return "OK";
|
||||
})));
|
||||
}
|
||||
|
||||
public Uni<?> setEmail(String userId, String email) {
|
||||
@@ -104,13 +112,14 @@ public class KeycloakService {
|
||||
|
||||
public Uni<?> setAutoRoleMembre(String id, RoleAsso role, GradeArbitrage gradeArbitrage) {
|
||||
List<String> toRemove = new ArrayList<>(List.of("club_president", "club_tresorier", "club_secretaire",
|
||||
"asseseur", "arbitre"));
|
||||
"club_respo_intra", "asseseur", "arbitre"));
|
||||
List<String> toAdd = new ArrayList<>();
|
||||
|
||||
switch (role) {
|
||||
case PRESIDENT -> toAdd.add("club_president");
|
||||
case TRESORIER -> toAdd.add("club_tresorier");
|
||||
case SECRETAIRE -> toAdd.add("club_secretaire");
|
||||
case PRESIDENT, VPRESIDENT -> toAdd.add("club_president");
|
||||
case TRESORIER, VTRESORIER -> toAdd.add("club_tresorier");
|
||||
case SECRETAIRE, VSECRETAIRE -> toAdd.add("club_secretaire");
|
||||
case MEMBREBUREAU -> toAdd.add("club_respo_intra");
|
||||
}
|
||||
switch (gradeArbitrage) {
|
||||
case ARBITRE -> toAdd.addAll(List.of("asseseur", "arbitre"));
|
||||
@@ -132,7 +141,8 @@ public class KeycloakService {
|
||||
|
||||
public Uni<List<String>> fetchRole(String id) {
|
||||
return vertx.getOrCreateContext().executeBlocking(() ->
|
||||
keycloak.realm(realm).users().get(id).roles().realmLevel().listEffective().stream().map(RoleRepresentation::getName).toList());
|
||||
keycloak.realm(realm).users().get(id).roles().realmLevel().listEffective().stream()
|
||||
.map(RoleRepresentation::getName).toList());
|
||||
}
|
||||
|
||||
public Uni<?> updateRole(String id, List<String> toAdd, List<String> toRemove) {
|
||||
@@ -184,13 +194,15 @@ public class KeycloakService {
|
||||
RequiredAction.UPDATE_PASSWORD.name()));
|
||||
|
||||
try (Response response = keycloak.realm(realm).users().create(user)) {
|
||||
if (!response.getStatusInfo().equals(Response.Status.CREATED) && !response.getStatusInfo().equals(Response.Status.CONFLICT))
|
||||
if (!response.getStatusInfo().equals(Response.Status.CREATED) && !response.getStatusInfo()
|
||||
.equals(Response.Status.CONFLICT))
|
||||
throw new KeycloakException("Fail to creat user %s (reason=%s)".formatted(login,
|
||||
response.getStatusInfo().getReasonPhrase()));
|
||||
}
|
||||
|
||||
String finalLogin = login;
|
||||
return getUser(login).orElseThrow(() -> new KeycloakException("Fail to fetch user %s".formatted(finalLogin)));
|
||||
return getUser(login).orElseThrow(
|
||||
() -> new KeycloakException("Fail to fetch user %s".formatted(finalLogin)));
|
||||
})
|
||||
//.invoke(user -> keycloak.realm(realm).users().get(user.getId()) // TODO enable for production
|
||||
// .executeActionsEmail(List.of(RequiredAction.VERIFY_EMAIL.name(),
|
||||
@@ -216,6 +228,30 @@ public class KeycloakService {
|
||||
});
|
||||
}
|
||||
|
||||
public Uni<?> removeClubGroup(String clubId) {
|
||||
return vertx.getOrCreateContext().executeBlocking(() -> {
|
||||
keycloak.realm(realm).groups().group(clubId).remove();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
public Uni<?> clearUser(String userId) {
|
||||
List<String> toRemove = new ArrayList<>(
|
||||
List.of("club_president", "club_tresorier", "club_secretaire", "club_respo_intra"));
|
||||
|
||||
return vertx.getOrCreateContext().executeBlocking(() -> {
|
||||
UserResource user = keycloak.realm(realm).users().get(userId);
|
||||
|
||||
RoleScopeResource resource = user.roles().realmLevel();
|
||||
List<RoleRepresentation> roles = keycloak.realm(realm).roles().list();
|
||||
resource.remove(roles.stream().filter(r -> toRemove.contains(r.getName())).toList());
|
||||
|
||||
user.groups().stream().filter(g -> g.getPath().startsWith("/club"))
|
||||
.forEach(g -> user.leaveGroup(g.getId()));
|
||||
return "OK";
|
||||
});
|
||||
}
|
||||
|
||||
private Optional<UserRepresentation> getUser(String username) {
|
||||
List<UserRepresentation> users = keycloak.realm(realm).users().searchByUsername(username, true);
|
||||
|
||||
@@ -226,7 +262,9 @@ public class KeycloakService {
|
||||
}
|
||||
|
||||
private String makeLogin(MembreModel model) {
|
||||
return Normalizer.normalize((model.getFname().toLowerCase() + "." + model.getLname().toLowerCase()).replace(' ', '_'), Normalizer.Form.NFD)
|
||||
return Normalizer.normalize(
|
||||
(model.getFname().toLowerCase() + "." + model.getLname().toLowerCase()).replace(' ', '_'),
|
||||
Normalizer.Form.NFD)
|
||||
.replaceAll("\\p{M}", "");
|
||||
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ public class MembreService {
|
||||
RoleAsso source = RoleAsso.MEMBRE;
|
||||
if (securityIdentity.getRoles().contains("club_president")) source = RoleAsso.PRESIDENT;
|
||||
else if (securityIdentity.getRoles().contains("club_secretaire")) source = RoleAsso.SECRETAIRE;
|
||||
else if (securityIdentity.getRoles().contains("club_respo_intra")) source = RoleAsso.SECRETAIRE;
|
||||
else if (securityIdentity.getRoles().contains("club_respo_intra")) source = RoleAsso.MEMBREBUREAU;
|
||||
if (!membre.getRole().equals(membreModel.getRole()) && membre.getRole().level > source.level)
|
||||
throw new ForbiddenException();
|
||||
}))
|
||||
|
||||
Reference in New Issue
Block a user