Merge pull request 'dev' (#20) from dev into master

Reviewed-on: #20
This commit is contained in:
Thibaut Valentin 2025-02-05 15:47:28 +01:00
commit 5e67820f7c
8 changed files with 71 additions and 34 deletions

32
pom.xml
View File

@ -76,22 +76,39 @@
</dependency> </dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-awt</artifactId>
<version>${quarkus.platform.version}</version>
</dependency>
<dependency>
<groupId>io.quarkiverse.openpdf</groupId>
<artifactId>quarkus-openpdf</artifactId>
<version>3.1.2</version>
<exclusions>
<exclusion>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-awt</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency> <dependency>
<groupId>io.quarkus</groupId> <groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId> <artifactId>quarkus-junit5</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.quarkus</groupId> <groupId>io.quarkus</groupId>
<artifactId>quarkus-oidc</artifactId> <artifactId>quarkus-oidc</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.quarkus</groupId> <groupId>io.quarkus</groupId>
<artifactId>quarkus-keycloak-authorization</artifactId> <artifactId>quarkus-keycloak-authorization</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.quarkus</groupId> <groupId>io.quarkus</groupId>
<artifactId>quarkus-keycloak-admin-rest-client</artifactId> <artifactId>quarkus-keycloak-admin-rest-client</artifactId>
@ -109,11 +126,11 @@
<artifactId>jodd-util</artifactId> <artifactId>jodd-util</artifactId>
<version>6.2.1</version> <version>6.2.1</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.quarkus</groupId> <groupId>io.quarkus</groupId>
<artifactId>quarkus-websockets</artifactId> <artifactId>quarkus-websockets</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.quarkus</groupId> <groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-openapi</artifactId> <artifactId>quarkus-smallrye-openapi</artifactId>
@ -128,12 +145,6 @@
<groupId>io.quarkus</groupId> <groupId>io.quarkus</groupId>
<artifactId>quarkus-cache</artifactId> <artifactId>quarkus-cache</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.github.librepdf</groupId>
<artifactId>openpdf</artifactId>
<version>2.0.3</version>
</dependency>
<dependency> <dependency>
<groupId>org.apache.xmlgraphics</groupId> <groupId>org.apache.xmlgraphics</groupId>
<artifactId>fop</artifactId> <artifactId>fop</artifactId>
@ -143,7 +154,6 @@
<groupId>io.quarkus</groupId> <groupId>io.quarkus</groupId>
<artifactId>quarkus-mailer</artifactId> <artifactId>quarkus-mailer</artifactId>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
@ -212,7 +222,9 @@
</activation> </activation>
<properties> <properties>
<skipITs>false</skipITs> <skipITs>false</skipITs>
<quarkus.native.additional-build-args>--initialize-at-run-time=com.fasterxml.jackson.databind.ext.DOMDeserializer</quarkus.native.additional-build-args> <quarkus.native.additional-build-args>
--initialize-at-run-time=com.fasterxml.jackson.databind.ext.DOMDeserializer\,com.lowagie\,java.awt\,sun.font
</quarkus.native.additional-build-args>
<quarkus.native.enabled>true</quarkus.native.enabled> <quarkus.native.enabled>true</quarkus.native.enabled>
<quarkus.package.jar.enabled>false</quarkus.package.jar.enabled> <quarkus.package.jar.enabled>false</quarkus.package.jar.enabled>
</properties> </properties>

View File

@ -240,10 +240,11 @@ public class AffiliationService {
.call(m -> ((m.getUserId() == null) ? keycloakService.initCompte(m.getId()) : .call(m -> ((m.getUserId() == null) ? keycloakService.initCompte(m.getId()) :
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(m -> m.getLicences().stream().anyMatch(l -> l.getSaison() == saison) ? .call(m -> Mutiny.fetch(m.getLicences())
Uni.createFrom().nullItem() : .call(l1 -> l1.stream().anyMatch(l -> l.getSaison() == saison) ?
Panache.withTransaction(() -> licenceRepository.persist( Uni.createFrom().nullItem() :
new LicenceModel(null, m, saison, null, true)))); Panache.withTransaction(() -> licenceRepository.persist(
new LicenceModel(null, m, saison, null, true)))));
} }
public Uni<?> accept(AffiliationRequestSaveForm form) { public Uni<?> accept(AffiliationRequestSaveForm form) {
@ -292,18 +293,19 @@ public class AffiliationService {
}) })
.call(club -> reactiveMailer.send( .call(club -> reactiveMailer.send(
Mail.withText(form.getM1_email(), Mail.withText(form.getM1_email(),
"FFSAF - Acceptation de votre demande d'affiliation", "FFSAF - Acceptation de votre demande d'affiliation",
String.format( String.format(
""" """
Bonjour, Bonjour,
Votre demande d'affiliation pour le club %s a été acceptée. Votre demande d'affiliation pour le club %s a été acceptée.
Le numéro d'affiliation de votre club est le %d. Le numéro d'affiliation de votre club est le %d.
Cordialement, Cordialement,
L'équipe de la FFSAF L'équipe de la FFSAF
""", club.getName(), club.getNo_affiliation()) """, club.getName(), club.getNo_affiliation())
).setFrom("FFSAF <no-reply@ffsaf.fr>").setReplyTo("contact@ffsaf.fr").addTo(form.getM2_email(), form.getM3_email()) ).setFrom("FFSAF <no-reply@ffsaf.fr>").setReplyTo("contact@ffsaf.fr")
.addTo(form.getM2_email(), form.getM3_email())
)); ));
} }

View File

@ -131,6 +131,10 @@ public class MembreService {
.call(m -> Mutiny.fetch(m.getLicences())); .call(m -> Mutiny.fetch(m.getLicences()));
} }
public Uni<MembreModel> getByAccountId(String subject) {
return repository.find("userId = ?1", subject).firstResult();
}
public Uni<MembreModel> getByLicence(long licence) { public Uni<MembreModel> getByLicence(long licence) {
return repository.find("licence = ?1", licence).firstResult(); return repository.find("licence = ?1", licence).firstResult();
} }

View File

@ -292,7 +292,7 @@ public class ClubEndpoints {
@GET @GET
@Path("{id}/status") @Path("{id}/status")
@RolesAllowed({"federation_admin", "club_president", "club_secretaire"}) @RolesAllowed({"federation_admin", "club_president", "club_secretaire", "club_respo_intra"})
@Operation(summary = "Renvoie le statut du club", description = "Renvoie le statut du club spécifié") @Operation(summary = "Renvoie le statut du club", description = "Renvoie le statut du club spécifié")
@APIResponses(value = { @APIResponses(value = {
@APIResponse(responseCode = "200", description = "Le statut du club"), @APIResponse(responseCode = "200", description = "Le statut du club"),

View File

@ -98,7 +98,7 @@ public class MembreEndpoints {
@Authenticated @Authenticated
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "Renvoie l'attestation d'adhesion du membre connecté", description = "Renvoie l'attestation d'adhesion du " + @Operation(summary = "Renvoie l'attestation d'adhesion du membre connecté", description = "Renvoie l'attestation d'adhesion du " +
"membre connecté, y compris le club et les licences") "membre connecté")
@APIResponses(value = { @APIResponses(value = {
@APIResponse(responseCode = "200", description = "L'attestation d'adhesion"), @APIResponse(responseCode = "200", description = "L'attestation d'adhesion"),
@APIResponse(responseCode = "403", description = "Accès refusé"), @APIResponse(responseCode = "403", description = "Accès refusé"),
@ -109,6 +109,21 @@ public class MembreEndpoints {
return membreService.getLicencePdf(securityCtx.getSubject()); return membreService.getLicencePdf(securityCtx.getSubject());
} }
@GET
@Path("me/photo")
@Authenticated
@Operation(summary = "Renvoie la photo du membre connecté", description = "Renvoie la photo du membre connecté")
@APIResponses(value = {
@APIResponse(responseCode = "200", description = "La photo"),
@APIResponse(responseCode = "403", description = "Accès refusé"),
@APIResponse(responseCode = "500", description = "Erreur interne du serveur")
})
public Uni<Response> getMePhoto() {
return membreService.getByAccountId(securityCtx.getSubject())
.chain(Unchecked.function(
m -> Utils.getMediaFile(m.getId(), media, "ppMembre", Uni.createFrom().nullItem())));
}
@GET @GET
@Path("{id}/photo") @Path("{id}/photo")
@RolesAllowed({"federation_admin", "club_president", "club_secretaire", "club_respo_intra"}) @RolesAllowed({"federation_admin", "club_president", "club_secretaire", "club_respo_intra"})

View File

@ -125,14 +125,14 @@ public class AffiliationRequestForm {
model.setM2_lname(this.getM2_lname()); model.setM2_lname(this.getM2_lname());
model.setM2_fname(this.getM2_fname()); model.setM2_fname(this.getM2_fname());
model.setM2_email(this.getM2_email()); model.setM2_email(this.getM2_email());
model.setM2_lincence((this.getM1_lincence() == null || this.getM1_lincence().isBlank()) model.setM2_lincence((this.getM2_lincence() == null || this.getM2_lincence().isBlank())
? -1 : Integer.parseInt(this.getM2_lincence())); ? -1 : Integer.parseInt(this.getM2_lincence()));
model.setM2_role(this.getM2_role()); model.setM2_role(this.getM2_role());
model.setM3_lname(this.getM3_lname()); model.setM3_lname(this.getM3_lname());
model.setM3_fname(this.getM3_fname()); model.setM3_fname(this.getM3_fname());
model.setM3_email(this.getM3_email()); model.setM3_email(this.getM3_email());
model.setM3_lincence((this.getM1_lincence() == null || this.getM1_lincence().isBlank()) model.setM3_lincence((this.getM3_lincence() == null || this.getM3_lincence().isBlank())
? -1 : Integer.parseInt(this.getM3_lincence())); ? -1 : Integer.parseInt(this.getM3_lincence()));
model.setM3_role(this.getM3_role()); model.setM3_role(this.getM3_role());

View File

@ -73,7 +73,7 @@ function PhotoCard({data}) {
<div className="card-body text-center"> <div className="card-body text-center">
<div className="input-group mb-3"> <div className="input-group mb-3">
<img <img
src={`${vite_url}/api/member/${data.id}/photo`} src={`${vite_url}/api/member/me/photo`}
alt="avatar" alt="avatar"
className="rounded-circle img-fluid" style={{object_fit: 'contain'}}/> className="rounded-circle img-fluid" style={{object_fit: 'contain'}}/>
</div> </div>

View File

@ -91,7 +91,6 @@ function sendLicence(event, dispatch) {
event.preventDefault(); event.preventDefault();
const formData = new FormData(event.target); const formData = new FormData(event.target);
formData.set('certificate', `${event.target.certificateBy?.value}¤${event.target.certificateDate?.value}`)
formData.set('licence', event.target.licence?.value?.length > 0 ? event.target.licence?.value : null) formData.set('licence', event.target.licence?.value?.length > 0 ? event.target.licence?.value : null)
toast.promise( toast.promise(
@ -152,8 +151,13 @@ function ModalContent({licence, dispatch}) {
if (licence.id !== -1) { if (licence.id !== -1) {
setNew(false) setNew(false)
setSaison(licence.saison) setSaison(licence.saison)
setCertificateBy(licence.certificate.split('¤')[0]) if (licence.certificate === null) {
setCertificateDate(licence.certificate.split('¤')[1]) setCertificateBy("")
setCertificateDate("")
} else {
setCertificateBy(licence.certificate.split('¤')[0])
setCertificateDate(licence.certificate.split('¤')[1])
}
setValidate(licence.validate) setValidate(licence.validate)
} else { } else {
setNew(true) setNew(true)