3 Commits

415 changed files with 888 additions and 10076 deletions

View File

@@ -76,7 +76,6 @@ jobs:
key: ${{ secrets.SSH_KEY }} key: ${{ secrets.SSH_KEY }}
script: | script: |
cd ${{ secrets.TARGET_DIR }} cd ${{ secrets.TARGET_DIR }}
docker logs ffsaf > "log/ffsaf_logs_$(date +"%Y-%m-%d_%H-%M-%S").log" 2>&1
docker stop ffsaf docker stop ffsaf
docker rm ffsaf docker rm ffsaf
docker compose up --build -d ffsaf docker compose up --build -d ffsaf

View File

@@ -133,11 +133,6 @@
<groupId>io.quarkus</groupId> <groupId>io.quarkus</groupId>
<artifactId>quarkus-mailer</artifactId> <artifactId>quarkus-mailer</artifactId>
</dependency> </dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-websockets-next</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>

View File

@@ -1,17 +1,20 @@
package fr.titionfire.ffsaf.data.id; package fr.titionfire.ffsaf.data.id;
import jakarta.persistence.Embeddable; import fr.titionfire.ffsaf.data.model.CompetitionModel;
import lombok.*; import fr.titionfire.ffsaf.data.model.MembreModel;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import lombok.Data;
import java.io.Serializable; import java.io.Serializable;
@Getter @Data
@Setter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
@Embeddable
public class RegisterId implements Serializable { public class RegisterId implements Serializable {
private Long competitionId; @ManyToOne
private Long membreId; @JoinColumn(name = "id_competition")
private CompetitionModel competition;
@ManyToOne
@JoinColumn(name = "id_membre")
private MembreModel membre;
} }

View File

@@ -21,7 +21,8 @@ public class AffiliationRequestModel {
Long id; Long id;
String name; String name;
String state_id; long siret;
String RNA;
String address; String address;
String contact; String contact;

View File

@@ -1,42 +0,0 @@
package fr.titionfire.ffsaf.data.model;
import io.quarkus.runtime.annotations.RegisterForReflection;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@RegisterForReflection
@Entity
@Table(name = "cardboard")
public class CardboardModel {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "comb", referencedColumnName = "id")
MembreModel comb;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "guest_comb", referencedColumnName = "id")
CompetitionGuestModel guestComb;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "match", referencedColumnName = "id")
MatchModel match;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "compet", referencedColumnName = "id")
CompetitionModel compet;
int red;
int yellow;
}

View File

@@ -55,8 +55,11 @@ public class ClubModel implements LoggableModel {
@Schema(description = "Adresse postale du club", example = "1 rue de l'exemple, 75000 Paris") @Schema(description = "Adresse postale du club", example = "1 rue de l'exemple, 75000 Paris")
String address; String address;
@Schema(description = "Numéro SIRET ou RNA du club", example = "12345678901234") @Schema(description = "RNA du club", example = "W123456789")
String StateId; String RNA;
@Schema(description = "Numéro SIRET du club", example = "12345678901234")
Long SIRET;
@Schema(description = "Numéro d'affiliation du club", example = "12345") @Schema(description = "Numéro d'affiliation du club", example = "12345")
Long no_affiliation; Long no_affiliation;

View File

@@ -1,50 +0,0 @@
package fr.titionfire.ffsaf.data.model;
import fr.titionfire.ffsaf.utils.Categorie;
import fr.titionfire.ffsaf.utils.Genre;
import io.quarkus.runtime.annotations.RegisterForReflection;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@RegisterForReflection
@Entity
@Table(name = "competition_guest")
public class CompetitionGuestModel {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "competition", referencedColumnName = "id")
CompetitionModel competition;
String lname = "";
String fname = "";
Categorie categorie = null;
String club = null;
Genre genre = null;
String country = "fr";
Integer weight = null;
public CompetitionGuestModel(String s) {
this.fname = s.substring(0, s.indexOf(" "));
this.lname = s.substring(s.indexOf(" ") + 1);
}
public String getName() {
return fname + " " + lname;
}
}

View File

@@ -1,7 +1,6 @@
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;
@@ -9,7 +8,6 @@ import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@@ -23,7 +21,6 @@ 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;
@@ -39,36 +36,9 @@ 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;
@OneToMany(mappedBy = "competition", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
List<CompetitionGuestModel> guests = new ArrayList<>();
List<Long> banMembre = new ArrayList<>();
String owner; String owner;
List<String> admin = new ArrayList<>();
@Column(name = "table_")
List<String> table = new ArrayList<>();
String data1;
String data2;
String data3;
String data4;
} }

View File

@@ -1,41 +0,0 @@
package fr.titionfire.ffsaf.data.model;
import fr.titionfire.ffsaf.data.id.RegisterId;
import io.quarkus.runtime.annotations.RegisterForReflection;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@RegisterForReflection
@Entity
@Table(name = "helloasso_register")
public class HelloAssoRegisterModel {
@EmbeddedId
RegisterId id;
@MapsId("competitionId")
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "id_competition")
CompetitionModel competition;
@MapsId("membreId")
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "id_membre")
MembreModel membre;
Integer orderId;
public HelloAssoRegisterModel(CompetitionModel competition, MembreModel membre, Integer orderId) {
this.id = new RegisterId(competition.getId(), membre.getId());
this.competition = competition;
this.membre = membre;
this.orderId = orderId;
}
}

View File

@@ -30,10 +30,8 @@ public class LogModel {
Long target_id; Long target_id;
@Column(columnDefinition = "TEXT")
String target_name; String target_name;
@Column(columnDefinition = "TEXT")
String message; String message;
public enum ActionType { public enum ActionType {

View File

@@ -7,7 +7,6 @@ import jakarta.persistence.*;
import lombok.*; import lombok.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import java.util.List; import java.util.List;
@Getter @Getter
@@ -33,65 +32,25 @@ public class MatchModel {
@JoinColumn(name = "c1", referencedColumnName = "id") @JoinColumn(name = "c1", referencedColumnName = "id")
MembreModel c1_id = null; MembreModel c1_id = null;
@ManyToOne(fetch = FetchType.EAGER) String c1_str = null;
@JoinColumn(name = "c1_guest", referencedColumnName = "id")
CompetitionGuestModel c1_guest = null;
@ManyToOne(fetch = FetchType.EAGER) @ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "c2", referencedColumnName = "id") @JoinColumn(name = "c2", referencedColumnName = "id")
MembreModel c2_id = null; MembreModel c2_id = null;
@ManyToOne(fetch = FetchType.EAGER) String c2_str = null;
@JoinColumn(name = "c2_guest", referencedColumnName = "id")
CompetitionGuestModel c2_guest = null;
@ManyToOne(fetch = FetchType.EAGER) @ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "id_category", referencedColumnName = "id") @JoinColumn(name = "id_poule", referencedColumnName = "id")
CategoryModel category = null; PouleModel poule = null;
long category_ord = 0; long poule_ord = 0;
boolean isEnd = true; boolean isEnd = true;
Date date = null;
@ElementCollection(fetch = FetchType.EAGER) @ElementCollection(fetch = FetchType.EAGER)
@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 poule = 'A'; char groupe = 'A';
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "match", referencedColumnName = "id")
List<CardboardModel> cardboard = new ArrayList<>();
public String getC1Name() {
if (c1_id != null)
return c1_id.fname + " " + c1_id.lname;
if (c1_guest != null)
return c1_guest.fname + " " + c1_guest.lname;
return "";
}
public String getC2Name() {
if (c2_id != null)
return c2_id.fname + " " + c2_id.lname;
if (c2_guest != null)
return c2_guest.fname + " " + c2_guest.lname;
return "";
}
public int win() {
int sum = 0;
for (ScoreEmbeddable score : this.getScores()) {
if (score.getS1() == -1000 || score.getS2() == -1000)
continue;
if (score.getS1() > score.getS2())
sum++;
else if (score.getS1() < score.getS2())
sum--;
}
return sum;
}
} }

View File

@@ -82,22 +82,4 @@ public class MembreModel implements LoggableModel {
public LogModel.ObjectType getObjectType() { public LogModel.ObjectType getObjectType() {
return LogModel.ObjectType.Membre; return LogModel.ObjectType.Membre;
} }
@Override
public String toString() {
return "MembreModel{" +
"id=" + id +
", userId='" + userId + '\'' +
", lname='" + lname + '\'' +
", fname='" + fname + '\'' +
", categorie=" + categorie +
", genre=" + genre +
", licence=" + licence +
", country='" + country + '\'' +
", birth_date=" + birth_date +
", email='" + email + '\'' +
", role=" + role +
", grade_arbitrage=" + grade_arbitrage +
'}';
}
} }

View File

@@ -17,8 +17,8 @@ import java.util.List;
@RegisterForReflection @RegisterForReflection
@Entity @Entity
@Table(name = "category") @Table(name = "poule")
public class CategoryModel { public class PouleModel {
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
Long id; Long id;
@@ -34,14 +34,12 @@ public class CategoryModel {
CompetitionModel compet; CompetitionModel compet;
@OneToMany(fetch = FetchType.LAZY) @OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name = "id_category", referencedColumnName = "id") @JoinColumn(name = "id_poule", referencedColumnName = "id")
List<MatchModel> matchs; List<MatchModel> matchs;
@OneToMany(fetch = FetchType.LAZY) @OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name = "id_category", referencedColumnName = "id") @JoinColumn(name = "id_poule", referencedColumnName = "id")
List<TreeModel> tree; List<TreeModel> tree;
Integer type; Integer type;
String liceName = "1";
} }

View File

@@ -8,8 +8,6 @@ import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;
@Getter @Getter
@Setter @Setter
@@ -19,17 +17,14 @@ import org.hibernate.annotations.OnDeleteAction;
@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;
@MapsId("membreId") @Id
@ManyToOne(fetch = FetchType.EAGER) @ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "id_membre") @JoinColumn(name = "id_membre")
MembreModel membre; MembreModel membre;
@@ -40,30 +35,6 @@ public class RegisterModel {
@ManyToOne(fetch = FetchType.EAGER) @ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "club") @JoinColumn(name = "club")
@OnDelete(action = OnDeleteAction.SET_NULL)
ClubModel club = null; ClubModel club = null;
@Column(nullable = false, columnDefinition = "boolean default false")
boolean lockEdit = false;
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;
}
public String getName() {
return membre.fname + " " + membre.lname;
}
public ClubModel getClub2() {
if (club == null)
return membre.club;
return club;
}
} }

View File

@@ -7,9 +7,6 @@ import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import java.util.ArrayList;
import java.util.List;
@Getter @Getter
@Setter @Setter
@AllArgsConstructor @AllArgsConstructor
@@ -23,8 +20,8 @@ public class TreeModel {
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
Long id; Long id;
@Column(name = "id_category") @Column(name = "id_poule")
Long category; Long poule;
Integer level; Integer level;
@@ -39,20 +36,4 @@ public class TreeModel {
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST) @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
@JoinColumn(referencedColumnName = "id") @JoinColumn(referencedColumnName = "id")
TreeModel right; TreeModel right;
public List<TreeModel> flat() {
List<TreeModel> out = new ArrayList<>();
this.flat(out);
return out;
}
private void flat(List<TreeModel> out) {
out.add(this);
if (this.right != null)
this.right.flat(out);
if (this.left != null)
this.left.flat(out);
}
} }

View File

@@ -1,19 +0,0 @@
package fr.titionfire.ffsaf.data.repository;
import fr.titionfire.ffsaf.data.model.CategoryModel;
import fr.titionfire.ffsaf.utils.CompetitionSystem;
import io.quarkus.hibernate.reactive.panache.Panache;
import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase;
import io.smallrye.mutiny.Uni;
import jakarta.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class CategoryRepository implements PanacheRepositoryBase<CategoryModel, Long> {
public Uni<CategoryModel> create(CategoryModel categoryModel) {
categoryModel.setSystem(CompetitionSystem.INTERNAL);
return Panache.withTransaction(() -> this.persist(categoryModel)
.invoke(categoryModel1 -> categoryModel1.setSystemId(categoryModel1.getId())))
.chain(this::persist);
}
}

View File

@@ -1,9 +0,0 @@
package fr.titionfire.ffsaf.data.repository;
import fr.titionfire.ffsaf.data.model.CompetitionGuestModel;
import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase;
import jakarta.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class CompetitionGuestRepository implements PanacheRepositoryBase<CompetitionGuestModel, Long> {
}

View File

@@ -1,9 +0,0 @@
package fr.titionfire.ffsaf.data.repository;
import fr.titionfire.ffsaf.data.model.HelloAssoRegisterModel;
import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase;
import jakarta.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class HelloAssoRegisterRepository implements PanacheRepositoryBase<HelloAssoRegisterModel, Long> {
}

View File

@@ -1,30 +1,9 @@
package fr.titionfire.ffsaf.data.repository; package fr.titionfire.ffsaf.data.repository;
import fr.titionfire.ffsaf.data.model.MatchModel; import fr.titionfire.ffsaf.data.model.MatchModel;
import fr.titionfire.ffsaf.utils.CompetitionSystem;
import io.quarkus.hibernate.reactive.panache.Panache;
import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase; import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase;
import io.smallrye.mutiny.Uni;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
import java.util.List;
@ApplicationScoped @ApplicationScoped
public class MatchRepository implements PanacheRepositoryBase<MatchModel, Long> { public class MatchRepository implements PanacheRepositoryBase<MatchModel, Long> {
public Uni<MatchModel> create(MatchModel matchModel) {
matchModel.setSystem(CompetitionSystem.INTERNAL);
return Panache.withTransaction(() -> this.persistAndFlush(matchModel)
.invoke(matchModel1 -> matchModel1.setSystemId(matchModel1.getId())))
.chain(this::persist);
}
public Uni<Void> create(List<MatchModel> matchModel) {
matchModel.forEach(model -> model.setSystem(CompetitionSystem.INTERNAL));
return Panache.withTransaction(() -> this.persist(matchModel)
.call(__ -> this.flush())
.invoke(__ -> matchModel.forEach(model -> model.setSystemId(model.getId())))
.map(__ -> matchModel))
.chain(this::persist);
}
} }

View File

@@ -1,9 +1,9 @@
package fr.titionfire.ffsaf.data.repository; package fr.titionfire.ffsaf.data.repository;
import fr.titionfire.ffsaf.data.model.CardboardModel; import fr.titionfire.ffsaf.data.model.PouleModel;
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 CardboardRepository implements PanacheRepositoryBase<CardboardModel, Long> { public class PouleRepository implements PanacheRepositoryBase<PouleModel, Long> {
} }

View File

@@ -1,11 +1,9 @@
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.PanacheRepositoryBase; import io.quarkus.hibernate.reactive.panache.PanacheRepository;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
@ApplicationScoped @ApplicationScoped
public class RegisterRepository implements PanacheRepositoryBase<RegisterModel, RegisterId> { public class RegisterRepository implements PanacheRepository<RegisterModel> {
} }

View File

@@ -2,22 +2,8 @@ package fr.titionfire.ffsaf.data.repository;
import fr.titionfire.ffsaf.data.model.TreeModel; import fr.titionfire.ffsaf.data.model.TreeModel;
import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase; import io.quarkus.hibernate.reactive.panache.PanacheRepositoryBase;
import io.quarkus.hibernate.reactive.panache.common.WithTransaction;
import io.smallrye.mutiny.Uni;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
@ApplicationScoped @ApplicationScoped
public class TreeRepository implements PanacheRepositoryBase<TreeModel, Long> { public class TreeRepository implements PanacheRepositoryBase<TreeModel, Long> {
@WithTransaction
public Uni<Boolean> deleteTree(TreeModel entity) {
Uni<Boolean> uni = Uni.createFrom().item(false);
if (entity == null)
return uni;
if (entity.getLeft() != null)
uni = uni.chain(__ -> this.deleteTree(entity.getLeft()));
if (entity.getRight() != null)
uni = uni.chain(__ -> this.deleteTree(entity.getRight()));
return uni.chain(__ -> this.deleteById(entity.getId()));
}
} }

View File

@@ -1,26 +0,0 @@
package fr.titionfire.ffsaf.domain.entity;
import fr.titionfire.ffsaf.data.model.CardboardModel;
import io.quarkus.runtime.annotations.RegisterForReflection;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
@RegisterForReflection
public class CardboardEntity {
long comb_id;
long match_id;
long compet_id;
int red;
int yellow;
public static CardboardEntity fromModel(CardboardModel model) {
return new CardboardEntity(
model.getComb() != null ? model.getComb().getId() : model.getGuestComb().getId() * -1,
model.getMatch().getId(),
model.getCompet().getId(),
model.getRed(), model.getYellow());
}
}

View File

@@ -22,7 +22,8 @@ public class ClubEntity {
private String training_location; private String training_location;
private String training_day_time; private String training_day_time;
private String contact_intern; private String contact_intern;
private String StateId; private String RNA;
private Long SIRET;
private Long no_affiliation; private Long no_affiliation;
private boolean international; private boolean international;
@@ -40,7 +41,8 @@ public class ClubEntity {
.training_location(model.getTraining_location()) .training_location(model.getTraining_location())
.training_day_time(model.getTraining_day_time()) .training_day_time(model.getTraining_day_time())
.contact_intern(model.getContact_intern()) .contact_intern(model.getContact_intern())
.StateId(model.getStateId()) .RNA(model.getRNA())
.SIRET(model.getSIRET())
.no_affiliation(model.getNo_affiliation()) .no_affiliation(model.getNo_affiliation())
.international(model.isInternational()) .international(model.isInternational())
.build(); .build();

View File

@@ -1,56 +0,0 @@
package fr.titionfire.ffsaf.domain.entity;
import fr.titionfire.ffsaf.data.model.CompetitionGuestModel;
import fr.titionfire.ffsaf.data.model.MembreModel;
import fr.titionfire.ffsaf.data.model.RegisterModel;
import fr.titionfire.ffsaf.utils.Categorie;
import fr.titionfire.ffsaf.utils.Genre;
import io.quarkus.runtime.annotations.RegisterForReflection;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
@RegisterForReflection
public class CombEntity {
private long id;
private String lname;
private String fname;
Categorie categorie;
String club_uuid;
String club_str;
Genre genre;
String country;
int overCategory;
Integer weight;
public static CombEntity fromModel(MembreModel model) {
if (model == null)
return null;
return new CombEntity(model.getId(), model.getLname(), model.getFname(), model.getCategorie(),
model.getClub() == null ? null : model.getClub().getClubId(),
model.getClub() == null ? "Sans club" : model.getClub().getName(), model.getGenre(), model.getCountry(),
0, null);
}
public static CombEntity fromModel(CompetitionGuestModel model) {
if (model == null)
return null;
return new CombEntity(model.getId() * -1, model.getLname(), model.getFname(), model.getCategorie(), null,
model.getClub(), model.getGenre(), model.getCountry(), 0, model.getWeight());
}
public static CombEntity fromModel(RegisterModel registerModel) {
if (registerModel == null || registerModel.getMembre() == null)
return null;
MembreModel model = registerModel.getMembre();
return new CombEntity(model.getId(), model.getLname(), model.getFname(), registerModel.getCategorie(),
registerModel.getClub2() == null ? null : registerModel.getClub2().getClubId(),
registerModel.getClub2() == null ? "Sans club" : registerModel.getClub2().getName(), model.getGenre(),
model.getCountry(), registerModel.getOverCategory(), registerModel.getWeight());
}
}

View File

@@ -1,56 +0,0 @@
package fr.titionfire.ffsaf.domain.entity;
import fr.titionfire.ffsaf.data.model.MatchModel;
import fr.titionfire.ffsaf.utils.ScoreEmbeddable;
import io.quarkus.runtime.annotations.RegisterForReflection;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Data
@AllArgsConstructor
@RegisterForReflection
public class MatchEntity {
private long id;
private CombEntity c1;
private CombEntity c2;
private long categorie_ord = 0;
private boolean isEnd;
private long categorie;
private Date date;
private List<ScoreEmbeddable> scores;
private char poule;
private List<CardboardEntity> cardboard;
public static MatchEntity fromModel(MatchModel model) {
if (model == null)
return null;
return new MatchEntity(model.getId(),
(model.getC1_id() == null) ? CombEntity.fromModel(model.getC1_guest()) : CombEntity.fromModel(
model.getC1_id()),
(model.getC2_id() == null) ? CombEntity.fromModel(model.getC2_guest()) : CombEntity.fromModel(
model.getC2_id()),
model.getCategory_ord(), model.isEnd(), model.getCategory().getId(), model.getDate(),
model.getScores(),
model.getPoule(),
(model.getCardboard() == null) ? new ArrayList<>() : model.getCardboard().stream()
.map(CardboardEntity::fromModel).toList());
}
public int win() {
int sum = 0;
for (ScoreEmbeddable score : scores) {
if (score.getS1() == -1000 || score.getS2() == -1000)
continue;
if (score.getS1() > score.getS2())
sum++;
else if (score.getS1() < score.getS2())
sum--;
}
return sum;
}
}

View File

@@ -1,71 +0,0 @@
package fr.titionfire.ffsaf.domain.entity;
import fr.titionfire.ffsaf.data.model.TreeModel;
import io.quarkus.runtime.annotations.RegisterForReflection;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
@RegisterForReflection
public class TreeEntity {
private Long id;
private Long categorie;
private Integer level;
private MatchEntity match;
private TreeEntity left;
private TreeEntity right;
private TreeEntity associatedNode;
public static TreeEntity fromModel(TreeModel model) {
if (model == null)
return null;
return new TreeEntity(model.getId(), model.getCategory(), model.getLevel(), MatchEntity.fromModel(model.getMatch()), fromModel(model.getLeft()),
fromModel(model.getRight()), null);
}
public TreeEntity getMatchNode(Long matchId) {
if (this.match != null && this.match.getId() == matchId) {
return this;
} else {
if (this.left != null) {
TreeEntity left = this.left.getMatchNode(matchId);
if (left != null) {
return left;
}
}
if (this.right != null) {
TreeEntity right = this.right.getMatchNode(matchId);
if (right != null) {
return right;
}
}
}
return null;
}
public static TreeEntity getParent(TreeEntity current, TreeEntity target) {
if (current == null) {
return null;
} else if (current.equals(target)) {
return null;
} else if (target.equals(current.left) || target.equals(current.right)) {
return current;
} else {
TreeEntity left = getParent(current.left, target);
if (left != null)
return left;
return getParent(current.right, target);
}
}
public static void setAssociated(TreeEntity current, TreeEntity next) {
if (current == null || next == null) {
return;
}
current.setAssociatedNode(next);
setAssociated(current.getLeft(), next.getLeft());
setAssociated(current.getRight(), next.getRight());
}
}

View File

@@ -2,8 +2,6 @@ package fr.titionfire.ffsaf.domain.service;
import fr.titionfire.ffsaf.data.model.*; import fr.titionfire.ffsaf.data.model.*;
import fr.titionfire.ffsaf.data.repository.*; import fr.titionfire.ffsaf.data.repository.*;
import fr.titionfire.ffsaf.rest.client.SirenService;
import fr.titionfire.ffsaf.rest.client.StateIdService;
import fr.titionfire.ffsaf.rest.data.SimpleAffiliation; import fr.titionfire.ffsaf.rest.data.SimpleAffiliation;
import fr.titionfire.ffsaf.rest.data.SimpleReqAffiliation; import fr.titionfire.ffsaf.rest.data.SimpleReqAffiliation;
import fr.titionfire.ffsaf.rest.exception.DBadRequestException; import fr.titionfire.ffsaf.rest.exception.DBadRequestException;
@@ -23,19 +21,15 @@ 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 org.eclipse.microprofile.config.inject.ConfigProperty; import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.hibernate.reactive.mutiny.Mutiny; import org.hibernate.reactive.mutiny.Mutiny;
import org.jboss.logging.Logger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Stream; import java.util.stream.Stream;
@WithSession @WithSession
@ApplicationScoped @ApplicationScoped
public class AffiliationService { public class AffiliationService {
private static final Logger LOGGER = Logger.getLogger(AffiliationService.class);
@Inject @Inject
CombRepository combRepository; CombRepository combRepository;
@@ -64,12 +58,6 @@ public class AffiliationService {
@Inject @Inject
LoggerService ls; LoggerService ls;
@RestClient
StateIdService stateIdService;
@RestClient
SirenService sirenService;
@ConfigProperty(name = "upload_dir") @ConfigProperty(name = "upload_dir")
String media; String media;
@@ -83,8 +71,6 @@ public class AffiliationService {
public Uni<AffiliationRequestModel> pre_save(AffiliationRequestForm form, boolean unique) { public Uni<AffiliationRequestModel> pre_save(AffiliationRequestForm form, boolean unique) {
AffiliationRequestModel affModel = form.toModel(); AffiliationRequestModel affModel = form.toModel();
int currentSaison = Utils.getSaison(); int currentSaison = Utils.getSaison();
List<String> out = new ArrayList<>();
out.add(affModel.getState_id());
return Uni.createFrom().item(affModel) return Uni.createFrom().item(affModel)
.invoke(Unchecked.consumer(model -> { .invoke(Unchecked.consumer(model -> {
@@ -92,26 +78,14 @@ public class AffiliationService {
throw new DBadRequestException("Saison non valid"); throw new DBadRequestException("Saison non valid");
} }
})) }))
.chain(() -> ((affModel.getState_id().charAt(0) == 'W') ? stateIdService.get_rna( .chain(() -> repositoryRequest.count("siret = ?1 and saison = ?2", affModel.getSiret(),
affModel.getState_id()) : sirenService.get_unite(affModel.getState_id()) affModel.getSaison()))
.chain(stateIdService::getAssoDataFromUnit)).onItem().transform(o -> {
if (o.getRna() != null && !o.getRna().isBlank())
out.add(o.getRna());
if (o.getSiren() != null && !o.getSiren().isBlank())
out.add(o.getSiren());
if (o.getIdentite().getSiret_siege() != null && !o.getIdentite().getSiret_siege().isBlank())
out.add(o.getIdentite().getSiret_siege());
return out;
}).onFailure().recoverWithItem(out)
.chain(a -> repositoryRequest.count("state_id IN ?1 and saison = ?2",
out, affModel.getSaison()))
.onItem().invoke(Unchecked.consumer(count -> { .onItem().invoke(Unchecked.consumer(count -> {
if (count != 0 && unique) { if (count != 0 && unique) {
throw new DBadRequestException("Demande d'affiliation déjà existante"); throw new DBadRequestException("Demande d'affiliation déjà existante");
} }
})) }))
) .chain(() -> clubRepository.find("SIRET = ?1", affModel.getSiret()).firstResult().chain(club ->
.chain(() -> clubRepository.find("StateId IN ?1", out).firstResult().chain(club ->
repository.count("club = ?1 and saison = ?2", club, affModel.getSaison()))) repository.count("club = ?1 and saison = ?2", club, affModel.getSaison())))
.onItem().invoke(Unchecked.consumer(count -> { .onItem().invoke(Unchecked.consumer(count -> {
if (count != 0) { if (count != 0) {
@@ -148,6 +122,7 @@ public class AffiliationService {
.onItem().ifNull().failWith(new DNotFoundException("Demande d'affiliation non trouvé")) .onItem().ifNull().failWith(new DNotFoundException("Demande d'affiliation non trouvé"))
.chain(origine -> { .chain(origine -> {
origine.setName(model.getName()); origine.setName(model.getName());
origine.setRNA(model.getRNA());
origine.setAddress(model.getAddress()); origine.setAddress(model.getAddress());
origine.setContact(model.getContact()); origine.setContact(model.getContact());
origine.setM1_lname(model.getM1_lname()); origine.setM1_lname(model.getM1_lname());
@@ -171,9 +146,6 @@ public class AffiliationService {
} }
public Uni<String> save(AffiliationRequestForm form) { public Uni<String> save(AffiliationRequestForm form) {
LOGGER.debug("Affiliation Request Created");
LOGGER.debug(form.toString());
// noinspection ResultOfMethodCallIgnored,ReactiveStreamsUnusedPublisher // noinspection ResultOfMethodCallIgnored,ReactiveStreamsUnusedPublisher
return pre_save(form, true) return pre_save(form, true)
.chain(model -> Panache.withTransaction(() -> repositoryRequest.persist(model))) .chain(model -> Panache.withTransaction(() -> repositoryRequest.persist(model)))
@@ -197,14 +169,12 @@ public class AffiliationService {
} }
public Uni<?> saveAdmin(AffiliationRequestSaveForm form) { public Uni<?> saveAdmin(AffiliationRequestSaveForm form) {
LOGGER.debug("Affiliation Request Saved");
LOGGER.debug(form.toString());
return repositoryRequest.findById(form.getId()) return repositoryRequest.findById(form.getId())
.onItem().ifNull().failWith(new DNotFoundException("Demande d'affiliation non trouvé")) .onItem().ifNull().failWith(new DNotFoundException("Demande d'affiliation non trouvé"))
.map(model -> { .map(model -> {
model.setName(form.getName()); model.setName(form.getName());
model.setState_id(form.getState_id()); model.setSiret(form.getSiret());
model.setRNA(form.getRna());
model.setAddress(form.getAddress()); model.setAddress(form.getAddress());
model.setContact(form.getContact()); model.setContact(form.getContact());
@@ -289,9 +259,7 @@ public class AffiliationService {
}).call(m -> Panache.withTransaction(() -> combRepository.persist(m))); }).call(m -> Panache.withTransaction(() -> combRepository.persist(m)));
} }
}) })
.call(m -> ((m.getUserId() == null) ? keycloakService.initCompte(m.getId()) .call(m -> ((m.getUserId() == null) ? keycloakService.initCompte(m.getId()) :
.onFailure().invoke(t -> LOGGER.warnf("Failed to init account: %s", t.getMessage())).onFailure()
.recoverWithNull() :
keycloakService.setClubGroupMembre(m, club).map(__ -> m.getUserId())) keycloakService.setClubGroupMembre(m, club).map(__ -> m.getUserId()))
.call(userId -> keycloakService.setAutoRoleMembre(userId, m.getRole(), m.getGrade_arbitrage())) .call(userId -> keycloakService.setAutoRoleMembre(userId, m.getRole(), m.getGrade_arbitrage()))
.call(userId -> keycloakService.setEmail(userId, m.getEmail()))) .call(userId -> keycloakService.setEmail(userId, m.getEmail())))
@@ -305,18 +273,13 @@ public class AffiliationService {
} }
public Uni<?> accept(AffiliationRequestSaveForm form) { public Uni<?> accept(AffiliationRequestSaveForm form) {
LOGGER.debug("Affiliation Request Accepted");
LOGGER.debug(form.toString());
return repositoryRequest.findById(form.getId()) return repositoryRequest.findById(form.getId())
.onItem().ifNull().failWith(new DNotFoundException("Demande d'affiliation non trouvé")) .onItem().ifNull().failWith(new DNotFoundException("Demande d'affiliation non trouvé"))
.chain(req -> .chain(req ->
clubRepository.find("StateId = ?1", form.getState_id()).firstResult() clubRepository.find("SIRET = ?1", form.getSiret()).firstResult()
.chain(model -> (model == null) ? acceptNew(form, req) : acceptOld(form, req, model)) .chain(model -> (model == null) ? acceptNew(form, req) : acceptOld(form, req, model))
.call(club -> setMembre(form.new Member(1), club, req.getSaison()).onFailure() .call(club -> setMembre(form.new Member(1), club, req.getSaison())
.recoverWithNull() .call(__ -> setMembre(form.new Member(2), club, req.getSaison())
.call(__ -> setMembre(form.new Member(2), club, req.getSaison()).onFailure()
.recoverWithNull()
.call(___ -> setMembre(form.new Member(3), club, req.getSaison())))) .call(___ -> setMembre(form.new Member(3), club, req.getSaison()))))
.onItem() .onItem()
.invoke(model -> Uni.createFrom() .invoke(model -> Uni.createFrom()
@@ -335,13 +298,13 @@ public class AffiliationService {
} }
private Uni<ClubModel> acceptNew(AffiliationRequestSaveForm form, AffiliationRequestModel model) { private Uni<ClubModel> acceptNew(AffiliationRequestSaveForm form, AffiliationRequestModel model) {
LOGGER.debug("New Club Accepted");
return Uni.createFrom().nullItem() return Uni.createFrom().nullItem()
.chain(() -> { .chain(() -> {
ClubModel club = new ClubModel(); ClubModel club = new ClubModel();
club.setName(form.getName()); club.setName(form.getName());
club.setCountry("FR"); club.setCountry("FR");
club.setStateId(form.getState_id()); club.setSIRET(form.getSiret());
club.setRNA(form.getRna());
club.setAddress(form.getAddress()); club.setAddress(form.getAddress());
club.setContact_intern(form.getContact()); club.setContact_intern(form.getContact());
club.setAffiliations(new ArrayList<>()); club.setAffiliations(new ArrayList<>());
@@ -373,24 +336,17 @@ public class AffiliationService {
} }
private Uni<ClubModel> acceptOld(AffiliationRequestSaveForm form, AffiliationRequestModel model, ClubModel club) { private Uni<ClubModel> acceptOld(AffiliationRequestSaveForm form, AffiliationRequestModel model, ClubModel club) {
AtomicBoolean nameChange = new AtomicBoolean(false);
LOGGER.debug("Old Club Accepted");
return Uni.createFrom().nullItem() return Uni.createFrom().nullItem()
.chain(() -> { .chain(() -> {
if (!form.getName().equals(club.getName())) {
club.setName(form.getName()); club.setName(form.getName());
nameChange.set(true);
}
club.setCountry("FR"); club.setCountry("FR");
club.setStateId(form.getState_id()); club.setSIRET(form.getSiret());
club.setRNA(form.getRna());
club.setAddress(form.getAddress()); club.setAddress(form.getAddress());
club.setContact_intern(form.getContact()); club.setContact_intern(form.getContact());
return Panache.withTransaction(() -> clubRepository.persist(club) return Panache.withTransaction(() -> clubRepository.persist(club)
.chain(() -> repository.persist(new AffiliationModel(null, club, model.getSaison()))) .chain(() -> repository.persist(new AffiliationModel(null, club, model.getSaison())))
.chain(() -> repositoryRequest.delete(model))) .chain(() -> repositoryRequest.delete(model)));
.call(() -> nameChange.get() ? keycloakService.updateGroupFromClub(
club) // update group in keycloak
: Uni.createFrom().nullItem());
}) })
.map(__ -> club); .map(__ -> club);
} }
@@ -398,7 +354,7 @@ public class AffiliationService {
public Uni<SimpleReqAffiliation> getRequest(long id) { public Uni<SimpleReqAffiliation> getRequest(long id) {
return repositoryRequest.findById(id).map(SimpleReqAffiliation::fromModel) return repositoryRequest.findById(id).map(SimpleReqAffiliation::fromModel)
.onItem().ifNull().failWith(new DNotFoundException("Demande d'affiliation non trouvé")) .onItem().ifNull().failWith(new DNotFoundException("Demande d'affiliation non trouvé"))
.call(out -> clubRepository.find("StateId = ?1", out.getStateId()).firstResult().invoke(c -> { .call(out -> clubRepository.find("SIRET = ?1", out.getSiret()).firstResult().invoke(c -> {
if (c != null) { if (c != null) {
out.setClub(c.getId()); out.setClub(c.getId());
out.setClub_name(c.getName()); out.setClub_name(c.getName());
@@ -411,7 +367,7 @@ public class AffiliationService {
public Uni<List<SimpleAffiliation>> getCurrentSaisonAffiliation() { public Uni<List<SimpleAffiliation>> getCurrentSaisonAffiliation() {
return repositoryRequest.list("saison = ?1 or saison = ?1 + 1", Utils.getSaison()) return repositoryRequest.list("saison = ?1 or saison = ?1 + 1", Utils.getSaison())
.map(models -> models.stream() .map(models -> models.stream()
.map(model -> new SimpleAffiliation(model.getId() * -1, model.getState_id(), model.getSaison(), .map(model -> new SimpleAffiliation(model.getId() * -1, model.getSiret(), model.getSaison(),
false)).toList()) false)).toList())
.chain(aff -> repository.list("saison = ?1", Utils.getSaison()) .chain(aff -> repository.list("saison = ?1", Utils.getSaison())
.map(models -> models.stream().map(SimpleAffiliation::fromModel).toList()) .map(models -> models.stream().map(SimpleAffiliation::fromModel).toList())
@@ -423,9 +379,9 @@ public class AffiliationService {
return clubRepository.findById(id) return clubRepository.findById(id)
.onItem().ifNull().failWith(new DNotFoundException("Club non trouvé")) .onItem().ifNull().failWith(new DNotFoundException("Club non trouvé"))
.call(model -> Mutiny.fetch(model.getAffiliations())) .call(model -> Mutiny.fetch(model.getAffiliations()))
.chain(model -> repositoryRequest.list("state_id = ?1", model.getStateId()) .chain(model -> repositoryRequest.list("siret = ?1", model.getSIRET())
.map(reqs -> reqs.stream().map(req -> .map(reqs -> reqs.stream().map(req ->
new SimpleAffiliation(req.getId() * -1, model.getStateId(), req.getSaison(), false))) new SimpleAffiliation(req.getId() * -1, model.getId(), req.getSaison(), false)))
.map(aff2 -> Stream.concat(aff2, .map(aff2 -> Stream.concat(aff2,
model.getAffiliations().stream().map(SimpleAffiliation::fromModel)).toList()) model.getAffiliations().stream().map(SimpleAffiliation::fromModel)).toList())
); );
@@ -455,9 +411,9 @@ public class AffiliationService {
return Panache.withTransaction(() -> repository.deleteById(id)); return Panache.withTransaction(() -> repository.deleteById(id));
} }
public Uni<?> deleteReqAffiliation(long id, String reason, boolean federationAdmin) { public Uni<?> deleteReqAffiliation(long id, String reason) {
return repositoryRequest.findById(id) return repositoryRequest.findById(id)
.call(aff -> federationAdmin ? reactiveMailer.send( .call(aff -> reactiveMailer.send(
Mail.withText(aff.getM1_email(), Mail.withText(aff.getM1_email(),
"FFSAF - Votre demande d'affiliation a été rejetée.", "FFSAF - Votre demande d'affiliation a été rejetée.",
String.format( String.format(
@@ -474,7 +430,7 @@ public class AffiliationService {
""", aff.getName(), reason) """, aff.getName(), reason)
).setFrom("FFSAF <no-reply@ffsaf.fr>").setReplyTo("contact@ffsaf.fr") ).setFrom("FFSAF <no-reply@ffsaf.fr>").setReplyTo("contact@ffsaf.fr")
.addTo(aff.getM2_email(), aff.getM3_email()) .addTo(aff.getM2_email(), aff.getM3_email())
) : Uni.createFrom().nullItem()) ))
.chain(aff -> Panache.withTransaction(() -> repositoryRequest.delete(aff))) .chain(aff -> Panache.withTransaction(() -> repositoryRequest.delete(aff)))
.call(__ -> Utils.deleteMedia(id, media, "aff_request/logo")) .call(__ -> Utils.deleteMedia(id, media, "aff_request/logo"))
.call(__ -> Utils.deleteMedia(id, media, "aff_request/status")); .call(__ -> Utils.deleteMedia(id, media, "aff_request/status"));

View File

@@ -10,7 +10,10 @@ import fr.titionfire.ffsaf.data.repository.CombRepository;
import fr.titionfire.ffsaf.net2.ServerCustom; import fr.titionfire.ffsaf.net2.ServerCustom;
import fr.titionfire.ffsaf.net2.data.SimpleClubModel; import fr.titionfire.ffsaf.net2.data.SimpleClubModel;
import fr.titionfire.ffsaf.net2.request.SReqClub; import fr.titionfire.ffsaf.net2.request.SReqClub;
import fr.titionfire.ffsaf.rest.data.*; import fr.titionfire.ffsaf.rest.data.ClubMapData;
import fr.titionfire.ffsaf.rest.data.DeskMember;
import fr.titionfire.ffsaf.rest.data.RenewAffData;
import fr.titionfire.ffsaf.rest.data.SimpleClubList;
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.rest.exception.DNotFoundException; import fr.titionfire.ffsaf.rest.exception.DNotFoundException;
@@ -32,7 +35,6 @@ import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.hibernate.reactive.mutiny.Mutiny; import org.hibernate.reactive.mutiny.Mutiny;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer; import java.util.function.Consumer;
import static fr.titionfire.ffsaf.net2.Client_Thread.MAPPER; import static fr.titionfire.ffsaf.net2.Client_Thread.MAPPER;
@@ -142,19 +144,6 @@ public class ClubService {
.toList()); .toList());
} }
public Uni<List<VerySimpleMembre>> getMembers(SecurityCtx securityCtx) {
return combRepository.find("userId = ?1", securityCtx.getSubject()).firstResult()
.invoke(Unchecked.consumer(m -> {
if (m == null || m.getClub() == null)
throw new DNotFoundException("Club non trouvé");
if (!securityCtx.isInClubGroup(m.getClub().getId()))
throw new DForbiddenException();
}))
.chain(m -> combRepository.list("club = ?1", m.getClub()))
.map(membreModels -> membreModels.stream()
.map(m -> new VerySimpleMembre(m.getLname(), m.getFname(), m.getLicence())).toList());
}
public Uni<String> updateOfUser(SecurityCtx securityCtx, PartClubForm form) { public Uni<String> updateOfUser(SecurityCtx securityCtx, PartClubForm form) {
TypeReference<HashMap<Contact, String>> typeRef = new TypeReference<>() { TypeReference<HashMap<Contact, String>> typeRef = new TypeReference<>() {
}; };
@@ -194,17 +183,12 @@ public class ClubService {
} }
public Uni<String> update(long id, FullClubForm input) { public Uni<String> update(long id, FullClubForm input) {
AtomicBoolean nameChange = new AtomicBoolean(false);
return repository.findById(id).call(m -> Mutiny.fetch(m.getContact())) return repository.findById(id).call(m -> Mutiny.fetch(m.getContact()))
.onItem().transformToUni(Unchecked.function(m -> { .onItem().transformToUni(Unchecked.function(m -> {
TypeReference<HashMap<Contact, String>> typeRef = new TypeReference<>() { TypeReference<HashMap<Contact, String>> typeRef = new TypeReference<>() {
}; };
if (!input.getName().equals(m.getName())) {
m.setName(input.getName()); m.setName(input.getName());
nameChange.set(true);
}
m.setCountry(input.getCountry()); m.setCountry(input.getCountry());
m.setInternational(input.isInternational()); m.setInternational(input.isInternational());
@@ -217,9 +201,11 @@ public class ClubService {
m.setTraining_day_time(input.getTraining_day_time()); m.setTraining_day_time(input.getTraining_day_time());
ls.logChange("Contact interne", m.getContact_intern(), input.getContact_intern(), m); ls.logChange("Contact interne", m.getContact_intern(), input.getContact_intern(), m);
m.setContact_intern(input.getContact_intern()); m.setContact_intern(input.getContact_intern());
if (input.getState_id() != null && !input.getState_id().isBlank()) { ls.logChange("N° RNA", m.getRNA(), input.getRna(), m);
ls.logChange("N° SIRET", m.getClubId(), input.getState_id(), m); m.setRNA(input.getRna());
m.setStateId(input.getState_id()); if (input.getSiret() != null && !input.getSiret().isBlank()) {
ls.logChange("N° SIRET", m.getSIRET(), input.getSiret(), m);
m.setSIRET(Long.parseLong(input.getSiret()));
} }
ls.logChange("Adresse administrative", m.getAddress(), input.getAddress(), m); ls.logChange("Adresse administrative", m.getAddress(), input.getAddress(), m);
m.setAddress(input.getAddress()); m.setAddress(input.getAddress());
@@ -234,8 +220,6 @@ public class ClubService {
} }
return Panache.withTransaction(() -> repository.persist(m)).call(() -> ls.append()); return Panache.withTransaction(() -> repository.persist(m)).call(() -> ls.append());
})) }))
.call(clubModel -> nameChange.get() ? keycloakService.updateGroupFromClub(clubModel) // update group in keycloak
: Uni.createFrom().nullItem())
.invoke(membreModel -> SReqClub.sendIfNeed(serverCustom.clients, .invoke(membreModel -> SReqClub.sendIfNeed(serverCustom.clients,
SimpleClubModel.fromModel(membreModel))) SimpleClubModel.fromModel(membreModel)))
.map(__ -> "OK"); .map(__ -> "OK");
@@ -257,8 +241,9 @@ public class ClubService {
clubModel.setTraining_location(input.getTraining_location()); clubModel.setTraining_location(input.getTraining_location());
clubModel.setTraining_day_time(input.getTraining_day_time()); clubModel.setTraining_day_time(input.getTraining_day_time());
clubModel.setContact_intern(input.getContact_intern()); clubModel.setContact_intern(input.getContact_intern());
if (input.getState_id() != null && !input.getState_id().isBlank()) clubModel.setRNA(input.getRna());
clubModel.setStateId(input.getState_id()); if (input.getSiret() != null && !input.getSiret().isBlank())
clubModel.setSIRET(Long.parseLong(input.getSiret()));
clubModel.setAddress(input.getAddress()); clubModel.setAddress(input.getAddress());
try { try {
@@ -305,9 +290,9 @@ public class ClubService {
.call(clubModel -> Mutiny.fetch(clubModel.getAffiliations())) .call(clubModel -> Mutiny.fetch(clubModel.getAffiliations()))
.invoke(clubModel -> { .invoke(clubModel -> {
data.setName(clubModel.getName()); data.setName(clubModel.getName());
data.setState_id(clubModel.getStateId()); data.setSiret(clubModel.getSIRET());
data.setRna(clubModel.getRNA());
data.setAddress(clubModel.getAddress()); data.setAddress(clubModel.getAddress());
data.setContact(clubModel.getContact_intern());
data.setSaison( data.setSaison(
clubModel.getAffiliations().stream().max(Comparator.comparing(AffiliationModel::getSaison)) clubModel.getAffiliations().stream().max(Comparator.comparing(AffiliationModel::getSaison))
.map(AffiliationModel::getSaison).map(i -> Math.min(i + 1, Utils.getSaison() + 1)) .map(AffiliationModel::getSaison).map(i -> Math.min(i + 1, Utils.getSaison() + 1))

View File

@@ -2,13 +2,11 @@ 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;
@@ -17,10 +15,7 @@ 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;
@@ -33,9 +28,6 @@ public class CompetPermService {
@Inject @Inject
ServerCustom serverCustom; ServerCustom serverCustom;
@Inject
CompetitionRepository competitionRepository;
@Inject @Inject
@CacheName("safca-config") @CacheName("safca-config")
Cache cache; Cache cache;
@@ -45,236 +37,76 @@ public class CompetPermService {
Cache cacheAccess; Cache cacheAccess;
@Inject @Inject
@CacheName("have-access") CompetitionRepository competitionRepository;
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(500, TimeUnit.MILLISECONDS); return f.get(1500, TimeUnit.MILLISECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) { } catch (InterruptedException | ExecutionException | TimeoutException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
}); });
} }
public Uni<List<Long>> getAllHaveAdminAccess(SecurityCtx securityCtx) { public Uni<HashMap<Long, String>> getAllHaveAccess(String subject) {
ArrayList<Long> out = new ArrayList<>(); return cacheAccess.get(subject, k -> {
CompletableFuture<HashMap<Long, String>> f = new CompletableFuture<>();
Uni<HashMap<Long, String>> safca = cacheAccess.getAsync(securityCtx.getSubject(), SReqCompet.getAllHaveAccess(serverCustom.clients, subject, f);
k -> competitionRepository.list("system = ?1", CompetitionSystem.SAFCA) System.out.println("get all have access");
.chain(competitionModels -> { try {
CompletableFuture<HashMap<String, String>> f = new CompletableFuture<>(); return f.get(1500, TimeUnit.MILLISECONDS);
SReqCompet.getAllHaveAccess(serverCustom.clients, securityCtx.getSubject(), f); } catch (InterruptedException | ExecutionException | TimeoutException e) {
return Uni.createFrom().future(f, Duration.ofMillis(500)) throw new RuntimeException(e);
.onFailure().recoverWithItem(new HashMap<>())
.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.INTERNAL)
.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 {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has view perm return in.call(o -> (
*/ securityCtx.getSubject().equals(o.getOwner()) || securityCtx.roleHas("federation_admin")) ?
public Uni<CompetitionModel> hasViewPerm(SecurityCtx securityCtx, Uni<CompetitionModel> in) { Uni.createFrom().nullItem()
return in.call(cm -> (cm.isPublicVisible() || cm.getRegisterMode() == RegisterMode.FREE :
|| cm.getRegisterMode() == RegisterMode.HELLOASSO o.getSystem() == CompetitionSystem.SAFCA ?
|| (cm.getRegisterMode() == RegisterMode.CLUB_ADMIN && securityCtx.isClubAdmin())) ? hasSafcaViewPerm(securityCtx, o.getId())
Uni.createFrom().nullItem() : : Uni.createFrom().nullItem().invoke(Unchecked.consumer(__ -> {
hasAdminViewPerm(securityCtx, cm).onFailure() if (!securityCtx.isInClubGroup(o.getClub().getId()))
.recoverWithUni(__ ->
registerRepository.count("membre.userId = ?1 AND competition = ?2",
securityCtx.getSubject(), cm).map(Unchecked.function(c -> {
if (c == 0)
throw new DForbiddenException(); 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.INTERNAL)
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(Unchecked.function(o -> { return in.call(o -> (
if (securityCtx.getSubject().equals(o.getOwner()) || securityCtx.roleHas("federation_admin")) securityCtx.getSubject().equals(o.getOwner()) || securityCtx.roleHas("federation_admin")) ?
return Uni.createFrom().nullItem(); Uni.createFrom().nullItem()
:
if (o.getSystem() == CompetitionSystem.SAFCA) o.getSystem() == CompetitionSystem.SAFCA ?
return hasSafcaEditPerm(securityCtx, o.getId()); hasSafcaEditPerm(securityCtx, o.getId())
: Uni.createFrom().nullItem().invoke(Unchecked.consumer(__ -> {
if (o.getSystem() == CompetitionSystem.INTERNAL) { if (!securityCtx.isInClubGroup(o.getClub().getId()))
if (securityCtx.isInClubGroup(o.getClub().getId()) && securityCtx.isClubAdmin())
return Uni.createFrom().nullItem();
if (o.getAdmin().contains(securityCtx.getSubject()))
return Uni.createFrom().nullItem();
throw new DForbiddenException();
}
throw new DForbiddenException(); throw new DForbiddenException();
}) })
); ));
}
/**
* @return {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has edit perm
*/
public Uni<CompetitionModel> hasTablePerm(SecurityCtx securityCtx, CompetitionModel competitionModel) {
return hasTablePerm(securityCtx, Uni.createFrom().item(competitionModel));
}
/**
* @return {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has edit perm
*/
public Uni<CompetitionModel> hasTablePerm(SecurityCtx securityCtx, long id) {
return hasTablePerm(securityCtx, competitionRepository.findById(id));
}
/**
* @return {@link fr.titionfire.ffsaf.data.model.CompetitionModel} if securityCtx has edit perm
*/
public Uni<CompetitionModel> hasTablePerm(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 hasSafcaTablePerm(securityCtx, o.getId());
if (o.getSystem() == CompetitionSystem.INTERNAL) {
if (securityCtx.isInClubGroup(o.getClub().getId()) && securityCtx.isClubAdmin())
return Uni.createFrom().nullItem();
if (o.getAdmin().contains(securityCtx.getSubject()))
return Uni.createFrom().nullItem();
if (o.getTable().contains(securityCtx.getSubject()))
return Uni.createFrom().nullItem();
throw new DForbiddenException();
}
throw new DForbiddenException();
})
);
} }
private Uni<?> hasSafcaViewPerm(SecurityCtx securityCtx, long id) { private Uni<?> hasSafcaViewPerm(SecurityCtx securityCtx, long id) {
@@ -282,8 +114,8 @@ public class CompetPermService {
Uni.createFrom().nullItem() Uni.createFrom().nullItem()
: :
getSafcaConfig(id).chain(Unchecked.function(o -> { getSafcaConfig(id).chain(Unchecked.function(o -> {
if (!o.admin().contains(UUID.fromString(securityCtx.getSubject())) if (!o.admin().contains(UUID.fromString(securityCtx.getSubject())) && !o.table()
&& !o.table().contains(UUID.fromString(securityCtx.getSubject()))) .contains(UUID.fromString(securityCtx.getSubject())))
throw new DForbiddenException(); throw new DForbiddenException();
return Uni.createFrom().nullItem(); return Uni.createFrom().nullItem();
})); }));
@@ -299,16 +131,4 @@ public class CompetPermService {
return Uni.createFrom().nullItem(); return Uni.createFrom().nullItem();
})); }));
} }
private Uni<?> hasSafcaTablePerm(SecurityCtx securityCtx, long id) {
return securityCtx.roleHas("safca_super_admin") ?
Uni.createFrom().nullItem()
:
getSafcaConfig(id).chain(Unchecked.function(o -> {
if (!o.admin().contains(UUID.fromString(securityCtx.getSubject()))
&& !o.table().contains(UUID.fromString(securityCtx.getSubject())))
throw new DForbiddenException();
return Uni.createFrom().nullItem();
}));
}
} }

View File

@@ -1,12 +1,12 @@
package fr.titionfire.ffsaf.domain.service; package fr.titionfire.ffsaf.domain.service;
import fr.titionfire.ffsaf.data.model.*; import fr.titionfire.ffsaf.data.model.CompetitionModel;
import fr.titionfire.ffsaf.data.model.MembreModel;
import fr.titionfire.ffsaf.data.repository.*; import fr.titionfire.ffsaf.data.repository.*;
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.net2.request.SReqRegister; import fr.titionfire.ffsaf.net2.request.SReqRegister;
import fr.titionfire.ffsaf.rest.client.dto.NotificationData;
import fr.titionfire.ffsaf.rest.data.CompetitionData; 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;
@@ -14,24 +14,21 @@ 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.rest.exception.DNotFoundException; import fr.titionfire.ffsaf.rest.exception.DNotFoundException;
import fr.titionfire.ffsaf.utils.*; import fr.titionfire.ffsaf.utils.CompetitionSystem;
import fr.titionfire.ffsaf.ws.send.SRegister; import fr.titionfire.ffsaf.data.model.RegisterModel;
import fr.titionfire.ffsaf.utils.SecurityCtx;
import fr.titionfire.ffsaf.utils.Utils;
import io.quarkus.cache.Cache; import io.quarkus.cache.Cache;
import io.quarkus.cache.CacheName; import io.quarkus.cache.CacheName;
import io.quarkus.hibernate.reactive.panache.Panache; import io.quarkus.hibernate.reactive.panache.Panache;
import io.quarkus.hibernate.reactive.panache.common.WithSession; import io.quarkus.hibernate.reactive.panache.common.WithSession;
import io.quarkus.mailer.Mail;
import io.quarkus.mailer.reactive.ReactiveMailer;
import io.smallrye.mutiny.Multi; import io.smallrye.mutiny.Multi;
import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.Uni;
import io.smallrye.mutiny.unchecked.Unchecked; import io.smallrye.mutiny.unchecked.Unchecked;
import io.vertx.mutiny.core.Vertx; import io.vertx.mutiny.core.Vertx;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.core.Response;
import org.hibernate.reactive.mutiny.Mutiny; import org.hibernate.reactive.mutiny.Mutiny;
import org.jboss.logging.Logger;
import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.representations.idm.UserRepresentation;
import java.util.*; import java.util.*;
@@ -40,51 +37,31 @@ import java.util.stream.Stream;
@WithSession @WithSession
@ApplicationScoped @ApplicationScoped
public class CompetitionService { public class CompetitionService {
private static final Logger LOGGER = Logger.getLogger(CompetitionService.class);
@Inject @Inject
CompetitionRepository repository; CompetitionRepository repository;
@Inject @Inject
CategoryRepository categoryRepository; PouleRepository pouleRepository;
@Inject @Inject
MatchRepository matchRepository; MatchRepository matchRepository;
@Inject
RegisterRepository registerRepository;
@Inject @Inject
KeycloakService keycloakService; KeycloakService keycloakService;
@Inject @Inject
CombRepository combRepository; CombRepository combRepository;
@Inject
CompetitionGuestRepository competitionGuestRepository;
@Inject @Inject
ServerCustom serverCustom; ServerCustom serverCustom;
@Inject
MembreService membreService;
@Inject @Inject
CompetPermService permService; CompetPermService permService;
@Inject
HelloAssoRegisterRepository helloAssoRepository;
@SuppressWarnings("CdiInjectionPointsInspection")
@Inject
ReactiveMailer reactiveMailer;
@Inject @Inject
Vertx vertx; Vertx vertx;
@Inject
SRegister sRegister;
@Inject @Inject
@CacheName("safca-config") @CacheName("safca-config")
Cache cache; Cache cache;
@@ -92,26 +69,18 @@ public class CompetitionService {
@Inject @Inject
@CacheName("safca-have-access") @CacheName("safca-have-access")
Cache cacheAccess; Cache cacheAccess;
@Inject @Inject
@CacheName("have-access") RegisterRepository registerRepository;
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(), new Date(), .item(new CompetitionData(null, "", "", new Date(), CompetitionSystem.SAFCA,
CompetitionSystem.INTERNAL, RegisterMode.FREE, new Date(), new Date(), true, null, "", "", null));
null, "", "", null, true, "", "", "", ""));
} }
return permService.hasAdminViewPerm(securityCtx, id) return permService.hasViewPerm(securityCtx, id)
.chain(competitionModel -> Mutiny.fetch(competitionModel.getInsc()) .chain(competitionModel -> Mutiny.fetch(competitionModel.getInsc())
.chain(insc -> Mutiny.fetch(competitionModel.getGuests()) .map(insc -> CompetitionData.fromModel(competitionModel).addInsc(insc)))
.map(guest -> CompetitionData.fromModel(competitionModel).addInsc(insc, guest))))
.chain(data -> .chain(data ->
vertx.getOrCreateContext().executeBlocking(() -> { vertx.getOrCreateContext().executeBlocking(() -> {
keycloakService.getUser(UUID.fromString(data.getOwner())) keycloakService.getUser(UUID.fromString(data.getOwner()))
@@ -122,61 +91,64 @@ public class CompetitionService {
} }
public Uni<List<CompetitionData>> getAll(SecurityCtx securityCtx) { public Uni<List<CompetitionData>> getAll(SecurityCtx securityCtx) {
List<CompetitionData> out = new ArrayList<>(); return repository.listAll()
return permService.getAllHaveAdminAccess(securityCtx) .chain(o ->
.call(ids -> repository.list("id IN ?1", ids) permService.getAllHaveAccess(securityCtx.getSubject())
.invoke(cm -> { .chain(map -> Uni.createFrom().item(o.stream()
out.addAll(cm.stream().map(CompetitionData::fromModelLight).toList()); .filter(p -> {
out.forEach(competition -> competition.setCanEdit(true)); if (securityCtx.getSubject().equals(p.getOwner()))
})) return true;
.call(ids -> if (p.getSystem() == CompetitionSystem.SAFCA) {
repository.list("id NOT IN ?1 AND (publicVisible = TRUE OR registerMode IN ?2)", ids, if (map.containsKey(p.getId()))
securityCtx.isClubAdmin() ? List.of(RegisterMode.FREE, RegisterMode.HELLOASSO, return map.get(p.getId()).equals("admin");
RegisterMode.CLUB_ADMIN) : List.of(RegisterMode.FREE, RegisterMode.HELLOASSO)) return securityCtx.roleHas("federation_admin")
.invoke(cm -> out.addAll(cm.stream().map(CompetitionData::fromModelLight).toList())) || securityCtx.roleHas("safca_super_admin");
.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 uni; return securityCtx.roleHas("federation_admin");
}) })
)) .map(CompetitionData::fromModel).toList())
.map(__ -> out); ));
} }
public Uni<List<CompetitionData>> getAllAdmin(SecurityCtx securityCtx) { public Uni<List<CompetitionData>> getAllSystem(SecurityCtx securityCtx,
return permService.getAllHaveAdminAccess(securityCtx)
.chain(ids -> repository.list("id IN ?1", ids))
.map(pouleModels -> pouleModels.stream().map(CompetitionData::fromModel).toList());
}
public Uni<List<CompetitionData>> getAllSystemAdmin(SecurityCtx securityCtx,
CompetitionSystem system) { CompetitionSystem system) {
return permService.getAllHaveAdminAccess(securityCtx) if (system == CompetitionSystem.SAFCA) {
.chain(ids -> repository.list("system = ?1 AND id IN ?2", system, 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())
);
} }
public Uni<List<CompetitionData>> getAllSystemTable(SecurityCtx securityCtx,
CompetitionSystem system) {
return repository.list("system = ?1", system) return repository.list("system = ?1", system)
.chain(l -> Uni.join().all(l.stream().map(cm -> permService.hasTablePerm(securityCtx, cm)).toList()) .map(data -> data.stream()
.andCollectFailures()) .filter(p -> {
.map(l -> l.stream().filter(Objects::nonNull).map(CompetitionData::fromModel).toList()); if (securityCtx.getSubject().equals(p.getOwner()))
return true;
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() if (combModel == null)
.contains("federation_admin")) throw new DNotFoundException("Profile non trouvé");
throw new DForbiddenException("Vous ne pouvez pas créer de compétition"); if (data.getSystem() == CompetitionSystem.SAFCA)
if (!securityCtx.getRoles().contains("safca_create_compet"))
throw new DForbiddenException("Vous ne pouvez pas créer de compétition SAFCA");
})) }))
.map(MembreModel::getClub) .map(MembreModel::getClub)
.chain(clubModel -> { .chain(clubModel -> {
@@ -185,25 +157,22 @@ 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.setGuests(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(c -> (c.getSystem() == CompetitionSystem.SAFCA) ? cacheAccess.invalidate( .call(__ -> cacheAccess.invalidate(securityCtx.getSubject()));
securityCtx.getSubject()) : Uni.createFrom().nullItem())
.call(c -> (c.getSystem() == CompetitionSystem.INTERNAL) ? 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 -> {
copyData(data, model); model.setDate(data.getDate());
model.setName(data.getName());
return vertx.getOrCreateContext().executeBlocking(() -> // Update owner return vertx.getOrCreateContext().executeBlocking(() ->
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)
@@ -218,154 +187,30 @@ public class CompetitionService {
})) }))
.chain(__ -> Panache.withTransaction(() -> repository.persist(model))); .chain(__ -> Panache.withTransaction(() -> repository.persist(model)));
}).map(CompetitionData::fromModel) }).map(CompetitionData::fromModel)
.call(c -> (c.getSystem() == CompetitionSystem.SAFCA) ? cacheAccess.invalidate( .call(__ -> cacheAccess.invalidate(securityCtx.getSubject()));
securityCtx.getSubject()) : Uni.createFrom().nullItem())
.call(c -> (c.getSystem() == CompetitionSystem.INTERNAL) ? cacheNoneAccess.invalidate(
securityCtx.getSubject()) : Uni.createFrom().nullItem());
} }
} }
private void copyData(CompetitionData data, CompetitionModel model) { public Uni<List<SimpleRegisterComb>> getRegister(SecurityCtx securityCtx, Long id) {
if (model.getBanMembre() == null)
model.setBanMembre(new ArrayList<>());
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, String source) {
if ("admin".equals(source))
return permService.hasEditPerm(securityCtx, id) return permService.hasEditPerm(securityCtx, id)
.chain(c -> { .chain(c -> Mutiny.fetch(c.getInsc()))
Uni<List<SimpleRegisterComb>> uni = Mutiny.fetch(c.getInsc())
.onItem().transformToMulti(Multi.createFrom()::iterable)
.onItem().call(combModel -> Mutiny.fetch(combModel.getMembre().getLicences()))
.map(cm -> SimpleRegisterComb.fromModel(cm, cm.getMembre().getLicences()))
.collect().asList();
return uni
.call(l -> Mutiny.fetch(c.getGuests())
.map(guest -> guest.stream().map(SimpleRegisterComb::fromModel).toList())
.invoke(l::addAll));
});
if ("club".equals(source))
return Uni.createFrom().nullItem()
.invoke(Unchecked.consumer(__ -> {
if (!securityCtx.isClubAdmin())
throw new DForbiddenException();
}))
.chain(__ -> membreService.getByAccountId(securityCtx.getSubject()))
.chain(model -> registerRepository.list("competition.id = ?1 AND membre.club = ?2", id,
model.getClub()))
.onItem().transformToMulti(Multi.createFrom()::iterable) .onItem().transformToMulti(Multi.createFrom()::iterable)
.onItem().call(combModel -> Mutiny.fetch(combModel.getMembre().getLicences())) .onItem().call(combModel -> Mutiny.fetch(combModel.getMembre().getLicences()))
.map(combModel -> SimpleRegisterComb.fromModel(combModel, combModel.getMembre().getLicences())) .map(combModel -> SimpleRegisterComb.fromModel(combModel, combModel.getMembre().getLicences()))
.collect().asList(); .collect().asList();
return membreService.getByAccountId(securityCtx.getSubject())
.chain(model -> registerRepository.find("competition.id = ?1 AND membre = ?2", id, model).firstResult()
.map(rm -> rm == null ? List.of() : List.of(SimpleRegisterComb.fromModel(rm, List.of()))));
} }
public Uni<SimpleRegisterComb> addRegisterComb(SecurityCtx securityCtx, Long id, RegisterRequestData data, public Uni<SimpleRegisterComb> addRegisterComb(SecurityCtx securityCtx, Long id, RegisterRequestData data) {
String source) {
if ("admin".equals(source))
if (data.getLicence() != -1) { // not a guest
return permService.hasEditPerm(securityCtx, id) return permService.hasEditPerm(securityCtx, id)
.chain(c -> findComb(data.getLicence(), data.getFname(), data.getLname()) .chain(c -> findComb(data.getLicence(), data.getFname(), data.getLname())
.call(combModel -> Mutiny.fetch(combModel.getLicences())) .chain(combModel -> Mutiny.fetch(c.getInsc())
.call(combModel -> { .chain(Unchecked.function(insc -> {
if (c.getBanMembre() == null) Optional<RegisterModel> opt = insc.stream()
c.setBanMembre(new ArrayList<>()); .filter(m -> m.getMembre().equals(combModel)).findAny();
c.getBanMembre().remove(combModel.getId());
return Panache.withTransaction(() -> repository.persist(c));
})
.chain(combModel -> updateRegister(data, c, combModel, true)))
.map(r -> SimpleRegisterComb.fromModel(r, r.getMembre().getLicences()));
} else {
return permService.hasEditPerm(securityCtx, id)
.chain(c -> competitionGuestRepository.findById(data.getId() * -1)
.map(g -> {
if (g != null)
return g;
CompetitionGuestModel model = new CompetitionGuestModel();
model.setCompetition(c);
return model;
}))
.chain(model -> {
model.setFname(data.getFname());
model.setLname(data.getLname());
model.setGenre(data.getGenre());
model.setClub(data.getClub());
model.setCountry(data.getCountry());
model.setWeight(data.getWeight());
model.setCategorie(data.getCategorie());
return Panache.withTransaction(() -> competitionGuestRepository.persist(model)) RegisterModel r;
.call(r -> model.getCompetition().getSystem() == CompetitionSystem.INTERNAL ? if (opt.isPresent()) {
sRegister.sendRegister(model.getCompetition().getUuid(), r = opt.get();
r) : Uni.createFrom().voidItem());
})
.map(SimpleRegisterComb::fromModel);
}
if ("club".equals(source))
return repository.findById(id)
.invoke(Unchecked.consumer(cm -> {
if (!(cm.getRegisterMode() == RegisterMode.CLUB_ADMIN || cm.getRegisterMode() == RegisterMode.FREE)
|| !securityCtx.isClubAdmin())
throw new DForbiddenException();
if (new Date().before(cm.getStartRegister()) || new Date().after(cm.getEndRegister()))
throw new DBadRequestException("Inscription fermée");
}))
.chain(c -> findComb(data.getLicence(), data.getFname(), data.getLname())
.call(combModel -> Mutiny.fetch(combModel.getLicences()))
.invoke(Unchecked.consumer(model -> {
if (!securityCtx.isInClubGroup(model.getClub().getId()))
throw new DForbiddenException();
if (c.getBanMembre().contains(model.getId()))
throw new DForbiddenException(
"Vous n'avez pas le droit d'inscrire ce membre (par décision de l'administrateur de la compétition)");
}))
.chain(combModel -> updateRegister(data, c, combModel, false)))
.map(r -> SimpleRegisterComb.fromModel(r, r.getMembre().getLicences()));
return repository.findById(id)
.invoke(Unchecked.consumer(cm -> {
if (cm.getRegisterMode() != RegisterMode.FREE)
throw new DForbiddenException();
if (new Date().before(cm.getStartRegister()) || new Date().after(cm.getEndRegister()))
throw new DBadRequestException("Inscription fermée");
}))
.chain(c -> membreService.getByAccountId(securityCtx.getSubject())
.invoke(Unchecked.consumer(model -> {
if (c.getBanMembre().contains(model.getId()))
throw new DForbiddenException(
"Vous n'avez pas le droit de vous inscrire (par décision de l'administrateur de la compétition)");
}))
.chain(combModel -> updateRegister(data, c, combModel, false)))
.map(r -> SimpleRegisterComb.fromModel(r, List.of()));
}
private Uni<RegisterModel> updateRegister(RegisterRequestData data, CompetitionModel c,
MembreModel combModel, boolean admin) {
return registerRepository.find("competition = ?1 AND membre = ?2", c, combModel).firstResult()
.onFailure().recoverWithNull()
.map(Unchecked.function(r -> {
if (r != null) {
if (!admin && r.isLockEdit())
throw new DForbiddenException(
"Modification bloquée par l'administrateur de la compétition");
r.setWeight(data.getWeight()); r.setWeight(data.getWeight());
r.setOverCategory(data.getOverCategory()); r.setOverCategory(data.getOverCategory());
r.setCategorie( r.setCategorie(
@@ -373,38 +218,32 @@ public class CompetitionService {
Utils.getCategoryFormBirthDate(combModel.getBirth_date(), Utils.getCategoryFormBirthDate(combModel.getBirth_date(),
c.getDate())); c.getDate()));
int days = Utils.getDaysBeforeCompetition(c.getDate()); int days = Utils.getDaysBeforeCompetition(c.getDate());
if (days > -7) if (days > -7) {
r.setClub(combModel.getClub()); r.setClub(combModel.getClub());
if (admin) }
r.setLockEdit(data.isLockEdit());
} 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()),
(combModel.getClub() == null) ? null : combModel.getClub()); (combModel.getClub() == null) ? null : combModel.getClub());
if (admin) insc.add(r);
r.setLockEdit(data.isLockEdit());
else
r.setLockEdit(false);
} }
if (c.getSystem() == CompetitionSystem.SAFCA) { if (c.getSystem() == CompetitionSystem.SAFCA) {
SReqRegister.sendIfNeed(serverCustom.clients, SReqRegister.sendIfNeed(serverCustom.clients,
new CompetitionData.SimpleRegister(r.getMembre().getId(), new CompetitionData.SimpleRegister(r.getMembre().getId(),
r.getOverCategory(), r.getWeight(), r.getCategorie(), r.getOverCategory(), r.getWeight(), r.getCategorie(),
(r.getClub() == null) ? null : r.getClub().getId(), (r.getClub() == null) ? null : r.getClub().getId()), c.getId());
(r.getClub() == null) ? null : r.getClub().getName()), c.getId());
} }
return r; return Panache.withTransaction(() -> repository.persist(c)).map(__ -> r);
})) }))))
.chain(r -> Panache.withTransaction(() -> registerRepository.persist(r))) .chain(r -> Mutiny.fetch(r.getMembre().getLicences())
.call(r -> c.getSystem() == CompetitionSystem.INTERNAL ? .map(licences -> SimpleRegisterComb.fromModel(r, licences)));
sRegister.sendRegister(c.getUuid(), r) : Uni.createFrom().voidItem());
} }
private Uni<MembreModel> findComb(Long licence, String fname, String lname) { private Uni<MembreModel> findComb(Long licence, String fname, String lname) {
if (licence != null && licence > 0) { if (licence != null && licence != 0) {
return combRepository.find("licence = ?1", licence).firstResult() return combRepository.find("licence = ?1", licence).firstResult()
.invoke(Unchecked.consumer(combModel -> { .invoke(Unchecked.consumer(combModel -> {
if (combModel == null) if (combModel == null)
@@ -413,8 +252,7 @@ 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)", return combRepository.find("unaccent(lname) ILIKE unaccent(?1) AND unaccent(fname) ILIKE unaccent(?2)", lname,
lname,
fname).firstResult() fname).firstResult()
.invoke(Unchecked.consumer(combModel -> { .invoke(Unchecked.consumer(combModel -> {
if (combModel == null) if (combModel == null)
@@ -423,71 +261,19 @@ public class CompetitionService {
} }
} }
public Uni<Void> removeRegisterComb(SecurityCtx securityCtx, Long id, Long combId, String source, boolean ban) { public Uni<Void> removeRegisterComb(SecurityCtx securityCtx, Long id, Long combId) {
if ("admin".equals(source))
return permService.hasEditPerm(securityCtx, id) return permService.hasEditPerm(securityCtx, id)
.chain(cm -> { .chain(c -> registerRepository.delete("competition = ?1 AND membre.id = ?2", c, combId)
if (cm.getBanMembre() == null) .invoke(Unchecked.consumer(l -> {
cm.setBanMembre(new ArrayList<>()); if (l != 0){
if (ban) { if (c.getSystem() == CompetitionSystem.SAFCA) {
if (!cm.getBanMembre().contains(combId)) SReqRegister.sendRmIfNeed(serverCustom.clients, combId, id);
cm.getBanMembre().add(combId); }
} else { }else{
cm.getBanMembre().remove(combId); throw new DBadRequestException("Combattant non inscrit");
} }
return Panache.withTransaction(() -> repository.persist(cm));
})
.chain(c -> deleteRegister(combId, c, true));
if ("club".equals(source))
return repository.findById(id)
.invoke(Unchecked.consumer(cm -> {
if (!(cm.getRegisterMode() == RegisterMode.CLUB_ADMIN || cm.getRegisterMode() == RegisterMode.FREE)
|| !securityCtx.isClubAdmin())
throw new DForbiddenException();
if (new Date().before(cm.getStartRegister()) || new Date().after(cm.getEndRegister()))
throw new DBadRequestException("Inscription fermée");
})) }))
.call(cm -> membreService.getById(combId) ).replaceWithVoid();
.invoke(Unchecked.consumer(model -> {
if (model == null)
throw new DNotFoundException("Membre " + combId + " n'existe pas");
if (!securityCtx.isInClubGroup(model.getClub().getId()))
throw new DForbiddenException();
})))
.chain(c -> deleteRegister(combId, c, false));
return repository.findById(id)
.call(cm -> membreService.getByAccountId(securityCtx.getSubject())
.invoke(Unchecked.consumer(model -> {
if (cm.getRegisterMode() != RegisterMode.FREE || !Objects.equals(model.getId(), combId))
throw new DForbiddenException();
if (new Date().before(cm.getStartRegister()) || new Date().after(cm.getEndRegister()))
throw new DBadRequestException("Inscription fermée");
})))
.chain(c -> deleteRegister(combId, c, false));
}
private Uni<Void> deleteRegister(Long combId, CompetitionModel c, boolean admin) {
if (admin && combId < 0) {
return competitionGuestRepository.find("competition = ?1 AND id = ?2", c, combId * -1).firstResult()
.onFailure().transform(t -> new DBadRequestException("Combattant non inscrit"))
.call(Unchecked.function(
model -> Panache.withTransaction(() -> competitionGuestRepository.delete(model))
.call(r -> c.getSystem() == CompetitionSystem.INTERNAL ?
sRegister.sendRegisterRemove(c.getUuid(), combId) : Uni.createFrom()
.voidItem())))
.replaceWithVoid();
}
return registerRepository.find("competition = ?1 AND membre.id = ?2", c, combId).firstResult()
.onFailure().transform(t -> new DBadRequestException("Combattant non inscrit"))
.call(Unchecked.function(registerModel -> {
if (!admin && registerModel.isLockEdit())
throw new DForbiddenException("Modification bloquée par l'administrateur de la compétition");
return Panache.withTransaction(() -> registerRepository.delete(registerModel))
.call(r -> c.getSystem() == CompetitionSystem.INTERNAL ?
sRegister.sendRegisterRemove(c.getUuid(), combId) : Uni.createFrom().voidItem());
}))
.replaceWithVoid();
} }
public Uni<?> delete(SecurityCtx securityCtx, Long id) { public Uni<?> delete(SecurityCtx securityCtx, Long id) {
@@ -495,7 +281,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 -> categoryRepository.list("compet = ?1", competitionModel) .call(competitionModel -> pouleRepository.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(
@@ -503,11 +289,7 @@ public class CompetitionService {
.toList()) .toList())
.andCollectFailures())) .andCollectFailures()))
.call(competitionModel -> Panache.withTransaction( .call(competitionModel -> Panache.withTransaction(
() -> categoryRepository.delete("compet = ?1", competitionModel))) () -> pouleRepository.delete("compet = ?1", competitionModel)))
.call(competitionModel -> Panache.withTransaction(
() -> registerRepository.delete("competition = ?1", competitionModel)))
.call(competitionModel -> Panache.withTransaction(
() -> competitionGuestRepository.delete("competition = ?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));
@@ -580,106 +362,4 @@ public class CompetitionService {
})) }))
.call(__ -> cache.invalidate(data.getId())); .call(__ -> cache.invalidate(data.getId()));
} }
public Uni<Response> unregisterHelloAsso(NotificationData data) {
if (!data.getState().equals("Refunded"))
return Uni.createFrom().item(Response.ok().build());
return helloAssoRepository.list("orderId = ?1", data.getOrder().getId())
.chain(regs -> {
Uni<?> uni = Uni.createFrom().nullItem();
for (HelloAssoRegisterModel reg : regs) {
if (reg.getCompetition().getRegisterMode() != RegisterMode.HELLOASSO)
continue;
if (!data.getOrder().getOrganizationSlug().equalsIgnoreCase(reg.getCompetition().getData1()))
continue;
uni = uni.call(__ -> Panache.withTransaction(
() -> registerRepository.delete("competition = ?1 AND membre = ?2",
reg.getCompetition(), reg.getMembre())))
.call(r -> reg.getCompetition().getSystem() == CompetitionSystem.INTERNAL ?
sRegister.sendRegisterRemove(reg.getCompetition().getUuid(),
reg.getMembre().getId()) : Uni.createFrom().voidItem()).onFailure()
.recoverWithNull()
;
}
return uni;
})
.onFailure().invoke(Throwable::printStackTrace)
.map(__ -> Response.ok().build());
}
public Uni<Response> registerHelloAsso(NotificationData data) {
String organizationSlug = data.getOrganizationSlug();
String formSlug = data.getFormSlug();
RegisterRequestData req = new RegisterRequestData(null, "", "", null, 0, false, null, Categorie.CADET, Genre.NA,
null, "fr");
return repository.find("data1 = ?1 AND data2 = ?2", organizationSlug, formSlug).firstResult()
.onFailure().recoverWithNull()
.chain(cm -> {
Uni<?> uni = Uni.createFrom().nullItem();
if (cm == null || cm.getRegisterMode() != RegisterMode.HELLOASSO)
return uni;
List<String> place = List.of(cm.getData3().toLowerCase().split(";"));
List<String> fail = new ArrayList<>();
for (NotificationData.Item item : data.getItems()) {
if (!place.contains(item.getName().toLowerCase()))
continue;
if (item.getCustomFields() == null || item.getCustomFields().isEmpty()) {
fail.add("%s %s - licence n°???".formatted(item.getUser().getLastName(),
item.getUser().getFirstName()));
continue;
}
Optional<Long> optional = item.getCustomFields().stream()
.filter(cf -> cf.getName().equalsIgnoreCase("Numéro de licence")).findAny().map(
NotificationData.CustomField::getAnswer).map(Long::valueOf);
if (optional.isPresent()) {
uni = uni.call(__ -> membreService.getByLicence(optional.get())
.invoke(Unchecked.consumer(m -> {
if (m == null)
throw new NotFoundException();
}))
.call(m -> Panache.withTransaction(() ->
helloAssoRepository.persist(
new HelloAssoRegisterModel(cm, m, data.getId()))))
.chain(m -> updateRegister(req, cm, m, true)))
.onFailure().recoverWithItem(throwable -> {
fail.add("%s %s - licence n°%d".formatted(item.getUser().getLastName(),
item.getUser().getFirstName(), optional.get()));
return null;
})
.replaceWithVoid();
} else {
fail.add("%s %s - licence n°???".formatted(item.getUser().getLastName(),
item.getUser().getFirstName()));
}
}
return uni.call(__ -> fail.isEmpty() ? Uni.createFrom().nullItem() :
reactiveMailer.send(
Mail.withText(cm.getData4(),
"FFSAF - Compétition - Erreur HelloAsso",
String.format(
"""
Bonjour,
Une erreur a été rencontrée lors de l'enregistrement d'une inscription à votre compétition %s pour les combattants suivants:
%s
Cordialement,
L'intranet de la FFSAF
""", cm.getName(), String.join("\r\n", fail))
).setFrom("FFSAF <no-reply@ffsaf.fr>").setReplyTo("support@ffsaf.fr")
).onFailure().invoke(e -> LOGGER.error("Fail to send email", e)));
})
.onFailure().invoke(Throwable::printStackTrace)
.map(__ -> Response.ok().build());
}
} }

View File

@@ -85,31 +85,6 @@ public class KeycloakService {
return Uni.createFrom().item(club::getClubId); return Uni.createFrom().item(club::getClubId);
} }
public Uni<String> updateGroupFromClub(ClubModel club) {
if (club.getClubId() == null) {
return getGroupFromClub(club);
} else {
LOGGER.infof("Updating name of club group %d-%s...", club.getId(), club.getName());
return vertx.getOrCreateContext().executeBlocking(() -> {
GroupRepresentation clubGroup =
keycloak.realm(realm).groups().groups().stream().filter(g -> g.getName().equals("club"))
.findAny()
.orElseThrow(() -> new KeycloakException("Fail to fetch group %s".formatted("club")));
keycloak.realm(realm).groups().group(clubGroup.getId()).getSubGroups(0, 1000, true).stream()
.filter(g -> g.getName().startsWith(club.getId() + "-")).findAny()
.ifPresent(groupRepresentation -> {
groupRepresentation.setName(club.getId() + "-" + club.getName());
keycloak.realm(realm).groups().group(groupRepresentation.getId())
.update(groupRepresentation);
});
return club.getClubId();
}
);
}
}
public Uni<String> getUserFromMember(MembreModel membreModel) { public Uni<String> getUserFromMember(MembreModel membreModel) {
if (membreModel.getUserId() == null) { if (membreModel.getUserId() == null) {
return Uni.createFrom() return Uni.createFrom()
@@ -256,6 +231,9 @@ public class KeycloakService {
user.setEmail(membreModel.getEmail()); user.setEmail(membreModel.getEmail());
user.setEnabled(true); user.setEnabled(true);
user.setRequiredActions(List.of(RequiredAction.VERIFY_EMAIL.name(),
RequiredAction.UPDATE_PASSWORD.name()));
try (Response response = keycloak.realm(realm).users().create(user)) { try (Response response = keycloak.realm(realm).users().create(user)) {
if (!response.getStatusInfo().equals(Response.Status.CREATED) && !response.getStatusInfo() if (!response.getStatusInfo().equals(Response.Status.CREATED) && !response.getStatusInfo()
.equals(Response.Status.CONFLICT)) .equals(Response.Status.CONFLICT))
@@ -267,8 +245,14 @@ public class KeycloakService {
return getUser(login).orElseThrow( return getUser(login).orElseThrow(
() -> new KeycloakException("Fail to fetch user %s".formatted(finalLogin))); () -> new KeycloakException("Fail to fetch user %s".formatted(finalLogin)));
}) })
.call(user -> enabled_email ?
vertx.getOrCreateContext().executeBlocking(() -> {
keycloak.realm(realm).users().get(user.getId())
.executeActionsEmail(List.of(RequiredAction.VERIFY_EMAIL.name(),
RequiredAction.UPDATE_PASSWORD.name()));
return null;
}) : Uni.createFrom().nullItem())
.invoke(user -> membreModel.setUserId(user.getId())) .invoke(user -> membreModel.setUserId(user.getId()))
.call(user -> updateRole(user.getId(), List.of("safca_user"), List.of()))
.call(user -> enabled_email ? reactiveMailer.send( .call(user -> enabled_email ? reactiveMailer.send(
Mail.withText(user.getEmail(), Mail.withText(user.getEmail(),
"FFSAF - Creation de votre compte sur l'intranet", "FFSAF - Creation de votre compte sur l'intranet",
@@ -276,14 +260,14 @@ public class KeycloakService {
""" """
Bonjour, Bonjour,
Suite à votre première inscription %sà la Fédération Française de Soft Armored Fighting (FFSAF), votre compte intranet a été créé. Suite à votre première inscription %sà la Fédération Française de Soft Armored Fighting (FFSAF), votre compte pour accéder à l'intranet a été créé.
Ce compte vous permettra de consulter vos informations et, dans un futur proche, de vous inscrire aux compétitions ainsi que d'en consulter les résultats. Ce compte vous permettra de consulter vos informations, de vous inscrire aux compétitions et de consulter vos résultats.
Vous allez recevoir dans les prochaines minutes un email vous demandant de vérifier votre email et de définir un mot de passe.
L'intranet est accessible à l'adresse suivante : https://intra.ffsaf.fr L'intranet est accessible à l'adresse suivante : https://intra.ffsaf.fr
Votre nom d'utilisateur est : %s Votre nom d'utilisateur est : %s
Pour définir votre mot de passe, rendez-vous sur l'intranet > "Connexion" > "Mot de passe oublié ?"
Si vous n'avez pas demandé cette inscription, veuillez contacter le support à l'adresse support@ffsaf.fr. Si vous n'avez pas demandé cette inscription, veuillez contacter le support à l'adresse support@ffsaf.fr.
(Pas de panique, nous ne vous enverrons pas de message autre que ce concernant votre compte) (Pas de panique, nous ne vous enverrons pas de message autre que ce concernant votre compte)

View File

@@ -18,7 +18,6 @@ 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 org.hibernate.reactive.mutiny.Mutiny; import org.hibernate.reactive.mutiny.Mutiny;
import org.jboss.logging.Logger;
import java.util.List; import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
@@ -27,7 +26,6 @@ import java.util.function.Function;
@WithSession @WithSession
@ApplicationScoped @ApplicationScoped
public class LicenceService { public class LicenceService {
private static final Logger LOGGER = Logger.getLogger(LicenceService.class);
@Inject @Inject
LicenceRepository repository; LicenceRepository repository;
@@ -127,9 +125,7 @@ public class LicenceService {
.chain(() -> combRepository.persist(membreModel)) .chain(() -> combRepository.persist(membreModel))
: Uni.createFrom().nullItem()) : Uni.createFrom().nullItem())
.call(__ -> (membreModel.getUserId() == null) ? .call(__ -> (membreModel.getUserId() == null) ?
keycloakService.initCompte(membreModel.getId()).onFailure() keycloakService.initCompte(membreModel.getId())
.invoke(t -> LOGGER.infof("Failed to init account: %s", t.getMessage())).onFailure()
.recoverWithNull()
: Uni.createFrom().nullItem()); : Uni.createFrom().nullItem());
} }

View File

@@ -1,11 +1,9 @@
package fr.titionfire.ffsaf.domain.service; package fr.titionfire.ffsaf.domain.service;
import fr.titionfire.ffsaf.data.model.CompetitionGuestModel;
import fr.titionfire.ffsaf.data.model.MatchModel; import fr.titionfire.ffsaf.data.model.MatchModel;
import fr.titionfire.ffsaf.data.repository.CategoryRepository;
import fr.titionfire.ffsaf.data.repository.CombRepository; import fr.titionfire.ffsaf.data.repository.CombRepository;
import fr.titionfire.ffsaf.data.repository.CompetitionGuestRepository;
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.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;
@@ -27,7 +25,7 @@ public class MatchService {
MatchRepository repository; MatchRepository repository;
@Inject @Inject
CategoryRepository categoryRepository; PouleRepository pouleRepository;
@Inject @Inject
CombRepository combRepository; CombRepository combRepository;
@@ -35,20 +33,17 @@ public class MatchService {
@Inject @Inject
CompetPermService permService; CompetPermService permService;
@Inject public Uni<MatchData> getById(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
CompetitionGuestRepository competitionGuestRepository;
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.hasAdminViewPerm(securityCtx, data.getCategory().getCompet())) .call(data -> permService.hasViewPerm(securityCtx, data.getPoule().getCompet()))
.map(MatchData::fromModel); .map(MatchData::fromModel);
} }
public Uni<List<MatchData>> getAllByPouleAdmin(SecurityCtx securityCtx, CompetitionSystem system, Long id) { public Uni<List<MatchData>> getAllByPoule(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
return categoryRepository.find("systemId = ?1 AND system = ?2", id, system).firstResult() return pouleRepository.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.hasAdminViewPerm(securityCtx, data.getCompet())) .call(data -> permService.hasViewPerm(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()));
} }
@@ -57,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 categoryRepository.find("systemId = ?1 AND system = ?2", data.getCategory(), system) return pouleRepository.find("systemId = ?1 AND system = ?2", data.getPoule(), 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(categoryModel -> { .map(pouleModel -> {
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.setCategory(categoryModel); model.setPoule(pouleModel);
return model; return model;
}); });
} else { } else {
return categoryRepository.find("systemId = ?1 AND system = ?2", data.getCategory(), system) return pouleRepository.find("systemId = ?1 AND system = ?2", data.getPoule(), 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()))
@@ -80,7 +75,9 @@ public class MatchService {
} }
) )
.chain(o -> { .chain(o -> {
o.setCategory_ord(data.getCategory_ord()); o.setC1_str(data.getC1_str());
o.setC2_str(data.getC2_str());
o.setPoule_ord(data.getPoule_ord());
o.getScores().clear(); o.getScores().clear();
o.getScores().addAll(data.getScores()); o.getScores().addAll(data.getScores());
@@ -91,20 +88,6 @@ public class MatchService {
.chain(() -> (data.getC1_id() == null) ? .chain(() -> (data.getC1_id() == null) ?
Uni.createFrom().nullItem() : combRepository.findById(data.getC2_id())) Uni.createFrom().nullItem() : combRepository.findById(data.getC2_id()))
.invoke(o::setC2_id) .invoke(o::setC2_id)
.chain(() -> (data.getC1_str() == null) ?
Uni.createFrom()
.item((CompetitionGuestModel) null) : competitionGuestRepository.find(
"fname = ?1 AND lname = ?2",
data.getC1_str().substring(0, data.getC1_str().indexOf(" ")),
data.getC1_str().substring(data.getC1_str().indexOf(" ") + 1)).firstResult())
.invoke(o::setC1_guest)
.chain(() -> (data.getC2_str() == null) ?
Uni.createFrom()
.item((CompetitionGuestModel) null) : competitionGuestRepository.find(
"fname = ?1 AND lname = ?2",
data.getC2_str().substring(0, data.getC2_str().indexOf(" ")),
data.getC2_str().substring(data.getC2_str().indexOf(" ") + 1)).firstResult())
.invoke(o::setC2_guest)
.chain(() -> Panache.withTransaction(() -> repository.persist(o))); .chain(() -> Panache.withTransaction(() -> repository.persist(o)));
}) })
.map(MatchData::fromModel); .map(MatchData::fromModel);
@@ -114,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.getCategory().getCompet())) .call(o2 -> permService.hasEditPerm(securityCtx, o2.getPoule().getCompet()))
.invoke(data -> { .invoke(data -> {
data.getScores().clear(); data.getScores().clear();
data.getScores().addAll(scores); data.getScores().addAll(scores);
@@ -126,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.getCategory().getCompet())) .call(o2 -> permService.hasEditPerm(securityCtx, o2.getPoule().getCompet()))
.chain(data -> Panache.withTransaction(() -> repository.delete(data))); .chain(data -> Panache.withTransaction(() -> repository.delete(data)));
} }
} }

View File

@@ -13,7 +13,6 @@ import fr.titionfire.ffsaf.rest.data.SimpleMembre;
import fr.titionfire.ffsaf.rest.data.SimpleMembreInOutData; import fr.titionfire.ffsaf.rest.data.SimpleMembreInOutData;
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.rest.exception.DInternalError;
import fr.titionfire.ffsaf.rest.from.FullMemberForm; import fr.titionfire.ffsaf.rest.from.FullMemberForm;
import fr.titionfire.ffsaf.utils.*; import fr.titionfire.ffsaf.utils.*;
import io.quarkus.hibernate.reactive.panache.Panache; import io.quarkus.hibernate.reactive.panache.Panache;
@@ -103,47 +102,15 @@ public class MembreService {
return baseUni; return baseUni;
} }
private Sort getSort(String order) {
Sort sort;
if (order == null || order.isBlank()) {
sort = Sort.ascending("fname", "lname");
} else {
sort = Sort.empty();
for (String e : order.split(",")) {
String[] split = e.split(" ");
if (split.length == 2) {
sort = sort.and(split[0],
split[1].equals("n") ? Sort.Direction.Ascending : Sort.Direction.Descending);
} else {
return null;
}
}
}
return sort;
}
public Uni<PageResult<SimpleMembre>> searchAdmin(int limit, int page, String search, String club, public Uni<PageResult<SimpleMembre>> searchAdmin(int limit, int page, String search, String club,
int licenceRequest, int payState, String order, String categorie) { int licenceRequest, int payState) {
if (search == null) if (search == null)
search = ""; search = "";
search = "%" + search.replaceAll(" ", "% %") + "%"; search = "%" + search.replaceAll(" ", "% %") + "%";
String categorieFilter;
if (categorie == null || categorie.isBlank())
categorieFilter = " True";
else
categorieFilter = "categorie = " + Categorie.valueOf(categorie).ordinal();
String finalSearch = search; String finalSearch = search;
Uni<List<LicenceModel>> baseUni = getLicenceListe(licenceRequest, payState); Uni<List<LicenceModel>> baseUni = getLicenceListe(licenceRequest, payState);
Sort sort = getSort(order);
if (sort == null)
return Uni.createFrom().failure(new DInternalError("Erreur lors calcul du trie"));
return baseUni return baseUni
.map(l -> l.stream().map(l2 -> l2.getMembre().getId()).toList()) .map(l -> l.stream().map(l2 -> l2.getMembre().getId()).toList())
.chain(ids -> { .chain(ids -> {
@@ -153,18 +120,18 @@ public class MembreService {
if (club == null || club.isBlank()) { if (club == null || club.isBlank()) {
query = repository.find( query = repository.find(
"id " + idf + " ?2 AND (" + FIND_NAME_REQUEST + ") AND " + categorieFilter, "id " + idf + " ?2 AND (" + FIND_NAME_REQUEST + ")",
sort, finalSearch, ids) Sort.ascending("fname", "lname"), finalSearch, ids)
.page(Page.ofSize(limit)); .page(Page.ofSize(limit));
} else { } else {
if (club.equals("null")) { if (club.equals("null")) {
query = repository.find( query = repository.find(
"id " + idf + " ?2 AND club IS NULL AND (" + FIND_NAME_REQUEST + ") AND " + categorieFilter, "id " + idf + " ?2 AND club IS NULL AND (" + FIND_NAME_REQUEST + ")",
sort, finalSearch, ids).page(Page.ofSize(limit)); Sort.ascending("fname", "lname"), finalSearch, ids).page(Page.ofSize(limit));
} else { } else {
query = repository.find( query = repository.find(
"id " + idf + " ?3 AND LOWER(club.name) LIKE LOWER(?2) AND (" + FIND_NAME_REQUEST + ") AND " + categorieFilter, "id " + idf + " ?3 AND LOWER(club.name) LIKE LOWER(?2) AND (" + FIND_NAME_REQUEST + ")",
sort, finalSearch, club, ids) Sort.ascending("fname", "lname"), finalSearch, club + "%", ids)
.page(Page.ofSize(limit)); .page(Page.ofSize(limit));
} }
} }
@@ -173,7 +140,7 @@ public class MembreService {
} }
public Uni<PageResult<SimpleMembre>> search(int limit, int page, String search, int licenceRequest, int payState, public Uni<PageResult<SimpleMembre>> search(int limit, int page, String search, int licenceRequest, int payState,
String order, String categorie, String subject) { String subject) {
if (search == null) if (search == null)
search = ""; search = "";
search = "%" + search.replaceAll(" ", "% %") + "%"; search = "%" + search.replaceAll(" ", "% %") + "%";
@@ -182,16 +149,6 @@ public class MembreService {
Uni<List<LicenceModel>> baseUni = getLicenceListe(licenceRequest, payState); Uni<List<LicenceModel>> baseUni = getLicenceListe(licenceRequest, payState);
String categorieFilter;
if (categorie == null || categorie.isBlank())
categorieFilter = " True";
else
categorieFilter = "categorie = " + Categorie.valueOf(categorie).ordinal();
Sort sort = getSort(order);
if (sort == null)
return Uni.createFrom().failure(new DInternalError("Erreur lors calcul du trie"));
return baseUni return baseUni
.map(l -> l.stream().map(l2 -> l2.getMembre().getId()).toList()) .map(l -> l.stream().map(l2 -> l2.getMembre().getId()).toList())
.chain(ids -> { .chain(ids -> {
@@ -200,8 +157,8 @@ public class MembreService {
return repository.find("userId = ?1", subject).firstResult() return repository.find("userId = ?1", subject).firstResult()
.chain(membreModel -> { .chain(membreModel -> {
PanacheQuery<MembreModel> query = repository.find( PanacheQuery<MembreModel> query = repository.find(
"id " + idf + " ?3 AND club = ?2 AND (" + FIND_NAME_REQUEST + ") AND " + categorieFilter, "id " + idf + " ?3 AND club = ?2 AND (" + FIND_NAME_REQUEST + ")",
sort, finalSearch, membreModel.getClub(), ids) Sort.ascending("fname", "lname"), finalSearch, membreModel.getClub(), ids)
.page(Page.ofSize(limit)); .page(Page.ofSize(limit));
return getPageResult(query, limit, page); return getPageResult(query, limit, page);
}); });
@@ -240,11 +197,6 @@ public class MembreService {
return Uni.createFrom().nullItem(); return Uni.createFrom().nullItem();
AtomicReference<ClubModel> clubModel = new AtomicReference<>(); AtomicReference<ClubModel> clubModel = new AtomicReference<>();
LOGGER.debugf("Membre import (size=%d)", data2.size());
for (SimpleMembreInOutData simpleMembreInOutData : data2) {
LOGGER.debugf("-> %s", simpleMembreInOutData.toString());
}
return repository.find("userId = ?1", subject).firstResult() return repository.find("userId = ?1", subject).firstResult()
.chain(membreModel -> { .chain(membreModel -> {
clubModel.set(membreModel.getClub()); clubModel.set(membreModel.getClub());
@@ -253,24 +205,20 @@ public class MembreService {
return repository.list("licence IN ?1 OR LOWER(lname || ' ' || fname) IN ?2 OR email IN ?3", return repository.list("licence IN ?1 OR LOWER(lname || ' ' || fname) IN ?2 OR email IN ?3",
data2.stream().map(SimpleMembreInOutData::getLicence).filter(Objects::nonNull).toList(), data2.stream().map(SimpleMembreInOutData::getLicence).filter(Objects::nonNull).toList(),
data2.stream().map(o -> (o.getNom() + " " + o.getPrenom()).toLowerCase()).toList(), data2.stream().map(o -> (o.getNom() + " " + o.getPrenom()).toLowerCase()).toList(),
data2.stream().map(SimpleMembreInOutData::getEmail).filter(o -> o != null && !o.isBlank()) data2.stream().map(SimpleMembreInOutData::getEmail).filter(Objects::nonNull).toList());
.toList());
}) })
.call(Unchecked.function(membres -> { .call(Unchecked.function(membres -> {
for (MembreModel membreModel : membres) { for (MembreModel membreModel : membres) {
if (!Objects.equals(membreModel.getClub(), clubModel.get())) { if (!Objects.equals(membreModel.getClub(), clubModel.get()))
LOGGER.info("Similar membres found: " + membreModel);
throw new DForbiddenException( throw new DForbiddenException(
"Le membre n°" + membreModel.getLicence() + " n'appartient pas à votre club"); "Le membre n°" + membreModel.getLicence() + " n'appartient pas à votre club");
} }
}
Uni<Void> uniResult = Uni.createFrom().voidItem(); Uni<Void> uniResult = Uni.createFrom().voidItem();
for (SimpleMembreInOutData dataIn : data2) { for (SimpleMembreInOutData dataIn : data2) {
MembreModel model = membres.stream() MembreModel model = membres.stream()
.filter(m -> (dataIn.getLicence() != null && Objects.equals(m.getLicence(), .filter(m -> Objects.equals(m.getLicence(), dataIn.getLicence()) || m.getLname()
dataIn.getLicence())) || m.getLname().equals(dataIn.getNom()) && m.getFname() .equals(dataIn.getNom()) && m.getFname().equals(dataIn.getPrenom()) ||
.equals(dataIn.getPrenom()) || (dataIn.getEmail() != null && !dataIn.getEmail() Objects.equals(m.getFname(), dataIn.getEmail())).findFirst()
.isBlank() && Objects.equals(m.getFname(), dataIn.getEmail()))).findFirst()
.orElseGet(() -> { .orElseGet(() -> {
MembreModel mm = new MembreModel(); MembreModel mm = new MembreModel();
mm.setClub(clubModel.get()); mm.setClub(clubModel.get());
@@ -278,23 +226,16 @@ public class MembreService {
mm.setCountry("FR"); mm.setCountry("FR");
return mm; return mm;
}); });
if (model.getId() != null) {
LOGGER.debugf("updating -> %s", dataIn.toString());
} else {
LOGGER.debugf("creating -> %s", dataIn.toString());
}
if (model.getEmail() != null && !model.getEmail().isBlank()) { if (model.getEmail() != null) {
if (model.getLicence() != null && !model.getLicence().equals(dataIn.getLicence())) { if (model.getLicence() != null && !model.getLicence().equals(dataIn.getLicence())) {
LOGGER.info("Similar membres found: " + model); throw new DBadRequestException("Email déja utiliser");
throw new DBadRequestException("Email '" + model.getEmail() + "' déja utiliser");
} }
if (StringSimilarity.similarity(model.getLname().toUpperCase(), if (StringSimilarity.similarity(model.getLname().toUpperCase(),
dataIn.getNom().toUpperCase()) > 3 || StringSimilarity.similarity( dataIn.getNom().toUpperCase()) > 3 || StringSimilarity.similarity(
model.getFname().toUpperCase(), dataIn.getPrenom().toUpperCase()) > 3) { model.getFname().toUpperCase(), dataIn.getPrenom().toUpperCase()) > 3) {
LOGGER.info("Similar membres found: " + model); throw new DBadRequestException("Email déja utiliser");
throw new DBadRequestException("Email '" + model.getEmail() + "' déja utiliser");
} }
} }
@@ -303,7 +244,6 @@ public class MembreService {
if ((!add && StringSimilarity.similarity(model.getLname().toUpperCase(), if ((!add && StringSimilarity.similarity(model.getLname().toUpperCase(),
dataIn.getNom().toUpperCase()) > 3) || (!add && StringSimilarity.similarity( dataIn.getNom().toUpperCase()) > 3) || (!add && StringSimilarity.similarity(
model.getFname().toUpperCase(), dataIn.getPrenom().toUpperCase()) > 3)) { model.getFname().toUpperCase(), dataIn.getPrenom().toUpperCase()) > 3)) {
LOGGER.info("Similar membres found: " + model);
throw new DBadRequestException( throw new DBadRequestException(
"Pour enregistrer un nouveau membre, veuillez laisser le champ licence vide."); "Pour enregistrer un nouveau membre, veuillez laisser le champ licence vide.");
} }
@@ -379,7 +319,7 @@ public class MembreService {
return update(repository.findById(id) return update(repository.findById(id)
.call(__ -> repository.count("email LIKE ?1 AND id != ?2", membre.getEmail(), id) .call(__ -> repository.count("email LIKE ?1 AND id != ?2", membre.getEmail(), id)
.invoke(Unchecked.consumer(c -> { .invoke(Unchecked.consumer(c -> {
if (c > 0 && !membre.getEmail().isBlank()) if (c > 0)
throw new DBadRequestException("Email déjà utiliser"); throw new DBadRequestException("Email déjà utiliser");
}))) })))
.chain(membreModel -> clubRepository.findById(membre.getClub()) .chain(membreModel -> clubRepository.findById(membre.getClub())
@@ -401,7 +341,7 @@ public class MembreService {
return update(repository.findById(id) return update(repository.findById(id)
.call(__ -> repository.count("email LIKE ?1 AND id != ?2", membre.getEmail(), id) .call(__ -> repository.count("email LIKE ?1 AND id != ?2", membre.getEmail(), id)
.invoke(Unchecked.consumer(c -> { .invoke(Unchecked.consumer(c -> {
if (c > 0 && !membre.getEmail().isBlank()) if (c > 0)
throw new DBadRequestException("Email déjà utiliser"); throw new DBadRequestException("Email déjà utiliser");
}))) })))
.invoke(Unchecked.consumer(membreModel -> { .invoke(Unchecked.consumer(membreModel -> {

View File

@@ -1,9 +1,12 @@
package fr.titionfire.ffsaf.domain.service; package fr.titionfire.ffsaf.domain.service;
import fr.titionfire.ffsaf.data.model.*; import fr.titionfire.ffsaf.data.model.MatchModel;
import fr.titionfire.ffsaf.data.model.MembreModel;
import fr.titionfire.ffsaf.data.model.PouleModel;
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.CategoryData; import fr.titionfire.ffsaf.rest.data.PouleData;
import fr.titionfire.ffsaf.rest.data.CategoryFullData; import fr.titionfire.ffsaf.rest.data.PouleFullData;
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;
@@ -22,10 +25,10 @@ import java.util.stream.Stream;
@WithSession @WithSession
@ApplicationScoped @ApplicationScoped
public class CategoryService { public class PouleService {
@Inject @Inject
CategoryRepository repository; PouleRepository repository;
@Inject @Inject
CompetitionRepository competRepository; CompetitionRepository competRepository;
@@ -42,24 +45,35 @@ public class CategoryService {
@Inject @Inject
CompetPermService permService; CompetPermService permService;
@Inject public Uni<PouleData> getById(SecurityCtx securityCtx, CompetitionSystem system, Long id) {
CompetitionGuestRepository competitionGuestRepository;
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("Category not found")) .onItem().ifNull().failWith(() -> new RuntimeException("Poule not found"))
.call(data -> permService.hasAdminViewPerm(securityCtx, data.getCompet())) .call(data -> permService.hasViewPerm(securityCtx, data.getCompet()))
.map(CategoryData::fromModel); .map(PouleData::fromModel);
} }
public Uni<List<CategoryData>> getAllAdmin(SecurityCtx securityCtx, CompetitionSystem system) { public Uni<List<PouleData>> getAll(SecurityCtx securityCtx, CompetitionSystem system) {
return permService.getAllHaveAdminAccess(securityCtx) return repository.list("system = ?1", system)
.chain(ids -> repository.list("system = ?1 AND compet.id IN ?2", system, ids)) .chain(o ->
.map(pouleModels -> pouleModels.stream().map(CategoryData::fromModel).toList()); permService.getAllHaveAccess(securityCtx.getSubject())
.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<CategoryData> addOrUpdate(SecurityCtx securityCtx, CompetitionSystem system, CategoryData data) { public Uni<PouleData> addOrUpdate(SecurityCtx securityCtx, CompetitionSystem system, PouleData 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) {
@@ -67,7 +81,7 @@ public class CategoryService {
.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 -> {
CategoryModel model = new CategoryModel(); PouleModel model = new PouleModel();
model.setId(null); model.setId(null);
model.setSystem(system); model.setSystem(system);
@@ -85,7 +99,7 @@ public class CategoryService {
o.setType(data.getType()); o.setType(data.getType());
return Panache.withTransaction(() -> repository.persist(o)); return Panache.withTransaction(() -> repository.persist(o));
} }
}).map(CategoryData::fromModel); }).map(PouleData::fromModel);
} }
private MatchModel findMatch(List<MatchModel> matchModelList, Long id) { private MatchModel findMatch(List<MatchModel> matchModelList, Long id) {
@@ -114,7 +128,7 @@ public class CategoryService {
} }
} }
private Uni<TreeModel> persisteTree(TreeData data, List<TreeModel> node, CategoryModel poule, private Uni<TreeModel> persisteTree(TreeData data, List<TreeModel> node, PouleModel 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) {
@@ -122,7 +136,7 @@ public class CategoryService {
mm.setId(null); mm.setId(null);
} }
mm.setLevel(data.getLevel()); mm.setLevel(data.getLevel());
mm.setCategory(poule.getId()); mm.setPoule(poule.getId());
mm.setMatch(findMatch(matchModelList, data.getMatch())); mm.setMatch(findMatch(matchModelList, data.getMatch()));
return Uni.createFrom().item(mm) return Uni.createFrom().item(mm)
@@ -133,7 +147,7 @@ public class CategoryService {
.chain(o -> Panache.withTransaction(() -> treeRepository.persist(o))); .chain(o -> Panache.withTransaction(() -> treeRepository.persist(o)));
} }
public Uni<?> syncCategory(SecurityCtx securityCtx, CompetitionSystem system, CategoryFullData data) { public Uni<?> syncPoule(SecurityCtx securityCtx, CompetitionSystem system, PouleFullData 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()))
@@ -142,7 +156,7 @@ public class CategoryService {
.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 -> {
CategoryModel model = new CategoryModel(); PouleModel model = new PouleModel();
model.setId(null); model.setId(null);
model.setSystem(system); model.setSystem(system);
model.setSystemId(data.getId()); model.setSystemId(data.getId());
@@ -158,10 +172,10 @@ public class CategoryService {
o.setType(data.getType()); o.setType(data.getType());
WorkData workData = new WorkData(); WorkData workData = new WorkData();
workData.category = o; workData.poule = o;
return workData; return workData;
}) })
.call(o -> Panache.withTransaction(() -> repository.persist(o.category))) .call(o -> Panache.withTransaction(() -> repository.persist(o.poule)))
.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())
@@ -171,18 +185,9 @@ public class CategoryService {
.invoke(o2 -> o2.forEach(m -> o.membres.put(m.getId(), m))) .invoke(o2 -> o2.forEach(m -> o.membres.put(m.getId(), m)))
) )
) )
.call(o -> Mutiny.fetch(o.category.getCompet().getGuests())
.invoke(o2 -> o2.forEach(m -> o.guest.put(m.getFname() + " " + m.getLname(), m)))
.map(o2 -> data.getMatches().stream().flatMap(m -> Stream.of(m.getC1_str(), m.getC2_str())
.filter(Objects::nonNull)).distinct().filter(s -> !o.guest.containsKey(s)).map(
CompetitionGuestModel::new).toList())
.call(o3 -> o3.isEmpty() ? Uni.createFrom().nullItem() :
Uni.join().all(o3.stream().map(o4 -> competitionGuestRepository.persist(o4)).toList())
.andFailFast())
.invoke(o2 -> o2.forEach(m -> o.guest.put(m.getFname() + " " + m.getLname(), m))))
.invoke(in -> { .invoke(in -> {
ArrayList<TreeModel> node = new ArrayList<>(); ArrayList<TreeModel> node = new ArrayList<>();
for (TreeModel treeModel : in.category.getTree()) for (TreeModel treeModel : in.poule.getTree())
flatTreeChild(treeModel, node); flatTreeChild(treeModel, node);
ArrayList<TreeData> new_node = new ArrayList<>(); ArrayList<TreeData> new_node = new ArrayList<>();
@@ -199,7 +204,7 @@ public class CategoryService {
n.setLeft(null); n.setLeft(null);
}); });
in.toRmMatch = in.category.getMatchs().stream() in.toRmMatch = in.poule.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();
}) })
@@ -214,21 +219,21 @@ public class CategoryService {
.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.category.getMatchs(), m.getId()); MatchModel mm = findMatch(in.poule.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.setCategory(in.category); mm.setPoule(in.poule);
mm.setCategory_ord(m.getCategory_ord()); mm.setPoule_ord(m.getPoule_ord());
mm.setC1_guest(in.guest.getOrDefault(m.getC1_str(), null)); mm.setC1_str(m.getC1_str());
mm.setC2_guest(in.guest.getOrDefault(m.getC2_str(), null)); 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.setPoule(m.getPoule()); mm.setGroupe(m.getGroupe());
mm.getScores().clear(); mm.getScores().clear();
mm.getScores().addAll(m.getScores()); mm.getScores().addAll(m.getScores());
@@ -239,15 +244,14 @@ public class CategoryService {
.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.category.getTree(), in.category, in.match)).toList()) .map(m -> persisteTree(m, in.poule.getTree(), in.poule, in.match)).toList())
.andCollectFailures()) .andCollectFailures())
.map(__ -> "OK"); .map(__ -> "OK");
} }
private static class WorkData { private static class WorkData {
CategoryModel category; PouleModel poule;
HashMap<Long, MembreModel> membres = new HashMap<>(); HashMap<Long, MembreModel> membres = new HashMap<>();
HashMap<String, CompetitionGuestModel> guest = new HashMap<>();
List<MatchModel> match = new ArrayList<>(); List<MatchModel> match = new ArrayList<>();
List<Long> toRmMatch; List<Long> toRmMatch;
List<TreeModel> unlinkNode; List<TreeModel> unlinkNode;
@@ -256,7 +260,7 @@ public class CategoryService {
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 RuntimeException("Category not found")) .onItem().ifNull().failWith(() -> new RuntimeException("Poule not found"))
.call(o -> permService.hasEditPerm(securityCtx, o.getCompet())) .call(o -> permService.hasEditPerm(securityCtx, o.getCompet()))
.call(o -> Mutiny.fetch(o.getTree()) .call(o -> Mutiny.fetch(o.getTree())
.call(o2 -> o2.isEmpty() ? Uni.createFrom().nullItem() : .call(o2 -> o2.isEmpty() ? Uni.createFrom().nullItem() :
@@ -270,7 +274,7 @@ public class CategoryService {
Panache.withTransaction(() -> treeRepository.delete("id IN ?1", in))) Panache.withTransaction(() -> treeRepository.delete("id IN ?1", in)))
) )
) )
.call(o -> matchRepository.delete("category.id = ?1", o.getId())) .call(o -> matchRepository.delete("poule.id = ?1", o.getId()))
.chain(model -> Panache.withTransaction(() -> repository.delete("id", model.getId()))); .chain(model -> Panache.withTransaction(() -> repository.delete("id", model.getId())));
} }
} }

View File

@@ -1,400 +0,0 @@
package fr.titionfire.ffsaf.domain.service;
import fr.titionfire.ffsaf.data.model.*;
import fr.titionfire.ffsaf.data.repository.CategoryRepository;
import fr.titionfire.ffsaf.data.repository.CompetitionRepository;
import fr.titionfire.ffsaf.data.repository.MatchRepository;
import fr.titionfire.ffsaf.data.repository.RegisterRepository;
import fr.titionfire.ffsaf.rest.data.ResultCategoryData;
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
import fr.titionfire.ffsaf.utils.*;
import io.quarkus.hibernate.reactive.panache.common.WithSession;
import io.quarkus.runtime.annotations.RegisterForReflection;
import io.smallrye.mutiny.Multi;
import io.smallrye.mutiny.Uni;
import io.smallrye.mutiny.unchecked.Unchecked;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import lombok.Builder;
import org.hibernate.reactive.mutiny.Mutiny;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;
@WithSession
@ApplicationScoped
public class ResultService {
@Inject
CompetitionRepository compRepository;
@Inject
RegisterRepository registerRepository;
@Inject
MembreService membreService;
@Inject
CategoryRepository categoryRepository;
@Inject
MatchRepository matchRepository;
private static final ResourceBundle BUNDLE = ResourceBundle.getBundle("lang.String");
public Uni<List<Object[]>> getList(SecurityCtx securityCtx) {
return membreService.getByAccountId(securityCtx.getSubject())
.chain(m -> registerRepository.list("membre = ?1", m))
.onItem().transformToMulti(Multi.createFrom()::iterable)
.onItem().call(r -> Mutiny.fetch(r.getCompetition()))
.onItem().transform(r -> new Object[]{r.getCompetition().getUuid(), r.getCompetition().getName(),
r.getCompetition().getDate()})
.collect().asList();
}
public Uni<List<ResultCategoryData>> getCategory(String uuid, SecurityCtx securityCtx) {
return hasAccess(uuid, securityCtx)
.chain(m -> categoryRepository.list("compet.uuid = ?1", uuid)
.chain(cats -> matchRepository.list("(c1_id = ?1 OR c2_id = ?1 OR True) AND category IN ?2", //TODO rm OR True
m.getMembre(), cats)))
.map(matchModels -> {
HashMap<Long, List<MatchModel>> map = new HashMap<>();
for (MatchModel matchModel : matchModels) {
if (!map.containsKey(matchModel.getCategory().getId()))
map.put(matchModel.getCategory().getId(), new ArrayList<>());
map.get(matchModel.getCategory().getId()).add(matchModel);
}
return map.values();
})
.onItem()
.transformToMulti(Multi.createFrom()::iterable)
.onItem().call(list -> Mutiny.fetch(list.get(0).getCategory().getTree()))
.onItem().transform(this::getData)
.collect().asList();
}
private ResultCategoryData getData(List<MatchModel> matchModels) {
ResultCategoryData out = new ResultCategoryData();
CategoryModel categoryModel = matchModels.get(0).getCategory();
out.setName(categoryModel.getName());
out.setType(categoryModel.getType());
getArray2(matchModels, out);
getTree(categoryModel.getTree(), out);
return out;
}
private void getArray2(List<MatchModel> matchModels_, ResultCategoryData out) {
List<MatchModel> matchModels = matchModels_.stream().filter(o -> o.getCategory_ord() >= 0).toList();
HashMap<Character, List<MatchModel>> matchMap = new HashMap<>();
for (MatchModel model : matchModels) {
char g = model.getPoule();
if (!matchMap.containsKey(g))
matchMap.put(g, new ArrayList<>());
matchMap.get(g).add(model);
}
matchMap.forEach((c, matchEntities) -> {
List<ResultCategoryData.PouleArrayData> matchs = matchEntities.stream()
.sorted(Comparator.comparing(MatchModel::getCategory_ord))
.map(ResultCategoryData.PouleArrayData::fromModel)
.toList();
List<ResultCategoryData.RankArray> rankArray = matchEntities.stream()
.flatMap(m -> Stream.of(m.getC1Name(), m.getC2Name()))
.distinct()
.map(combName -> {
AtomicInteger w = new AtomicInteger(0);
AtomicInteger pointMake = new AtomicInteger(0);
AtomicInteger pointTake = new AtomicInteger(0);
matchEntities.stream()
.filter(m -> m.isEnd() && (m.getC1Name().equals(combName) || m.getC2Name()
.equals(combName)))
.forEach(matchModel -> {
int win = matchModel.win();
if ((matchModel.getC1Name()
.equals(combName) && win > 0) || matchModel.getC2Name()
.equals(combName) && win < 0)
w.getAndIncrement();
for (ScoreEmbeddable score : matchModel.getScores()) {
if (score.getS1() <= -900 || score.getS2() <= -900)
continue;
if (matchModel.getC1Name().equals(combName)) {
pointMake.addAndGet(score.getS1());
pointTake.addAndGet(score.getS2());
} else {
pointMake.addAndGet(score.getS2());
pointTake.addAndGet(score.getS1());
}
}
});
float pointRate = (pointTake.get() == 0) ? pointMake.get() : (float) pointMake.get() / pointTake.get();
return new ResultCategoryData.RankArray(0, combName, w.get(),
pointMake.get(), pointTake.get(), pointRate);
})
.sorted(Comparator
.comparing(ResultCategoryData.RankArray::getWin)
.thenComparing(ResultCategoryData.RankArray::getPointRate).reversed())
.toList();
out.getMatchs().put(c, matchs);
int lastWin = -1;
float pointRate = 0;
int rank = 0;
for (ResultCategoryData.RankArray rankArray1 : rankArray) {
if (rankArray1.getWin() != lastWin || pointRate != rankArray1.getPointRate()) {
lastWin = rankArray1.getWin();
pointRate = rankArray1.getPointRate();
rank++;
}
rankArray1.setRank(rank);
}
out.getRankArray().put(c, rankArray);
});
}
private static void convertTree(TreeModel src, TreeNode<ResultCategoryData.TreeData> dst) {
dst.setData(ResultCategoryData.TreeData.from(src.getMatch()));
if (src.getLeft() != null) {
dst.setLeft(new TreeNode<>());
convertTree(src.getLeft(), dst.getLeft());
}
if (src.getRight() != null) {
dst.setRight(new TreeNode<>());
convertTree(src.getRight(), dst.getRight());
}
}
private void getTree(List<TreeModel> treeModels, ResultCategoryData out) {
ArrayList<TreeNode<ResultCategoryData.TreeData>> trees = new ArrayList<>();
treeModels.stream().filter(t -> t.getLevel() != 0).forEach(treeModel -> {
TreeNode<ResultCategoryData.TreeData> root = new TreeNode<>();
convertTree(treeModel, root);
trees.add(root);
});
out.setTrees(trees);
}
public Uni<CombsArrayData> getAllCombArray(String uuid, SecurityCtx securityCtx) {
return hasAccess(uuid, securityCtx)
.chain(cm_register -> registerRepository.list("competition.uuid = ?1", uuid)
.chain(registers -> matchRepository.list("category.compet.uuid = ?1", uuid)
.map(matchModels -> new Pair<>(registers, matchModels)))
.map(pair -> {
List<RegisterModel> registers = pair.getKey();
List<MatchModel> matchModels = pair.getValue();
CombsArrayData.CombsArrayDataBuilder builder = CombsArrayData.builder();
List<CombsArrayData.CombsData> combs = matchModels.stream()
.flatMap(m -> Stream.of(m.getC1Name(), m.getC2Name()))
.filter(Objects::nonNull)
.distinct()
.map(combName -> {
var builder2 = CombsArrayData.CombsData.builder();
AtomicInteger w = new AtomicInteger(0);
AtomicInteger l = new AtomicInteger(0);
AtomicInteger pointMake = new AtomicInteger();
AtomicInteger pointTake = new AtomicInteger();
matchModels.stream()
.filter(m -> m.isEnd() && (m.getC1Name().equals(combName)
|| m.getC2Name().equals(combName)))
.forEach(matchModel -> {
int win = matchModel.win();
if ((combName.equals(matchModel.getC1Name()) && win > 0) ||
combName.equals(matchModel.getC2Name()) && win < 0) {
w.getAndIncrement();
} else {
l.getAndIncrement();
}
matchModel.getScores().stream()
.filter(s -> s.getS1() > -900 && s.getS2() > -900)
.forEach(score -> {
if (combName.equals(matchModel.getC1Name())) {
pointMake.addAndGet(score.getS1());
pointTake.addAndGet(score.getS2());
} else {
pointMake.addAndGet(score.getS2());
pointTake.addAndGet(score.getS1());
}
});
});
Categorie categorie = null;
ClubModel club = null;
Optional<RegisterModel> register = registers.stream()
.filter(r -> r.getName().equals(combName)).findFirst();
if (register.isPresent()) {
categorie = register.get().getCategorie();
club = register.get().getClub2();
}
builder2.cat((categorie == null) ? "---" : categorie.getName(BUNDLE));
builder2.name(combName);
builder2.w(w.get());
builder2.l(l.get());
builder2.ratioVictoire((l.get() == 0) ? w.get() : (float) w.get() / l.get());
builder2.club((club == null) ? BUNDLE.getString("no.licence") : club.getName());
builder2.pointMake(pointMake.get());
builder2.pointTake(pointTake.get());
builder2.ratioPoint(
(pointTake.get() == 0) ? pointMake.get() : (float) pointMake.get() / pointTake.get());
return builder2.build();
})
.sorted(Comparator.comparing(CombsArrayData.CombsData::name))
.toList();
builder.nb_insc(combs.size());
builder.tt_match((int) matchModels.stream().filter(MatchModel::isEnd).count());
builder.point(combs.stream().mapToInt(CombsArrayData.CombsData::pointMake).sum());
builder.combs(combs);
return builder.build();
})
);
}
@Builder
@RegisterForReflection
public static record CombsArrayData(int nb_insc, int tt_match, long point, List<CombsData> combs) {
@Builder
@RegisterForReflection
public static record CombsData(String cat, String club, String name, int w, int l, float ratioVictoire,
float ratioPoint, int pointMake, int pointTake) {
}
}
public Uni<ClubArrayData> getClubArray(String uuid, SecurityCtx securityCtx) {
ClubArrayData.ClubArrayDataBuilder builder = ClubArrayData.builder();
return hasAccess(uuid, securityCtx)
.invoke(cm_register -> builder.name(cm_register.getClub2().getName()))
.chain(cm_register -> registerRepository.list("competition.uuid = ?1 AND membre.club = ?2", uuid,
cm_register.getClub2())
.chain(registers -> matchRepository.list("category.compet.uuid = ?1", uuid)
.map(matchModels -> new Pair<>(registers, matchModels)))
.map(pair -> {
List<RegisterModel> registers = pair.getKey();
List<MatchModel> matchModels = pair.getValue();
builder.nb_insc(registers.size());
AtomicInteger tt_win = new AtomicInteger(0);
AtomicInteger tt_match = new AtomicInteger(0);
List<ClubArrayData.CombData> combData = registers.stream()
.map(register -> {
var builder2 = ClubArrayData.CombData.builder();
AtomicInteger w = new AtomicInteger(0);
AtomicInteger l = new AtomicInteger(0);
AtomicInteger pointMake = new AtomicInteger();
AtomicInteger pointTake = new AtomicInteger();
matchModels.stream()
.filter(m -> m.isEnd() && (register.getMembre().equals(m.getC1_id())
|| register.getMembre().equals(m.getC2_id())))
.forEach(matchModel -> {
int win = matchModel.win();
if ((register.getMembre()
.equals(matchModel.getC1_id()) && win > 0) ||
register.getMembre()
.equals(matchModel.getC2_id()) && win < 0) {
w.getAndIncrement();
} else {
l.getAndIncrement();
}
matchModel.getScores().stream()
.filter(s -> s.getS1() > -900 && s.getS2() > -900)
.forEach(score -> {
if (register.getMembre()
.equals(matchModel.getC1_id())) {
pointMake.addAndGet(score.getS1());
pointTake.addAndGet(score.getS2());
} else {
pointMake.addAndGet(score.getS2());
pointTake.addAndGet(score.getS1());
}
});
});
Categorie categorie = register.getCategorie();
if (categorie == null)
categorie = register.getMembre().getCategorie();
builder2.cat((categorie == null) ? "---" : categorie.getName(BUNDLE));
builder2.name(register.getName());
builder2.w(w.get());
builder2.l(l.get());
builder2.ratioVictoire((l.get() == 0) ? w.get() : (float) w.get() / l.get());
builder2.pointMake(pointMake.get());
builder2.pointTake(pointTake.get());
builder2.ratioPoint(
(pointTake.get() == 0) ? pointMake.get() : (float) pointMake.get() / pointTake.get());
tt_win.addAndGet(w.get());
tt_match.addAndGet(w.get() + l.get());
return builder2.build();
})
.sorted(Comparator.comparing(ClubArrayData.CombData::name))
.toList();
builder.nb_match(tt_match.get());
builder.match_w(tt_win.get());
builder.ratioVictoire((float) combData.stream().filter(c -> c.l + c.w != 0)
.mapToDouble(ClubArrayData.CombData::ratioVictoire).average().orElse(0L));
builder.pointMake(combData.stream().mapToInt(ClubArrayData.CombData::pointMake).sum());
builder.pointTake(combData.stream().mapToInt(ClubArrayData.CombData::pointTake).sum());
builder.ratioPoint((float) combData.stream().filter(c -> c.l + c.w != 0)
.mapToDouble(ClubArrayData.CombData::ratioPoint).average().orElse(0L));
builder.combs(combData);
return builder.build();
})
);
}
@Builder
@RegisterForReflection
public static record ClubArrayData(String name, int nb_insc, int nb_match, int match_w, float ratioVictoire,
float ratioPoint, int pointMake, int pointTake, List<CombData> combs) {
@Builder
@RegisterForReflection
public static record CombData(String cat, String name, int w, int l, float ratioVictoire,
float ratioPoint, int pointMake, int pointTake) {
}
}
private Uni<RegisterModel> hasAccess(String uuid, SecurityCtx securityCtx) {
return registerRepository.find("membre.userId = ?1 AND competition.uuid = ?2", securityCtx.getSubject(), uuid)
.firstResult()
.invoke(Unchecked.consumer(o -> {
if (o == null)
throw new DForbiddenException("Access denied");
}));
}
private Uni<RegisterModel> hasAccess(Long compId, SecurityCtx securityCtx) {
return registerRepository.find("membre.userId = ?1 AND competition.id = ?2", securityCtx.getSubject(), compId)
.firstResult()
.invoke(Unchecked.consumer(o -> {
if (o == null)
throw new DForbiddenException("Access denied");
}));
}
}

View File

@@ -0,0 +1,4 @@
package fr.titionfire.ffsaf.domain.service;
public class TreeService {
}

View File

@@ -13,25 +13,13 @@ public class WebhookService {
@Inject @Inject
CheckoutService checkoutService; CheckoutService checkoutService;
@Inject
CompetitionService competitionService;
@ConfigProperty(name = "helloasso.organizationSlug") @ConfigProperty(name = "helloasso.organizationSlug")
String organizationSlug; String organizationSlug;
public Uni<Response> helloAssoNotification(HelloassoNotification notification) { public Uni<Response> helloAssoNotification(HelloassoNotification notification) {
if (notification.getEventType().equals("Payment")) { if (notification.getEventType().equals("Payment")){
if (notification.getData().getOrder().getFormType().equals("Checkout")) { if (notification.getData().getOrder().getOrganizationSlug().equalsIgnoreCase(organizationSlug)){
if (notification.getData().getOrder().getOrganizationSlug().equalsIgnoreCase(organizationSlug)) { return checkoutService.paymentStatusChange(notification.getData().getState(), notification.getMetadata());
return checkoutService.paymentStatusChange(notification.getData().getState(),
notification.getMetadata());
}
} else if (notification.getData().getOrder().getFormType().equals("Event")) {
return competitionService.unregisterHelloAsso(notification.getData());
}
}else if (notification.getEventType().equals("Order")){
if (notification.getData().getFormType().equals("Event")) {
return competitionService.registerHelloAsso(notification.getData());
} }
} }

View File

@@ -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<String, String>> future) { CompletableFuture<HashMap<Long, 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));

View File

@@ -92,7 +92,7 @@ public class AffiliationRequestEndpoints {
@DELETE @DELETE
@Path("/{id}") @Path("/{id}")
@RolesAllowed({"federation_admin", "club_president", "club_secretaire", "club_respo_intra"}) @RolesAllowed({"federation_admin"})
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "Supprime une demande d'affiliation", description = "Cette méthode supprime une demande " + @Operation(summary = "Supprime une demande d'affiliation", description = "Cette méthode supprime une demande " +
"d'affiliation pour l'identifiant spécifié.") "d'affiliation pour l'identifiant spécifié.")
@@ -107,7 +107,7 @@ public class AffiliationRequestEndpoints {
if (o.getClub() == null && !securityCtx.roleHas("federation_admin")) if (o.getClub() == null && !securityCtx.roleHas("federation_admin"))
throw new DForbiddenException(); throw new DForbiddenException();
})).invoke(o -> checkPerm.accept(o.getClub())) })).invoke(o -> checkPerm.accept(o.getClub()))
.chain(o -> service.deleteReqAffiliation(id, reason, securityCtx.roleHas("federation_admin"))); .chain(o -> service.deleteReqAffiliation(id, reason));
} }
@PUT @PUT
@@ -186,6 +186,6 @@ public class AffiliationRequestEndpoints {
public Uni<Response> getStatus( public Uni<Response> getStatus(
@Parameter(description = "L'identifiant de la demande d'affiliation") @PathParam("id") long id) throws URISyntaxException { @Parameter(description = "L'identifiant de la demande d'affiliation") @PathParam("id") long id) throws URISyntaxException {
return Utils.getMediaFile(id, media, "aff_request/status", "affiliation_request_" + id, return Utils.getMediaFile(id, media, "aff_request/status", "affiliation_request_" + id,
Uni.createFrom().nullItem(), false); Uni.createFrom().nullItem());
} }
} }

View File

@@ -1,8 +1,7 @@
package fr.titionfire.ffsaf.rest; package fr.titionfire.ffsaf.rest;
import fr.titionfire.ffsaf.rest.client.SirenService; import fr.titionfire.ffsaf.rest.client.SirenService;
import fr.titionfire.ffsaf.rest.client.StateIdService; import fr.titionfire.ffsaf.rest.data.UniteLegaleRoot;
import fr.titionfire.ffsaf.rest.data.AssoData;
import fr.titionfire.ffsaf.rest.exception.DNotFoundException; import fr.titionfire.ffsaf.rest.exception.DNotFoundException;
import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.Uni;
import jakarta.ws.rs.*; import jakarta.ws.rs.*;
@@ -13,24 +12,18 @@ import org.eclipse.microprofile.rest.client.inject.RestClient;
@Path("api/asso") @Path("api/asso")
public class AssoEndpoints { public class AssoEndpoints {
@RestClient
StateIdService stateIdService;
@RestClient @RestClient
SirenService sirenService; SirenService sirenService;
@GET @GET
@Path("state_id/{stateId}") @Path("siren/{siren}")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@Operation(hidden = true) @Operation(hidden = true)
public Uni<AssoData> getAssoInfo(@PathParam("stateId") String stateId) { public Uni<UniteLegaleRoot> getInfoSiren(@PathParam("siren") String siren) {
return ((stateId.charAt(0) == 'W') ? stateIdService.get_rna(stateId) : sirenService.get_unite( return sirenService.get_unite(siren).onFailure().transform(throwable -> {
stateId).chain(stateIdService::getAssoDataFromUnit)).onFailure().transform(throwable -> {
if (throwable instanceof WebApplicationException exception) { if (throwable instanceof WebApplicationException exception) {
if (exception.getResponse().getStatus() == 404)
return new DNotFoundException("Service momentanément indisponible");
if (exception.getResponse().getStatus() == 400) if (exception.getResponse().getStatus() == 400)
return new DNotFoundException("Asso introuvable"); return new DNotFoundException("Siret introuvable");
} }
return throwable; return throwable;
}); });

View File

@@ -29,7 +29,6 @@ import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
import org.eclipse.microprofile.openapi.annotations.tags.Tag; import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
@@ -70,8 +69,7 @@ public class ClubEndpoints {
@APIResponse(responseCode = "500", description = "Erreur interne du serveur") @APIResponse(responseCode = "500", description = "Erreur interne du serveur")
}) })
public Uni<List<SimpleClubModel>> getAll() { public Uni<List<SimpleClubModel>> getAll() {
return clubService.getAll().map(clubModels -> clubModels.stream().map(SimpleClubModel::fromModel).sorted( return clubService.getAll().map(clubModels -> clubModels.stream().map(SimpleClubModel::fromModel).toList());
Comparator.comparing(SimpleClubModel::getName)).toList());
} }
@GET @GET
@@ -277,23 +275,6 @@ public class ClubEndpoints {
return pdfService.getAffiliationPdf(securityCtx.getSubject()); return pdfService.getAffiliationPdf(securityCtx.getSubject());
} }
@GET
@Path("/members")
@RolesAllowed({"club_president", "club_secretaire", "club_respo_intra", "club_tresorier"})
@Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "Revoie tout les membres de votre club")
@APIResponses(value = {
@APIResponse(responseCode = "200", description = "List des membres"),
@APIResponse(responseCode = "403", description = "Accès refusé"),
@APIResponse(responseCode = "404", description = "L'utilisateur n'est pas membre d'un club"),
@APIResponse(responseCode = "500", description = "Erreur interne du serveur")
})
public Uni<List<VerySimpleMembre>> getMembers() {
return clubService.getMembers(securityCtx);
}
@GET @GET
@Path("/renew/{id}") @Path("/renew/{id}")
@RolesAllowed({"club_president", "club_secretaire", "club_respo_intra"}) @RolesAllowed({"club_president", "club_secretaire", "club_respo_intra"})
@@ -335,7 +316,7 @@ public class ClubEndpoints {
@Parameter(description = "Identifiant long (clubId) de club") @PathParam("clubId") String clubId) { @Parameter(description = "Identifiant long (clubId) de club") @PathParam("clubId") String clubId) {
return clubService.getByClubId(clubId).chain(Unchecked.function(clubModel -> { return clubService.getByClubId(clubId).chain(Unchecked.function(clubModel -> {
try { try {
return Utils.getMediaFileNoDefault((clubModel != null) ? clubModel.getId() : -1, media, "ppClub", return Utils.getMediaFile((clubModel != null) ? clubModel.getId() : -1, media, "ppClub",
Uni.createFrom().nullItem()); Uni.createFrom().nullItem());
} catch (URISyntaxException e) { } catch (URISyntaxException e) {
throw new InternalError(); throw new InternalError();
@@ -358,7 +339,7 @@ public class ClubEndpoints {
return clubService.getById(id).onItem().invoke(checkPerm).chain(Unchecked.function(clubModel -> { return clubService.getById(id).onItem().invoke(checkPerm).chain(Unchecked.function(clubModel -> {
try { try {
return Utils.getMediaFile(clubModel.getId(), media, "clubStatus", return Utils.getMediaFile(clubModel.getId(), media, "clubStatus",
"statue-" + clubModel.getName(), Uni.createFrom().nullItem(), false); "statue-" + clubModel.getName(), Uni.createFrom().nullItem());
} catch (URISyntaxException e) { } catch (URISyntaxException e) {
throw new InternalError(); throw new InternalError();
} }

View File

@@ -1,58 +0,0 @@
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);
}
@GET
@Path("all/{system}/table")
@Authenticated
@Produces(MediaType.APPLICATION_JSON)
public Uni<List<CompetitionData>> getAllSystemTable(@PathParam("system") CompetitionSystem system) {
return service.getAllSystemTable(securityCtx, system);
}
}

View File

@@ -5,6 +5,7 @@ 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;
@@ -28,39 +29,34 @@ 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, @QueryParam("light") boolean light) { public Uni<CompetitionData> getById(@PathParam("id") Long id) {
if (light)
return service.getById(securityCtx, id); return service.getById(securityCtx, id);
else
return service.getByIdAdmin(securityCtx, id);
} }
@GET @GET
@Path("{id}/register/{source}") @Path("{id}/register")
@Authenticated @Authenticated
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public Uni<List<SimpleRegisterComb>> getRegister(@PathParam("id") Long id, @PathParam("source") String source) { public Uni<List<SimpleRegisterComb>> getRegister(@PathParam("id") Long id) {
return service.getRegister(securityCtx, id, source); return service.getRegister(securityCtx, id);
} }
@POST @POST
@Path("{id}/register/{source}") @Path("{id}/register")
@Authenticated @Authenticated
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@Operation(hidden = true) @Operation(hidden = true)
public Uni<SimpleRegisterComb> addRegisterComb(@PathParam("id") Long id, @PathParam("source") String source, public Uni<SimpleRegisterComb> addRegisterComb(@PathParam("id") Long id, RegisterRequestData data) {
RegisterRequestData data) { return service.addRegisterComb(securityCtx, id, data);
return service.addRegisterComb(securityCtx, id, data, source);
} }
@DELETE @DELETE
@Path("{id}/register/{comb_id}/{source}") @Path("{id}/register/{comb_id}")
@Authenticated @Authenticated
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@Operation(hidden = true) @Operation(hidden = true)
public Uni<Void> removeRegisterComb(@PathParam("id") Long id, @PathParam("comb_id") Long combId, public Uni<Void> removeRegisterComb(@PathParam("id") Long id, @PathParam("comb_id") Long combId) {
@PathParam("source") String source, @QueryParam("ban") boolean ban) { return service.removeRegisterComb(securityCtx, id, combId);
return service.removeRegisterComb(securityCtx, id, combId, source, ban);
} }
@GET @GET
@@ -80,6 +76,14 @@ 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)

View File

@@ -115,8 +115,8 @@ public class CompteEndpoints {
else toRemove.add("safca_super_admin"); else toRemove.add("safca_super_admin");
if (form.isSafca_user()) toAdd.add("safca_user"); if (form.isSafca_user()) toAdd.add("safca_user");
else toRemove.add("safca_user"); else toRemove.add("safca_user");
if (form.isCreate_compet()) toAdd.add("create_compet"); if (form.isSafca_create_compet()) toAdd.add("safca_create_compet");
else toRemove.add("create_compet"); else toRemove.add("safca_create_compet");
return service.updateRole(id, toAdd, toRemove); return service.updateRole(id, toAdd, toRemove);
} }

View File

@@ -14,8 +14,8 @@ import jakarta.ws.rs.core.MediaType;
import java.util.List; import java.util.List;
@Authenticated @Authenticated
@Path("api/match/{system}/admin") @Path("api/match/{system}/")
public class MatchAdminEndpoints { public class MatchEndpoints {
@PathParam("system") @PathParam("system")
private CompetitionSystem system; private CompetitionSystem system;
@@ -30,15 +30,15 @@ public class MatchAdminEndpoints {
@GET @GET
@Path("{id}") @Path("{id}")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public Uni<MatchData> getByIdAdmin(@PathParam("id") Long id) { public Uni<MatchData> getById(@PathParam("id") Long id) {
return service.getByIdAdmin(securityCtx, system, id); return service.getById(securityCtx, system, id);
} }
@GET @GET
@Path("getAllByPoule/{id}") @Path("getAllByPoule/{id}")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public Uni<List<MatchData>> getAllByPouleAdmin(@PathParam("id") Long id) { public Uni<List<MatchData>> getAllByPoule(@PathParam("id") Long id) {
return service.getAllByPouleAdmin(securityCtx, system, id); return service.getAllByPoule(securityCtx, system, id);
} }
@POST @POST

View File

@@ -58,15 +58,13 @@ public class MembreAdminEndpoints {
@Parameter(description = "Page à consulter") @QueryParam("page") Integer page, @Parameter(description = "Page à consulter") @QueryParam("page") Integer page,
@Parameter(description = "Text à rechercher") @QueryParam("search") String search, @Parameter(description = "Text à rechercher") @QueryParam("search") String search,
@Parameter(description = "Club à filter") @QueryParam("club") String club, @Parameter(description = "Club à filter") @QueryParam("club") String club,
@Parameter(description = "Catégorie à filter") @QueryParam("categorie") String categorie, @Parameter(description = "Etat de la demande de licence: 0 -> sans demande, 1 -> avec demande ou validée, 2 -> toute les demande non validée, 3 -> validée, 4 -> tout, 5 -> demande complete, 6 -> demande incomplete") @QueryParam("licenceRequest") int licenceRequest,
@Parameter(description = "État de la demande de licence: 0 -> sans demande, 1 -> avec demande ou validée, 2 -> toute les demande non validée, 3 -> validée, 4 -> tout, 5 -> demande complete, 6 -> demande incomplete") @QueryParam("licenceRequest") int licenceRequest, @Parameter(description = "Etat du payment: 0 -> non payer, 1 -> payer, 2 -> tout") @QueryParam("payment") int payment) {
@Parameter(description = "État du payment: 0 -> non payer, 1 -> payer, 2 -> tout") @QueryParam("payment") int payment,
@Parameter(description = "Ordre") @QueryParam("order") String order) {
if (limit == null) if (limit == null)
limit = 50; limit = 50;
if (page == null || page < 1) if (page == null || page < 1)
page = 1; page = 1;
return membreService.searchAdmin(limit, page - 1, search, club, licenceRequest, payment, order, categorie); return membreService.searchAdmin(limit, page - 1, search, club, licenceRequest, payment);
} }
@GET @GET

View File

@@ -50,15 +50,13 @@ public class MembreClubEndpoints {
@Parameter(description = "Nombre max de résulta (max 50)") @QueryParam("limit") Integer limit, @Parameter(description = "Nombre max de résulta (max 50)") @QueryParam("limit") Integer limit,
@Parameter(description = "Page à consulter") @QueryParam("page") Integer page, @Parameter(description = "Page à consulter") @QueryParam("page") Integer page,
@Parameter(description = "Text à rechercher") @QueryParam("search") String search, @Parameter(description = "Text à rechercher") @QueryParam("search") String search,
@Parameter(description = "Catégorie à filter") @QueryParam("categorie") String categorie,
@Parameter(description = "Etat de la demande de licence: 0 -> sans demande, 1 -> avec demande ou validée, 2 -> toute les demande non validée, 3 -> validée, 4 -> tout, 5 -> demande complete, 6 -> demande incomplete") @QueryParam("licenceRequest") int licenceRequest, @Parameter(description = "Etat de la demande de licence: 0 -> sans demande, 1 -> avec demande ou validée, 2 -> toute les demande non validée, 3 -> validée, 4 -> tout, 5 -> demande complete, 6 -> demande incomplete") @QueryParam("licenceRequest") int licenceRequest,
@Parameter(description = "Etat du payment: 0 -> non payer, 1 -> payer, 2 -> tout") @QueryParam("payment") int payment, @Parameter(description = "Etat du payment: 0 -> non payer, 1 -> payer, 2 -> tout") @QueryParam("payment") int payment) {
@Parameter(description = "Ordre") @QueryParam("order") String order) {
if (limit == null) if (limit == null)
limit = 50; limit = 50;
if (page == null || page < 1) if (page == null || page < 1)
page = 1; page = 1;
return membreService.search(limit, page - 1, search, licenceRequest, payment, order, categorie, securityCtx.getSubject()); return membreService.search(limit, page - 1, search, licenceRequest, payment, securityCtx.getSubject());
} }
@GET @GET

View File

@@ -1,8 +1,8 @@
package fr.titionfire.ffsaf.rest; package fr.titionfire.ffsaf.rest;
import fr.titionfire.ffsaf.domain.service.CategoryService; import fr.titionfire.ffsaf.domain.service.PouleService;
import fr.titionfire.ffsaf.rest.data.CategoryData; import fr.titionfire.ffsaf.rest.data.PouleData;
import fr.titionfire.ffsaf.rest.data.CategoryFullData; import fr.titionfire.ffsaf.rest.data.PouleFullData;
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}/admin/") @Path("api/poule/{system}/")
public class CategoryAdminEndpoints { public class PouleEndpoints {
@PathParam("system") @PathParam("system")
private CompetitionSystem system; private CompetitionSystem system;
@Inject @Inject
CategoryService service; PouleService service;
@Inject @Inject
SecurityCtx securityCtx; SecurityCtx securityCtx;
@@ -30,28 +30,28 @@ public class CategoryAdminEndpoints {
@GET @GET
@Path("{id}") @Path("{id}")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public Uni<CategoryData> getByIdAdmin(@PathParam("id") Long id) { public Uni<PouleData> getById(@PathParam("id") Long id) {
return service.getByIdAdmin(securityCtx, system, id); return service.getById(securityCtx, system, id);
} }
@GET @GET
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public Uni<List<CategoryData>> getAllAdmin() { public Uni<List<PouleData>> getAll() {
return service.getAllAdmin(securityCtx, system); return service.getAll(securityCtx, system);
} }
@POST @POST
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public Uni<CategoryData> addOrUpdate(CategoryData data) { public Uni<PouleData> addOrUpdate(PouleData 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<?> syncCategory(CategoryFullData data) { public Uni<?> syncPoule(PouleFullData data) {
return service.syncCategory(securityCtx, system, data); return service.syncPoule(securityCtx, system, data);
} }
@DELETE @DELETE

View File

@@ -1,48 +0,0 @@
package fr.titionfire.ffsaf.rest;
import fr.titionfire.ffsaf.domain.service.ResultService;
import fr.titionfire.ffsaf.rest.data.ResultCategoryData;
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 java.util.List;
@Authenticated
@Path("api/result")
public class ResultEndpoints {
@Inject
ResultService resultService;
@Inject
SecurityCtx securityCtx;
@GET
@Path("list")
public Uni<List<Object[]>> getList() {
return resultService.getList(securityCtx);
}
@GET
@Path("{uuid}")
public Uni<List<ResultCategoryData>> getCategory(@PathParam("uuid") String uuid) {
return resultService.getCategory(uuid, securityCtx);
}
@GET
@Path("{uuid}/club")
public Uni<ResultService.ClubArrayData> getClub(@PathParam("uuid") String uuid) {
return resultService.getClubArray(uuid, securityCtx);
}
@GET
@Path("{uuid}/comb")
public Uni<ResultService.CombsArrayData> getComb(@PathParam("uuid") String uuid) {
return resultService.getAllCombArray(uuid, securityCtx);
}
}

View File

@@ -1,7 +1,6 @@
package fr.titionfire.ffsaf.rest.client; package fr.titionfire.ffsaf.rest.client;
import fr.titionfire.ffsaf.rest.data.UniteLegaleRoot; import fr.titionfire.ffsaf.rest.data.UniteLegaleRoot;
import io.quarkus.cache.CacheResult;
import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.Uni;
import jakarta.ws.rs.GET; import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path; import jakarta.ws.rs.Path;
@@ -16,6 +15,5 @@ public interface SirenService {
@GET @GET
@Path("/v3/unites_legales/{SIREN}") @Path("/v3/unites_legales/{SIREN}")
@CacheResult(cacheName = "AssoData_siren")
Uni<UniteLegaleRoot> get_unite(@PathParam("SIREN") String siren); Uni<UniteLegaleRoot> get_unite(@PathParam("SIREN") String siren);
} }

View File

@@ -1,48 +0,0 @@
package fr.titionfire.ffsaf.rest.client;
import fr.titionfire.ffsaf.rest.data.AssoData;
import fr.titionfire.ffsaf.rest.data.UniteLegaleRoot;
import io.quarkus.cache.CacheResult;
import io.smallrye.mutiny.Uni;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
@Path("/")
@RegisterRestClient
public interface StateIdService {
@GET
@Path("/associations/{rna}")
@CacheResult(cacheName = "AssoData_rna")
Uni<AssoData> get_rna(@PathParam("rna") String rna);
default Uni<AssoData> getAssoDataFromUnit(UniteLegaleRoot u) {
AssoData assoData = new AssoData();
assoData.setSiren(u.getUnite_legale().getSiren());
assoData.setRna(u.getUnite_legale().getIdentifiant_association());
AssoData.Identite identite = new AssoData.Identite();
identite.setNom(u.getUnite_legale().getDenomination());
identite.setSiret_siege(u.getUnite_legale().getEtablissement_siege().getSiret());
assoData.setIdentite(identite);
AssoData.Address address = new AssoData.Address();
StringBuilder voie = new StringBuilder();
if (u.getUnite_legale().getEtablissement_siege().getNumero_voie() != null)
voie.append(u.getUnite_legale().getEtablissement_siege().getNumero_voie()).append(' ');
if (u.getUnite_legale().getEtablissement_siege().getType_voie() != null)
voie.append(u.getUnite_legale().getEtablissement_siege().getType_voie()).append(' ');
if (u.getUnite_legale().getEtablissement_siege().getLibelle_voie() != null)
voie.append(u.getUnite_legale().getEtablissement_siege().getLibelle_voie()).append(' ');
address.setVoie(voie.toString().trim());
address.setComplement(u.getUnite_legale().getEtablissement_siege().getComplement_adresse());
address.setCode_postal(u.getUnite_legale().getEtablissement_siege().getCode_postal());
address.setCommune(
new AssoData.Commune(u.getUnite_legale().getEtablissement_siege().getLibelle_commune()));
assoData.setCoordonnees(new AssoData.Coordonnee(address));
return Uni.createFrom().item(assoData);
}
}

View File

@@ -5,8 +5,6 @@ import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.util.List;
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@@ -14,14 +12,11 @@ import java.util.List;
public class NotificationData { public class NotificationData {
private Order order; private Order order;
private Integer id; private Integer id;
private String formSlug;
private String formType;
private String organizationSlug; private String organizationSlug;
private String checkoutIntentId; private String checkoutIntentId;
private String oldSlugOrganization; // Pour les changements de nom d'association private String oldSlugOrganization; // Pour les changements de nom d'association
private String newSlugOrganization; private String newSlugOrganization;
private String state; // Pour les formulaires private String state; // Pour les formulaires
private List<Item> items;
@Data @Data
@@ -31,35 +26,5 @@ public class NotificationData {
public static class Order { public static class Order {
private Integer id; private Integer id;
private String organizationSlug; private String organizationSlug;
private String formSlug;
private String formType;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@RegisterForReflection
public static class Item {
private String name;
private User user;
private List<CustomField> customFields;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@RegisterForReflection
public static class User {
private String firstName;
private String lastName;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@RegisterForReflection
public static class CustomField {
private String name;
private String answer;
} }
} }

View File

@@ -1,48 +0,0 @@
package fr.titionfire.ffsaf.rest.data;
import io.quarkus.runtime.annotations.RegisterForReflection;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@RegisterForReflection
public class AssoData {
String siren;
String rna;
Identite identite;
Coordonnee coordonnees;
@Data
@RegisterForReflection
public static class Identite {
String nom;
String siret_siege;
}
@Data
@RegisterForReflection
@NoArgsConstructor
@AllArgsConstructor
public static class Coordonnee {
Address adresse_gestion;
}
@Data
@RegisterForReflection
public static class Address {
String voie;
String complement;
String code_postal;
String pays;
Commune commune;
}
@Data
@RegisterForReflection
@NoArgsConstructor
@AllArgsConstructor
public static class Commune {
String nom;
}
}

View File

@@ -1,18 +1,15 @@
package fr.titionfire.ffsaf.rest.data; package fr.titionfire.ffsaf.rest.data;
import fr.titionfire.ffsaf.data.model.CompetitionGuestModel;
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.utils.RegisterMode; import fr.titionfire.ffsaf.data.model.RegisterModel;
import io.quarkus.runtime.annotations.RegisterForReflection; import io.quarkus.runtime.annotations.RegisterForReflection;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.stream.Stream;
@Data @Data
@AllArgsConstructor @AllArgsConstructor
@@ -20,64 +17,26 @@ import java.util.stream.Stream;
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.getDescription(), model.getAdresse(), return new CompetitionData(model.getId(), model.getName(), model.getUuid(), model.getDate(), model.getSystem(),
model.getUuid(), model.getDate(), model.getTodate(), model.getSystem(), model.getClub().getId(), model.getClub().getName(), model.getOwner(), null);
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) { public CompetitionData addInsc(List<RegisterModel> insc) {
if (model == null) this.registers = insc.stream()
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, List<CompetitionGuestModel> guests) {
this.registers = Stream.concat(
insc.stream()
.map(i -> new SimpleRegister(i.getMembre().getId(), i.getOverCategory(), i.getWeight(), .map(i -> new SimpleRegister(i.getMembre().getId(), i.getOverCategory(), i.getWeight(),
i.getCategorie(), (i.getClub() == null) ? null : i.getClub().getId(), i.getCategorie(), (i.getClub() == null) ? null : i.getClub().getId())).toList();
(i.getClub() == null) ? null : i.getClub().getName())),
guests.stream()
.map(i -> new SimpleRegister(i.getId() * -1, 0, i.getWeight(),
i.getCategorie(), null, i.getClub()))).toList();
return this; return this;
} }
@@ -90,6 +49,5 @@ public class CompetitionData {
Integer weight; Integer weight;
Categorie categorie; Categorie categorie;
Long club; Long club;
String club_str;
} }
} }

View File

@@ -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 category; private Long poule;
private long category_ord; private long poule_ord;
private boolean isEnd = true; private boolean isEnd = true;
private char poule; private char groupe;
private List<ScoreEmbeddable> scores; private List<ScoreEmbeddable> scores;
public static MatchData fromModel(MatchModel model) { public static MatchData fromModel(MatchModel model) {
@@ -28,11 +28,9 @@ public class MatchData {
return null; return null;
return new MatchData(model.getSystemId(), return new MatchData(model.getSystemId(),
(model.getC1_id() == null) ? null : model.getC1_id().getId(), (model.getC1_id() == null) ? null : model.getC1_id().getId(), model.getC1_str(),
(model.getC1_guest() == null) ? null : model.getC1_guest().getName(), (model.getC2_id() == null) ? null : model.getC2_id().getId(), model.getC2_str(),
(model.getC2_id() == null) ? null : model.getC2_id().getId(), model.getPoule().getId(), model.getPoule_ord(), model.isEnd(), model.getGroupe(),
(model.getC2_guest() == null) ? null : model.getC2_guest().getName(),
model.getCategory().getId(), model.getCategory_ord(), model.isEnd(), model.getPoule(),
model.getScores()); model.getScores());
} }
} }

View File

@@ -1,6 +1,6 @@
package fr.titionfire.ffsaf.rest.data; package fr.titionfire.ffsaf.rest.data;
import fr.titionfire.ffsaf.data.model.CategoryModel; import fr.titionfire.ffsaf.data.model.PouleModel;
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 CategoryData { public class PouleData {
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 CategoryData fromModel(CategoryModel model) { public static PouleData fromModel(PouleModel model) {
if (model == null) if (model == null)
return null; return null;
return new CategoryData(model.getSystemId(), model.getName(), model.getCompet().getId(), model.getType()); return new PouleData(model.getSystemId(), model.getName(), model.getCompet().getId(), model.getType());
} }
} }

View File

@@ -7,7 +7,7 @@ import java.util.List;
@Data @Data
@AllArgsConstructor @AllArgsConstructor
public class CategoryFullData { public class PouleFullData {
private Long id; private Long id;
private String name; private String name;
private Long compet; private Long compet;

View File

@@ -1,15 +1,9 @@
package fr.titionfire.ffsaf.rest.data; package fr.titionfire.ffsaf.rest.data;
import fr.titionfire.ffsaf.utils.Categorie;
import fr.titionfire.ffsaf.utils.Genre;
import io.quarkus.runtime.annotations.RegisterForReflection; import io.quarkus.runtime.annotations.RegisterForReflection;
import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor;
@Data @Data
@AllArgsConstructor
@NoArgsConstructor
@RegisterForReflection @RegisterForReflection
public class RegisterRequestData { public class RegisterRequestData {
private Long licence; private Long licence;
@@ -18,12 +12,4 @@ public class RegisterRequestData {
private Integer weight; private Integer weight;
private int overCategory; private int overCategory;
private boolean lockEdit = false;
// for guest registration only
private Long id = null;
private Categorie categorie = Categorie.CADET;
private Genre genre = Genre.NA;
private String club = null;
private String country = null;
} }

View File

@@ -17,9 +17,9 @@ import java.util.List;
@RegisterForReflection @RegisterForReflection
public class RenewAffData { public class RenewAffData {
String name; String name;
String state_id; Long siret;
String rna;
String address; String address;
String contact;
int saison; int saison;
List<RenewMember> members; List<RenewMember> members;

View File

@@ -1,59 +0,0 @@
package fr.titionfire.ffsaf.rest.data;
import fr.titionfire.ffsaf.data.model.MatchModel;
import fr.titionfire.ffsaf.utils.ScoreEmbeddable;
import fr.titionfire.ffsaf.utils.TreeNode;
import io.quarkus.runtime.annotations.RegisterForReflection;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@Data
@NoArgsConstructor
@RegisterForReflection
public class ResultCategoryData {
int type;
String name;
HashMap<Character, List<PouleArrayData>> matchs = new HashMap<>();
HashMap<Character, List<RankArray>> rankArray = new HashMap<>();
ArrayList<TreeNode<TreeData>> trees;
@Data
@AllArgsConstructor
@RegisterForReflection
public static class RankArray {
int rank;
String name;
int win;
int pointMake;
int pointTake;
float pointRate;
}
@RegisterForReflection
public record PouleArrayData(String red, boolean red_w, List<Integer[]> score, boolean blue_w, String blue, boolean end) {
public static PouleArrayData fromModel(MatchModel matchModel) {
return new PouleArrayData(
matchModel.getC1Name(),
matchModel.isEnd() && matchModel.win() > 0,
matchModel.isEnd() ?
matchModel.getScores().stream().map(s -> new Integer[]{s.getS1(), s.getS2()}).toList()
: new ArrayList<>(),
matchModel.isEnd() && matchModel.win() < 0,
matchModel.getC2Name(),
matchModel.isEnd());
}
}
@RegisterForReflection
public static record TreeData(long id, String c1FullName, String c2FullName, List<ScoreEmbeddable> scores,
boolean end) {
public static TreeData from(MatchModel match) {
return new TreeData(match.getId(), match.getC1Name(), match.getC2Name(), match.getScores(), match.isEnd());
}
}
}

View File

@@ -14,8 +14,8 @@ import org.eclipse.microprofile.openapi.annotations.media.Schema;
public class SimpleAffiliation { public class SimpleAffiliation {
@Schema(description = "L'identifiant de l'affiliation.", example = "1") @Schema(description = "L'identifiant de l'affiliation.", example = "1")
private Long id; private Long id;
@Schema(description = "L'identifiant du club associé à l'affiliation si id > 0 sinon n° SIRET ou RNA du club.", example = "123") @Schema(description = "L'identifiant du club associé à l'affiliation.", example = "123")
private String club; private Long club;
@Schema(description = "La saison de l'affiliation.", example = "2022") @Schema(description = "La saison de l'affiliation.", example = "2022")
private int saison; private int saison;
@Schema(description = "Indique si l'affiliation est validée ou non.", example = "true") @Schema(description = "Indique si l'affiliation est validée ou non.", example = "true")
@@ -27,7 +27,7 @@ public class SimpleAffiliation {
return new SimpleAffiliationBuilder() return new SimpleAffiliationBuilder()
.id(model.getId()) .id(model.getId())
.club(String.valueOf(model.getClub().getId())) .club(model.getClub().getId())
.saison(model.getSaison()) .saison(model.getSaison())
.validate(true) .validate(true)
.build(); .build();

View File

@@ -36,8 +36,10 @@ public class SimpleClub {
private String contact_intern; private String contact_intern;
@Schema(description = "Adresse postale du club", example = "1 rue de l'exemple, 75000 Paris") @Schema(description = "Adresse postale du club", example = "1 rue de l'exemple, 75000 Paris")
private String address; private String address;
@Schema(description = "Numéro SIRET ou RNA du club", example = "12345678901234") @Schema(description = "RNA du club", example = "W123456789")
private String state_id; private String RNA;
@Schema(description = "Numéro SIRET du club", example = "12345678901234")
private Long SIRET;
@Schema(description = "Numéro d'affiliation du club", example = "12345") @Schema(description = "Numéro d'affiliation du club", example = "12345")
private Long no_affiliation; private Long no_affiliation;
@Schema(description = "Club international", example = "false") @Schema(description = "Club international", example = "false")
@@ -58,7 +60,8 @@ public class SimpleClub {
.training_location(model.getTraining_location()) .training_location(model.getTraining_location())
.training_day_time(model.getTraining_day_time()) .training_day_time(model.getTraining_day_time())
.contact_intern(model.getContact_intern()) .contact_intern(model.getContact_intern())
.state_id(model.getStateId()) .RNA(model.getRNA())
.SIRET(model.getSIRET())
.no_affiliation(model.getNo_affiliation()) .no_affiliation(model.getNo_affiliation())
.international(model.isInternational()) .international(model.isInternational())
.address(model.getAddress()) .address(model.getAddress())

View File

@@ -20,8 +20,8 @@ public class SimpleClubList {
String name; String name;
@Schema(description = "Pays du club", example = "FR") @Schema(description = "Pays du club", example = "FR")
String country; String country;
@Schema(description = "Numéro SIRET ou RNA du club", example = "12345678901234") @Schema(description = "Numéro SIRET du club", example = "12345678901234")
String state_id; Long siret;
@Schema(description = "Numéro d'affiliation du club", example = "12345") @Schema(description = "Numéro d'affiliation du club", example = "12345")
Long no_affiliation; Long no_affiliation;
@@ -29,7 +29,7 @@ public class SimpleClubList {
if (model == null) if (model == null)
return null; return null;
return new SimpleClubList(model.getId(), model.getName(), model.getCountry(), model.getStateId(), return new SimpleClubList(model.getId(), model.getName(), model.getCountry(), model.getSIRET(),
model.getNo_affiliation()); model.getNo_affiliation());
} }
} }

View File

@@ -1,12 +1,9 @@
package fr.titionfire.ffsaf.rest.data; package fr.titionfire.ffsaf.rest.data;
import fr.titionfire.ffsaf.data.model.CompetitionGuestModel;
import fr.titionfire.ffsaf.data.model.LicenceModel; import fr.titionfire.ffsaf.data.model.LicenceModel;
import fr.titionfire.ffsaf.data.model.MembreModel; import fr.titionfire.ffsaf.data.model.MembreModel;
import fr.titionfire.ffsaf.data.model.RegisterModel;
import fr.titionfire.ffsaf.net2.data.SimpleClubModel; import fr.titionfire.ffsaf.net2.data.SimpleClubModel;
import fr.titionfire.ffsaf.utils.Categorie; import fr.titionfire.ffsaf.data.model.RegisterModel;
import fr.titionfire.ffsaf.utils.Genre;
import fr.titionfire.ffsaf.utils.Utils; import fr.titionfire.ffsaf.utils.Utils;
import io.quarkus.runtime.annotations.RegisterForReflection; import io.quarkus.runtime.annotations.RegisterForReflection;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
@@ -21,31 +18,19 @@ public class SimpleRegisterComb {
private long id; private long id;
private String fname; private String fname;
private String lname; private String lname;
private Genre genre; private String categorie;
private String country;
private Categorie categorie;
private SimpleClubModel club; private SimpleClubModel club;
private Integer licence; private Integer licence;
private Integer weight; private Integer weight;
private int overCategory; private int overCategory;
private boolean hasLicenceActive; private boolean hasLicenceActive;
private boolean lockEdit;
public static SimpleRegisterComb fromModel(RegisterModel register, List<LicenceModel> licences) { public static SimpleRegisterComb fromModel(RegisterModel register, List<LicenceModel> licences) {
MembreModel membreModel = register.getMembre(); MembreModel membreModel = register.getMembre();
return new SimpleRegisterComb(membreModel.getId(), membreModel.getFname(), membreModel.getLname(), return new SimpleRegisterComb(membreModel.getId(), membreModel.getFname(), membreModel.getLname(),
membreModel.getGenre(), membreModel.getCountry(), (register.getCategorie() == null) ? "Catégorie inconnue" : register.getCategorie().getName(),
(register.getCategorie() == null) ? null : register.getCategorie(),
SimpleClubModel.fromModel(register.getClub()), membreModel.getLicence(), register.getWeight(), SimpleClubModel.fromModel(register.getClub()), membreModel.getLicence(), register.getWeight(),
register.getOverCategory(), register.getOverCategory(),
licences.stream().anyMatch(l -> l.isValidate() && l.getSaison() == Utils.getSaison()), licences.stream().anyMatch(l -> l.isValidate() && l.getSaison() == Utils.getSaison()));
register.isLockEdit());
}
public static SimpleRegisterComb fromModel(CompetitionGuestModel guest) {
return new SimpleRegisterComb(guest.getId() * -1, guest.getFname(), guest.getLname(),
guest.getGenre(), guest.getCountry(), guest.getCategorie(),
new SimpleClubModel(null, guest.getClub(), "fr", null),
null, guest.getWeight(), 0, false, false);
} }
} }

View File

@@ -25,8 +25,10 @@ public class SimpleReqAffiliation {
Long club_no_aff; Long club_no_aff;
@Schema(description = "Nom du club demander", example = "Association sportive") @Schema(description = "Nom du club demander", example = "Association sportive")
String name; String name;
@Schema(description = "Numéro SIRET ou RNA de l'association", example = "12345678901234") @Schema(description = "Numéro SIRET de l'association", example = "12345678901234")
String stateId; long siret;
@Schema(description = "Numéro RNA de l'association", example = "W123456789")
String RNA;
@Schema(description = "Adresse de l'association", example = "1 rue de l'exemple, 75000 Paris") @Schema(description = "Adresse de l'association", example = "1 rue de l'exemple, 75000 Paris")
String address; String address;
@Schema(description = "Email de contact de l'association", example = "test@test.fr") @Schema(description = "Email de contact de l'association", example = "test@test.fr")
@@ -43,7 +45,8 @@ public class SimpleReqAffiliation {
return new SimpleReqAffiliation.SimpleReqAffiliationBuilder() return new SimpleReqAffiliation.SimpleReqAffiliationBuilder()
.id(model.getId()) .id(model.getId())
.name(model.getName()) .name(model.getName())
.stateId(model.getState_id()) .siret(model.getSiret())
.RNA(model.getRNA())
.address(model.getAddress()) .address(model.getAddress())
.saison(model.getSaison()) .saison(model.getSaison())
.contact(model.getContact()) .contact(model.getContact())

View File

@@ -16,8 +16,8 @@ public class SimpleReqAffiliationResume {
Long id; Long id;
@Schema(description = "Le nom de l'association.", example = "Association sportive") @Schema(description = "Le nom de l'association.", example = "Association sportive")
String name; String name;
@Schema(description = "Le numéro SIRET ou RNA de l'association.", example = "12345678901234") @Schema(description = "Le numéro SIRET de l'association.", example = "12345678901234")
String stateId; long siret;
@Schema(description = "La saison de l'affiliation.", example = "2025") @Schema(description = "La saison de l'affiliation.", example = "2025")
int saison; int saison;
@@ -25,10 +25,10 @@ public class SimpleReqAffiliationResume {
if (model == null) if (model == null)
return null; return null;
return new SimpleReqAffiliationResumeBuilder() return new SimpleReqAffiliationResume.SimpleReqAffiliationResumeBuilder()
.id(model.getId()) .id(model.getId())
.name(model.getName()) .name(model.getName())
.stateId(model.getState_id()) .siret(model.getSiret())
.saison(model.getSaison()) .saison(model.getSaison())
.build(); .build();
} }

View File

@@ -10,7 +10,7 @@ import lombok.Data;
@RegisterForReflection @RegisterForReflection
public class TreeData { public class TreeData {
private Long id; private Long id;
private Long category; private Long poule;
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.getCategory(), model.getLevel(), model.getMatch().getId(), return new TreeData(model.getId(), model.getPoule(), model.getLevel(), model.getMatch().getId(),
fromModel(model.getLeft()), fromModel(model.getRight())); fromModel(model.getLeft()), fromModel(model.getRight()));
} }
} }

View File

@@ -33,8 +33,8 @@ public class UniteLegaleRoot {
public String etat_administratif; public String etat_administratif;
public String identifiant_association; public String identifiant_association;
public String nic_siege; public String nic_siege;
public String nom; public Object nom;
public String nom_usage; public Object nom_usage;
public int nombre_periodes; public int nombre_periodes;
public String nomenclature_activite_principale; public String nomenclature_activite_principale;
public Object prenom_1; public Object prenom_1;
@@ -67,7 +67,7 @@ public class UniteLegaleRoot {
private Object code_pays_etranger_2; private Object code_pays_etranger_2;
private String code_postal; private String code_postal;
private Object code_postal_2; private Object code_postal_2;
private String complement_adresse; private Object complement_adresse;
private Object complement_adresse2; private Object complement_adresse2;
private String date_creation; private String date_creation;
private String date_debut; private String date_debut;

View File

@@ -1,18 +0,0 @@
package fr.titionfire.ffsaf.rest.data;
import io.quarkus.runtime.annotations.RegisterForReflection;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.eclipse.microprofile.openapi.annotations.media.Schema;
@Data
@AllArgsConstructor
@RegisterForReflection
public class VerySimpleMembre {
@Schema(description = "Le nom du membre.", example = "Dupont")
private String lname = "";
@Schema(description = "Le prénom du membre.", example = "Jean")
private String fname = "";
@Schema(description = "Le numéro de licence du membre.", example = "12345")
private Integer licence;
}

View File

@@ -11,7 +11,7 @@ import org.eclipse.microprofile.openapi.annotations.media.Schema;
import org.jboss.resteasy.reactive.PartType; import org.jboss.resteasy.reactive.PartType;
@Getter @Getter
@ToString(exclude = {"status", "logo"}) @ToString
public class AffiliationRequestForm { public class AffiliationRequestForm {
@Schema(description = "L'identifiant de l'affiliation. (null si nouvelle demande d'affiliation)") @Schema(description = "L'identifiant de l'affiliation. (null si nouvelle demande d'affiliation)")
@FormParam("id") @FormParam("id")
@@ -21,9 +21,13 @@ public class AffiliationRequestForm {
@FormParam("name") @FormParam("name")
private String name = null; private String name = null;
@Schema(description = "Le numéro SIRET/RNA de l'association.", example = "12345678901234", required = true) @Schema(description = "Le numéro SIRET de l'association.", example = "12345678901234", required = true)
@FormParam("state_id") @FormParam("siret")
private String state_id = null; private Long siret = null;
@Schema(description = "Le numéro RNA de l'association. (peut être null)", example = "W123456789")
@FormParam("rna")
private String rna = null;
@Schema(description = "L'adresse de l'association.", example = "1 rue de l'exemple, 75000 Paris", required = true) @Schema(description = "L'adresse de l'association.", example = "1 rue de l'exemple, 75000 Paris", required = true)
@FormParam("adresse") @FormParam("adresse")
@@ -110,7 +114,8 @@ public class AffiliationRequestForm {
public AffiliationRequestModel toModel() { public AffiliationRequestModel toModel() {
AffiliationRequestModel model = new AffiliationRequestModel(); AffiliationRequestModel model = new AffiliationRequestModel();
model.setName(this.getName()); model.setName(this.getName());
model.setState_id(this.getState_id()); model.setSiret(this.getSiret());
model.setRNA(this.getRna());
model.setAddress(this.getAdresse()); model.setAddress(this.getAdresse());
model.setSaison(this.getSaison()); model.setSaison(this.getSaison());
model.setContact(this.getContact()); model.setContact(this.getContact());

View File

@@ -4,10 +4,12 @@ import fr.titionfire.ffsaf.utils.RoleAsso;
import jakarta.ws.rs.FormParam; import jakarta.ws.rs.FormParam;
import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.MediaType;
import lombok.Getter; import lombok.Getter;
import lombok.ToString;
import org.eclipse.microprofile.openapi.annotations.media.Schema; import org.eclipse.microprofile.openapi.annotations.media.Schema;
import org.jboss.resteasy.reactive.PartType; import org.jboss.resteasy.reactive.PartType;
@Getter @Getter
@ToString
public class AffiliationRequestSaveForm { public class AffiliationRequestSaveForm {
@Schema(description = "L'identifiant de l'affiliation.", example = "1", required = true) @Schema(description = "L'identifiant de l'affiliation.", example = "1", required = true)
@FormParam("id") @FormParam("id")
@@ -17,9 +19,13 @@ public class AffiliationRequestSaveForm {
@FormParam("name") @FormParam("name")
private String name = null; private String name = null;
@Schema(description = "Le numéro SIRET ou RNA de l'association.", example = "12345678901234", required = true) @Schema(description = "Le numéro SIRET de l'association.", example = "12345678901234", required = true)
@FormParam("state_id") @FormParam("siret")
private String state_id = null; private Long siret = null;
@Schema(description = "Le numéro RNA de l'association. (peut être null)", example = "W123456789")
@FormParam("rna")
private String rna = null;
@Schema(description = "L'adresse de l'association.", example = "1 rue de l'exemple, 75000 Paris", required = true) @Schema(description = "L'adresse de l'association.", example = "1 rue de l'exemple, 75000 Paris", required = true)
@FormParam("address") @FormParam("address")
@@ -165,38 +171,4 @@ public class AffiliationRequestSaveForm {
} }
} }
} }
@Override
public String toString() {
return "AffiliationRequestSaveForm{" +
"id=" + id +
", name='" + name + '\'' +
", state_id=" + state_id +
", address='" + address + '\'' +
", contact='" + contact + '\'' +
", status_len=" + status.length +
", logo_len=" + logo.length +
", m1_mode=" + m1_mode +
", m1_role=" + m1_role +
", m1_lincence='" + m1_lincence + '\'' +
", m1_lname='" + m1_lname + '\'' +
", m1_fname='" + m1_fname + '\'' +
", m1_email='" + m1_email + '\'' +
", m1_email_mode=" + m1_email_mode +
", m2_mode=" + m2_mode +
", m2_role=" + m2_role +
", m2_lincence='" + m2_lincence + '\'' +
", m2_lname='" + m2_lname + '\'' +
", m2_fname='" + m2_fname + '\'' +
", m2_email='" + m2_email + '\'' +
", m2_email_mode=" + m2_email_mode +
", m3_mode=" + m3_mode +
", m3_role=" + m3_role +
", m3_lincence='" + m3_lincence + '\'' +
", m3_lname='" + m3_lname + '\'' +
", m3_fname='" + m3_fname + '\'' +
", m3_email='" + m3_email + '\'' +
", m3_email_mode=" + m3_email_mode +
'}';
}
} }

View File

@@ -43,9 +43,13 @@ public class FullClubForm {
@Schema(description = "Adresse postale du club", example = "1 rue de l'exemple, 75000 Paris", required = true) @Schema(description = "Adresse postale du club", example = "1 rue de l'exemple, 75000 Paris", required = true)
private String address = null; private String address = null;
@FormParam("state_id") @FormParam("rna")
@Schema(description = "Numéro SIRET ou RNA du club", example = "12345678901234", required = true) @Schema(description = "RNA du club", example = "W123456789")
private String state_id = null; private String rna = null;
@FormParam("siret")
@Schema(description = "Numéro SIRET du club", example = "12345678901234", required = true)
private String siret = null;
@FormParam("international") @FormParam("international")
@Schema(description = "Club international", example = "false", required = true) @Schema(description = "Club international", example = "false", required = true)

View File

@@ -16,9 +16,9 @@ public class MemberPermForm {
@FormParam("safca_user") @FormParam("safca_user")
private boolean safca_user; private boolean safca_user;
@Schema(description = "Indique si le membre peut créer des compétitions.", example = "false", required = true) @Schema(description = "Indique si le membre peut créer des compétitions sur SAFCA.", example = "false", required = true)
@FormParam("create_compet") @FormParam("safca_create_compet")
private boolean create_compet; private boolean safca_create_compet;
@Schema(description = "Indique si le membre est un super administrateur SAFCA.", example = "false", required = true) @Schema(description = "Indique si le membre est un super administrateur SAFCA.", example = "false", required = true)
@FormParam("safca_super_admin") @FormParam("safca_super_admin")

View File

@@ -1,5 +1,5 @@
package fr.titionfire.ffsaf.utils; package fr.titionfire.ffsaf.utils;
public enum CompetitionSystem { public enum CompetitionSystem {
SAFCA, INTERNAL SAFCA,
} }

View File

@@ -1,12 +0,0 @@
package fr.titionfire.ffsaf.utils;
public enum RegisterMode {
FREE, CLUB_ADMIN, ADMIN, HELLOASSO
}
/*
HELLOASSO:
-> data1 = organizationSlug
-> data2 = formSlug
-> data3 = tarifs
-> data4 = errorEmail
*/

View File

@@ -31,11 +31,6 @@ 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;

View File

@@ -1,35 +0,0 @@
package fr.titionfire.ffsaf.utils;
import io.quarkus.runtime.annotations.RegisterForReflection;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@RegisterForReflection
public class TreeNode<T> {
private T data;
private TreeNode<T> left;
private TreeNode<T> right;
public TreeNode(T data) {
this(data, null, null);
}
public int death() {
int dg = 0;
int dd = 0;
if (this.right != null)
dg = this.right.death();
if (this.left != null)
dg = this.left.death();
return 1 + Math.max(dg, dd);
}
}

View File

@@ -150,16 +150,11 @@ public class Utils {
public static Uni<Response> getMediaFile(long id, String media, String dirname, public static Uni<Response> getMediaFile(long id, String media, String dirname,
Uni<?> uniBase) throws URISyntaxException { Uni<?> uniBase) throws URISyntaxException {
return getMediaFile(id, media, dirname, null, uniBase, true); return getMediaFile(id, media, dirname, null, uniBase);
}
public static Uni<Response> getMediaFileNoDefault(long id, String media, String dirname,
Uni<?> uniBase) throws URISyntaxException {
return getMediaFile(id, media, dirname, null, uniBase, false);
} }
public static Uni<Response> getMediaFile(long id, String media, String dirname, String out_filename, public static Uni<Response> getMediaFile(long id, String media, String dirname, String out_filename,
Uni<?> uniBase, boolean default_) throws URISyntaxException { Uni<?> uniBase) throws URISyntaxException {
Future<Pair<File, byte[]>> future = CompletableFuture.supplyAsync(() -> { Future<Pair<File, byte[]>> future = CompletableFuture.supplyAsync(() -> {
FilenameFilter filter = (directory, filename) -> filename.startsWith(id + "."); FilenameFilter filter = (directory, filename) -> filename.startsWith(id + ".");
File[] files = new File(media, dirname).listFiles(filter); File[] files = new File(media, dirname).listFiles(filter);
@@ -187,7 +182,6 @@ public class Utils {
return uniBase.chain(__ -> Uni.createFrom().future(future) return uniBase.chain(__ -> Uni.createFrom().future(future)
.chain(filePair -> { .chain(filePair -> {
if (filePair == null) { if (filePair == null) {
if (default_) {
return Uni.createFrom().future(future2).map(data -> { return Uni.createFrom().future(future2).map(data -> {
if (data == null) if (data == null)
return Response.noContent().build(); return Response.noContent().build();
@@ -201,11 +195,6 @@ public class Utils {
"inline; " + ((out_filename == null) ? "" : "filename=\"" + out_filename + "\"")); "inline; " + ((out_filename == null) ? "" : "filename=\"" + out_filename + "\""));
return resp.build(); return resp.build();
}); });
} else {
Response.ResponseBuilder resp = Response.status(404);
resp.header(HttpHeaders.CACHE_CONTROL, "max-age=600");
return Uni.createFrom().item(resp.build());
}
} else { } else {
return Uni.createFrom().item(() -> { return Uni.createFrom().item(() -> {
String mimeType = URLConnection.guessContentTypeFromName(filePair.getKey().getName()); String mimeType = URLConnection.guessContentTypeFromName(filePair.getKey().getName());

View File

@@ -1,207 +0,0 @@
package fr.titionfire.ffsaf.ws;
import com.fasterxml.jackson.core.JsonProcessingException;
import fr.titionfire.ffsaf.data.repository.CompetitionRepository;
import fr.titionfire.ffsaf.domain.service.CompetPermService;
import fr.titionfire.ffsaf.net2.MessageType;
import fr.titionfire.ffsaf.utils.SecurityCtx;
import fr.titionfire.ffsaf.ws.data.WelcomeInfo;
import fr.titionfire.ffsaf.ws.recv.*;
import fr.titionfire.ffsaf.ws.send.JsonUni;
import io.quarkus.hibernate.reactive.panache.common.WithSession;
import io.quarkus.security.Authenticated;
import io.quarkus.websockets.next.*;
import io.smallrye.mutiny.Multi;
import io.smallrye.mutiny.Uni;
import io.smallrye.mutiny.unchecked.Unchecked;
import jakarta.annotation.PostConstruct;
import jakarta.inject.Inject;
import jakarta.ws.rs.ForbiddenException;
import org.jboss.logging.Logger;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import static fr.titionfire.ffsaf.net2.Client_Thread.MAPPER;
@Authenticated
@WebSocket(path = "api/ws/competition/{uuid}")
public class CompetitionWS {
private static final Logger LOGGER = Logger.getLogger(CompetitionWS.class);
private static final HashMap<WebSocketConnection, HashMap<UUID, JsonUni<?>>> waitingResponse = new HashMap<>();
@Inject
RMatch rMatch;
@Inject
RCategorie rCategorie;
@Inject
RRegister rRegister;
@Inject
RCardboard rCardboard;
@Inject
SecurityCtx securityCtx;
@Inject
CompetPermService competPermService;
@Inject
CompetitionRepository competitionRepository;
HashMap<Method, Object> wsMethods = new HashMap<>();
public void getWSReceiverMethods(Class<?> clazz, Object object) {
for (Method method : clazz.getDeclaredMethods()) {
if (method.isAnnotationPresent(WSReceiver.class)) {
if (method.getParameterCount() <= 1) {
LOGGER.warnf("@WSReceiver has no parameters for method %s", method.getName());
continue;
}
if (!method.getReturnType().equals(Uni.class)) {
LOGGER.warnf("@WSReceiver has returned unexpected type %s", method.getReturnType());
continue;
}
// method.setAccessible(true);
wsMethods.put(method, object);
}
}
}
@PostConstruct
void init() {
getWSReceiverMethods(RMatch.class, rMatch);
getWSReceiverMethods(RCategorie.class, rCategorie);
getWSReceiverMethods(RRegister.class, rRegister);
getWSReceiverMethods(RCardboard.class, rCardboard);
}
@OnOpen
@WithSession
Uni<MessageOut> open(WebSocketConnection connection) {
LOGGER.infof("Opening CompetitionWS for %s", connection.pathParam("uuid"));
LOGGER.debugf("Active connections: %d", connection.getOpenConnections().size());
return competitionRepository.find("uuid", connection.pathParam("uuid")).firstResult()
.invoke(Unchecked.consumer(cm -> {
if (cm == null)
throw new ForbiddenException();
}))
.call(cm -> competPermService.hasEditPerm(securityCtx, cm).map(__ -> PermLevel.ADMIN)
.onFailure()
.recoverWithUni(competPermService.hasTablePerm(securityCtx, cm).map(__ -> PermLevel.TABLE))
.onFailure()
.recoverWithUni(competPermService.hasViewPerm(securityCtx, cm).map(__ -> PermLevel.VIEW))
.invoke(prem -> connection.userData().put(UserData.TypedKey.forString("prem"), prem.toString()))
.invoke(prem -> LOGGER.infof("Connection permission: %s", prem))
.onFailure().transform(t -> new ForbiddenException()))
.invoke(__ -> {
connection.userData().put(UserData.TypedKey.forString("subject"), securityCtx.getSubject());
waitingResponse.put(connection, new HashMap<>());
})
.map(cm -> {
WelcomeInfo welcomeInfo = new WelcomeInfo();
welcomeInfo.setName(cm.getName());
welcomeInfo.setPerm(connection.userData().get(UserData.TypedKey.forString("prem")));
return new MessageOut(UUID.randomUUID(), "welcomeInfo", MessageType.NOTIFY, welcomeInfo);
});
}
@OnClose
void close(WebSocketConnection connection) {
LOGGER.infof("Closing CompetitionWS for %s ", connection.pathParam("uuid"));
LOGGER.debugf("Active connections: %d", connection.getOpenConnections().size());
waitingResponse.remove(connection);
}
private MessageOut makeReply(MessageIn message, Object data) {
return new MessageOut(message.uuid(), message.code(), MessageType.REPLY, data);
}
private MessageOut makeError(MessageIn message, Object data) {
return new MessageOut(message.uuid(), message.code(), MessageType.ERROR, data);
}
@OnTextMessage
Multi<MessageOut> processAsync(WebSocketConnection connection, MessageIn message) {
System.out.println(message);
if (message.type() == MessageType.REPLY || message.type() == MessageType.ERROR) {
try {
JsonUni<?> jsonUni = waitingResponse.get(connection).get(message.uuid());
if (jsonUni == null) {
LOGGER.debugf("No JsonUni found for %s", message.uuid());
if (message.type() == MessageType.ERROR)
LOGGER.errorf("request %s make error %s", message.uuid(), message.data());
return null;
}
waitingResponse.get(connection).remove(message.uuid());
if (message.type() == MessageType.ERROR)
return jsonUni.castAndError(message.data()).onFailure()
.invoke(t -> LOGGER.error(t.getMessage(), t))
.replaceWith((MessageOut) null).toMulti().filter(__ -> false);
return jsonUni.castAndChain(message.data()).onFailure()
.invoke(t -> LOGGER.error(t.getMessage(), t))
.replaceWith((MessageOut) null).toMulti().filter(__ -> false);
} catch (JsonProcessingException e) {
LOGGER.warn(e.getMessage(), e);
}
}
try {
for (Map.Entry<Method, Object> entry : wsMethods.entrySet()) {
Method method = entry.getKey();
WSReceiver wsReceiver = method.getAnnotation(WSReceiver.class);
PermLevel perm = PermLevel.valueOf(connection.userData().get(UserData.TypedKey.forString("prem")));
if (wsReceiver.code().equalsIgnoreCase(message.code())) {
if (wsReceiver.permission().ordinal() > perm.ordinal())
return Uni.createFrom().item(makeError(message, "Permission denied")).toMulti();
return ((Uni<?>) method.invoke(entry.getValue(), connection,
MAPPER.treeToValue(message.data(), method.getParameterTypes()[1])))
.map(o -> makeReply(message, o))
.onFailure()
.recoverWithItem(t -> {
LOGGER.error(t.getMessage(), t);
return makeError(message, t.getMessage());
}).toMulti()
.filter(__ -> message.type() == MessageType.REQUEST);
}
}
return Uni.createFrom().item(makeError(message, "No receiver method found")).toMulti();
} catch (IllegalAccessException | InvocationTargetException | JsonProcessingException e) {
LOGGER.warn(e.getMessage(), e);
return Uni.createFrom().item(makeError(message, e.getMessage())).toMulti();
}
// return Uni.createFrom().item(new Message<>(message.uuid(), message.code(), MessageType.REPLY, "ko"));
}
public static Uni<Void> sendNotifyToOtherEditor(WebSocketConnection connection, String code, Object data) {
String uuid = connection.pathParam("uuid");
List<Uni<Void>> queue = new ArrayList<>();
queue.add(Uni.createFrom().voidItem()); // For avoid empty queue
connection.getOpenConnections().forEach(c -> {
if (uuid.equals(c.pathParam("uuid"))) {
queue.add(c.sendText(new MessageOut(UUID.randomUUID(), code, MessageType.NOTIFY, data)));
}
});
return Uni.join().all(queue).andCollectFailures().onFailure().recoverWithNull().replaceWithVoid();
}
@OnError
Uni<Void> error(WebSocketConnection connection, ForbiddenException t) {
return connection.close(CloseReason.INTERNAL_SERVER_ERROR);
//return "forbidden: " + securityCtx.getSubject();
}
}

View File

@@ -1,12 +0,0 @@
package fr.titionfire.ffsaf.ws;
import com.fasterxml.jackson.databind.JsonNode;
import fr.titionfire.ffsaf.net2.MessageType;
import io.quarkus.runtime.annotations.RegisterForReflection;
import java.util.UUID;
@RegisterForReflection
public record MessageIn (UUID uuid, String code, MessageType type, JsonNode data){
}

View File

@@ -1,11 +0,0 @@
package fr.titionfire.ffsaf.ws;
import fr.titionfire.ffsaf.net2.MessageType;
import io.quarkus.runtime.annotations.RegisterForReflection;
import java.util.UUID;
@RegisterForReflection
public record MessageOut(UUID uuid, String code, MessageType type, Object data){
}

View File

@@ -1,8 +0,0 @@
package fr.titionfire.ffsaf.ws;
public enum PermLevel {
NONE,
VIEW,
TABLE,
ADMIN,
}

View File

@@ -1,11 +0,0 @@
package fr.titionfire.ffsaf.ws.data;
import io.quarkus.runtime.annotations.RegisterForReflection;
import lombok.Data;
@Data
@RegisterForReflection
public class WelcomeInfo {
private String name;
private String perm;
}

View File

@@ -1,128 +0,0 @@
package fr.titionfire.ffsaf.ws.recv;
import fr.titionfire.ffsaf.data.model.CardboardModel;
import fr.titionfire.ffsaf.data.model.MatchModel;
import fr.titionfire.ffsaf.data.repository.CardboardRepository;
import fr.titionfire.ffsaf.data.repository.MatchRepository;
import fr.titionfire.ffsaf.domain.entity.CardboardEntity;
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
import fr.titionfire.ffsaf.rest.exception.DNotFoundException;
import fr.titionfire.ffsaf.ws.PermLevel;
import fr.titionfire.ffsaf.ws.send.SSCardboard;
import io.quarkus.hibernate.reactive.panache.Panache;
import io.quarkus.hibernate.reactive.panache.common.WithSession;
import io.quarkus.runtime.annotations.RegisterForReflection;
import io.quarkus.websockets.next.WebSocketConnection;
import io.smallrye.mutiny.Uni;
import io.smallrye.mutiny.unchecked.Unchecked;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import lombok.Data;
import java.util.Objects;
@WithSession
@ApplicationScoped
@RegisterForReflection
public class RCardboard {
@Inject
MatchRepository matchRepository;
@Inject
CardboardRepository cardboardRepository;
private Uni<MatchModel> getById(long id, WebSocketConnection connection) {
return matchRepository.findById(id)
.invoke(Unchecked.consumer(o -> {
if (o == null)
throw new DNotFoundException("Matche non trouver");
if (!o.getCategory().getCompet().getUuid().equals(connection.pathParam("uuid")))
throw new DForbiddenException("Permission denied");
}));
}
@WSReceiver(code = "sendCardboardChange", permission = PermLevel.TABLE)
public Uni<Void> sendCardboardChange(WebSocketConnection connection, SendCardboard card) {
return getById(card.matchId, connection)
.chain(matchModel -> cardboardRepository.find("(comb.id = ?1 OR guestComb.id = ?2) AND match.id = ?3",
card.combId, card.combId * -1, card.matchId).firstResult()
.chain(model -> {
if (model != null) {
model.setRed(model.getRed() + card.red);
model.setYellow(model.getYellow() + card.yellow);
return Panache.withTransaction(() -> cardboardRepository.persist(model));
}
CardboardModel cardboardModel = new CardboardModel();
cardboardModel.setCompet(matchModel.getCategory().getCompet());
cardboardModel.setMatch(matchModel);
cardboardModel.setRed(card.red);
cardboardModel.setYellow(card.yellow);
cardboardModel.setComb(null);
cardboardModel.setGuestComb(null);
if (card.combId >= 0) {
if (matchModel.getC1_id() != null && matchModel.getC1_id().getId() == card.combId)
cardboardModel.setComb(matchModel.getC1_id());
if (matchModel.getC2_id() != null && matchModel.getC2_id().getId() == card.combId)
cardboardModel.setComb(matchModel.getC2_id());
} else {
if (matchModel.getC1_guest() != null && matchModel.getC1_guest()
.getId() == card.combId * -1)
cardboardModel.setGuestComb(matchModel.getC1_guest());
if (matchModel.getC2_guest() != null && matchModel.getC2_guest()
.getId() == card.combId * -1)
cardboardModel.setGuestComb(matchModel.getC2_guest());
}
if (cardboardModel.getComb() == null && cardboardModel.getGuestComb() == null)
return Uni.createFrom().nullItem();
return Panache.withTransaction(() -> cardboardRepository.persist(cardboardModel));
}))
.call(model -> SSCardboard.sendCardboard(connection, CardboardEntity.fromModel(model)))
.replaceWithVoid();
}
@WSReceiver(code = "getCardboardWithoutThis", permission = PermLevel.VIEW)
public Uni<CardboardAllMatch> getCardboardWithoutThis(WebSocketConnection connection, Long matchId) {
return getById(matchId, connection)
.chain(matchModel -> cardboardRepository.list("compet = ?1 AND match != ?2", matchModel.getCategory().getCompet(), matchModel)
.map(models -> {
CardboardAllMatch out = new CardboardAllMatch();
models.stream().filter(c -> (matchModel.getC1_id() != null
&& Objects.equals(c.getComb(), matchModel.getC1_id()))
|| (matchModel.getC1_guest() != null
&& Objects.equals(c.getGuestComb(), matchModel.getC1_guest())))
.forEach(c -> {
out.c1_yellow += c.getYellow();
out.c1_red += c.getRed();
});
models.stream().filter(c -> (matchModel.getC2_id() != null
&& Objects.equals(c.getComb(), matchModel.getC2_id()))
|| (matchModel.getC2_guest() != null
&& Objects.equals(c.getGuestComb(), matchModel.getC2_guest())))
.forEach(c -> {
out.c2_yellow += c.getYellow();
out.c2_red += c.getRed();
});
return out;
}));
}
@RegisterForReflection
public record SendCardboard(long matchId, long combId, int yellow, int red) {
}
@Data
@RegisterForReflection
public static class CardboardAllMatch {
int c1_yellow = 0;
int c1_red = 0;
int c2_yellow = 0;
int c2_red = 0;
}
}

View File

@@ -1,229 +0,0 @@
package fr.titionfire.ffsaf.ws.recv;
import fr.titionfire.ffsaf.data.model.CategoryModel;
import fr.titionfire.ffsaf.data.model.MatchModel;
import fr.titionfire.ffsaf.data.model.TreeModel;
import fr.titionfire.ffsaf.data.repository.CategoryRepository;
import fr.titionfire.ffsaf.data.repository.CompetitionRepository;
import fr.titionfire.ffsaf.data.repository.MatchRepository;
import fr.titionfire.ffsaf.data.repository.TreeRepository;
import fr.titionfire.ffsaf.domain.entity.MatchEntity;
import fr.titionfire.ffsaf.domain.entity.TreeEntity;
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
import fr.titionfire.ffsaf.rest.exception.DNotFoundException;
import fr.titionfire.ffsaf.utils.TreeNode;
import fr.titionfire.ffsaf.ws.PermLevel;
import fr.titionfire.ffsaf.ws.send.SSCategorie;
import io.quarkus.hibernate.reactive.panache.Panache;
import io.quarkus.hibernate.reactive.panache.common.WithSession;
import io.quarkus.runtime.annotations.RegisterForReflection;
import io.quarkus.websockets.next.WebSocketConnection;
import io.smallrye.mutiny.Uni;
import io.smallrye.mutiny.unchecked.Unchecked;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import lombok.Data;
import org.hibernate.reactive.mutiny.Mutiny;
import java.util.ArrayList;
import java.util.List;
@WithSession
@ApplicationScoped
@RegisterForReflection
public class RCategorie {
//private static final Logger LOGGER = Logger.getLogger(RCategorie.class);
@Inject
CategoryRepository categoryRepository;
@Inject
CompetitionRepository competitionRepository;
@Inject
MatchRepository matchRepository;
@Inject
TreeRepository treeRepository;
private Uni<CategoryModel> getById(long id, WebSocketConnection connection) {
return categoryRepository.findById(id)
.invoke(Unchecked.consumer(o -> {
if (o == null)
throw new DNotFoundException("Catégorie non trouver");
if (!o.getCompet().getUuid().equals(connection.pathParam("uuid")))
throw new DForbiddenException("Permission denied");
}));
}
@WSReceiver(code = "getAllCategory", permission = PermLevel.VIEW)
public Uni<List<JustCategorie>> getAllCategory(WebSocketConnection connection, Object o) {
return categoryRepository.list("compet.uuid", connection.pathParam("uuid"))
.map(category -> category.stream().map(JustCategorie::from).toList());
}
@WSReceiver(code = "getFullCategory", permission = PermLevel.VIEW)
public Uni<FullCategory> getFullCategory(WebSocketConnection connection, Long id) {
FullCategory fullCategory = new FullCategory();
return getById(id, connection)
.invoke(cat -> {
fullCategory.setId(cat.getId());
fullCategory.setName(cat.getName());
fullCategory.setLiceName(cat.getLiceName());
fullCategory.setType(cat.getType());
})
.call(cat -> Mutiny.fetch(cat.getMatchs())
.map(matchModels -> matchModels.stream().filter(o -> o.getCategory_ord() >= 0)
.map(MatchEntity::fromModel).toList())
.invoke(fullCategory::setMatches))
.call(cat -> treeRepository.list("category = ?1 AND level != 0", cat.getId())
.map(treeModels -> treeModels.stream().map(TreeEntity::fromModel).toList())
.invoke(fullCategory::setTrees))
.map(__ -> fullCategory);
}
@WSReceiver(code = "createCategory", permission = PermLevel.ADMIN)
public Uni<Long> createCategory(WebSocketConnection connection, JustCategorie categorie) {
return competitionRepository.find("uuid", connection.pathParam("uuid")).firstResult()
.chain(cm -> {
CategoryModel categoryModel = new CategoryModel();
categoryModel.setName(categorie.name);
categoryModel.setCompet(cm);
categoryModel.setMatchs(new ArrayList<>());
categoryModel.setTree(new ArrayList<>());
categoryModel.setType(categorie.type);
categoryModel.setLiceName(categorie.liceName);
return categoryRepository.create(categoryModel);
})
.call(cat -> SSCategorie.sendAddCategory(connection, cat))
.map(CategoryModel::getId);
}
@WSReceiver(code = "updateCategory", permission = PermLevel.ADMIN)
public Uni<Void> updateCategory(WebSocketConnection connection, JustCategorie categorie) {
return getById(categorie.id, connection)
.chain(cat -> {
cat.setName(categorie.name);
cat.setLiceName(categorie.liceName);
cat.setType(categorie.type);
return Panache.withTransaction(() -> categoryRepository.persist(cat));
})
.call(cat -> {
Uni<Long> uni = Uni.createFrom().nullItem();
if ((categorie.type() & 1) == 0)
uni = uni.chain(__ -> matchRepository.delete("category = ?1 AND category_ord >= 0", cat));
if ((categorie.type() & 2) == 0) {
uni = uni.chain(__ -> treeRepository.delete("category = ?1", cat.getId()))
.chain(__ -> matchRepository.delete("category = ?1 AND category_ord = -42", cat));
}
return uni;
})
.call(cat -> SSCategorie.sendCategory(connection, cat))
.replaceWithVoid();
}
private Uni<TreeModel> getOrCreateTreeNode(Long id, Long categorieId, int level) {
if (id == null) {
TreeModel treeModel = new TreeModel();
treeModel.setCategory(categorieId);
treeModel.setLevel(level);
return Panache.withTransaction(() -> treeRepository.persistAndFlush(treeModel));
} else {
return Panache.withTransaction(
() -> treeRepository.find("match.id = ?1", id).firstResult()
.invoke(t -> t.setLevel(level))
.chain(t -> treeRepository.persist(t)));
}
}
private Uni<Void> updateNode(TreeNode<Long> current, TreeModel currentTreeModel, CategoryModel category) {
return Uni.createFrom().item(currentTreeModel)
.chain(t -> {
if (current.getData() != null)
return Uni.createFrom().item(t);
MatchModel matchModel = new MatchModel();
matchModel.setCategory(category);
matchModel.setCategory_ord(-42);
matchModel.setEnd(false);
return matchRepository.create(matchModel).onItem()
.invoke(t::setMatch)
.chain(__ -> treeRepository.persistAndFlush(t));
})
.call(t -> {
if (current.getLeft() == null)
return Uni.createFrom().item(t);
return getOrCreateTreeNode(current.getLeft().getData(), category.getId(), 0)
.invoke(t::setLeft)
.call(treeModel -> updateNode(current.getLeft(), treeModel, category));
})
.call(t -> {
if (current.getRight() == null)
return Uni.createFrom().item(t);
return getOrCreateTreeNode(current.getRight().getData(), category.getId(), 0)
.invoke(t::setRight)
.call(treeModel -> updateNode(current.getRight(), treeModel, category));
})
.chain(t -> treeRepository.persist(t))
.replaceWithVoid();
}
@WSReceiver(code = "updateTrees", permission = PermLevel.ADMIN)
public Uni<Void> updateTrees(WebSocketConnection connection, TreeUpdate data) {
return getById(data.categoryId, connection)
.call(cat -> treeRepository.update("level = -1, left = NULL, right = NULL WHERE category = ?1",
cat.getId()))
.call(cat -> {
Uni<?> uni = Uni.createFrom().voidItem();
for (int i = 0; i < data.trees().size(); i++) {
TreeNode<Long> current = data.trees().get(i);
int finalI = i;
uni = uni.chain(() -> getOrCreateTreeNode(current.getData(), cat.getId(), finalI + 1)
.call(treeModel -> updateNode(current, treeModel, cat)));
}
Uni<?> finalUni = uni;
return Panache.withTransaction(() -> finalUni);
})
.call(cat -> treeRepository.list("category = ?1 AND level = -1", cat.getId())
.map(l -> l.stream().map(o -> o.getMatch().getId()).toList())
.call(__ -> treeRepository.delete("category = ?1 AND level = -1", cat.getId()))
.call(ids -> matchRepository.delete("id IN ?1", ids)))
.call(__ -> treeRepository.flush())
.call(cat -> treeRepository.list("category = ?1 AND level != 0", cat.getId())
.map(treeModels -> treeModels.stream().map(TreeEntity::fromModel).toList())
.chain(trees -> SSCategorie.sendTreeCategory(connection, trees)))
.replaceWithVoid();
}
@RegisterForReflection
public record JustCategorie(long id, String name, int type, String liceName) {
public static JustCategorie from(CategoryModel m) {
return new JustCategorie(m.getId(), m.getName(), m.getType(), m.getLiceName());
}
}
@RegisterForReflection
public record TreeUpdate(long categoryId, List<TreeNode<Long>> trees) {
}
@Data
@RegisterForReflection
public static class FullCategory {
long id;
String name;
int type;
String liceName;
List<TreeEntity> trees = null;
List<MatchEntity> matches;
}
}

View File

@@ -1,346 +0,0 @@
package fr.titionfire.ffsaf.ws.recv;
import fr.titionfire.ffsaf.data.model.*;
import fr.titionfire.ffsaf.data.repository.*;
import fr.titionfire.ffsaf.domain.entity.MatchEntity;
import fr.titionfire.ffsaf.domain.entity.TreeEntity;
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
import fr.titionfire.ffsaf.rest.exception.DNotFoundException;
import fr.titionfire.ffsaf.utils.ScoreEmbeddable;
import fr.titionfire.ffsaf.ws.PermLevel;
import fr.titionfire.ffsaf.ws.send.SSMatch;
import io.quarkus.hibernate.reactive.panache.Panache;
import io.quarkus.hibernate.reactive.panache.common.WithSession;
import io.quarkus.panache.common.Sort;
import io.quarkus.runtime.annotations.RegisterForReflection;
import io.quarkus.websockets.next.WebSocketConnection;
import io.smallrye.mutiny.Uni;
import io.smallrye.mutiny.unchecked.Unchecked;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import org.jboss.logging.Logger;
import java.util.*;
import java.util.stream.Stream;
@WithSession
@ApplicationScoped
@RegisterForReflection
public class RMatch {
private static final Logger LOGGER = Logger.getLogger(RMatch.class);
@Inject
MatchRepository matchRepository;
@Inject
CombRepository combRepository;
@Inject
CategoryRepository categoryRepository;
@Inject
TreeRepository treeRepository;
@Inject
CompetitionGuestRepository competitionGuestRepository;
private Uni<MatchModel> getById(long id, WebSocketConnection connection) {
return matchRepository.findById(id)
.invoke(Unchecked.consumer(o -> {
if (o == null)
throw new DNotFoundException("Matche non trouver");
if (!o.getCategory().getCompet().getUuid().equals(connection.pathParam("uuid")))
throw new DForbiddenException("Permission denied");
}));
}
private Uni<MatchModel> creatMatch(CategoryModel categoryModel, AddMatch m) {
return Uni.createFrom().item(() -> {
MatchModel matchModel = new MatchModel();
matchModel.setCategory(categoryModel);
matchModel.setCategory_ord(m.categorie_ord);
matchModel.setEnd(false);
matchModel.setPoule(m.poule);
return matchModel;
})
.call(mm -> m.c1() >= 0 ?
combRepository.findById(m.c1()).invoke(mm::setC1_id) :
competitionGuestRepository.findById(m.c1() * -1).invoke(mm::setC1_guest))
.call(mm -> m.c2() >= 0 ?
combRepository.findById(m.c2()).invoke(mm::setC2_id) :
competitionGuestRepository.findById(m.c2() * -1).invoke(mm::setC2_guest));
}
@WSReceiver(code = "addMatch", permission = PermLevel.ADMIN)
public Uni<Void> addMatch(WebSocketConnection connection, AddMatch m) {
return categoryRepository.findById(m.categorie)
.invoke(Unchecked.consumer(o -> {
if (o == null)
throw new DNotFoundException("Catégorie non trouver");
if (!o.getCompet().getUuid().equals(connection.pathParam("uuid")))
throw new DForbiddenException("Permission denied");
}))
.chain(categoryModel -> creatMatch(categoryModel, m))
.chain(mm -> Panache.withTransaction(() -> matchRepository.create(mm)))
.call(mm -> SSMatch.sendMatch(connection, MatchEntity.fromModel(mm)))
.replaceWithVoid();
}
@WSReceiver(code = "updateMatchComb", permission = PermLevel.ADMIN)
public Uni<Void> updateMatchComb(WebSocketConnection connection, MatchComb match) {
return getById(match.id(), connection)
.call(mm -> match.c1() != null ?
match.c1() >= 0 ?
combRepository.findById(match.c1()).invoke(model -> {
mm.setC1_id(model);
mm.setC1_guest(null);
}) :
competitionGuestRepository.findById(match.c1() * -1).invoke(model -> {
mm.setC1_id(null);
mm.setC1_guest(model);
}) :
Uni.createFrom().nullItem().invoke(__ -> {
mm.setC1_id(null);
mm.setC1_guest(null);
}))
.call(mm -> match.c2() != null ?
match.c2() >= 0 ?
combRepository.findById(match.c2()).invoke(model -> {
mm.setC2_id(model);
mm.setC2_guest(null);
}) :
competitionGuestRepository.findById(match.c2() * -1).invoke(model -> {
mm.setC2_id(null);
mm.setC2_guest(model);
}) :
Uni.createFrom().nullItem().invoke(__ -> {
mm.setC2_id(null);
mm.setC2_guest(null);
}))
.chain(mm -> Panache.withTransaction(() -> matchRepository.persist(mm)))
.call(mm -> SSMatch.sendMatch(connection, MatchEntity.fromModel(mm)))
.replaceWithVoid();
}
@WSReceiver(code = "updateMatchOrder", permission = PermLevel.ADMIN)
public Uni<Void> updateMatchComb(WebSocketConnection connection, MatchOrder order) {
return getById(order.id(), connection)
.call(m -> matchRepository.update(
"category_ord = category_ord + 1 WHERE category_ord >= ?1 AND category_ord < ?2", order.pos,
m.getCategory_ord()))
.call(m -> matchRepository.update(
"category_ord = category_ord - 1 WHERE category_ord <= ?1 AND category_ord > ?2", order.pos,
m.getCategory_ord()))
.invoke(m -> m.setCategory_ord(order.pos))
.call(m -> Panache.withTransaction(() -> matchRepository.persist(m)))
.call(mm -> SSMatch.sendMatchOrder(connection, order))
.replaceWithVoid();
}
@WSReceiver(code = "updateMatchScore", permission = PermLevel.TABLE)
public Uni<Void> updateMatchScore(WebSocketConnection connection, MatchScore score) {
return getById(score.matchId(), connection)
.chain(matchModel -> {
int old_win = matchModel.win();
Optional<ScoreEmbeddable> optional = matchModel.getScores().stream()
.filter(s -> s.getN_round() == score.n_round()).findAny();
boolean b = score.s1() != -1000 || score.s2() != -1000;
if (optional.isPresent()) {
if (b) {
optional.get().setS1(score.s1());
optional.get().setS2(score.s2());
} else {
matchModel.getScores().remove(optional.get());
}
} else if (b) {
matchModel.getScores().add(new ScoreEmbeddable(score.n_round(), score.s1(), score.s2()));
}
return Panache.withTransaction(() -> matchRepository.persist(matchModel))
.call(mm -> {
if (mm.isEnd() && mm.win() != old_win && mm.getCategory_ord() == -42) {
return updateEndAndTree(mm, new ArrayList<>())
.call(l -> SSMatch.sendMatch(connection, l));
}
return Uni.createFrom().nullItem();
});
})
.call(mm -> SSMatch.sendMatch(connection, MatchEntity.fromModel(mm)))
.replaceWithVoid();
}
@WSReceiver(code = "updateMatchEnd", permission = PermLevel.TABLE)
public Uni<Void> updateMatchEnd(WebSocketConnection connection, MatchEnd matchEnd) {
List<MatchEntity> toSend = new ArrayList<>();
return getById(matchEnd.matchId(), connection)
.chain(mm -> {
if (mm.getCategory_ord() == -42 && mm.win() == 0) { // Tournois
mm.setDate(null);
mm.setEnd(false);
} else {
mm.setDate((matchEnd.end) ? new Date() : null);
mm.setEnd(matchEnd.end);
}
return Panache.withTransaction(() -> matchRepository.persist(mm));
})
.invoke(mm -> toSend.add(MatchEntity.fromModel(mm)))
.chain(mm -> updateEndAndTree(mm, toSend))
.call(__ -> SSMatch.sendMatch(connection, toSend))
.replaceWithVoid();
}
private Uni<List<MatchEntity>> updateEndAndTree(MatchModel mm, List<MatchEntity> toSend) {
return (mm.getCategory_ord() != -42) ?
Uni.createFrom().item(toSend) :
treeRepository.list("category = ?1 AND level != 0", Sort.ascending("level"), mm.getCategory().getId())
.chain(treeModels -> {
List<TreeModel> node = treeModels.stream().flatMap(t -> t.flat().stream()).toList();
List<TreeEntity> trees = treeModels.stream().map(TreeEntity::fromModel).toList();
for (int i = 0; i < trees.size() - 1; i++) {
TreeEntity.setAssociated(trees.get(i), trees.get(i + 1));
}
TreeEntity root = trees.stream()
.filter(t -> t.getMatchNode(mm.getId()) != null)
.findFirst()
.orElseThrow();
TreeEntity currentNode = root.getMatchNode(mm.getId());
if (currentNode == null) {
LOGGER.error(
"currentNode is empty for " + mm.getId() + " in " + mm.getCategory().getId());
return Uni.createFrom().voidItem();
}
TreeEntity parent = TreeEntity.getParent(root, currentNode);
if (parent == null) {
LOGGER.error("parent is empty for " + mm.getId() + " in " + mm.getCategory().getId());
return Uni.createFrom().voidItem();
}
int w = mm.win();
MembreModel toSetWin = null;
MembreModel toSetLose = null;
CompetitionGuestModel toSetWinGuest = null;
CompetitionGuestModel toSetLoseGuest = null;
if (mm.isEnd() && w != 0) {
toSetWin = (w > 0) ? mm.getC1_id() : mm.getC2_id();
toSetLose = (w > 0) ? mm.getC2_id() : mm.getC1_id();
toSetWinGuest = (w > 0) ? mm.getC1_guest() : mm.getC2_guest();
toSetLoseGuest = (w > 0) ? mm.getC2_guest() : mm.getC1_guest();
}
MatchModel modelWin = node.stream()
.filter(n -> Objects.equals(n.getId(), parent.getId()))
.findAny()
.map(TreeModel::getMatch)
.orElseThrow();
MatchModel modelLose = (parent.getAssociatedNode() == null) ? null : node.stream()
.filter(n -> Objects.equals(n.getId(), parent.getAssociatedNode().getId()))
.findAny()
.map(TreeModel::getMatch)
.orElseThrow();
if (currentNode.equals(parent.getLeft())) {
modelWin.setC1_id(toSetWin);
modelWin.setC1_guest(toSetWinGuest);
if (modelLose != null) {
modelLose.setC1_id(toSetLose);
modelLose.setC1_guest(toSetLoseGuest);
}
} else if (currentNode.equals(parent.getRight())) {
modelWin.setC2_id(toSetWin);
modelWin.setC2_guest(toSetWinGuest);
if (modelLose != null) {
modelLose.setC2_id(toSetLose);
modelLose.setC2_guest(toSetLoseGuest);
}
}
return Panache.withTransaction(() -> matchRepository.persist(modelWin)
.invoke(mm2 -> toSend.add(MatchEntity.fromModel(mm2)))
.call(__ -> modelLose == null ? Uni.createFrom().nullItem() :
matchRepository.persist(modelLose)
.invoke(mm2 -> toSend.add(MatchEntity.fromModel(mm2)))
)
.replaceWithVoid());
})
.map(__ -> toSend);
}
@WSReceiver(code = "deleteMatch", permission = PermLevel.ADMIN)
public Uni<Void> deleteMatch(WebSocketConnection connection, Long idMatch) {
return getById(idMatch, connection)
.chain(matchModel -> Panache.withTransaction(() -> matchRepository.delete(matchModel)))
.call(__ -> SSMatch.sendDeleteMatch(connection, idMatch))
.replaceWithVoid();
}
@WSReceiver(code = "recalculateMatch", permission = PermLevel.ADMIN)
public Uni<Void> recalculateMatch(WebSocketConnection connection, RecalculateMatch data) {
ArrayList<MatchEntity> matches = new ArrayList<>();
return categoryRepository.findById(data.categorie)
.invoke(Unchecked.consumer(o -> {
if (o == null)
throw new DNotFoundException("Catégorie non trouver");
if (!o.getCompet().getUuid().equals(connection.pathParam("uuid")))
throw new DForbiddenException("Permission denied");
}))
.call(cm -> matchRepository.delete("id IN ?1 AND category = ?2", data.matchesToRemove, cm)
.call(__ -> SSMatch.sendDeleteMatch(connection, data.matchesToRemove)))
.call(cm -> matchRepository.list("id IN ?1 AND category = ?2",
Stream.concat(data.matchOrderToUpdate.keySet().stream(),
data.matchPouleToUpdate.keySet().stream())
.distinct().toList(), cm)
.invoke(matchModels -> matchModels.forEach(model -> {
if (data.matchPouleToUpdate.containsKey(model.getId()))
model.setPoule(data.matchPouleToUpdate.get(model.getId()));
if (data.matchOrderToUpdate.containsKey(model.getId()))
model.setCategory_ord(data.matchOrderToUpdate.get(model.getId()));
}))
.call(mm -> Panache.withTransaction(() -> matchRepository.persist(mm)))
.invoke(mm -> matches.addAll(mm.stream().map(MatchEntity::fromModel).toList()))
)
.chain(categoryModel -> {
Uni<List<MatchModel>> uni = Uni.createFrom().item(new ArrayList<>());
for (AddMatch match : data.newMatch)
uni = uni.call(l -> creatMatch(categoryModel, match).invoke(l::add));
return uni;
}
)
.chain(mm -> Panache.withTransaction(() -> matchRepository.create(mm))
.invoke(__ -> matches.addAll(mm.stream().map(MatchEntity::fromModel).toList())))
.call(__ -> SSMatch.sendMatch(connection, matches))
.replaceWithVoid();
}
@RegisterForReflection
public record MatchComb(long id, Long c1, Long c2) {
}
@RegisterForReflection
public record MatchScore(long matchId, int n_round, int s1, int s2) {
}
@RegisterForReflection
public record MatchEnd(long matchId, boolean end) {
}
@RegisterForReflection
public record MatchOrder(long id, long pos) {
}
@RegisterForReflection
public record AddMatch(long categorie, long categorie_ord, char poule, long c1, long c2) {
}
public record RecalculateMatch(long categorie, List<AddMatch> newMatch, HashMap<Long, Integer> matchOrderToUpdate,
HashMap<Long, Character> matchPouleToUpdate, List<Long> matchesToRemove) {
}
}

View File

@@ -1,37 +0,0 @@
package fr.titionfire.ffsaf.ws.recv;
import fr.titionfire.ffsaf.data.repository.CompetitionRepository;
import fr.titionfire.ffsaf.domain.entity.CombEntity;
import fr.titionfire.ffsaf.ws.PermLevel;
import io.quarkus.hibernate.reactive.panache.common.WithSession;
import io.quarkus.runtime.annotations.RegisterForReflection;
import io.quarkus.websockets.next.WebSocketConnection;
import io.smallrye.mutiny.Uni;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import org.hibernate.reactive.mutiny.Mutiny;
import java.util.ArrayList;
import java.util.List;
@WithSession
@ApplicationScoped
@RegisterForReflection
public class RRegister {
@Inject
CompetitionRepository competitionRepository;
@WSReceiver(code = "getRegister", permission = PermLevel.TABLE)
public Uni<List<CombEntity>> getRegister(WebSocketConnection connection, Object o) {
return competitionRepository.find("uuid", connection.pathParam("uuid")).firstResult()
.call(cm -> Mutiny.fetch(cm.getInsc()))
.call(cm -> Mutiny.fetch(cm.getGuests()))
.map(cm -> {
ArrayList<CombEntity> combEntities = new ArrayList<>();
combEntities.addAll(cm.getInsc().stream().map(CombEntity::fromModel).toList());
combEntities.addAll(cm.getGuests().stream().map(CombEntity::fromModel).toList());
return combEntities;
});
}
}

View File

@@ -1,17 +0,0 @@
package fr.titionfire.ffsaf.ws.recv;
import fr.titionfire.ffsaf.ws.PermLevel;
import io.quarkus.runtime.annotations.RegisterForReflection;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@RegisterForReflection
@Retention(RetentionPolicy.RUNTIME)
public @interface WSReceiver {
String code();
PermLevel permission() default PermLevel.VIEW;
}

View File

@@ -1,33 +0,0 @@
package fr.titionfire.ffsaf.ws.send;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import io.quarkus.runtime.annotations.RegisterForReflection;
import io.smallrye.mutiny.Uni;
import io.smallrye.mutiny.unchecked.Unchecked;
import java.util.function.Function;
import static fr.titionfire.ffsaf.net2.Client_Thread.MAPPER;
@RegisterForReflection
public class JsonUni<T> {
private final Class<T> clazz;
private final Function<? super T, Uni<?>> mapper;
public JsonUni(Class<T> clazz, Function<? super T, Uni<?>> mapper) {
this.clazz = clazz;
this.mapper = mapper;
}
public Uni<?> castAndChain(JsonNode message) throws JsonProcessingException {
return Uni.createFrom().item(MAPPER.treeToValue(message, clazz)).chain(mapper);
}
public Uni<?> castAndError(JsonNode message) throws JsonProcessingException {
return Uni.createFrom().item((T) null).invoke(Unchecked.consumer(__ -> {
throw new WSClientError(MAPPER.treeToValue(message, String.class));
})).chain(mapper);
}
}

View File

@@ -1,53 +0,0 @@
package fr.titionfire.ffsaf.ws.send;
import fr.titionfire.ffsaf.data.model.CompetitionGuestModel;
import fr.titionfire.ffsaf.data.model.RegisterModel;
import fr.titionfire.ffsaf.domain.entity.CombEntity;
import fr.titionfire.ffsaf.net2.MessageType;
import fr.titionfire.ffsaf.ws.CompetitionWS;
import fr.titionfire.ffsaf.ws.MessageOut;
import fr.titionfire.ffsaf.ws.PermLevel;
import io.quarkus.runtime.annotations.RegisterForReflection;
import io.quarkus.websockets.next.OpenConnections;
import io.quarkus.websockets.next.UserData;
import io.smallrye.mutiny.Uni;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import java.util.List;
import java.util.UUID;
@ApplicationScoped
@RegisterForReflection
public class SRegister {
@SuppressWarnings("CdiInjectionPointsInspection")
@Inject
OpenConnections connections;
public Uni<Void> sendRegister(String uuid, RegisterModel registerModel) {
return send(uuid, "sendRegister", CombEntity.fromModel(registerModel));
}
public Uni<Void> sendRegister(String uuid, CompetitionGuestModel model) {
return send(uuid, "sendRegister", CombEntity.fromModel(model));
}
public Uni<Void> sendRegisterRemove(String uuid, Long combId) {
return send(uuid, "sendRegisterRemove", combId);
}
public Uni<Void> send(String uuid, String code, Object data) {
List<Uni<Void>> queue = connections.findByEndpointId(CompetitionWS.class.getCanonicalName()).stream()
.filter(c -> c.pathParam("uuid").equals(uuid) && PermLevel.valueOf(
c.userData().get(UserData.TypedKey.forString("prem"))).ordinal() >= PermLevel.TABLE.ordinal())
.map(c -> c.sendText(
new MessageOut(UUID.randomUUID(), code, MessageType.NOTIFY, data)))
.toList();
if (queue.isEmpty())
return Uni.createFrom().voidItem();
return Uni.join().all(queue).andCollectFailures().replaceWithVoid();
}
}

View File

@@ -1,13 +0,0 @@
package fr.titionfire.ffsaf.ws.send;
import fr.titionfire.ffsaf.domain.entity.CardboardEntity;
import fr.titionfire.ffsaf.ws.CompetitionWS;
import io.quarkus.websockets.next.WebSocketConnection;
import io.smallrye.mutiny.Uni;
public class SSCardboard {
public static Uni<Void> sendCardboard(WebSocketConnection connection, CardboardEntity cardboardEntity) {
return CompetitionWS.sendNotifyToOtherEditor(connection, "sendCardboard", cardboardEntity);
}
}

View File

@@ -1,33 +0,0 @@
package fr.titionfire.ffsaf.ws.send;
import fr.titionfire.ffsaf.data.model.CategoryModel;
import fr.titionfire.ffsaf.domain.entity.TreeEntity;
import fr.titionfire.ffsaf.ws.CompetitionWS;
import fr.titionfire.ffsaf.ws.recv.RCategorie;
import io.quarkus.websockets.next.WebSocketConnection;
import io.smallrye.mutiny.Uni;
import java.util.List;
public class SSCategorie {
public static Uni<Void> sendAddCategory(WebSocketConnection connection, CategoryModel category) {
return SSCategorie.sendAddCategory(connection, RCategorie.JustCategorie.from(category));
}
public static Uni<Void> sendAddCategory(WebSocketConnection connection, RCategorie.JustCategorie justCategorie) {
return CompetitionWS.sendNotifyToOtherEditor(connection, "sendAddCategory", justCategorie);
}
public static Uni<Void> sendCategory(WebSocketConnection connection, CategoryModel category) {
return SSCategorie.sendCategory(connection, RCategorie.JustCategorie.from(category));
}
public static Uni<Void> sendCategory(WebSocketConnection connection, RCategorie.JustCategorie justCategorie) {
return CompetitionWS.sendNotifyToOtherEditor(connection, "sendCategory", justCategorie);
}
public static Uni<Void> sendTreeCategory(WebSocketConnection connection, List<TreeEntity> treeEntities) {
return CompetitionWS.sendNotifyToOtherEditor(connection, "sendTreeCategory", treeEntities);
}
}

View File

@@ -1,32 +0,0 @@
package fr.titionfire.ffsaf.ws.send;
import fr.titionfire.ffsaf.domain.entity.MatchEntity;
import fr.titionfire.ffsaf.ws.CompetitionWS;
import fr.titionfire.ffsaf.ws.recv.RMatch;
import io.quarkus.websockets.next.WebSocketConnection;
import io.smallrye.mutiny.Uni;
import java.util.List;
public class SSMatch {
public static Uni<Void> sendMatch(WebSocketConnection connection, MatchEntity matchEntity) {
return SSMatch.sendMatch(connection, List.of(matchEntity));
}
public static Uni<Void> sendMatch(WebSocketConnection connection, List<MatchEntity> matchEntities) {
return CompetitionWS.sendNotifyToOtherEditor(connection, "sendMatch", matchEntities);
}
public static Uni<Void> sendMatchOrder(WebSocketConnection connection, RMatch.MatchOrder matchOrder) {
return CompetitionWS.sendNotifyToOtherEditor(connection, "sendMatchOrder", matchOrder);
}
public static Uni<Void> sendDeleteMatch(WebSocketConnection connection, Long l) {
return SSMatch.sendDeleteMatch(connection, List.of(l));
}
public static Uni<Void> sendDeleteMatch(WebSocketConnection connection, List<Long> longs) {
return CompetitionWS.sendNotifyToOtherEditor(connection, "sendDeleteMatch", longs);
}
}

View File

@@ -1,13 +0,0 @@
package fr.titionfire.ffsaf.ws.send;
import java.io.IOException;
import java.io.Serial;
public class WSClientError extends IOException {
@Serial
private static final long serialVersionUID = -3790479241838684450L;
public WSClientError(String message) {
super(message);
}
}

View File

@@ -43,10 +43,6 @@ notif.affRequest.mail=
siren-api.key=siren-ap siren-api.key=siren-ap
quarkus.rest-client."fr.titionfire.ffsaf.rest.client.SirenService".url=https://data.siren-api.fr/ quarkus.rest-client."fr.titionfire.ffsaf.rest.client.SirenService".url=https://data.siren-api.fr/
quarkus.rest-client."fr.titionfire.ffsaf.rest.client.StateIdService".url=https://www.data-asso.fr/api/
quarkus.websockets-next.server.auto-ping-interval=PT10s
quarkus.websockets-next.client.connection-idle-timeout=PT30s
#Login #Login
quarkus.oidc.token-state-manager.split-tokens=true quarkus.oidc.token-state-manager.split-tokens=true

View File

@@ -1,16 +0,0 @@
filtre.all=--tout--
no.licence=Non licenci\u00E9
# Categories
Cat.SUPER_MINI=Super Mini
Cat.MINI_POUSSIN=Mini Poussin
Cat.POUSSIN= Poussin
Cat.BENJAMIN=Benjamin
Cat.MINIME=Minime
Cat.CADET=Cadet
Cat.JUNIOR=Junior
Cat.SENIOR1=Senior 1
Cat.SENIOR2=Senior 2
Cat.VETERAN1=V\u00E9t\u00E9ran 1
Cat.VETERAN2=V\u00E9t\u00E9ran 2

View File

@@ -8,8 +8,12 @@
<link href="/index.css" rel="stylesheet"> <link href="/index.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" <link
integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous"> rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
crossorigin="anonymous"
/>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
@@ -23,8 +27,11 @@
<div class="spinner"></div> <div class="spinner"></div>
</div> </div>
</div> </div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js" <script
integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI" crossorigin="anonymous"></script> src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p"
crossorigin="anonymous"
></script>
<script async type="module" src="/src/main.jsx"></script> <script async type="module" src="/src/main.jsx"></script>
</body> </body>
</html> </html>

View File

@@ -8,9 +8,6 @@
"name": "webapp", "name": "webapp",
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@fortawesome/fontawesome-svg-core": "^6.5.1", "@fortawesome/fontawesome-svg-core": "^6.5.1",
"@fortawesome/free-brands-svg-icons": "^6.5.1", "@fortawesome/free-brands-svg-icons": "^6.5.1",
"@fortawesome/free-regular-svg-icons": "^6.5.1", "@fortawesome/free-regular-svg-icons": "^6.5.1",
@@ -402,55 +399,6 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@dnd-kit/accessibility": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.1.1.tgz",
"integrity": "sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==",
"dependencies": {
"tslib": "^2.0.0"
},
"peerDependencies": {
"react": ">=16.8.0"
}
},
"node_modules/@dnd-kit/core": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz",
"integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==",
"dependencies": {
"@dnd-kit/accessibility": "^3.1.1",
"@dnd-kit/utilities": "^3.2.2",
"tslib": "^2.0.0"
},
"peerDependencies": {
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
}
},
"node_modules/@dnd-kit/sortable": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-10.0.0.tgz",
"integrity": "sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg==",
"dependencies": {
"@dnd-kit/utilities": "^3.2.2",
"tslib": "^2.0.0"
},
"peerDependencies": {
"@dnd-kit/core": "^6.3.0",
"react": ">=16.8.0"
}
},
"node_modules/@dnd-kit/utilities": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.2.2.tgz",
"integrity": "sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==",
"dependencies": {
"tslib": "^2.0.0"
},
"peerDependencies": {
"react": ">=16.8.0"
}
},
"node_modules/@emotion/is-prop-valid": { "node_modules/@emotion/is-prop-valid": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz",

Some files were not shown because too many files have changed in this diff Show More