competition rework #51
@ -1,20 +1,17 @@
|
|||||||
package fr.titionfire.ffsaf.data.id;
|
package fr.titionfire.ffsaf.data.id;
|
||||||
|
|
||||||
import fr.titionfire.ffsaf.data.model.CompetitionModel;
|
import jakarta.persistence.Embeddable;
|
||||||
import fr.titionfire.ffsaf.data.model.MembreModel;
|
import lombok.*;
|
||||||
import jakarta.persistence.JoinColumn;
|
|
||||||
import jakarta.persistence.ManyToOne;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
@Data
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EqualsAndHashCode
|
||||||
|
@Embeddable
|
||||||
public class RegisterId implements Serializable {
|
public class RegisterId implements Serializable {
|
||||||
@ManyToOne
|
private Long competitionId;
|
||||||
@JoinColumn(name = "id_competition")
|
private Long membreId;
|
||||||
private CompetitionModel competition;
|
|
||||||
|
|
||||||
@ManyToOne
|
|
||||||
@JoinColumn(name = "id_membre")
|
|
||||||
private MembreModel membre;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,8 +17,8 @@ import java.util.List;
|
|||||||
@RegisterForReflection
|
@RegisterForReflection
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "poule")
|
@Table(name = "category")
|
||||||
public class PouleModel {
|
public class CategoryModel {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
Long id;
|
Long id;
|
||||||
@ -34,11 +34,11 @@ public class PouleModel {
|
|||||||
CompetitionModel compet;
|
CompetitionModel compet;
|
||||||
|
|
||||||
@OneToMany(fetch = FetchType.LAZY)
|
@OneToMany(fetch = FetchType.LAZY)
|
||||||
@JoinColumn(name = "id_poule", referencedColumnName = "id")
|
@JoinColumn(name = "id_category", referencedColumnName = "id")
|
||||||
List<MatchModel> matchs;
|
List<MatchModel> matchs;
|
||||||
|
|
||||||
@OneToMany(fetch = FetchType.LAZY)
|
@OneToMany(fetch = FetchType.LAZY)
|
||||||
@JoinColumn(name = "id_poule", referencedColumnName = "id")
|
@JoinColumn(name = "id_category", referencedColumnName = "id")
|
||||||
List<TreeModel> tree;
|
List<TreeModel> tree;
|
||||||
|
|
||||||
Integer type;
|
Integer type;
|
||||||
@ -1,6 +1,7 @@
|
|||||||
package fr.titionfire.ffsaf.data.model;
|
package fr.titionfire.ffsaf.data.model;
|
||||||
|
|
||||||
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
||||||
|
import fr.titionfire.ffsaf.utils.RegisterMode;
|
||||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
@ -21,6 +22,7 @@ import java.util.List;
|
|||||||
@Table(name = "compet")
|
@Table(name = "compet")
|
||||||
public class CompetitionModel {
|
public class CompetitionModel {
|
||||||
@Id
|
@Id
|
||||||
|
@Access(AccessType.PROPERTY)
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
Long id;
|
Long id;
|
||||||
|
|
||||||
@ -36,9 +38,26 @@ public class CompetitionModel {
|
|||||||
String uuid;
|
String uuid;
|
||||||
|
|
||||||
Date date;
|
Date date;
|
||||||
|
Date todate;
|
||||||
|
|
||||||
|
@Column(columnDefinition = "TEXT")
|
||||||
|
String description;
|
||||||
|
String adresse;
|
||||||
|
|
||||||
|
Date startRegister;
|
||||||
|
Date endRegister;
|
||||||
|
|
||||||
|
RegisterMode registerMode;
|
||||||
|
|
||||||
|
boolean publicVisible;
|
||||||
|
|
||||||
@OneToMany(mappedBy = "competition", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
|
@OneToMany(mappedBy = "competition", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
|
||||||
List<RegisterModel> insc;
|
List<RegisterModel> insc;
|
||||||
|
|
||||||
String owner;
|
String owner;
|
||||||
|
|
||||||
|
String data1;
|
||||||
|
String data2;
|
||||||
|
String data3;
|
||||||
|
String data4;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,10 +41,10 @@ public class MatchModel {
|
|||||||
String c2_str = null;
|
String c2_str = null;
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.EAGER)
|
@ManyToOne(fetch = FetchType.EAGER)
|
||||||
@JoinColumn(name = "id_poule", referencedColumnName = "id")
|
@JoinColumn(name = "id_category", referencedColumnName = "id")
|
||||||
PouleModel poule = null;
|
CategoryModel category = null;
|
||||||
|
|
||||||
long poule_ord = 0;
|
long category_ord = 0;
|
||||||
|
|
||||||
boolean isEnd = true;
|
boolean isEnd = true;
|
||||||
|
|
||||||
@ -52,5 +52,5 @@ public class MatchModel {
|
|||||||
@CollectionTable(name = "score", joinColumns = @JoinColumn(name = "id_match"))
|
@CollectionTable(name = "score", joinColumns = @JoinColumn(name = "id_match"))
|
||||||
List<ScoreEmbeddable> scores = new ArrayList<>();
|
List<ScoreEmbeddable> scores = new ArrayList<>();
|
||||||
|
|
||||||
char groupe = 'A';
|
char poule = 'A';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,14 +17,17 @@ import lombok.Setter;
|
|||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "register")
|
@Table(name = "register")
|
||||||
@IdClass(RegisterId.class)
|
|
||||||
public class RegisterModel {
|
public class RegisterModel {
|
||||||
@Id
|
|
||||||
|
@EmbeddedId
|
||||||
|
RegisterId id;
|
||||||
|
|
||||||
|
@MapsId("competitionId")
|
||||||
@ManyToOne(fetch = FetchType.LAZY)
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
@JoinColumn(name = "id_competition")
|
@JoinColumn(name = "id_competition")
|
||||||
CompetitionModel competition;
|
CompetitionModel competition;
|
||||||
|
|
||||||
@Id
|
@MapsId("membreId")
|
||||||
@ManyToOne(fetch = FetchType.EAGER)
|
@ManyToOne(fetch = FetchType.EAGER)
|
||||||
@JoinColumn(name = "id_membre")
|
@JoinColumn(name = "id_membre")
|
||||||
MembreModel membre;
|
MembreModel membre;
|
||||||
@ -37,4 +40,14 @@ public class RegisterModel {
|
|||||||
@JoinColumn(name = "club")
|
@JoinColumn(name = "club")
|
||||||
ClubModel club = null;
|
ClubModel club = null;
|
||||||
|
|
||||||
|
public RegisterModel(CompetitionModel competition, MembreModel membre, Integer weight, int overCategory,
|
||||||
|
Categorie categorie, ClubModel club) {
|
||||||
|
this.id = new RegisterId(competition.getId(), membre.getId());
|
||||||
|
this.competition = competition;
|
||||||
|
this.membre = membre;
|
||||||
|
this.weight = weight;
|
||||||
|
this.overCategory = overCategory;
|
||||||
|
this.categorie = categorie;
|
||||||
|
this.club = club;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,8 +20,8 @@ public class TreeModel {
|
|||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
Long id;
|
Long id;
|
||||||
|
|
||||||
@Column(name = "id_poule")
|
@Column(name = "id_category")
|
||||||
Long poule;
|
Long category;
|
||||||
|
|
||||||
Integer level;
|
Integer level;
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
package fr.titionfire.ffsaf.data.repository;
|
package fr.titionfire.ffsaf.data.repository;
|
||||||
|
|
||||||
import fr.titionfire.ffsaf.data.model.PouleModel;
|
import fr.titionfire.ffsaf.data.model.CategoryModel;
|
||||||
import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase;
|
import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase;
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
|
||||||
@ApplicationScoped
|
@ApplicationScoped
|
||||||
public class PouleRepository implements PanacheRepositoryBase<PouleModel, Long> {
|
public class CategoryRepository implements PanacheRepositoryBase<CategoryModel, Long> {
|
||||||
}
|
}
|
||||||
@ -1,9 +1,11 @@
|
|||||||
package fr.titionfire.ffsaf.data.repository;
|
package fr.titionfire.ffsaf.data.repository;
|
||||||
|
|
||||||
|
import fr.titionfire.ffsaf.data.id.RegisterId;
|
||||||
import fr.titionfire.ffsaf.data.model.RegisterModel;
|
import fr.titionfire.ffsaf.data.model.RegisterModel;
|
||||||
import io.quarkus.hibernate.reactive.panache.PanacheRepository;
|
import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase;
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
|
||||||
@ApplicationScoped
|
@ApplicationScoped
|
||||||
public class RegisterRepository implements PanacheRepository<RegisterModel> {
|
public class RegisterRepository implements PanacheRepositoryBase<RegisterModel, RegisterId> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,11 +2,11 @@ package fr.titionfire.ffsaf.domain.service;
|
|||||||
|
|
||||||
import fr.titionfire.ffsaf.data.model.MatchModel;
|
import fr.titionfire.ffsaf.data.model.MatchModel;
|
||||||
import fr.titionfire.ffsaf.data.model.MembreModel;
|
import fr.titionfire.ffsaf.data.model.MembreModel;
|
||||||
import fr.titionfire.ffsaf.data.model.PouleModel;
|
import fr.titionfire.ffsaf.data.model.CategoryModel;
|
||||||
import fr.titionfire.ffsaf.data.model.TreeModel;
|
import fr.titionfire.ffsaf.data.model.TreeModel;
|
||||||
import fr.titionfire.ffsaf.data.repository.*;
|
import fr.titionfire.ffsaf.data.repository.*;
|
||||||
import fr.titionfire.ffsaf.rest.data.PouleData;
|
import fr.titionfire.ffsaf.rest.data.CategoryData;
|
||||||
import fr.titionfire.ffsaf.rest.data.PouleFullData;
|
import fr.titionfire.ffsaf.rest.data.CategoryFullData;
|
||||||
import fr.titionfire.ffsaf.rest.data.TreeData;
|
import fr.titionfire.ffsaf.rest.data.TreeData;
|
||||||
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
||||||
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
||||||
@ -25,10 +25,10 @@ import java.util.stream.Stream;
|
|||||||
|
|
||||||
@WithSession
|
@WithSession
|
||||||
@ApplicationScoped
|
@ApplicationScoped
|
||||||
public class PouleService {
|
public class CategoryService {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
PouleRepository repository;
|
CategoryRepository repository;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
CompetitionRepository competRepository;
|
CompetitionRepository competRepository;
|
||||||
@ -45,35 +45,21 @@ public class PouleService {
|
|||||||
@Inject
|
@Inject
|
||||||
CompetPermService permService;
|
CompetPermService permService;
|
||||||
|
|
||||||
public Uni<PouleData> getById(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
|
public Uni<CategoryData> getByIdAdmin(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
|
||||||
return repository.find("systemId = ?1 AND system = ?2", id, system)
|
return repository.find("systemId = ?1 AND system = ?2", id, system)
|
||||||
.firstResult()
|
.firstResult()
|
||||||
.onItem().ifNull().failWith(() -> new RuntimeException("Poule not found"))
|
.onItem().ifNull().failWith(() -> new RuntimeException("Poule not found"))
|
||||||
.call(data -> permService.hasViewPerm(securityCtx, data.getCompet()))
|
.call(data -> permService.hasAdminViewPerm(securityCtx, data.getCompet()))
|
||||||
.map(PouleData::fromModel);
|
.map(CategoryData::fromModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uni<List<PouleData>> getAll(SecurityCtx securityCtx, CompetitionSystem system) {
|
public Uni<List<CategoryData>> getAllAdmin(SecurityCtx securityCtx, CompetitionSystem system) {
|
||||||
return repository.list("system = ?1", system)
|
return permService.getAllHaveAdminAccess(securityCtx)
|
||||||
.chain(o ->
|
.chain(ids -> repository.list("system = ?1 AND compet.id IN ?2", system, ids))
|
||||||
permService.getAllHaveAccess(securityCtx.getSubject())
|
.map(pouleModels -> pouleModels.stream().map(CategoryData::fromModel).toList());
|
||||||
.chain(map -> Uni.createFrom().item(o.stream()
|
|
||||||
.filter(p -> {
|
|
||||||
if (securityCtx.getSubject().equals(p.getCompet().getOwner()))
|
|
||||||
return true;
|
|
||||||
if (p.getSystem() == CompetitionSystem.SAFCA) {
|
|
||||||
if (map.containsKey(p.getCompet().getId()))
|
|
||||||
return map.get(p.getId()).equals("admin");
|
|
||||||
return securityCtx.roleHas("federation_admin")
|
|
||||||
|| securityCtx.roleHas("safca_super_admin");
|
|
||||||
}
|
|
||||||
return securityCtx.roleHas("federation_admin");
|
|
||||||
})
|
|
||||||
.map(PouleData::fromModel).toList())
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uni<PouleData> addOrUpdate(SecurityCtx securityCtx, CompetitionSystem system, PouleData data) {
|
public Uni<CategoryData> addOrUpdate(SecurityCtx securityCtx, CompetitionSystem system, CategoryData data) {
|
||||||
return repository.find("systemId = ?1 AND system = ?2", data.getId(), system).firstResult()
|
return repository.find("systemId = ?1 AND system = ?2", data.getId(), system).firstResult()
|
||||||
.chain(o -> {
|
.chain(o -> {
|
||||||
if (o == null) {
|
if (o == null) {
|
||||||
@ -81,7 +67,7 @@ public class PouleService {
|
|||||||
.onItem().ifNull().failWith(() -> new RuntimeException("Competition not found"))
|
.onItem().ifNull().failWith(() -> new RuntimeException("Competition not found"))
|
||||||
.call(o2 -> permService.hasEditPerm(securityCtx, o2))
|
.call(o2 -> permService.hasEditPerm(securityCtx, o2))
|
||||||
.chain(competitionModel -> {
|
.chain(competitionModel -> {
|
||||||
PouleModel model = new PouleModel();
|
CategoryModel model = new CategoryModel();
|
||||||
|
|
||||||
model.setId(null);
|
model.setId(null);
|
||||||
model.setSystem(system);
|
model.setSystem(system);
|
||||||
@ -99,7 +85,7 @@ public class PouleService {
|
|||||||
o.setType(data.getType());
|
o.setType(data.getType());
|
||||||
return Panache.withTransaction(() -> repository.persist(o));
|
return Panache.withTransaction(() -> repository.persist(o));
|
||||||
}
|
}
|
||||||
}).map(PouleData::fromModel);
|
}).map(CategoryData::fromModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private MatchModel findMatch(List<MatchModel> matchModelList, Long id) {
|
private MatchModel findMatch(List<MatchModel> matchModelList, Long id) {
|
||||||
@ -128,7 +114,7 @@ public class PouleService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Uni<TreeModel> persisteTree(TreeData data, List<TreeModel> node, PouleModel poule,
|
private Uni<TreeModel> persisteTree(TreeData data, List<TreeModel> node, CategoryModel poule,
|
||||||
List<MatchModel> matchModelList) {
|
List<MatchModel> matchModelList) {
|
||||||
TreeModel mm = findNode(node, data.getMatch());
|
TreeModel mm = findNode(node, data.getMatch());
|
||||||
if (mm == null) {
|
if (mm == null) {
|
||||||
@ -136,7 +122,7 @@ public class PouleService {
|
|||||||
mm.setId(null);
|
mm.setId(null);
|
||||||
}
|
}
|
||||||
mm.setLevel(data.getLevel());
|
mm.setLevel(data.getLevel());
|
||||||
mm.setPoule(poule.getId());
|
mm.setCategory(poule.getId());
|
||||||
mm.setMatch(findMatch(matchModelList, data.getMatch()));
|
mm.setMatch(findMatch(matchModelList, data.getMatch()));
|
||||||
|
|
||||||
return Uni.createFrom().item(mm)
|
return Uni.createFrom().item(mm)
|
||||||
@ -147,7 +133,7 @@ public class PouleService {
|
|||||||
.chain(o -> Panache.withTransaction(() -> treeRepository.persist(o)));
|
.chain(o -> Panache.withTransaction(() -> treeRepository.persist(o)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uni<?> syncPoule(SecurityCtx securityCtx, CompetitionSystem system, PouleFullData data) {
|
public Uni<?> syncCategory(SecurityCtx securityCtx, CompetitionSystem system, CategoryFullData data) {
|
||||||
return repository.find("systemId = ?1 AND system = ?2", data.getId(), system)
|
return repository.find("systemId = ?1 AND system = ?2", data.getId(), system)
|
||||||
.firstResult()
|
.firstResult()
|
||||||
.onItem().ifNotNull().call(o2 -> permService.hasEditPerm(securityCtx, o2.getCompet()))
|
.onItem().ifNotNull().call(o2 -> permService.hasEditPerm(securityCtx, o2.getCompet()))
|
||||||
@ -156,7 +142,7 @@ public class PouleService {
|
|||||||
.onItem().ifNull().failWith(() -> new RuntimeException("Compet not found"))
|
.onItem().ifNull().failWith(() -> new RuntimeException("Compet not found"))
|
||||||
.call(o -> permService.hasEditPerm(securityCtx, o))
|
.call(o -> permService.hasEditPerm(securityCtx, o))
|
||||||
.map(o -> {
|
.map(o -> {
|
||||||
PouleModel model = new PouleModel();
|
CategoryModel model = new CategoryModel();
|
||||||
model.setId(null);
|
model.setId(null);
|
||||||
model.setSystem(system);
|
model.setSystem(system);
|
||||||
model.setSystemId(data.getId());
|
model.setSystemId(data.getId());
|
||||||
@ -172,10 +158,10 @@ public class PouleService {
|
|||||||
o.setType(data.getType());
|
o.setType(data.getType());
|
||||||
|
|
||||||
WorkData workData = new WorkData();
|
WorkData workData = new WorkData();
|
||||||
workData.poule = o;
|
workData.category = o;
|
||||||
return workData;
|
return workData;
|
||||||
})
|
})
|
||||||
.call(o -> Panache.withTransaction(() -> repository.persist(o.poule)))
|
.call(o -> Panache.withTransaction(() -> repository.persist(o.category)))
|
||||||
.call(o -> (data.getMatches() == null || data.getMatches().isEmpty()) ? Uni.createFrom().nullItem() :
|
.call(o -> (data.getMatches() == null || data.getMatches().isEmpty()) ? Uni.createFrom().nullItem() :
|
||||||
Uni.createFrom()
|
Uni.createFrom()
|
||||||
.item(data.getMatches().stream().flatMap(m -> Stream.of(m.getC1_id(), m.getC2_id())
|
.item(data.getMatches().stream().flatMap(m -> Stream.of(m.getC1_id(), m.getC2_id())
|
||||||
@ -187,7 +173,7 @@ public class PouleService {
|
|||||||
)
|
)
|
||||||
.invoke(in -> {
|
.invoke(in -> {
|
||||||
ArrayList<TreeModel> node = new ArrayList<>();
|
ArrayList<TreeModel> node = new ArrayList<>();
|
||||||
for (TreeModel treeModel : in.poule.getTree())
|
for (TreeModel treeModel : in.category.getTree())
|
||||||
flatTreeChild(treeModel, node);
|
flatTreeChild(treeModel, node);
|
||||||
|
|
||||||
ArrayList<TreeData> new_node = new ArrayList<>();
|
ArrayList<TreeData> new_node = new ArrayList<>();
|
||||||
@ -204,7 +190,7 @@ public class PouleService {
|
|||||||
n.setLeft(null);
|
n.setLeft(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
in.toRmMatch = in.poule.getMatchs().stream()
|
in.toRmMatch = in.category.getMatchs().stream()
|
||||||
.filter(m -> data.getMatches().stream().noneMatch(m2 -> m2.getId().equals(m.getSystemId())))
|
.filter(m -> data.getMatches().stream().noneMatch(m2 -> m2.getId().equals(m.getSystemId())))
|
||||||
.map(MatchModel::getId).toList();
|
.map(MatchModel::getId).toList();
|
||||||
})
|
})
|
||||||
@ -219,21 +205,21 @@ public class PouleService {
|
|||||||
.call(in -> data.getMatches().isEmpty() ? Uni.createFrom().nullItem() :
|
.call(in -> data.getMatches().isEmpty() ? Uni.createFrom().nullItem() :
|
||||||
Uni.join().all(
|
Uni.join().all(
|
||||||
data.getMatches().stream().map(m -> {
|
data.getMatches().stream().map(m -> {
|
||||||
MatchModel mm = findMatch(in.poule.getMatchs(), m.getId());
|
MatchModel mm = findMatch(in.category.getMatchs(), m.getId());
|
||||||
if (mm == null) {
|
if (mm == null) {
|
||||||
mm = new MatchModel();
|
mm = new MatchModel();
|
||||||
mm.setId(null);
|
mm.setId(null);
|
||||||
mm.setSystem(system);
|
mm.setSystem(system);
|
||||||
mm.setSystemId(m.getId());
|
mm.setSystemId(m.getId());
|
||||||
}
|
}
|
||||||
mm.setPoule(in.poule);
|
mm.setCategory(in.category);
|
||||||
mm.setPoule_ord(m.getPoule_ord());
|
mm.setCategory_ord(m.getCategory_ord());
|
||||||
mm.setC1_str(m.getC1_str());
|
mm.setC1_str(m.getC1_str());
|
||||||
mm.setC2_str(m.getC2_str());
|
mm.setC2_str(m.getC2_str());
|
||||||
mm.setC1_id(in.membres.getOrDefault(m.getC1_id(), null));
|
mm.setC1_id(in.membres.getOrDefault(m.getC1_id(), null));
|
||||||
mm.setC2_id(in.membres.getOrDefault(m.getC2_id(), null));
|
mm.setC2_id(in.membres.getOrDefault(m.getC2_id(), null));
|
||||||
mm.setEnd(m.isEnd());
|
mm.setEnd(m.isEnd());
|
||||||
mm.setGroupe(m.getGroupe());
|
mm.setPoule(m.getPoule());
|
||||||
mm.getScores().clear();
|
mm.getScores().clear();
|
||||||
mm.getScores().addAll(m.getScores());
|
mm.getScores().addAll(m.getScores());
|
||||||
|
|
||||||
@ -244,13 +230,13 @@ public class PouleService {
|
|||||||
.andCollectFailures())
|
.andCollectFailures())
|
||||||
.call(in -> data.getTrees().isEmpty() ? Uni.createFrom().nullItem() :
|
.call(in -> data.getTrees().isEmpty() ? Uni.createFrom().nullItem() :
|
||||||
Uni.join().all(data.getTrees().stream()
|
Uni.join().all(data.getTrees().stream()
|
||||||
.map(m -> persisteTree(m, in.poule.getTree(), in.poule, in.match)).toList())
|
.map(m -> persisteTree(m, in.category.getTree(), in.category, in.match)).toList())
|
||||||
.andCollectFailures())
|
.andCollectFailures())
|
||||||
.map(__ -> "OK");
|
.map(__ -> "OK");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class WorkData {
|
private static class WorkData {
|
||||||
PouleModel poule;
|
CategoryModel category;
|
||||||
HashMap<Long, MembreModel> membres = new HashMap<>();
|
HashMap<Long, MembreModel> membres = new HashMap<>();
|
||||||
List<MatchModel> match = new ArrayList<>();
|
List<MatchModel> match = new ArrayList<>();
|
||||||
List<Long> toRmMatch;
|
List<Long> toRmMatch;
|
||||||
@ -2,11 +2,13 @@ package fr.titionfire.ffsaf.domain.service;
|
|||||||
|
|
||||||
import fr.titionfire.ffsaf.data.model.CompetitionModel;
|
import fr.titionfire.ffsaf.data.model.CompetitionModel;
|
||||||
import fr.titionfire.ffsaf.data.repository.CompetitionRepository;
|
import fr.titionfire.ffsaf.data.repository.CompetitionRepository;
|
||||||
|
import fr.titionfire.ffsaf.data.repository.RegisterRepository;
|
||||||
import fr.titionfire.ffsaf.net2.ServerCustom;
|
import fr.titionfire.ffsaf.net2.ServerCustom;
|
||||||
import fr.titionfire.ffsaf.net2.data.SimpleCompet;
|
import fr.titionfire.ffsaf.net2.data.SimpleCompet;
|
||||||
import fr.titionfire.ffsaf.net2.request.SReqCompet;
|
import fr.titionfire.ffsaf.net2.request.SReqCompet;
|
||||||
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
|
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
|
||||||
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
||||||
|
import fr.titionfire.ffsaf.utils.RegisterMode;
|
||||||
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
||||||
import io.quarkus.cache.Cache;
|
import io.quarkus.cache.Cache;
|
||||||
import io.quarkus.cache.CacheName;
|
import io.quarkus.cache.CacheName;
|
||||||
@ -15,7 +17,10 @@ import io.smallrye.mutiny.unchecked.Unchecked;
|
|||||||
import jakarta.enterprise.context.ApplicationScoped;
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
@ -28,6 +33,9 @@ public class CompetPermService {
|
|||||||
@Inject
|
@Inject
|
||||||
ServerCustom serverCustom;
|
ServerCustom serverCustom;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
CompetitionRepository competitionRepository;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@CacheName("safca-config")
|
@CacheName("safca-config")
|
||||||
Cache cache;
|
Cache cache;
|
||||||
@ -37,13 +45,16 @@ public class CompetPermService {
|
|||||||
Cache cacheAccess;
|
Cache cacheAccess;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
CompetitionRepository competitionRepository;
|
@CacheName("have-access")
|
||||||
|
Cache cacheNoneAccess;
|
||||||
|
@Inject
|
||||||
|
RegisterRepository registerRepository;
|
||||||
|
|
||||||
|
|
||||||
public Uni<SimpleCompet> getSafcaConfig(long id) {
|
public Uni<SimpleCompet> getSafcaConfig(long id) {
|
||||||
return cache.get(id, k -> {
|
return cache.get(id, k -> {
|
||||||
CompletableFuture<SimpleCompet> f = new CompletableFuture<>();
|
CompletableFuture<SimpleCompet> f = new CompletableFuture<>();
|
||||||
SReqCompet.getConfig(serverCustom.clients, id, f);
|
SReqCompet.getConfig(serverCustom.clients, id, f);
|
||||||
System.out.println("get config");
|
|
||||||
try {
|
try {
|
||||||
return f.get(1500, TimeUnit.MILLISECONDS);
|
return f.get(1500, TimeUnit.MILLISECONDS);
|
||||||
} catch (InterruptedException | ExecutionException | TimeoutException e) {
|
} catch (InterruptedException | ExecutionException | TimeoutException e) {
|
||||||
@ -52,61 +63,172 @@ public class CompetPermService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uni<HashMap<Long, String>> getAllHaveAccess(String subject) {
|
public Uni<List<Long>> getAllHaveAdminAccess(SecurityCtx securityCtx) {
|
||||||
return cacheAccess.get(subject, k -> {
|
ArrayList<Long> out = new ArrayList<>();
|
||||||
CompletableFuture<HashMap<Long, String>> f = new CompletableFuture<>();
|
|
||||||
SReqCompet.getAllHaveAccess(serverCustom.clients, subject, f);
|
Uni<HashMap<Long, String>> safca = cacheAccess.getAsync(securityCtx.getSubject(),
|
||||||
System.out.println("get all have access");
|
k -> competitionRepository.list("system = ?1", CompetitionSystem.SAFCA)
|
||||||
try {
|
.chain(competitionModels -> {
|
||||||
return f.get(1500, TimeUnit.MILLISECONDS);
|
CompletableFuture<HashMap<String, String>> f = new CompletableFuture<>();
|
||||||
} catch (InterruptedException | ExecutionException | TimeoutException e) {
|
SReqCompet.getAllHaveAccess(serverCustom.clients, securityCtx.getSubject(), f);
|
||||||
throw new RuntimeException(e);
|
return Uni.createFrom().future(f, Duration.ofMillis(1500))
|
||||||
}
|
.map(map_ -> {
|
||||||
});
|
HashMap<Long, String> map = new HashMap<>();
|
||||||
|
map_.forEach((key, value) -> map.put(Long.parseLong(key), value));
|
||||||
|
|
||||||
|
for (CompetitionModel model : competitionModels) {
|
||||||
|
if (model.getOwner().equals(securityCtx.getSubject()))
|
||||||
|
map.putIfAbsent(model.getId(), "owner");
|
||||||
|
else if (securityCtx.roleHas("federation_admin")
|
||||||
|
|| securityCtx.roleHas("safca_super_admin"))
|
||||||
|
map.putIfAbsent(model.getId(), "admin");
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
});
|
||||||
|
}))
|
||||||
|
.onFailure().call(throwable -> cacheAccess.invalidate(securityCtx.getSubject()));
|
||||||
|
|
||||||
|
Uni<HashMap<Long, String>> none = cacheNoneAccess.getAsync(securityCtx.getSubject(),
|
||||||
|
k -> competitionRepository.list("system = ?1", CompetitionSystem.NONE)
|
||||||
|
.map(competitionModels -> {
|
||||||
|
HashMap<Long, String> map = new HashMap<>();
|
||||||
|
for (CompetitionModel model : competitionModels) {
|
||||||
|
if (model.getOwner().equals(securityCtx.getSubject()))
|
||||||
|
map.putIfAbsent(model.getId(), "owner");
|
||||||
|
else if (securityCtx.roleHas("federation_admin"))
|
||||||
|
map.putIfAbsent(model.getId(), "admin");
|
||||||
|
else if (securityCtx.isInClubGroup(model.getClub().getId()) && (securityCtx.roleHas(
|
||||||
|
"club_president")
|
||||||
|
|| securityCtx.roleHas("club_respo_intra") || securityCtx.roleHas(
|
||||||
|
"club_secretaire")
|
||||||
|
|| securityCtx.roleHas("club_tresorier")))
|
||||||
|
map.putIfAbsent(model.getId(), "admin");
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}));
|
||||||
|
|
||||||
|
return safca.invoke(map ->
|
||||||
|
map.forEach((k, v) -> {
|
||||||
|
if (v.equals("owner") || v.equals("admin"))
|
||||||
|
out.add(k);
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.call(__ -> none.invoke(map ->
|
||||||
|
map.forEach((k, v) -> {
|
||||||
|
if (v.equals("owner") || v.equals("admin"))
|
||||||
|
out.add(k);
|
||||||
|
})
|
||||||
|
))
|
||||||
|
.map(__ -> out.stream().distinct().toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has view perm
|
||||||
|
*/
|
||||||
public Uni<CompetitionModel> hasViewPerm(SecurityCtx securityCtx, CompetitionModel competitionModel) {
|
public Uni<CompetitionModel> hasViewPerm(SecurityCtx securityCtx, CompetitionModel competitionModel) {
|
||||||
return hasViewPerm(securityCtx, Uni.createFrom().item(competitionModel));
|
return hasViewPerm(securityCtx, Uni.createFrom().item(competitionModel));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has view perm
|
||||||
|
*/
|
||||||
public Uni<CompetitionModel> hasViewPerm(SecurityCtx securityCtx, long id) {
|
public Uni<CompetitionModel> hasViewPerm(SecurityCtx securityCtx, long id) {
|
||||||
return hasViewPerm(securityCtx, competitionRepository.findById(id));
|
return hasViewPerm(securityCtx, competitionRepository.findById(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Uni<CompetitionModel> hasViewPerm(SecurityCtx securityCtx, Uni<CompetitionModel> in) {
|
/**
|
||||||
return in.call(o -> (
|
* @return {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has view perm
|
||||||
securityCtx.getSubject().equals(o.getOwner()) || securityCtx.roleHas("federation_admin")) ?
|
*/
|
||||||
Uni.createFrom().nullItem()
|
public Uni<CompetitionModel> hasViewPerm(SecurityCtx securityCtx, Uni<CompetitionModel> in) {
|
||||||
:
|
return in.call(cm -> (cm.isPublicVisible() || cm.getRegisterMode() == RegisterMode.FREE
|
||||||
o.getSystem() == CompetitionSystem.SAFCA ?
|
|| cm.getRegisterMode() == RegisterMode.HELLOASSO
|
||||||
hasSafcaViewPerm(securityCtx, o.getId())
|
|| (cm.getRegisterMode() == RegisterMode.CLUB_ADMIN && securityCtx.isClubAdmin())) ?
|
||||||
: Uni.createFrom().nullItem().invoke(Unchecked.consumer(__ -> {
|
Uni.createFrom().nullItem() :
|
||||||
if (!securityCtx.isInClubGroup(o.getClub().getId()))
|
hasAdminViewPerm(securityCtx, cm).onFailure()
|
||||||
throw new DForbiddenException();
|
.recoverWithUni(__ ->
|
||||||
})
|
registerRepository.count("membre.userId = ?1 AND competition = ?2",
|
||||||
));
|
securityCtx.getSubject(), cm).map(Unchecked.function(c -> {
|
||||||
|
if (c == 0)
|
||||||
|
throw new DForbiddenException();
|
||||||
|
return cm;
|
||||||
|
}))
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has admin view perm
|
||||||
|
*/
|
||||||
|
public Uni<CompetitionModel> hasAdminViewPerm(SecurityCtx securityCtx, CompetitionModel competitionModel) {
|
||||||
|
return hasAdminViewPerm(securityCtx, Uni.createFrom().item(competitionModel));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has admin view perm
|
||||||
|
*/
|
||||||
|
public Uni<CompetitionModel> hasAdminViewPerm(SecurityCtx securityCtx, long id) {
|
||||||
|
return hasAdminViewPerm(securityCtx, competitionRepository.findById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has admin view perm
|
||||||
|
*/
|
||||||
|
public Uni<CompetitionModel> hasAdminViewPerm(SecurityCtx securityCtx, Uni<CompetitionModel> in) {
|
||||||
|
return in.call(Unchecked.function(o -> {
|
||||||
|
if (securityCtx.getSubject().equals(o.getOwner()) || securityCtx.roleHas("federation_admin"))
|
||||||
|
return Uni.createFrom().nullItem();
|
||||||
|
|
||||||
|
if (o.getSystem() == CompetitionSystem.SAFCA)
|
||||||
|
return hasSafcaViewPerm(securityCtx, o.getId());
|
||||||
|
|
||||||
|
if (!securityCtx.isInClubGroup(o.getClub().getId())) // Only membre club pass here
|
||||||
|
throw new DForbiddenException();
|
||||||
|
|
||||||
|
if (o.getSystem() == CompetitionSystem.NONE)
|
||||||
|
if (securityCtx.roleHas("club_president") || securityCtx.roleHas("club_respo_intra")
|
||||||
|
|| securityCtx.roleHas("club_secretaire") || securityCtx.roleHas("club_tresorier"))
|
||||||
|
return Uni.createFrom().nullItem();
|
||||||
|
|
||||||
|
throw new DForbiddenException();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has edit perm
|
||||||
|
*/
|
||||||
public Uni<CompetitionModel> hasEditPerm(SecurityCtx securityCtx, CompetitionModel competitionModel) {
|
public Uni<CompetitionModel> hasEditPerm(SecurityCtx securityCtx, CompetitionModel competitionModel) {
|
||||||
return hasEditPerm(securityCtx, Uni.createFrom().item(competitionModel));
|
return hasEditPerm(securityCtx, Uni.createFrom().item(competitionModel));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has edit perm
|
||||||
|
*/
|
||||||
public Uni<CompetitionModel> hasEditPerm(SecurityCtx securityCtx, long id) {
|
public Uni<CompetitionModel> hasEditPerm(SecurityCtx securityCtx, long id) {
|
||||||
return hasEditPerm(securityCtx, competitionRepository.findById(id));
|
return hasEditPerm(securityCtx, competitionRepository.findById(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has edit perm
|
||||||
|
*/
|
||||||
public Uni<CompetitionModel> hasEditPerm(SecurityCtx securityCtx, Uni<CompetitionModel> in) {
|
public Uni<CompetitionModel> hasEditPerm(SecurityCtx securityCtx, Uni<CompetitionModel> in) {
|
||||||
return in.call(o -> (
|
return in.call(Unchecked.function(o -> {
|
||||||
securityCtx.getSubject().equals(o.getOwner()) || securityCtx.roleHas("federation_admin")) ?
|
if (securityCtx.getSubject().equals(o.getOwner()) || securityCtx.roleHas("federation_admin"))
|
||||||
Uni.createFrom().nullItem()
|
return Uni.createFrom().nullItem();
|
||||||
:
|
|
||||||
o.getSystem() == CompetitionSystem.SAFCA ?
|
if (o.getSystem() == CompetitionSystem.SAFCA)
|
||||||
hasSafcaEditPerm(securityCtx, o.getId())
|
return hasSafcaEditPerm(securityCtx, o.getId());
|
||||||
: Uni.createFrom().nullItem().invoke(Unchecked.consumer(__ -> {
|
|
||||||
if (!securityCtx.isInClubGroup(o.getClub().getId()))
|
if (!securityCtx.isInClubGroup(o.getClub().getId())) // Only membre club pass here
|
||||||
throw new DForbiddenException();
|
throw new DForbiddenException();
|
||||||
})
|
|
||||||
));
|
if (o.getSystem() == CompetitionSystem.NONE)
|
||||||
|
if (securityCtx.isClubAdmin())
|
||||||
|
return Uni.createFrom().nullItem();
|
||||||
|
|
||||||
|
throw new DForbiddenException();
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Uni<?> hasSafcaViewPerm(SecurityCtx securityCtx, long id) {
|
private Uni<?> hasSafcaViewPerm(SecurityCtx securityCtx, long id) {
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import fr.titionfire.ffsaf.rest.data.SimpleRegisterComb;
|
|||||||
import fr.titionfire.ffsaf.rest.exception.DBadRequestException;
|
import fr.titionfire.ffsaf.rest.exception.DBadRequestException;
|
||||||
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
|
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
|
||||||
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
||||||
|
import fr.titionfire.ffsaf.utils.RegisterMode;
|
||||||
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
||||||
import fr.titionfire.ffsaf.utils.Utils;
|
import fr.titionfire.ffsaf.utils.Utils;
|
||||||
import io.quarkus.cache.Cache;
|
import io.quarkus.cache.Cache;
|
||||||
@ -41,11 +42,14 @@ public class CompetitionService {
|
|||||||
CompetitionRepository repository;
|
CompetitionRepository repository;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
PouleRepository pouleRepository;
|
CategoryRepository categoryRepository;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
MatchRepository matchRepository;
|
MatchRepository matchRepository;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
RegisterRepository registerRepository;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
KeycloakService keycloakService;
|
KeycloakService keycloakService;
|
||||||
|
|
||||||
@ -68,16 +72,23 @@ public class CompetitionService {
|
|||||||
@Inject
|
@Inject
|
||||||
@CacheName("safca-have-access")
|
@CacheName("safca-have-access")
|
||||||
Cache cacheAccess;
|
Cache cacheAccess;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
RegisterRepository registerRepository;
|
@CacheName("have-access")
|
||||||
|
Cache cacheNoneAccess;
|
||||||
|
|
||||||
public Uni<CompetitionData> getById(SecurityCtx securityCtx, Long id) {
|
public Uni<CompetitionData> getById(SecurityCtx securityCtx, Long id) {
|
||||||
|
return permService.hasViewPerm(securityCtx, id).map(CompetitionData::fromModelLight);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Uni<CompetitionData> getByIdAdmin(SecurityCtx securityCtx, Long id) {
|
||||||
if (id == 0) {
|
if (id == 0) {
|
||||||
return Uni.createFrom()
|
return Uni.createFrom()
|
||||||
.item(new CompetitionData(null, "", "", new Date(), CompetitionSystem.SAFCA,
|
.item(new CompetitionData(null, "", "", "", "", new Date(), new Date(),
|
||||||
null, "", "", null));
|
CompetitionSystem.NONE, RegisterMode.FREE, new Date(), new Date(), true,
|
||||||
|
null, "", "", null, true, "", "", "", ""));
|
||||||
}
|
}
|
||||||
return permService.hasViewPerm(securityCtx, id)
|
return permService.hasAdminViewPerm(securityCtx, id)
|
||||||
.chain(competitionModel -> Mutiny.fetch(competitionModel.getInsc())
|
.chain(competitionModel -> Mutiny.fetch(competitionModel.getInsc())
|
||||||
.map(insc -> CompetitionData.fromModel(competitionModel).addInsc(insc)))
|
.map(insc -> CompetitionData.fromModel(competitionModel).addInsc(insc)))
|
||||||
.chain(data ->
|
.chain(data ->
|
||||||
@ -90,60 +101,52 @@ public class CompetitionService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Uni<List<CompetitionData>> getAll(SecurityCtx securityCtx) {
|
public Uni<List<CompetitionData>> getAll(SecurityCtx securityCtx) {
|
||||||
return repository.listAll()
|
List<CompetitionData> out = new ArrayList<>();
|
||||||
.chain(o ->
|
return permService.getAllHaveAdminAccess(securityCtx)
|
||||||
permService.getAllHaveAccess(securityCtx.getSubject())
|
.call(ids -> repository.list("id IN ?1", ids)
|
||||||
.chain(map -> Uni.createFrom().item(o.stream()
|
.invoke(cm -> {
|
||||||
.filter(p -> {
|
out.addAll(cm.stream().map(CompetitionData::fromModelLight).toList());
|
||||||
if (securityCtx.getSubject().equals(p.getOwner()))
|
out.forEach(competition -> competition.setCanEdit(true));
|
||||||
return true;
|
}))
|
||||||
if (p.getSystem() == CompetitionSystem.SAFCA) {
|
.call(ids ->
|
||||||
if (map.containsKey(p.getId()))
|
repository.list("id NOT IN ?1 AND (publicVisible = TRUE OR registerMode IN ?2)", ids,
|
||||||
return map.get(p.getId()).equals("admin");
|
securityCtx.isClubAdmin() ? List.of(RegisterMode.FREE, RegisterMode.HELLOASSO,
|
||||||
return securityCtx.roleHas("federation_admin")
|
RegisterMode.CLUB_ADMIN) : List.of(RegisterMode.FREE, RegisterMode.HELLOASSO))
|
||||||
|| securityCtx.roleHas("safca_super_admin");
|
.invoke(cm -> out.addAll(cm.stream().map(CompetitionData::fromModelLight).toList()))
|
||||||
|
.call(cm -> registerRepository.list(
|
||||||
|
"membre.userId = ?1 AND competition.id NOT IN ?2 AND competition NOT IN ?3",
|
||||||
|
securityCtx.getSubject(), ids, cm)
|
||||||
|
.chain(registerModels -> {
|
||||||
|
Uni<Void> uni = Uni.createFrom().nullItem();
|
||||||
|
for (RegisterModel registerModel : registerModels) {
|
||||||
|
uni = uni.call(__ -> Mutiny.fetch(registerModel.getCompetition())
|
||||||
|
.invoke(cm2 -> out.add(CompetitionData.fromModelLight(cm2))));
|
||||||
}
|
}
|
||||||
return securityCtx.roleHas("federation_admin");
|
return uni;
|
||||||
})
|
})
|
||||||
.map(CompetitionData::fromModel).toList())
|
))
|
||||||
));
|
.map(__ -> out);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uni<List<CompetitionData>> getAllSystem(SecurityCtx securityCtx,
|
public Uni<List<CompetitionData>> getAllAdmin(SecurityCtx securityCtx) {
|
||||||
CompetitionSystem system) {
|
return permService.getAllHaveAdminAccess(securityCtx)
|
||||||
if (system == CompetitionSystem.SAFCA) {
|
.chain(ids -> repository.list("id IN ?1", ids))
|
||||||
return permService.getAllHaveAccess(securityCtx.getSubject())
|
.map(pouleModels -> pouleModels.stream().map(CompetitionData::fromModel).toList());
|
||||||
.chain(map ->
|
}
|
||||||
repository.list("system = ?1", system)
|
|
||||||
.map(data -> data.stream()
|
|
||||||
.filter(p -> {
|
|
||||||
if (securityCtx.getSubject().equals(p.getOwner()))
|
|
||||||
return true;
|
|
||||||
if (map.containsKey(p.getId()))
|
|
||||||
return map.get(p.getId()).equals("admin");
|
|
||||||
return securityCtx.roleHas("federation_admin")
|
|
||||||
|| securityCtx.roleHas("safca_super_admin");
|
|
||||||
})
|
|
||||||
.map(CompetitionData::fromModel).toList())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return repository.list("system = ?1", system)
|
public Uni<List<CompetitionData>> getAllSystemAdmin(SecurityCtx securityCtx,
|
||||||
.map(data -> data.stream()
|
CompetitionSystem system) {
|
||||||
.filter(p -> {
|
return permService.getAllHaveAdminAccess(securityCtx)
|
||||||
if (securityCtx.getSubject().equals(p.getOwner()))
|
.chain(ids -> repository.list("system = ?1 AND id IN ?2", system, ids))
|
||||||
return true;
|
.map(pouleModels -> pouleModels.stream().map(CompetitionData::fromModel).toList());
|
||||||
return securityCtx.roleHas("federation_admin") ||
|
|
||||||
securityCtx.isInClubGroup(p.getClub().getId());
|
|
||||||
})
|
|
||||||
.map(CompetitionData::fromModel).toList());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uni<CompetitionData> addOrUpdate(SecurityCtx securityCtx, CompetitionData data) {
|
public Uni<CompetitionData> addOrUpdate(SecurityCtx securityCtx, CompetitionData data) {
|
||||||
if (data.getId() == null) {
|
if (data.getId() == null) {
|
||||||
return combRepository.find("userId = ?1", securityCtx.getSubject()).firstResult()
|
return combRepository.find("userId = ?1", securityCtx.getSubject()).firstResult()
|
||||||
.invoke(Unchecked.consumer(combModel -> {
|
.invoke(Unchecked.consumer(combModel -> {
|
||||||
if (!securityCtx.getRoles().contains("create_compet") && !securityCtx.getRoles().contains("federation_admin"))
|
if (!securityCtx.getRoles().contains("create_compet") && !securityCtx.getRoles()
|
||||||
|
.contains("federation_admin"))
|
||||||
throw new DForbiddenException("Vous ne pouvez pas créer de compétition");
|
throw new DForbiddenException("Vous ne pouvez pas créer de compétition");
|
||||||
}))
|
}))
|
||||||
.map(MembreModel::getClub)
|
.map(MembreModel::getClub)
|
||||||
@ -153,22 +156,24 @@ public class CompetitionService {
|
|||||||
model.setId(null);
|
model.setId(null);
|
||||||
model.setSystem(data.getSystem());
|
model.setSystem(data.getSystem());
|
||||||
model.setClub(clubModel);
|
model.setClub(clubModel);
|
||||||
model.setDate(data.getDate());
|
|
||||||
model.setInsc(new ArrayList<>());
|
model.setInsc(new ArrayList<>());
|
||||||
model.setUuid(UUID.randomUUID().toString());
|
model.setUuid(UUID.randomUUID().toString());
|
||||||
model.setName(data.getName());
|
|
||||||
model.setOwner(securityCtx.getSubject());
|
model.setOwner(securityCtx.getSubject());
|
||||||
|
|
||||||
|
copyData(data, model);
|
||||||
|
|
||||||
return Panache.withTransaction(() -> repository.persist(model));
|
return Panache.withTransaction(() -> repository.persist(model));
|
||||||
}).map(CompetitionData::fromModel)
|
}).map(CompetitionData::fromModel)
|
||||||
.call(__ -> cacheAccess.invalidate(securityCtx.getSubject()));
|
.call(c -> (c.getSystem() == CompetitionSystem.SAFCA) ? cacheAccess.invalidate(
|
||||||
|
securityCtx.getSubject()) : Uni.createFrom().nullItem())
|
||||||
|
.call(c -> (c.getSystem() == CompetitionSystem.NONE) ? cacheNoneAccess.invalidate(
|
||||||
|
securityCtx.getSubject()) : Uni.createFrom().nullItem());
|
||||||
} else {
|
} else {
|
||||||
return permService.hasEditPerm(securityCtx, data.getId())
|
return permService.hasEditPerm(securityCtx, data.getId())
|
||||||
.chain(model -> {
|
.chain(model -> {
|
||||||
model.setDate(data.getDate());
|
copyData(data, model);
|
||||||
model.setName(data.getName());
|
|
||||||
|
|
||||||
return vertx.getOrCreateContext().executeBlocking(() ->
|
return vertx.getOrCreateContext().executeBlocking(() -> // Update owner
|
||||||
keycloakService.getUser(data.getOwner()).map(UserRepresentation::getId).orElse(null))
|
keycloakService.getUser(data.getOwner()).map(UserRepresentation::getId).orElse(null))
|
||||||
.invoke(Unchecked.consumer(newOwner -> {
|
.invoke(Unchecked.consumer(newOwner -> {
|
||||||
if (newOwner == null)
|
if (newOwner == null)
|
||||||
@ -183,10 +188,29 @@ public class CompetitionService {
|
|||||||
}))
|
}))
|
||||||
.chain(__ -> Panache.withTransaction(() -> repository.persist(model)));
|
.chain(__ -> Panache.withTransaction(() -> repository.persist(model)));
|
||||||
}).map(CompetitionData::fromModel)
|
}).map(CompetitionData::fromModel)
|
||||||
.call(__ -> cacheAccess.invalidate(securityCtx.getSubject()));
|
.call(c -> (c.getSystem() == CompetitionSystem.SAFCA) ? cacheAccess.invalidate(
|
||||||
|
securityCtx.getSubject()) : Uni.createFrom().nullItem())
|
||||||
|
.call(c -> (c.getSystem() == CompetitionSystem.NONE) ? cacheNoneAccess.invalidate(
|
||||||
|
securityCtx.getSubject()) : Uni.createFrom().nullItem());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void copyData(CompetitionData data, CompetitionModel model) {
|
||||||
|
model.setName(data.getName());
|
||||||
|
model.setAdresse(data.getAdresse());
|
||||||
|
model.setDescription(data.getDescription());
|
||||||
|
model.setDate(data.getDate());
|
||||||
|
model.setTodate(data.getDate());
|
||||||
|
model.setPublicVisible(data.isPublicVisible());
|
||||||
|
model.setStartRegister(data.getStartRegister());
|
||||||
|
model.setEndRegister(data.getEndRegister());
|
||||||
|
model.setRegisterMode(data.getRegisterMode());
|
||||||
|
model.setData1(data.getData1());
|
||||||
|
model.setData2(data.getData2());
|
||||||
|
model.setData3(data.getData3());
|
||||||
|
model.setData4(data.getData4());
|
||||||
|
}
|
||||||
|
|
||||||
public Uni<List<SimpleRegisterComb>> getRegister(SecurityCtx securityCtx, Long id) {
|
public Uni<List<SimpleRegisterComb>> getRegister(SecurityCtx securityCtx, Long id) {
|
||||||
return permService.hasEditPerm(securityCtx, id)
|
return permService.hasEditPerm(securityCtx, id)
|
||||||
.chain(c -> Mutiny.fetch(c.getInsc()))
|
.chain(c -> Mutiny.fetch(c.getInsc()))
|
||||||
@ -218,7 +242,7 @@ public class CompetitionService {
|
|||||||
r.setClub(combModel.getClub());
|
r.setClub(combModel.getClub());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
r = new RegisterModel(c ,combModel, data.getWeight(), data.getOverCategory(),
|
r = new RegisterModel(c, combModel, data.getWeight(), data.getOverCategory(),
|
||||||
(combModel.getBirth_date() == null) ? combModel.getCategorie() :
|
(combModel.getBirth_date() == null) ? combModel.getCategorie() :
|
||||||
Utils.getCategoryFormBirthDate(combModel.getBirth_date(),
|
Utils.getCategoryFormBirthDate(combModel.getBirth_date(),
|
||||||
c.getDate()),
|
c.getDate()),
|
||||||
@ -248,7 +272,8 @@ public class CompetitionService {
|
|||||||
} else {
|
} else {
|
||||||
if (fname == null || lname == null)
|
if (fname == null || lname == null)
|
||||||
return Uni.createFrom().failure(new DBadRequestException("Nom et prénom requis"));
|
return Uni.createFrom().failure(new DBadRequestException("Nom et prénom requis"));
|
||||||
return combRepository.find("unaccent(lname) ILIKE unaccent(?1) AND unaccent(fname) ILIKE unaccent(?2)", lname,
|
return combRepository.find("unaccent(lname) ILIKE unaccent(?1) AND unaccent(fname) ILIKE unaccent(?2)",
|
||||||
|
lname,
|
||||||
fname).firstResult()
|
fname).firstResult()
|
||||||
.invoke(Unchecked.consumer(combModel -> {
|
.invoke(Unchecked.consumer(combModel -> {
|
||||||
if (combModel == null)
|
if (combModel == null)
|
||||||
@ -261,11 +286,11 @@ public class CompetitionService {
|
|||||||
return permService.hasEditPerm(securityCtx, id)
|
return permService.hasEditPerm(securityCtx, id)
|
||||||
.chain(c -> registerRepository.delete("competition = ?1 AND membre.id = ?2", c, combId)
|
.chain(c -> registerRepository.delete("competition = ?1 AND membre.id = ?2", c, combId)
|
||||||
.invoke(Unchecked.consumer(l -> {
|
.invoke(Unchecked.consumer(l -> {
|
||||||
if (l != 0){
|
if (l != 0) {
|
||||||
if (c.getSystem() == CompetitionSystem.SAFCA) {
|
if (c.getSystem() == CompetitionSystem.SAFCA) {
|
||||||
SReqRegister.sendRmIfNeed(serverCustom.clients, combId, id);
|
SReqRegister.sendRmIfNeed(serverCustom.clients, combId, id);
|
||||||
}
|
}
|
||||||
}else{
|
} else {
|
||||||
throw new DBadRequestException("Combattant non inscrit");
|
throw new DBadRequestException("Combattant non inscrit");
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
@ -277,7 +302,7 @@ public class CompetitionService {
|
|||||||
if (!(securityCtx.getSubject().equals(c.getOwner()) || securityCtx.roleHas("federation_admin")))
|
if (!(securityCtx.getSubject().equals(c.getOwner()) || securityCtx.roleHas("federation_admin")))
|
||||||
throw new DForbiddenException();
|
throw new DForbiddenException();
|
||||||
}))
|
}))
|
||||||
.call(competitionModel -> pouleRepository.list("compet = ?1", competitionModel)
|
.call(competitionModel -> categoryRepository.list("compet = ?1", competitionModel)
|
||||||
.call(pouleModels -> pouleModels.isEmpty() ? Uni.createFrom().nullItem() :
|
.call(pouleModels -> pouleModels.isEmpty() ? Uni.createFrom().nullItem() :
|
||||||
Uni.join().all(pouleModels.stream()
|
Uni.join().all(pouleModels.stream()
|
||||||
.map(pouleModel -> Panache.withTransaction(
|
.map(pouleModel -> Panache.withTransaction(
|
||||||
@ -285,7 +310,7 @@ public class CompetitionService {
|
|||||||
.toList())
|
.toList())
|
||||||
.andCollectFailures()))
|
.andCollectFailures()))
|
||||||
.call(competitionModel -> Panache.withTransaction(
|
.call(competitionModel -> Panache.withTransaction(
|
||||||
() -> pouleRepository.delete("compet = ?1", competitionModel)))
|
() -> categoryRepository.delete("compet = ?1", competitionModel)))
|
||||||
.chain(model -> Panache.withTransaction(() -> repository.delete("id", model.getId())))
|
.chain(model -> Panache.withTransaction(() -> repository.delete("id", model.getId())))
|
||||||
.invoke(o -> SReqCompet.rmCompet(serverCustom.clients, id))
|
.invoke(o -> SReqCompet.rmCompet(serverCustom.clients, id))
|
||||||
.call(__ -> cache.invalidate(id));
|
.call(__ -> cache.invalidate(id));
|
||||||
|
|||||||
@ -3,7 +3,7 @@ package fr.titionfire.ffsaf.domain.service;
|
|||||||
import fr.titionfire.ffsaf.data.model.MatchModel;
|
import fr.titionfire.ffsaf.data.model.MatchModel;
|
||||||
import fr.titionfire.ffsaf.data.repository.CombRepository;
|
import fr.titionfire.ffsaf.data.repository.CombRepository;
|
||||||
import fr.titionfire.ffsaf.data.repository.MatchRepository;
|
import fr.titionfire.ffsaf.data.repository.MatchRepository;
|
||||||
import fr.titionfire.ffsaf.data.repository.PouleRepository;
|
import fr.titionfire.ffsaf.data.repository.CategoryRepository;
|
||||||
import fr.titionfire.ffsaf.rest.data.MatchData;
|
import fr.titionfire.ffsaf.rest.data.MatchData;
|
||||||
import fr.titionfire.ffsaf.rest.exception.DNotFoundException;
|
import fr.titionfire.ffsaf.rest.exception.DNotFoundException;
|
||||||
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
||||||
@ -25,7 +25,7 @@ public class MatchService {
|
|||||||
MatchRepository repository;
|
MatchRepository repository;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
PouleRepository pouleRepository;
|
CategoryRepository categoryRepository;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
CombRepository combRepository;
|
CombRepository combRepository;
|
||||||
@ -33,17 +33,17 @@ public class MatchService {
|
|||||||
@Inject
|
@Inject
|
||||||
CompetPermService permService;
|
CompetPermService permService;
|
||||||
|
|
||||||
public Uni<MatchData> getById(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
|
public Uni<MatchData> getByIdAdmin(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
|
||||||
return repository.find("systemId = ?1 AND system = ?2", id, system).firstResult()
|
return repository.find("systemId = ?1 AND system = ?2", id, system).firstResult()
|
||||||
.onItem().ifNull().failWith(() -> new DNotFoundException("Match not found"))
|
.onItem().ifNull().failWith(() -> new DNotFoundException("Match not found"))
|
||||||
.call(data -> permService.hasViewPerm(securityCtx, data.getPoule().getCompet()))
|
.call(data -> permService.hasAdminViewPerm(securityCtx, data.getCategory().getCompet()))
|
||||||
.map(MatchData::fromModel);
|
.map(MatchData::fromModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uni<List<MatchData>> getAllByPoule(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
|
public Uni<List<MatchData>> getAllByPouleAdmin(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
|
||||||
return pouleRepository.find("systemId = ?1 AND system = ?2", id, system).firstResult()
|
return categoryRepository.find("systemId = ?1 AND system = ?2", id, system).firstResult()
|
||||||
.onItem().ifNull().failWith(() -> new DNotFoundException("Poule not found"))
|
.onItem().ifNull().failWith(() -> new DNotFoundException("Poule not found"))
|
||||||
.call(data -> permService.hasViewPerm(securityCtx, data.getCompet()))
|
.call(data -> permService.hasAdminViewPerm(securityCtx, data.getCompet()))
|
||||||
.chain(data -> repository.list("poule = ?1", data.getId())
|
.chain(data -> repository.list("poule = ?1", data.getId())
|
||||||
.map(o -> o.stream().map(MatchData::fromModel).toList()));
|
.map(o -> o.stream().map(MatchData::fromModel).toList()));
|
||||||
}
|
}
|
||||||
@ -52,21 +52,21 @@ public class MatchService {
|
|||||||
return repository.find("systemId = ?1 AND system = ?2", data.getId(), system).firstResult()
|
return repository.find("systemId = ?1 AND system = ?2", data.getId(), system).firstResult()
|
||||||
.chain(o -> {
|
.chain(o -> {
|
||||||
if (o == null) {
|
if (o == null) {
|
||||||
return pouleRepository.find("systemId = ?1 AND system = ?2", data.getPoule(), system)
|
return categoryRepository.find("systemId = ?1 AND system = ?2", data.getCategory(), system)
|
||||||
.firstResult()
|
.firstResult()
|
||||||
.onItem().ifNull().failWith(() -> new DNotFoundException("Poule not found"))
|
.onItem().ifNull().failWith(() -> new DNotFoundException("Poule not found"))
|
||||||
.call(o2 -> permService.hasEditPerm(securityCtx, o2.getCompet()))
|
.call(o2 -> permService.hasEditPerm(securityCtx, o2.getCompet()))
|
||||||
.map(pouleModel -> {
|
.map(categoryModel -> {
|
||||||
MatchModel model = new MatchModel();
|
MatchModel model = new MatchModel();
|
||||||
|
|
||||||
model.setId(null);
|
model.setId(null);
|
||||||
model.setSystem(system);
|
model.setSystem(system);
|
||||||
model.setSystemId(data.getId());
|
model.setSystemId(data.getId());
|
||||||
model.setPoule(pouleModel);
|
model.setCategory(categoryModel);
|
||||||
return model;
|
return model;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return pouleRepository.find("systemId = ?1 AND system = ?2", data.getPoule(), system)
|
return categoryRepository.find("systemId = ?1 AND system = ?2", data.getCategory(), system)
|
||||||
.firstResult()
|
.firstResult()
|
||||||
.onItem().ifNull().failWith(() -> new DNotFoundException("Poule not found"))
|
.onItem().ifNull().failWith(() -> new DNotFoundException("Poule not found"))
|
||||||
.call(o2 -> permService.hasEditPerm(securityCtx, o2.getCompet()))
|
.call(o2 -> permService.hasEditPerm(securityCtx, o2.getCompet()))
|
||||||
@ -77,7 +77,7 @@ public class MatchService {
|
|||||||
.chain(o -> {
|
.chain(o -> {
|
||||||
o.setC1_str(data.getC1_str());
|
o.setC1_str(data.getC1_str());
|
||||||
o.setC2_str(data.getC2_str());
|
o.setC2_str(data.getC2_str());
|
||||||
o.setPoule_ord(data.getPoule_ord());
|
o.setCategory_ord(data.getCategory_ord());
|
||||||
o.getScores().clear();
|
o.getScores().clear();
|
||||||
o.getScores().addAll(data.getScores());
|
o.getScores().addAll(data.getScores());
|
||||||
|
|
||||||
@ -97,7 +97,7 @@ public class MatchService {
|
|||||||
List<ScoreEmbeddable> scores) {
|
List<ScoreEmbeddable> scores) {
|
||||||
return repository.find("systemId = ?1 AND system = ?2", id, system).firstResult()
|
return repository.find("systemId = ?1 AND system = ?2", id, system).firstResult()
|
||||||
.onItem().ifNull().failWith(() -> new DNotFoundException("Match not found"))
|
.onItem().ifNull().failWith(() -> new DNotFoundException("Match not found"))
|
||||||
.call(o2 -> permService.hasEditPerm(securityCtx, o2.getPoule().getCompet()))
|
.call(o2 -> permService.hasEditPerm(securityCtx, o2.getCategory().getCompet()))
|
||||||
.invoke(data -> {
|
.invoke(data -> {
|
||||||
data.getScores().clear();
|
data.getScores().clear();
|
||||||
data.getScores().addAll(scores);
|
data.getScores().addAll(scores);
|
||||||
@ -109,7 +109,7 @@ public class MatchService {
|
|||||||
public Uni<?> delete(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
|
public Uni<?> delete(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
|
||||||
return repository.find("systemId = ?1 AND system = ?2", id, system).firstResult()
|
return repository.find("systemId = ?1 AND system = ?2", id, system).firstResult()
|
||||||
.onItem().ifNull().failWith(() -> new DNotFoundException("Match not found"))
|
.onItem().ifNull().failWith(() -> new DNotFoundException("Match not found"))
|
||||||
.call(o2 -> permService.hasEditPerm(securityCtx, o2.getPoule().getCompet()))
|
.call(o2 -> permService.hasEditPerm(securityCtx, o2.getCategory().getCompet()))
|
||||||
.chain(data -> Panache.withTransaction(() -> repository.delete(data)));
|
.chain(data -> Panache.withTransaction(() -> repository.delete(data)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +0,0 @@
|
|||||||
package fr.titionfire.ffsaf.domain.service;
|
|
||||||
|
|
||||||
public class TreeService {
|
|
||||||
}
|
|
||||||
@ -24,7 +24,7 @@ public class SReqCompet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void getAllHaveAccess(ArrayList<Client_Thread> client_Thread, String userId,
|
public static void getAllHaveAccess(ArrayList<Client_Thread> client_Thread, String userId,
|
||||||
CompletableFuture<HashMap<Long, String>> future) {
|
CompletableFuture<HashMap<String, String>> future) {
|
||||||
if (client_Thread.isEmpty()) return;
|
if (client_Thread.isEmpty()) return;
|
||||||
client_Thread.get(0).sendReq(userId, "getAllHaveAccess",
|
client_Thread.get(0).sendReq(userId, "getAllHaveAccess",
|
||||||
new JsonConsumer<>(HashMap.class, future::complete));
|
new JsonConsumer<>(HashMap.class, future::complete));
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
package fr.titionfire.ffsaf.rest;
|
package fr.titionfire.ffsaf.rest;
|
||||||
|
|
||||||
import fr.titionfire.ffsaf.domain.service.PouleService;
|
import fr.titionfire.ffsaf.domain.service.CategoryService;
|
||||||
import fr.titionfire.ffsaf.rest.data.PouleData;
|
import fr.titionfire.ffsaf.rest.data.CategoryData;
|
||||||
import fr.titionfire.ffsaf.rest.data.PouleFullData;
|
import fr.titionfire.ffsaf.rest.data.CategoryFullData;
|
||||||
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
||||||
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
||||||
import io.quarkus.security.Authenticated;
|
import io.quarkus.security.Authenticated;
|
||||||
@ -14,14 +14,14 @@ import jakarta.ws.rs.core.MediaType;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Authenticated
|
@Authenticated
|
||||||
@Path("api/poule/{system}/")
|
@Path("api/poule/{system}/admin/")
|
||||||
public class PouleEndpoints {
|
public class CategoryAdminEndpoints {
|
||||||
|
|
||||||
@PathParam("system")
|
@PathParam("system")
|
||||||
private CompetitionSystem system;
|
private CompetitionSystem system;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
PouleService service;
|
CategoryService service;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
SecurityCtx securityCtx;
|
SecurityCtx securityCtx;
|
||||||
@ -30,28 +30,28 @@ public class PouleEndpoints {
|
|||||||
@GET
|
@GET
|
||||||
@Path("{id}")
|
@Path("{id}")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public Uni<PouleData> getById(@PathParam("id") Long id) {
|
public Uni<CategoryData> getByIdAdmin(@PathParam("id") Long id) {
|
||||||
return service.getById(securityCtx, system, id);
|
return service.getByIdAdmin(securityCtx, system, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public Uni<List<PouleData>> getAll() {
|
public Uni<List<CategoryData>> getAllAdmin() {
|
||||||
return service.getAll(securityCtx, system);
|
return service.getAllAdmin(securityCtx, system);
|
||||||
}
|
}
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public Uni<PouleData> addOrUpdate(PouleData data) {
|
public Uni<CategoryData> addOrUpdate(CategoryData data) {
|
||||||
return service.addOrUpdate(securityCtx, system, data);
|
return service.addOrUpdate(securityCtx, system, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Path("sync")
|
@Path("sync")
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
public Uni<?> syncPoule(PouleFullData data) {
|
public Uni<?> syncCategory(CategoryFullData data) {
|
||||||
return service.syncPoule(securityCtx, system, data);
|
return service.syncCategory(securityCtx, system, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@DELETE
|
@DELETE
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
package fr.titionfire.ffsaf.rest;
|
||||||
|
|
||||||
|
import fr.titionfire.ffsaf.domain.service.CompetitionService;
|
||||||
|
import fr.titionfire.ffsaf.rest.data.CompetitionData;
|
||||||
|
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
||||||
|
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
||||||
|
import io.quarkus.security.Authenticated;
|
||||||
|
import io.smallrye.mutiny.Uni;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import jakarta.ws.rs.GET;
|
||||||
|
import jakarta.ws.rs.Path;
|
||||||
|
import jakarta.ws.rs.PathParam;
|
||||||
|
import jakarta.ws.rs.Produces;
|
||||||
|
import jakarta.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Path("api/competition/admin")
|
||||||
|
public class CompetitionAdminEndpoints {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
CompetitionService service;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
SecurityCtx securityCtx;
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("{id}")
|
||||||
|
@Authenticated
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public Uni<CompetitionData> getByIdAdmin(@PathParam("id") Long id) {
|
||||||
|
return service.getByIdAdmin(securityCtx, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("all")
|
||||||
|
@Authenticated
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public Uni<List<CompetitionData>> getAllAdmin() {
|
||||||
|
return service.getAllAdmin(securityCtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("all/{system}")
|
||||||
|
@Authenticated
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public Uni<List<CompetitionData>> getAllSystemAdmin(@PathParam("system") CompetitionSystem system) {
|
||||||
|
return service.getAllSystemAdmin(securityCtx, system);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,7 +5,6 @@ import fr.titionfire.ffsaf.rest.data.CompetitionData;
|
|||||||
import fr.titionfire.ffsaf.rest.data.RegisterRequestData;
|
import fr.titionfire.ffsaf.rest.data.RegisterRequestData;
|
||||||
import fr.titionfire.ffsaf.rest.data.SimpleCompetData;
|
import fr.titionfire.ffsaf.rest.data.SimpleCompetData;
|
||||||
import fr.titionfire.ffsaf.rest.data.SimpleRegisterComb;
|
import fr.titionfire.ffsaf.rest.data.SimpleRegisterComb;
|
||||||
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
|
||||||
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
import fr.titionfire.ffsaf.utils.SecurityCtx;
|
||||||
import io.quarkus.security.Authenticated;
|
import io.quarkus.security.Authenticated;
|
||||||
import io.smallrye.mutiny.Uni;
|
import io.smallrye.mutiny.Uni;
|
||||||
@ -29,8 +28,11 @@ public class CompetitionEndpoints {
|
|||||||
@Path("{id}")
|
@Path("{id}")
|
||||||
@Authenticated
|
@Authenticated
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public Uni<CompetitionData> getById(@PathParam("id") Long id) {
|
public Uni<CompetitionData> getById(@PathParam("id") Long id, @QueryParam("light") boolean light) {
|
||||||
return service.getById(securityCtx, id);
|
if (light)
|
||||||
|
return service.getById(securityCtx, id);
|
||||||
|
else
|
||||||
|
return service.getByIdAdmin(securityCtx, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@ -76,14 +78,6 @@ public class CompetitionEndpoints {
|
|||||||
return service.getAll(securityCtx);
|
return service.getAll(securityCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("all/{system}")
|
|
||||||
@Authenticated
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
public Uni<List<CompetitionData>> getAllSystem(@PathParam("system") CompetitionSystem system) {
|
|
||||||
return service.getAllSystem(securityCtx, system);
|
|
||||||
}
|
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Authenticated
|
@Authenticated
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
|||||||
@ -14,8 +14,8 @@ import jakarta.ws.rs.core.MediaType;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Authenticated
|
@Authenticated
|
||||||
@Path("api/match/{system}/")
|
@Path("api/match/{system}/admin")
|
||||||
public class MatchEndpoints {
|
public class MatchAdminEndpoints {
|
||||||
|
|
||||||
@PathParam("system")
|
@PathParam("system")
|
||||||
private CompetitionSystem system;
|
private CompetitionSystem system;
|
||||||
@ -30,15 +30,15 @@ public class MatchEndpoints {
|
|||||||
@GET
|
@GET
|
||||||
@Path("{id}")
|
@Path("{id}")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public Uni<MatchData> getById(@PathParam("id") Long id) {
|
public Uni<MatchData> getByIdAdmin(@PathParam("id") Long id) {
|
||||||
return service.getById(securityCtx, system, id);
|
return service.getByIdAdmin(securityCtx, system, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("getAllByPoule/{id}")
|
@Path("getAllByPoule/{id}")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public Uni<List<MatchData>> getAllByPoule(@PathParam("id") Long id) {
|
public Uni<List<MatchData>> getAllByPouleAdmin(@PathParam("id") Long id) {
|
||||||
return service.getAllByPoule(securityCtx, system, id);
|
return service.getAllByPouleAdmin(securityCtx, system, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@ -1,6 +1,6 @@
|
|||||||
package fr.titionfire.ffsaf.rest.data;
|
package fr.titionfire.ffsaf.rest.data;
|
||||||
|
|
||||||
import fr.titionfire.ffsaf.data.model.PouleModel;
|
import fr.titionfire.ffsaf.data.model.CategoryModel;
|
||||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@ -8,16 +8,16 @@ import lombok.Data;
|
|||||||
@Data
|
@Data
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@RegisterForReflection
|
@RegisterForReflection
|
||||||
public class PouleData {
|
public class CategoryData {
|
||||||
private Long id;
|
private Long id;
|
||||||
private String name;
|
private String name;
|
||||||
private Long compet;
|
private Long compet;
|
||||||
private Integer type;
|
private Integer type;
|
||||||
|
|
||||||
public static PouleData fromModel(PouleModel model) {
|
public static CategoryData fromModel(CategoryModel model) {
|
||||||
if (model == null)
|
if (model == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return new PouleData(model.getSystemId(), model.getName(), model.getCompet().getId(), model.getType());
|
return new CategoryData(model.getSystemId(), model.getName(), model.getCompet().getId(), model.getType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7,7 +7,7 @@ import java.util.List;
|
|||||||
|
|
||||||
@Data
|
@Data
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class PouleFullData {
|
public class CategoryFullData {
|
||||||
private Long id;
|
private Long id;
|
||||||
private String name;
|
private String name;
|
||||||
private Long compet;
|
private Long compet;
|
||||||
@ -1,9 +1,10 @@
|
|||||||
package fr.titionfire.ffsaf.rest.data;
|
package fr.titionfire.ffsaf.rest.data;
|
||||||
|
|
||||||
import fr.titionfire.ffsaf.data.model.CompetitionModel;
|
import fr.titionfire.ffsaf.data.model.CompetitionModel;
|
||||||
|
import fr.titionfire.ffsaf.data.model.RegisterModel;
|
||||||
import fr.titionfire.ffsaf.utils.Categorie;
|
import fr.titionfire.ffsaf.utils.Categorie;
|
||||||
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
import fr.titionfire.ffsaf.utils.CompetitionSystem;
|
||||||
import fr.titionfire.ffsaf.data.model.RegisterModel;
|
import fr.titionfire.ffsaf.utils.RegisterMode;
|
||||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@ -17,20 +18,53 @@ import java.util.List;
|
|||||||
public class CompetitionData {
|
public class CompetitionData {
|
||||||
private Long id;
|
private Long id;
|
||||||
private String name;
|
private String name;
|
||||||
|
private String description;
|
||||||
|
private String adresse;
|
||||||
private String uuid;
|
private String uuid;
|
||||||
private Date date;
|
private Date date;
|
||||||
|
private Date toDate;
|
||||||
private CompetitionSystem system;
|
private CompetitionSystem system;
|
||||||
|
private RegisterMode registerMode;
|
||||||
|
private Date startRegister;
|
||||||
|
private Date endRegister;
|
||||||
|
private boolean publicVisible;
|
||||||
private Long club;
|
private Long club;
|
||||||
private String clubName;
|
private String clubName;
|
||||||
private String owner;
|
private String owner;
|
||||||
private List<SimpleRegister> registers;
|
private List<SimpleRegister> registers;
|
||||||
|
private boolean canEdit;
|
||||||
|
private String data1;
|
||||||
|
private String data2;
|
||||||
|
private String data3;
|
||||||
|
private String data4;
|
||||||
|
|
||||||
public static CompetitionData fromModel(CompetitionModel model) {
|
public static CompetitionData fromModel(CompetitionModel model) {
|
||||||
if (model == null)
|
if (model == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return new CompetitionData(model.getId(), model.getName(), model.getUuid(), model.getDate(), model.getSystem(),
|
return new CompetitionData(model.getId(), model.getName(), model.getDescription(), model.getAdresse(),
|
||||||
model.getClub().getId(), model.getClub().getName(), model.getOwner(), null);
|
model.getUuid(), model.getDate(), model.getTodate(), model.getSystem(),
|
||||||
|
model.getRegisterMode(), model.getStartRegister(), model.getEndRegister(), model.isPublicVisible(),
|
||||||
|
model.getClub().getId(), model.getClub().getName(), model.getOwner(), null, false,
|
||||||
|
model.getData1(), model.getData2(), model.getData3(), model.getData4());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CompetitionData fromModelLight(CompetitionModel model) {
|
||||||
|
if (model == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
CompetitionData out = new CompetitionData(model.getId(), model.getName(), model.getDescription(),
|
||||||
|
model.getAdresse(), "", model.getDate(), model.getTodate(), null,
|
||||||
|
model.getRegisterMode(), model.getStartRegister(), model.getEndRegister(), model.isPublicVisible(),
|
||||||
|
null, model.getClub().getName(), "", null, false,
|
||||||
|
"","", "","");
|
||||||
|
|
||||||
|
if (model.getRegisterMode() == RegisterMode.HELLOASSO){
|
||||||
|
out.setData1(model.getData1());
|
||||||
|
out.setData2(model.getData2());
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompetitionData addInsc(List<RegisterModel> insc) {
|
public CompetitionData addInsc(List<RegisterModel> insc) {
|
||||||
|
|||||||
@ -17,10 +17,10 @@ public class MatchData {
|
|||||||
private String c1_str;
|
private String c1_str;
|
||||||
private Long c2_id;
|
private Long c2_id;
|
||||||
private String c2_str;
|
private String c2_str;
|
||||||
private Long poule;
|
private Long category;
|
||||||
private long poule_ord;
|
private long category_ord;
|
||||||
private boolean isEnd = true;
|
private boolean isEnd = true;
|
||||||
private char groupe;
|
private char poule;
|
||||||
private List<ScoreEmbeddable> scores;
|
private List<ScoreEmbeddable> scores;
|
||||||
|
|
||||||
public static MatchData fromModel(MatchModel model) {
|
public static MatchData fromModel(MatchModel model) {
|
||||||
@ -30,7 +30,7 @@ public class MatchData {
|
|||||||
return new MatchData(model.getSystemId(),
|
return new MatchData(model.getSystemId(),
|
||||||
(model.getC1_id() == null) ? null : model.getC1_id().getId(), model.getC1_str(),
|
(model.getC1_id() == null) ? null : model.getC1_id().getId(), model.getC1_str(),
|
||||||
(model.getC2_id() == null) ? null : model.getC2_id().getId(), model.getC2_str(),
|
(model.getC2_id() == null) ? null : model.getC2_id().getId(), model.getC2_str(),
|
||||||
model.getPoule().getId(), model.getPoule_ord(), model.isEnd(), model.getGroupe(),
|
model.getCategory().getId(), model.getCategory_ord(), model.isEnd(), model.getPoule(),
|
||||||
model.getScores());
|
model.getScores());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import lombok.Data;
|
|||||||
@RegisterForReflection
|
@RegisterForReflection
|
||||||
public class TreeData {
|
public class TreeData {
|
||||||
private Long id;
|
private Long id;
|
||||||
private Long poule;
|
private Long category;
|
||||||
private Integer level;
|
private Integer level;
|
||||||
private Long match;
|
private Long match;
|
||||||
private TreeData left;
|
private TreeData left;
|
||||||
@ -20,7 +20,7 @@ public class TreeData {
|
|||||||
if (model == null)
|
if (model == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return new TreeData(model.getId(), model.getPoule(), model.getLevel(), model.getMatch().getId(),
|
return new TreeData(model.getId(), model.getCategory(), model.getLevel(), model.getMatch().getId(),
|
||||||
fromModel(model.getLeft()), fromModel(model.getRight()));
|
fromModel(model.getLeft()), fromModel(model.getRight()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
package fr.titionfire.ffsaf.utils;
|
package fr.titionfire.ffsaf.utils;
|
||||||
|
|
||||||
public enum CompetitionSystem {
|
public enum CompetitionSystem {
|
||||||
SAFCA,
|
SAFCA, NONE
|
||||||
}
|
}
|
||||||
|
|||||||
12
src/main/java/fr/titionfire/ffsaf/utils/RegisterMode.java
Normal file
12
src/main/java/fr/titionfire/ffsaf/utils/RegisterMode.java
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package fr.titionfire.ffsaf.utils;
|
||||||
|
|
||||||
|
public enum RegisterMode {
|
||||||
|
FREE, CLUB_ADMIN, ADMIN, HELLOASSO
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
HELLOASSO:
|
||||||
|
-> data1 = organizationSlug
|
||||||
|
-> data2 = formSlug
|
||||||
|
-> data3 = tarifs
|
||||||
|
-> data4 = errorEmail
|
||||||
|
*/
|
||||||
@ -31,6 +31,11 @@ public class SecurityCtx {
|
|||||||
return securityIdentity.getRoles().contains(role);
|
return securityIdentity.getRoles().contains(role);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isClubAdmin() {
|
||||||
|
return this.roleHas("club_president") || this.roleHas("club_respo_intra")
|
||||||
|
|| this.roleHas("club_secretaire") || this.roleHas("club_tresorier");
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isInClubGroup(long id) {
|
public boolean isInClubGroup(long id) {
|
||||||
if (idToken == null || idToken.getClaim("user_groups") == null)
|
if (idToken == null || idToken.getClaim("user_groups") == null)
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
BIN
src/main/webapp/public/img/HA-help-2.png
Normal file
BIN
src/main/webapp/public/img/HA-help-2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
BIN
src/main/webapp/public/img/HA-help-3.png
Normal file
BIN
src/main/webapp/public/img/HA-help-3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 118 KiB |
BIN
src/main/webapp/public/img/HA-help-4.png
Normal file
BIN
src/main/webapp/public/img/HA-help-4.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 102 KiB |
@ -4,9 +4,7 @@ import {AxiosError} from "./AxiosError.jsx";
|
|||||||
|
|
||||||
export function ClubSelect({defaultValue, name, na = false, disabled = false}) {
|
export function ClubSelect({defaultValue, name, na = false, disabled = false}) {
|
||||||
return <LoadingProvider>
|
return <LoadingProvider>
|
||||||
<div className="input-group mb-3">
|
<ClubSelect_ defaultValue={defaultValue} name={name} na={na} disabled={disabled}/>
|
||||||
<ClubSelect_ defaultValue={defaultValue} name={name} na={na} disabled={disabled}/>
|
|
||||||
</div>
|
|
||||||
</LoadingProvider>
|
</LoadingProvider>
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,7 +17,7 @@ function ClubSelect_({defaultValue, name, na, disabled}) {
|
|||||||
? <div className="input-group mb-3">
|
? <div className="input-group mb-3">
|
||||||
<label className="input-group-text" id="inputGroupSelect02">Club</label>
|
<label className="input-group-text" id="inputGroupSelect02">Club</label>
|
||||||
<select className="form-select" id="inputGroupSelect02" disabled={disabled}
|
<select className="form-select" id="inputGroupSelect02" disabled={disabled}
|
||||||
defaultValue={defaultValue? defaultValue : -1} name={name}>
|
defaultValue={defaultValue ? defaultValue : -1} name={name}>
|
||||||
<option>Sélectionner...</option>
|
<option>Sélectionner...</option>
|
||||||
{na && <option value={-1}>-- Non licencier --</option>}
|
{na && <option value={-1}>-- Non licencier --</option>}
|
||||||
{data.map(club => (<option key={club.id} value={club.id}>{club.name}</option>))}
|
{data.map(club => (<option key={club.id} value={club.id}>{club.name}</option>))}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import {useNavigate, useParams} from "react-router-dom";
|
|||||||
import {useLoadingSwitcher} from "../../hooks/useLoading.jsx";
|
import {useLoadingSwitcher} from "../../hooks/useLoading.jsx";
|
||||||
import {useFetch} from "../../hooks/useFetch.js";
|
import {useFetch} from "../../hooks/useFetch.js";
|
||||||
import {AxiosError} from "../../components/AxiosError.jsx";
|
import {AxiosError} from "../../components/AxiosError.jsx";
|
||||||
import {Checkbox, CheckField, OptionField, TextField} from "../../components/MemberCustomFiels.jsx";
|
import {CheckField, OptionField, TextField} from "../../components/MemberCustomFiels.jsx";
|
||||||
import {ClubSelect} from "../../components/ClubSelect.jsx";
|
import {ClubSelect} from "../../components/ClubSelect.jsx";
|
||||||
import {ConfirmDialog} from "../../components/ConfirmDialog.jsx";
|
import {ConfirmDialog} from "../../components/ConfirmDialog.jsx";
|
||||||
import {toast} from "react-toastify";
|
import {toast} from "react-toastify";
|
||||||
@ -10,14 +10,14 @@ import {apiAxios, errFormater} from "../../utils/Tools.js";
|
|||||||
import {useEffect, useReducer, useState} from "react";
|
import {useEffect, useReducer, useState} from "react";
|
||||||
import {SimpleReducer} from "../../utils/SimpleReducer.jsx";
|
import {SimpleReducer} from "../../utils/SimpleReducer.jsx";
|
||||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||||
import {faAdd, faPen, faTrashCan} from "@fortawesome/free-solid-svg-icons";
|
import {faAdd, faTrashCan} from "@fortawesome/free-solid-svg-icons";
|
||||||
|
|
||||||
export function CompetitionEdit() {
|
export function CompetitionEdit() {
|
||||||
const {id} = useParams()
|
const {id} = useParams()
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const setLoading = useLoadingSwitcher()
|
const setLoading = useLoadingSwitcher()
|
||||||
const {data, refresh, error} = useFetch(`/competition/${id}`, setLoading, 1)
|
const {data, refresh, error} = useFetch(`/competition/${id}?light=false`, setLoading, 1)
|
||||||
|
|
||||||
const handleRm = () => {
|
const handleRm = () => {
|
||||||
toast.promise(
|
toast.promise(
|
||||||
@ -49,7 +49,7 @@ export function CompetitionEdit() {
|
|||||||
{data.id !== null && <button style={{marginBottom: "1.5em", width: "100%"}} className="btn btn-primary"
|
{data.id !== null && <button style={{marginBottom: "1.5em", width: "100%"}} className="btn btn-primary"
|
||||||
onClick={_ => navigate(`/competition/${data.id}/register`)}>Voir/Modifier les participants</button>}
|
onClick={_ => navigate(`/competition/${data.id}/register`)}>Voir/Modifier les participants</button>}
|
||||||
|
|
||||||
{data.id !== null && <ContentSAFCA data2={data}/>}
|
{data.id !== null && data.system === "SAFCA" && <ContentSAFCA data2={data}/>}
|
||||||
|
|
||||||
{data.id !== null && <>
|
{data.id !== null && <>
|
||||||
<div className="col" style={{textAlign: 'right', marginTop: '1em'}}>
|
<div className="col" style={{textAlign: 'right', marginTop: '1em'}}>
|
||||||
@ -212,17 +212,74 @@ function ContentSAFCA({data2}) {
|
|||||||
|
|
||||||
function Content({data}) {
|
function Content({data}) {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const [registerMode, setRegisterMode] = useState(data.registerMode || "FREE");
|
||||||
|
|
||||||
const handleSubmit = (event) => {
|
const handleSubmit = (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
|
let err = false;
|
||||||
|
|
||||||
const out = {}
|
const out = {}
|
||||||
out['id'] = (data.id === "") ? null : data.id
|
out['id'] = (data.id === "") ? null : data.id
|
||||||
out['name'] = event.target.name?.value
|
out['name'] = event.target.name?.value
|
||||||
out['date'] = event.target.date?.value
|
out['date'] = event.target.date?.value
|
||||||
|
out['toDate'] = event.target.toDate?.value
|
||||||
out['system'] = event.target.system?.value
|
out['system'] = event.target.system?.value
|
||||||
out['club'] = event.target.club?.value
|
out['club'] = event.target.club?.value
|
||||||
out['owner'] = event.target.owner?.value
|
out['owner'] = event.target.owner?.value
|
||||||
|
out['description'] = event.target.description?.value
|
||||||
|
out['adresse'] = event.target.adresse?.value
|
||||||
|
out['publicVisible'] = event.target.publicVisible?.checked
|
||||||
|
|
||||||
|
out['startRegister'] = event.target.startRegister?.value
|
||||||
|
out['endRegister'] = event.target.endRegister?.value
|
||||||
|
out['registerMode'] = registerMode
|
||||||
|
|
||||||
|
if (out['registerMode'] === "HELLOASSO") {
|
||||||
|
out['data3'] = event.target.data3?.value
|
||||||
|
|
||||||
|
const url = event.target.helloassoUrl?.value
|
||||||
|
|
||||||
|
if (!url || !event.target.data3?.value) {
|
||||||
|
toast.error("Veuillez renseigner l'URL de la billetterie HelloAsso et les tarifs associés.")
|
||||||
|
err = true;
|
||||||
|
} else {
|
||||||
|
const regex = /\/associations\/([^/]+)\/evenements\/([^/]+)/;
|
||||||
|
const match = url.match(regex);
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
out['data1'] = match[1]
|
||||||
|
out['data2'] = match[2]
|
||||||
|
} else {
|
||||||
|
toast.error("L'URL de la billetterie HelloAsso n'est pas valide. Veuillez vérifier le format de l'URL.")
|
||||||
|
err = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out['data4'] = event.target.data4?.value
|
||||||
|
if (!out['data4']) {
|
||||||
|
toast.error("Veuillez renseigner l'email de réception des inscriptions échouées.")
|
||||||
|
err = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out['date'] > out['toDate']) {
|
||||||
|
toast.error("La date de fin doit être postérieure à la date de début.")
|
||||||
|
err = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((out['registerMode'] === "FREE" || out['registerMode'] === "CLUB_ADMIN") && (!out['startRegister'] || !out['endRegister'])) {
|
||||||
|
toast.error("Veuillez renseigner les dates de début et de fin d'inscription.")
|
||||||
|
err = true;
|
||||||
|
}
|
||||||
|
if ((out['registerMode'] === "FREE" || out['registerMode'] === "CLUB_ADMIN") && out['startRegister'] > out['endRegister']) {
|
||||||
|
toast.error("La date de fin d'inscription doit être postérieure à la date de début d'inscription.")
|
||||||
|
err = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
toast.promise(
|
toast.promise(
|
||||||
apiAxios.post(`/competition`, out),
|
apiAxios.post(`/competition`, out),
|
||||||
@ -246,24 +303,135 @@ function Content({data}) {
|
|||||||
<input name="id" value={data.id || ""} readOnly hidden/>
|
<input name="id" value={data.id || ""} readOnly hidden/>
|
||||||
<div className="card-header">{data.id ? "Edition competition" : "Création competition"}</div>
|
<div className="card-header">{data.id ? "Edition competition" : "Création competition"}</div>
|
||||||
<div className="card-body text-center">
|
<div className="card-body text-center">
|
||||||
<TextField name="uuid" text="UUID" value={data.uuid} disabled={true}/>
|
|
||||||
<TextField name="name" text="Nom" value={data.name}/>
|
|
||||||
|
|
||||||
<div className="input-group mb-3">
|
<div className="accordion" id="accordionExample">
|
||||||
<span className="input-group-text" id="birth_date">Date</span>
|
<div className="accordion-item">
|
||||||
<input type="date" className="form-control" placeholder="jj/mm/aaaa" aria-label="date"
|
<h2 className="accordion-header">
|
||||||
name="date" aria-describedby="date" defaultValue={data.date ? data.date.split('T')[0] : ''} required/>
|
<button className="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOne"
|
||||||
</div>
|
aria-expanded="false" aria-controls="collapseOne">
|
||||||
|
Informations techniques
|
||||||
{data.id !== null && <TextField name="owner" text="Propriétaire" value={data.owner}/>}
|
</button>
|
||||||
|
</h2>
|
||||||
<OptionField name="system" text="System" value={data.system} values={{SAFCA: 'SAFCA'}} disabled={data.id !== null}/>
|
<div id="collapseOne" className="accordion-collapse collapse" data-bs-parent="#accordionExample">
|
||||||
|
<div className="accordion-body">
|
||||||
{data.id !== null &&
|
<TextField name="uuid" text="UUID" value={data.uuid} disabled={true}/>
|
||||||
<div className="row">
|
<OptionField name="system" text="System" value={data.system} values={{SAFCA: 'SAFCA', NONE: "intranet"}}
|
||||||
<ClubSelect defaultValue={data.club} name="club" na={false} disabled={true}/>
|
disabled={data.id !== null}/>
|
||||||
|
{data.id !== null &&
|
||||||
|
<div className="row">
|
||||||
|
<ClubSelect defaultValue={data.club} name="club" na={false} disabled={true}/>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
{data.id !== null && <TextField name="owner" text="Propriétaire" value={data.owner}/>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
<div className="accordion-item">
|
||||||
|
<h2 className="accordion-header">
|
||||||
|
<button className="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTwo"
|
||||||
|
aria-expanded="true" aria-controls="collapseTwo">
|
||||||
|
Informations générales sur la competition
|
||||||
|
</button>
|
||||||
|
</h2>
|
||||||
|
<div id="collapseTwo" className="accordion-collapse collapse show" data-bs-parent="#accordionExample">
|
||||||
|
<div className="accordion-body">
|
||||||
|
<TextField name="name" text="Nom*" value={data.name}/>
|
||||||
|
<div className="input-group mb-3">
|
||||||
|
<span className="input-group-text" id="date">Date*</span>
|
||||||
|
<span className="input-group-text" id="date">Du</span>
|
||||||
|
<input type="date" className="form-control" placeholder="jj/mm/aaaa" aria-label="date"
|
||||||
|
name="date" aria-describedby="date" defaultValue={data.date ? data.date.split('T')[0] : ''} required/>
|
||||||
|
<span className="input-group-text" id="date">Au</span>
|
||||||
|
<input type="date" className="form-control" placeholder="jj/mm/aaaa" aria-label="toDate"
|
||||||
|
name="toDate" aria-describedby="toDate" defaultValue={data.toDate ? data.toDate.split('T')[0] : ''}
|
||||||
|
required/>
|
||||||
|
</div>
|
||||||
|
<TextField name="description" text="Description" value={data.description} required={false}/>
|
||||||
|
<TextField name="adresse" text="Adresse" value={data.adresse} required={false}/>
|
||||||
|
<CheckField name="publicVisible" text="Visible par le public (Apparaît dans la liste des compétitions)"
|
||||||
|
value={data.publicVisible} row={true}/>
|
||||||
|
<small>Si non coché, la compétition ne sera visible que par les personnes pouvant y inscrire des participants.</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="accordion-item">
|
||||||
|
<h2 className="accordion-header">
|
||||||
|
<button className="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseThree"
|
||||||
|
aria-expanded="false" aria-controls="collapseThree">
|
||||||
|
Informations sur le mode d'inscription
|
||||||
|
</button>
|
||||||
|
</h2>
|
||||||
|
<div id="collapseThree" className="accordion-collapse collapse" data-bs-parent="#accordionExample">
|
||||||
|
<div className="accordion-body">
|
||||||
|
|
||||||
|
<div className="row">
|
||||||
|
<div className="input-group mb-3">
|
||||||
|
<label className="input-group-text">Qui peut inscrire</label>
|
||||||
|
<select className="form-select" value={registerMode} onChange={event => setRegisterMode(event.target.value)}>
|
||||||
|
<option value="FREE">Tous les membres de la FFSAF</option>
|
||||||
|
<option value="CLUB_ADMIN">Responsables et bureaux des associations</option>
|
||||||
|
<option value="ADMIN">Uniquement les administrateurs de la compétition</option>
|
||||||
|
<option value="HELLOASSO">Billetterie HelloAsso</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="input-group mb-3"
|
||||||
|
style={{display: registerMode === "FREE" || registerMode === "CLUB_ADMIN" ? "flex" : "none"}}>
|
||||||
|
<span className="input-group-text" id="startRegister">Date d'inscription</span>
|
||||||
|
<span className="input-group-text" id="startRegister">Du</span>
|
||||||
|
<input type="datetime-local" className="form-control" placeholder="jj/mm/aaaa" aria-label="date"
|
||||||
|
name="startRegister" aria-describedby="startRegister"
|
||||||
|
defaultValue={data.startRegister ? data.startRegister.split('+')[0] : ''}/>
|
||||||
|
<span className="input-group-text" id="endRegister">Au</span>
|
||||||
|
<input type="datetime-local" className="form-control" placeholder="jj/mm/aaaa" aria-label="endRegister"
|
||||||
|
name="endRegister" aria-describedby="endRegister"
|
||||||
|
defaultValue={data.endRegister ? data.endRegister.split('+')[0] : ''}/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{display: registerMode === "HELLOASSO" ? "initial" : "none"}}>
|
||||||
|
<span style={{textAlign: "left"}}>
|
||||||
|
<div>Afin de permettre une bonne interconnexion avec HelloAsso, merci de suivre les instructions suivantes :</div>
|
||||||
|
<ul>
|
||||||
|
<li><strong>Configurer l'url de notification : </strong>afin que nous puissions recevoir une notification à
|
||||||
|
chaque inscription, il est nécessaire de configurer l'url de notification de votre compte HelloAsso pour
|
||||||
|
qu'il redirige vers "https://intra.ffsaf.fr/api/webhook/ha". Pour ce faire, depuis la page d'accueil de
|
||||||
|
votre association sur HelloAsso, allez dans <strong>Mon compte</strong> > <strong>Paramètres</strong> >
|
||||||
|
<strong> Intégrations et API</strong> section Notification et copier-coller <strong>https://intra.ffsaf.fr/api/webhook/ha </strong>
|
||||||
|
dans le champ <strong>Mon URL de callback</strong> et enregister.
|
||||||
|
<img src="/img/HA-help-4.png" alt="" className="img-fluid" style={{objectFit: "contain"}}/></li>
|
||||||
|
<li><strong>Copier-coller le nom exacte des tarifs</strong> <em>-sépare par des point-virgules-</em> qui donneront
|
||||||
|
lieux à une inscription automatique. Tous ces tarifs doivent impérativement demander le numéro de licence
|
||||||
|
en champs obligatoire. Pour ce faire, lors de la configuration de votre billetterie à l'étape n°3,
|
||||||
|
cliquer sur <strong>+ Ajouter une information</strong>, saisissez l'intituler exact suivant
|
||||||
|
<strong> Numéro de licence</strong>, dans <strong>Type de réponse souhaitée</strong> rentrer Nombre,
|
||||||
|
sélectionner les tarifs entrés plus précédemment et rendre l'information obligatoire.
|
||||||
|
<img src="/img/HA-help-3.png" className="img-fluid" alt="..." style={{object_fit: 'contain'}}/>
|
||||||
|
<img src="/img/HA-help-2.png" className="img-fluid" alt="..." style={{object_fit: 'contain'}}/></li>
|
||||||
|
<li><strong>Copier-coller l'url de votre billetterie</strong> dans le champs si dessous. Il devrais avoir la forme suivante:
|
||||||
|
<em> https://www.helloasso.com/associations/<nom-asso-sur-helloasso>/evenements/<nom-billetterie></em></li>
|
||||||
|
</ul>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<TextField name="helloassoUrl" text="Url de la billetterie HelloAsso" required={false}
|
||||||
|
value={data.data1 && data.data2 && `https://www.helloasso.com/associations/${data.data1}/evenements/${data.data2}` || ""}
|
||||||
|
placeholder="https://www.helloasso.com/associations/nom-asso-sur-helloasso/evenements/nom-billetterie"/>
|
||||||
|
|
||||||
|
<TextField name="data3" text="Tarifs HelloAsso"
|
||||||
|
value={data.data3 || ""} required={false}
|
||||||
|
placeholder="Tarif1;Tarif2;Tarif3"/>
|
||||||
|
|
||||||
|
<TextField name="data4" text="Email de réception des inscriptions échoué"
|
||||||
|
value={data.data4 || ""} required={false}/>
|
||||||
|
<small>Si pour une raison quelconque l'inscription automatique échoue, un email sera envoyé à cette adresse pour
|
||||||
|
vous en informer</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="row mb-3">
|
<div className="row mb-3">
|
||||||
@ -273,4 +441,4 @@ function Content({data}) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,14 +42,32 @@ function MakeCentralPanel({data, navigate}) {
|
|||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const inscText = (type) => {
|
||||||
|
if (type === "FREE") {
|
||||||
|
return "Inscriptions libres"
|
||||||
|
} else if (type === "CLUB_ADMIN") {
|
||||||
|
return "Inscriptions par les responsables de club"
|
||||||
|
} else if (type === "ADMIN") {
|
||||||
|
return "Inscriptions par les administrateurs de la compétition"
|
||||||
|
} else if (type === "HELLOASSO") {
|
||||||
|
return "Inscriptions sur la billetterie HelloAsso"
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
function MakeRow({data, navigate}) {
|
function MakeRow({data, navigate}) {
|
||||||
return <div className="list-group-item d-flex justify-content-between align-items-start list-group-item-action"
|
return <div className="list-group-item list-group-item-action"
|
||||||
onClick={() => navigate("" + data.id)}>
|
onClick={() => data.canEdit ? navigate("" + data.id) : navigate("view/" + data.id)}>
|
||||||
<div className="ms-2 col-auto">
|
<div className="row justify-content-between align-items-start ">
|
||||||
<div className="fw-bold">{data.name}</div>
|
<div className="ms-2 col-auto">
|
||||||
<small>{data.date.split('T')[0]}</small>
|
<div><strong>{data.name}</strong> <small>par {data.clubName}</small></div>
|
||||||
|
<small>Du {new Date(data.date.split('T')[0]).toLocaleDateString()} au {new Date(data.toDate.split('T')[0]).toLocaleDateString()}</small>
|
||||||
|
</div>
|
||||||
|
<div className="ms-2 col-auto">
|
||||||
|
<small style={{textAlign: 'right'}}>{inscText(data.registerMode)}</small>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<small style={{textAlign: 'right'}}>{data.clubName}<br/>{data.system}</small>
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import {Outlet} from "react-router-dom";
|
|||||||
import {CompetitionList} from "./CompetitionList.jsx";
|
import {CompetitionList} from "./CompetitionList.jsx";
|
||||||
import {CompetitionEdit} from "./CompetitionEdit.jsx";
|
import {CompetitionEdit} from "./CompetitionEdit.jsx";
|
||||||
import {CompetitionRegisterAdmin} from "./CompetitionRegisterAdmin.jsx";
|
import {CompetitionRegisterAdmin} from "./CompetitionRegisterAdmin.jsx";
|
||||||
|
import {CompetitionView} from "./CompetitionView.jsx";
|
||||||
|
|
||||||
export function CompetitionRoot() {
|
export function CompetitionRoot() {
|
||||||
return <>
|
return <>
|
||||||
@ -23,9 +24,13 @@ export function getCompetitionChildren() {
|
|||||||
path: ':id',
|
path: ':id',
|
||||||
element: <CompetitionEdit/>
|
element: <CompetitionEdit/>
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'view/:id',
|
||||||
|
element: <CompetitionView/>
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: ':id/register',
|
path: ':id/register',
|
||||||
element: <CompetitionRegisterAdmin/>
|
element: <CompetitionRegisterAdmin/>
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
72
src/main/webapp/src/pages/competition/CompetitionView.jsx
Normal file
72
src/main/webapp/src/pages/competition/CompetitionView.jsx
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
import {useNavigate, useParams} from "react-router-dom";
|
||||||
|
import {useLoadingSwitcher} from "../../hooks/useLoading.jsx";
|
||||||
|
import {useFetch} from "../../hooks/useFetch.js";
|
||||||
|
import {AxiosError} from "../../components/AxiosError.jsx";
|
||||||
|
import {useAuth} from "../../hooks/useAuth.jsx";
|
||||||
|
import {isClubAdmin} from "../../utils/Tools.js";
|
||||||
|
|
||||||
|
export function CompetitionView() {
|
||||||
|
|
||||||
|
const {id} = useParams()
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const setLoading = useLoadingSwitcher()
|
||||||
|
const {data, error} = useFetch(`/competition/${id}?light=true`, setLoading, 1)
|
||||||
|
|
||||||
|
return <>
|
||||||
|
<button type="button" className="btn btn-link" onClick={() => navigate("/competition")}>
|
||||||
|
« retour
|
||||||
|
</button>
|
||||||
|
<div>
|
||||||
|
{data ? <>
|
||||||
|
<MakeContent data={data}/>
|
||||||
|
</>
|
||||||
|
: error && <AxiosError error={error}/>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
||||||
|
const inscText = (type) => {
|
||||||
|
if (type === "FREE") {
|
||||||
|
return "Libres"
|
||||||
|
} else if (type === "CLUB_ADMIN") {
|
||||||
|
return "Par les responsables de club"
|
||||||
|
} else if (type === "ADMIN") {
|
||||||
|
return "Par les administrateurs de la compétition"
|
||||||
|
} else if (type === "HELLOASSO") {
|
||||||
|
return "Sur la billetterie HelloAsso"
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
function MakeContent({data}) {
|
||||||
|
const {userinfo} = useAuth()
|
||||||
|
|
||||||
|
return <div className="card mb-4">
|
||||||
|
<div className="card-header">
|
||||||
|
<h2 className="card-title" style={{textAlign: "center"}}>{data.name}</h2>
|
||||||
|
</div>
|
||||||
|
<div className="card-body">
|
||||||
|
<p>{data.description}</p>
|
||||||
|
<p><strong>Date
|
||||||
|
:</strong> Du {new Date(data.date.split('T')[0]).toLocaleDateString()} au {new Date(data.toDate.split('T')[0]).toLocaleDateString()}
|
||||||
|
</p>
|
||||||
|
<p><strong>Lieu :</strong> {data.adresse}</p>
|
||||||
|
<p><strong>Organisateur :</strong> {data.clubName}</p>
|
||||||
|
<p><strong>Type d'inscription :</strong> {inscText(data.registerMode)}</p>
|
||||||
|
{(data.registerMode === "FREE" || data.registerMode === "CLUB_ADMIN") &&
|
||||||
|
<p><strong>Date d'inscription :</strong> Du {new Date(data.startRegister.split('+')[0]).toLocaleString()} au {new Date(data.endRegister.split('+')[0]).toLocaleString()}</p>
|
||||||
|
}
|
||||||
|
{(data.registerMode === "CLUB_ADMIN" && isClubAdmin(userinfo)) || data.registerMode === "FREE" &&
|
||||||
|
<button type="button" className="btn btn-primary" disabled={new Date() < new Date(data.startRegister.split('+')[0]) || new Date() > new Date(data.endRegister.split('+')[0])}>Inscription</button>
|
||||||
|
}
|
||||||
|
{data.registerMode === "HELLOASSO" &&
|
||||||
|
<p><strong>Billetterie :</strong> <a
|
||||||
|
href={`https://www.helloasso.com/associations/${data.data1}/evenements/${data.data2}`} target="_blank"
|
||||||
|
rel="noopener noreferrer">{`https://www.helloasso.com/associations/${data.data1}/evenements/${data.data2}`}</a></p>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
@ -7,6 +7,15 @@ export const apiAxios = axios.create({
|
|||||||
});
|
});
|
||||||
apiAxios.defaults.headers.post['Accept'] = 'application/json; charset=UTF-8';
|
apiAxios.defaults.headers.post['Accept'] = 'application/json; charset=UTF-8';
|
||||||
|
|
||||||
|
export function isInClub(userinfo, clubId) {
|
||||||
|
return userinfo?.groups.filter((g => g.startsWith("/club/"))).map(g => g.split("/")[2]).map(g => Number(g.split("-")[0])).includes(clubId)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isClubAdmin(userinfo) {
|
||||||
|
return userinfo?.roles?.includes("club_president") || userinfo?.roles?.includes("club_respo_intra")
|
||||||
|
|| userinfo?.roles?.includes("club_secretaire") || userinfo?.roles?.includes("club_tresorier");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export const errFormater = (data, msg) => {
|
export const errFormater = (data, msg) => {
|
||||||
if (typeof data.response.data === 'string' || data.response.data instanceof String)
|
if (typeof data.response.data === 'string' || data.response.data instanceof String)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user