Compare commits
No commits in common. "e3a1d1c50bab61cf80f16ae180378f9e776c97cc" and "12326fe1224ff9919a0f7eb12c1ba3ad728d1356" have entirely different histories.
e3a1d1c50b
...
12326fe122
@ -67,15 +67,8 @@ public class CompetitionModel {
|
|||||||
@Column(name = "table_")
|
@Column(name = "table_")
|
||||||
List<String> table = new ArrayList<>();
|
List<String> table = new ArrayList<>();
|
||||||
|
|
||||||
@Column(columnDefinition = "TEXT")
|
|
||||||
String data1;
|
String data1;
|
||||||
@Column(columnDefinition = "TEXT")
|
|
||||||
String data2;
|
String data2;
|
||||||
@Column(columnDefinition = "TEXT")
|
|
||||||
String data3;
|
String data3;
|
||||||
@Column(columnDefinition = "TEXT")
|
|
||||||
String data4;
|
String data4;
|
||||||
|
|
||||||
@Column(columnDefinition = "TEXT")
|
|
||||||
String config;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -98,13 +98,7 @@ public class CompetitionService {
|
|||||||
Cache cacheNoneAccess;
|
Cache cacheNoneAccess;
|
||||||
|
|
||||||
public Uni<CompetitionData> getById(SecurityCtx securityCtx, Long id) {
|
public Uni<CompetitionData> getById(SecurityCtx securityCtx, Long id) {
|
||||||
return permService.hasViewPerm(securityCtx, id).map(cm -> {
|
return permService.hasViewPerm(securityCtx, id).map(CompetitionData::fromModelLight);
|
||||||
CompetitionData out = CompetitionData.fromModelLight(cm);
|
|
||||||
if (cm.getAdmin() != null) {
|
|
||||||
out.setCanEditRegisters(cm.getAdmin().stream().anyMatch(u -> u.equals(securityCtx.getSubject())));
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uni<CompetitionData> getByIdAdmin(SecurityCtx securityCtx, Long id) {
|
public Uni<CompetitionData> getByIdAdmin(SecurityCtx securityCtx, Long id) {
|
||||||
@ -112,8 +106,7 @@ public class CompetitionService {
|
|||||||
return Uni.createFrom()
|
return Uni.createFrom()
|
||||||
.item(new CompetitionData(null, "", "", "", "", new Date(), new Date(),
|
.item(new CompetitionData(null, "", "", "", "", new Date(), new Date(),
|
||||||
CompetitionSystem.INTERNAL, RegisterMode.FREE, new Date(), new Date(), true,
|
CompetitionSystem.INTERNAL, RegisterMode.FREE, new Date(), new Date(), true,
|
||||||
null, "", "", null, true, true,
|
null, "", "", null, true, "", "", "", ""));
|
||||||
"", "", "", "", "{}"));
|
|
||||||
}
|
}
|
||||||
return permService.hasAdminViewPerm(securityCtx, id)
|
return permService.hasAdminViewPerm(securityCtx, id)
|
||||||
.chain(competitionModel -> Mutiny.fetch(competitionModel.getInsc())
|
.chain(competitionModel -> Mutiny.fetch(competitionModel.getInsc())
|
||||||
@ -136,14 +129,6 @@ public class CompetitionService {
|
|||||||
out.addAll(cm.stream().map(CompetitionData::fromModelLight).toList());
|
out.addAll(cm.stream().map(CompetitionData::fromModelLight).toList());
|
||||||
out.forEach(competition -> competition.setCanEdit(true));
|
out.forEach(competition -> competition.setCanEdit(true));
|
||||||
}))
|
}))
|
||||||
.chain(ids -> repository.list("id NOT IN ?1 AND ?2 IN admin", ids, securityCtx.getSubject())
|
|
||||||
.map(cm -> {
|
|
||||||
out.addAll(cm.stream().map(CompetitionData::fromModelLight).toList());
|
|
||||||
out.forEach(competition -> competition.setCanEditRegisters(true));
|
|
||||||
List<Long> ids2 = new ArrayList<>(ids);
|
|
||||||
ids2.addAll(cm.stream().map(CompetitionModel::getId).toList());
|
|
||||||
return ids2;
|
|
||||||
}))
|
|
||||||
.call(ids ->
|
.call(ids ->
|
||||||
repository.list("id NOT IN ?1 AND (publicVisible = TRUE OR registerMode IN ?2)", ids,
|
repository.list("id NOT IN ?1 AND (publicVisible = TRUE OR registerMode IN ?2)", ids,
|
||||||
securityCtx.isClubAdmin() ? List.of(RegisterMode.FREE, RegisterMode.HELLOASSO,
|
securityCtx.isClubAdmin() ? List.of(RegisterMode.FREE, RegisterMode.HELLOASSO,
|
||||||
@ -180,9 +165,8 @@ public class CompetitionService {
|
|||||||
public Uni<List<CompetitionData>> getAllSystemTable(SecurityCtx securityCtx,
|
public Uni<List<CompetitionData>> getAllSystemTable(SecurityCtx securityCtx,
|
||||||
CompetitionSystem system) {
|
CompetitionSystem system) {
|
||||||
return repository.list("system = ?1", system)
|
return repository.list("system = ?1", system)
|
||||||
.chain(l -> Uni.join().all(l.stream().map(cm ->
|
.chain(l -> Uni.join().all(l.stream().map(cm -> permService.hasTablePerm(securityCtx, cm)).toList())
|
||||||
permService.hasTablePerm(securityCtx, cm).onFailure().recoverWithNull()
|
.andCollectFailures())
|
||||||
).toList()).andCollectFailures())
|
|
||||||
.map(l -> l.stream().filter(Objects::nonNull).map(CompetitionData::fromModel).toList());
|
.map(l -> l.stream().filter(Objects::nonNull).map(CompetitionData::fromModel).toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -529,64 +513,6 @@ public class CompetitionService {
|
|||||||
.call(__ -> cache.invalidate(id));
|
.call(__ -> cache.invalidate(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Uni<SimpleCompetData> getInternalData(SecurityCtx securityCtx, Long id) {
|
|
||||||
return permService.hasEditPerm(securityCtx, id)
|
|
||||||
.invoke(Unchecked.consumer(cm -> {
|
|
||||||
if (cm.getSystem() != CompetitionSystem.INTERNAL)
|
|
||||||
throw new DBadRequestException("Competition is not INTERNAL");
|
|
||||||
}))
|
|
||||||
.chain(competitionModel -> {
|
|
||||||
SimpleCompetData data = SimpleCompetData.fromModel(competitionModel);
|
|
||||||
return vertx.getOrCreateContext().executeBlocking(() -> {
|
|
||||||
if (competitionModel.getAdmin() != null)
|
|
||||||
data.setAdmin(
|
|
||||||
competitionModel.getAdmin().stream().map(uuid -> keycloakService.getUserById(uuid))
|
|
||||||
.filter(Optional::isPresent)
|
|
||||||
.map(user -> user.get().getUsername())
|
|
||||||
.toList());
|
|
||||||
if (competitionModel.getTable() != null)
|
|
||||||
data.setTable(
|
|
||||||
competitionModel.getTable().stream().map(uuid -> keycloakService.getUserById(uuid))
|
|
||||||
.filter(Optional::isPresent)
|
|
||||||
.map(user -> user.get().getUsername())
|
|
||||||
.toList());
|
|
||||||
return data;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public Uni<Void> setInternalData(SecurityCtx securityCtx, SimpleCompetData data) {
|
|
||||||
return permService.hasEditPerm(securityCtx, data.getId())
|
|
||||||
.invoke(Unchecked.consumer(cm -> {
|
|
||||||
if (cm.getSystem() != CompetitionSystem.INTERNAL)
|
|
||||||
throw new DBadRequestException("Competition is not INTERNAL");
|
|
||||||
}))
|
|
||||||
.chain(cm -> vertx.getOrCreateContext().executeBlocking(() -> {
|
|
||||||
ArrayList<String> admin = new ArrayList<>();
|
|
||||||
ArrayList<String> table = new ArrayList<>();
|
|
||||||
for (String username : data.getAdmin()) {
|
|
||||||
Optional<UserRepresentation> opt = keycloakService.getUser(username);
|
|
||||||
if (opt.isEmpty())
|
|
||||||
throw new DBadRequestException("User " + username + " not found");
|
|
||||||
admin.add(opt.get().getId());
|
|
||||||
}
|
|
||||||
for (String username : data.getTable()) {
|
|
||||||
Optional<UserRepresentation> opt = keycloakService.getUser(username);
|
|
||||||
if (opt.isEmpty())
|
|
||||||
throw new DBadRequestException("User " + username + " not found");
|
|
||||||
table.add(opt.get().getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
cm.setAdmin(admin);
|
|
||||||
cm.setTable(table);
|
|
||||||
cm.setConfig(data.getConfigForInternal());
|
|
||||||
|
|
||||||
return cm;
|
|
||||||
}))
|
|
||||||
.chain(cm -> Panache.withTransaction(() -> repository.persist(cm)))
|
|
||||||
.replaceWithVoid();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Uni<SimpleCompetData> getSafcaData(SecurityCtx securityCtx, Long id) {
|
public Uni<SimpleCompetData> getSafcaData(SecurityCtx securityCtx, Long id) {
|
||||||
return permService.getSafcaConfig(id)
|
return permService.getSafcaConfig(id)
|
||||||
.call(Unchecked.function(o -> {
|
.call(Unchecked.function(o -> {
|
||||||
|
|||||||
@ -377,11 +377,7 @@ public class KeycloakService {
|
|||||||
|
|
||||||
|
|
||||||
public Optional<UserRepresentation> getUser(UUID userId) {
|
public Optional<UserRepresentation> getUser(UUID userId) {
|
||||||
return getUserById(userId.toString());
|
UserResource user = keycloak.realm(realm).users().get(userId.toString());
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<UserRepresentation> getUserById(String userId) {
|
|
||||||
UserResource user = keycloak.realm(realm).users().get(userId);
|
|
||||||
if (user == null)
|
if (user == null)
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
else
|
else
|
||||||
|
|||||||
@ -71,14 +71,6 @@ public class CompetitionEndpoints {
|
|||||||
return service.getSafcaData(securityCtx, id);
|
return service.getSafcaData(securityCtx, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("{id}/internalData")
|
|
||||||
@Authenticated
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
public Uni<SimpleCompetData> getInternalData(@PathParam("id") Long id) {
|
|
||||||
return service.getInternalData(securityCtx, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("all")
|
@Path("all")
|
||||||
@ -103,14 +95,6 @@ public class CompetitionEndpoints {
|
|||||||
return service.setSafcaData(securityCtx, data);
|
return service.setSafcaData(securityCtx, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@POST
|
|
||||||
@Path("/internalData")
|
|
||||||
@Authenticated
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
public Uni<?> setInternalData(SimpleCompetData data) {
|
|
||||||
return service.setInternalData(securityCtx, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@DELETE
|
@DELETE
|
||||||
@Path("{id}")
|
@Path("{id}")
|
||||||
@Authenticated
|
@Authenticated
|
||||||
|
|||||||
@ -35,12 +35,10 @@ public class CompetitionData {
|
|||||||
private String owner;
|
private String owner;
|
||||||
private List<SimpleRegister> registers;
|
private List<SimpleRegister> registers;
|
||||||
private boolean canEdit;
|
private boolean canEdit;
|
||||||
private boolean canEditRegisters;
|
|
||||||
private String data1;
|
private String data1;
|
||||||
private String data2;
|
private String data2;
|
||||||
private String data3;
|
private String data3;
|
||||||
private String data4;
|
private String data4;
|
||||||
private String config;
|
|
||||||
|
|
||||||
public static CompetitionData fromModel(CompetitionModel model) {
|
public static CompetitionData fromModel(CompetitionModel model) {
|
||||||
if (model == null)
|
if (model == null)
|
||||||
@ -49,8 +47,8 @@ public class CompetitionData {
|
|||||||
return new CompetitionData(model.getId(), model.getName(), model.getDescription(), model.getAdresse(),
|
return new CompetitionData(model.getId(), model.getName(), model.getDescription(), model.getAdresse(),
|
||||||
model.getUuid(), model.getDate(), model.getTodate(), model.getSystem(),
|
model.getUuid(), model.getDate(), model.getTodate(), model.getSystem(),
|
||||||
model.getRegisterMode(), model.getStartRegister(), model.getEndRegister(), model.isPublicVisible(),
|
model.getRegisterMode(), model.getStartRegister(), model.getEndRegister(), model.isPublicVisible(),
|
||||||
model.getClub().getId(), model.getClub().getName(), model.getOwner(), null, false, false,
|
model.getClub().getId(), model.getClub().getName(), model.getOwner(), null, false,
|
||||||
model.getData1(), model.getData2(), model.getData3(), model.getData4(), model.getConfig());
|
model.getData1(), model.getData2(), model.getData3(), model.getData4());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CompetitionData fromModelLight(CompetitionModel model) {
|
public static CompetitionData fromModelLight(CompetitionModel model) {
|
||||||
@ -60,15 +58,14 @@ public class CompetitionData {
|
|||||||
CompetitionData out = new CompetitionData(model.getId(), model.getName(), model.getDescription(),
|
CompetitionData out = new CompetitionData(model.getId(), model.getName(), model.getDescription(),
|
||||||
model.getAdresse(), "", model.getDate(), model.getTodate(), null,
|
model.getAdresse(), "", model.getDate(), model.getTodate(), null,
|
||||||
model.getRegisterMode(), model.getStartRegister(), model.getEndRegister(), model.isPublicVisible(),
|
model.getRegisterMode(), model.getStartRegister(), model.getEndRegister(), model.isPublicVisible(),
|
||||||
null, model.getClub().getName(), "", null, false, false,
|
null, model.getClub().getName(), "", null, false,
|
||||||
"", "", "", "", "{}");
|
"", "", "", "");
|
||||||
|
|
||||||
if (model.getRegisterMode() == RegisterMode.HELLOASSO) {
|
if (model.getRegisterMode() == RegisterMode.HELLOASSO) {
|
||||||
out.setData1(model.getData1());
|
out.setData1(model.getData1());
|
||||||
out.setData2(model.getData2());
|
out.setData2(model.getData2());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,5 @@
|
|||||||
package fr.titionfire.ffsaf.rest.data;
|
package fr.titionfire.ffsaf.rest.data;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import fr.titionfire.ffsaf.data.model.CompetitionModel;
|
|
||||||
import fr.titionfire.ffsaf.net2.data.SimpleCompet;
|
import fr.titionfire.ffsaf.net2.data.SimpleCompet;
|
||||||
import io.quarkus.runtime.annotations.RegisterForReflection;
|
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
@ -29,41 +25,4 @@ public class SimpleCompetData {
|
|||||||
return new SimpleCompetData(compet.id(), compet.show_blason(), compet.show_flag(),
|
return new SimpleCompetData(compet.id(), compet.show_blason(), compet.show_flag(),
|
||||||
new ArrayList<>(), new ArrayList<>());
|
new ArrayList<>(), new ArrayList<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SimpleCompetData fromModel(CompetitionModel competitionModel) {
|
|
||||||
if (competitionModel == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
boolean show_blason = true;
|
|
||||||
boolean show_flag = false;
|
|
||||||
|
|
||||||
if (competitionModel.getConfig() != null) {
|
|
||||||
try {
|
|
||||||
ObjectMapper objectMapper = new ObjectMapper();
|
|
||||||
JsonNode rootNode = objectMapper.readTree(competitionModel.getConfig());
|
|
||||||
|
|
||||||
if (rootNode.has("show_blason"))
|
|
||||||
show_blason = rootNode.get("show_blason").asBoolean();
|
|
||||||
if (rootNode.has("show_flag"))
|
|
||||||
show_flag = rootNode.get("show_flag").asBoolean();
|
|
||||||
|
|
||||||
} catch (JsonProcessingException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new SimpleCompetData(competitionModel.getId(), show_blason, show_flag,
|
|
||||||
new ArrayList<>(), new ArrayList<>());
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getConfigForInternal(){
|
|
||||||
ObjectMapper objectMapper = new ObjectMapper();
|
|
||||||
JsonNode rootNode = objectMapper.createObjectNode()
|
|
||||||
.put("show_blason", this.show_blason)
|
|
||||||
.put("show_flag", this.show_flag);
|
|
||||||
try {
|
|
||||||
return objectMapper.writeValueAsString(rootNode);
|
|
||||||
} catch (JsonProcessingException e) {
|
|
||||||
return "{}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -108,8 +108,8 @@ public class CompetitionWS {
|
|||||||
.call(cm -> competPermService.hasEditPerm(securityCtx, cm).map(__ -> PermLevel.ADMIN)
|
.call(cm -> competPermService.hasEditPerm(securityCtx, cm).map(__ -> PermLevel.ADMIN)
|
||||||
.onFailure()
|
.onFailure()
|
||||||
.recoverWithUni(competPermService.hasTablePerm(securityCtx, cm).map(__ -> PermLevel.TABLE))
|
.recoverWithUni(competPermService.hasTablePerm(securityCtx, cm).map(__ -> PermLevel.TABLE))
|
||||||
//.onFailure()
|
.onFailure()
|
||||||
//.recoverWithUni(competPermService.hasViewPerm(securityCtx, cm).map(__ -> PermLevel.VIEW))
|
.recoverWithUni(competPermService.hasViewPerm(securityCtx, cm).map(__ -> PermLevel.VIEW))
|
||||||
.invoke(prem -> connection.userData().put(UserData.TypedKey.forString("prem"), prem.toString()))
|
.invoke(prem -> connection.userData().put(UserData.TypedKey.forString("prem"), prem.toString()))
|
||||||
.invoke(prem -> LOGGER.infof("Connection permission: %s", prem))
|
.invoke(prem -> LOGGER.infof("Connection permission: %s", prem))
|
||||||
.onFailure().transform(t -> new ForbiddenException()))
|
.onFailure().transform(t -> new ForbiddenException()))
|
||||||
|
|||||||
@ -3,7 +3,10 @@ package fr.titionfire.ffsaf.ws.recv;
|
|||||||
import fr.titionfire.ffsaf.data.model.CategoryModel;
|
import fr.titionfire.ffsaf.data.model.CategoryModel;
|
||||||
import fr.titionfire.ffsaf.data.model.MatchModel;
|
import fr.titionfire.ffsaf.data.model.MatchModel;
|
||||||
import fr.titionfire.ffsaf.data.model.TreeModel;
|
import fr.titionfire.ffsaf.data.model.TreeModel;
|
||||||
import fr.titionfire.ffsaf.data.repository.*;
|
import fr.titionfire.ffsaf.data.repository.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.MatchEntity;
|
||||||
import fr.titionfire.ffsaf.domain.entity.TreeEntity;
|
import fr.titionfire.ffsaf.domain.entity.TreeEntity;
|
||||||
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
|
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
|
||||||
@ -43,9 +46,6 @@ public class RCategorie {
|
|||||||
@Inject
|
@Inject
|
||||||
TreeRepository treeRepository;
|
TreeRepository treeRepository;
|
||||||
|
|
||||||
@Inject
|
|
||||||
CardboardRepository cardboardRepository;
|
|
||||||
|
|
||||||
private Uni<CategoryModel> getById(long id, WebSocketConnection connection) {
|
private Uni<CategoryModel> getById(long id, WebSocketConnection connection) {
|
||||||
return categoryRepository.findById(id)
|
return categoryRepository.findById(id)
|
||||||
.invoke(Unchecked.consumer(o -> {
|
.invoke(Unchecked.consumer(o -> {
|
||||||
@ -210,7 +210,6 @@ public class RCategorie {
|
|||||||
public Uni<Void> deleteCategory(WebSocketConnection connection, Long id) {
|
public Uni<Void> deleteCategory(WebSocketConnection connection, Long id) {
|
||||||
return getById(id, connection)
|
return getById(id, connection)
|
||||||
.call(cat -> Panache.withTransaction(() -> treeRepository.delete("category = ?1", cat.getId())
|
.call(cat -> Panache.withTransaction(() -> treeRepository.delete("category = ?1", cat.getId())
|
||||||
.call(__ -> cardboardRepository.delete("match.category = ?1", cat))
|
|
||||||
.call(__ -> matchRepository.delete("category = ?1", cat))))
|
.call(__ -> matchRepository.delete("category = ?1", cat))))
|
||||||
.chain(cat -> Panache.withTransaction(() -> categoryRepository.delete(cat)))
|
.chain(cat -> Panache.withTransaction(() -> categoryRepository.delete(cat)))
|
||||||
.invoke(__ -> SSCategorie.sendDelCategory(connection, id))
|
.invoke(__ -> SSCategorie.sendDelCategory(connection, id))
|
||||||
|
|||||||
@ -44,9 +44,6 @@ public class RMatch {
|
|||||||
@Inject
|
@Inject
|
||||||
CompetitionGuestRepository competitionGuestRepository;
|
CompetitionGuestRepository competitionGuestRepository;
|
||||||
|
|
||||||
@Inject
|
|
||||||
CardboardRepository cardboardRepository;
|
|
||||||
|
|
||||||
private Uni<MatchModel> getById(long id, WebSocketConnection connection) {
|
private Uni<MatchModel> getById(long id, WebSocketConnection connection) {
|
||||||
return matchRepository.findById(id)
|
return matchRepository.findById(id)
|
||||||
.invoke(Unchecked.consumer(o -> {
|
.invoke(Unchecked.consumer(o -> {
|
||||||
@ -280,10 +277,7 @@ public class RMatch {
|
|||||||
@WSReceiver(code = "deleteMatch", permission = PermLevel.ADMIN)
|
@WSReceiver(code = "deleteMatch", permission = PermLevel.ADMIN)
|
||||||
public Uni<Void> deleteMatch(WebSocketConnection connection, Long idMatch) {
|
public Uni<Void> deleteMatch(WebSocketConnection connection, Long idMatch) {
|
||||||
return getById(idMatch, connection)
|
return getById(idMatch, connection)
|
||||||
.map(__ -> idMatch)
|
.chain(matchModel -> Panache.withTransaction(() -> matchRepository.delete(matchModel)))
|
||||||
.chain(l -> Panache.withTransaction(() ->
|
|
||||||
cardboardRepository.delete("match.id = ?1", l)
|
|
||||||
.chain(__ -> matchRepository.delete("id = ?1", l))))
|
|
||||||
.invoke(__ -> SSMatch.sendDeleteMatch(connection, idMatch))
|
.invoke(__ -> SSMatch.sendDeleteMatch(connection, idMatch))
|
||||||
.replaceWithVoid();
|
.replaceWithVoid();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
import {createContext, useContext, useEffect, useId, useReducer, useRef, useState} from "react";
|
import {createContext, useContext, useEffect, useId, useReducer, useRef, useState} from "react";
|
||||||
|
import {apiAxios} from "../utils/Tools.js";
|
||||||
|
import {toast} from "react-toastify";
|
||||||
import {useAuth} from "./useAuth.jsx";
|
import {useAuth} from "./useAuth.jsx";
|
||||||
|
|
||||||
function uuidv4() {
|
function uuidv4() {
|
||||||
@ -43,7 +45,6 @@ export function WSProvider({url, onmessage, children}) {
|
|||||||
const id = useId();
|
const id = useId();
|
||||||
const {is_authenticated} = useAuth()
|
const {is_authenticated} = useAuth()
|
||||||
const [isReady, setIsReady] = useState(false)
|
const [isReady, setIsReady] = useState(false)
|
||||||
const [doReconnect, setDoReconnect] = useState(false)
|
|
||||||
const [state, dispatch] = useReducer(reducer, {listener: []})
|
const [state, dispatch] = useReducer(reducer, {listener: []})
|
||||||
const ws = useRef(null)
|
const ws = useRef(null)
|
||||||
const listenersRef = useRef([])
|
const listenersRef = useRef([])
|
||||||
@ -58,33 +59,10 @@ export function WSProvider({url, onmessage, children}) {
|
|||||||
listenersRef.current = state.listener
|
listenersRef.current = state.listener
|
||||||
}, [state.listener])
|
}, [state.listener])
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!doReconnect && !is_authenticated && isReady)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const timer = setInterval(() => {
|
|
||||||
if (isReady || !doReconnect || !is_authenticated)
|
|
||||||
return;
|
|
||||||
|
|
||||||
console.log("WSProvider: reconnecting to", url);
|
|
||||||
try {
|
|
||||||
const newSocket = new WebSocket(url)
|
|
||||||
newSocket.onopen = ws.current.onopen
|
|
||||||
newSocket.onclose = ws.current.onclose
|
|
||||||
newSocket.onmessage = ws.current.onmessage
|
|
||||||
ws.current = newSocket
|
|
||||||
}catch (e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}, 5000);
|
|
||||||
return () => clearInterval(timer);
|
|
||||||
}, [isReady, doReconnect, is_authenticated]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!mountCounter[id])
|
if (!mountCounter[id])
|
||||||
mountCounter[id] = 0
|
mountCounter[id] = 0
|
||||||
mountCounter[id] += 1
|
mountCounter[id] += 1
|
||||||
setDoReconnect(true)
|
|
||||||
console.log(`WSProvider ${id} mounted ${mountCounter[id]} time(s)`);
|
console.log(`WSProvider ${id} mounted ${mountCounter[id]} time(s)`);
|
||||||
|
|
||||||
if (mountCounter[id] === 1 && (ws.current === null || ws.current.readyState >= WebSocket.CLOSING)){
|
if (mountCounter[id] === 1 && (ws.current === null || ws.current.readyState >= WebSocket.CLOSING)){
|
||||||
@ -94,6 +72,24 @@ export function WSProvider({url, onmessage, children}) {
|
|||||||
socket.onopen = () => setIsReady(true)
|
socket.onopen = () => setIsReady(true)
|
||||||
socket.onclose = () => {
|
socket.onclose = () => {
|
||||||
setIsReady(false)
|
setIsReady(false)
|
||||||
|
if (mountCounter[id] > 0) {
|
||||||
|
setTimeout(() => {
|
||||||
|
//if (is_authenticated){
|
||||||
|
console.log("WSProvider: reconnecting to", url);
|
||||||
|
try {
|
||||||
|
const newSocket = new WebSocket(url)
|
||||||
|
ws.current = newSocket
|
||||||
|
newSocket.onopen = socket.onopen
|
||||||
|
newSocket.onclose = socket.onclose
|
||||||
|
newSocket.onmessage = socket.onmessage
|
||||||
|
}catch (e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
//}else{
|
||||||
|
// console.log("WSProvider: not reconnecting, user is not authenticated");
|
||||||
|
//}
|
||||||
|
}, 5000)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
socket.onmessage = (event) => {
|
socket.onmessage = (event) => {
|
||||||
const msg = JSON.parse(event.data)
|
const msg = JSON.parse(event.data)
|
||||||
@ -136,7 +132,6 @@ export function WSProvider({url, onmessage, children}) {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
console.log(`WSProvider ${id} checking for close, ${mountCounter[id]} instance(s) remain`);
|
console.log(`WSProvider ${id} checking for close, ${mountCounter[id]} instance(s) remain`);
|
||||||
if (mountCounter[id] === 0) {
|
if (mountCounter[id] === 0) {
|
||||||
setDoReconnect(false)
|
|
||||||
console.log("WSProvider: closing connection to", url);
|
console.log("WSProvider: closing connection to", url);
|
||||||
ws.current.close()
|
ws.current.close()
|
||||||
}
|
}
|
||||||
@ -144,14 +139,13 @@ export function WSProvider({url, onmessage, children}) {
|
|||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const send2 = (uuid, code, type, data, resolve = () => {
|
const send = (uuid, code, type, data, resolve = () => {
|
||||||
}, reject = () => {
|
}, reject = () => {
|
||||||
}) => {
|
}) => {
|
||||||
if (!isReadyRef.current) {
|
if (!isReadyRef.current) {
|
||||||
reject("WebSocket is not connected");
|
reject("WebSocket is not connected");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type === "REQUEST") {
|
if (type === "REQUEST") {
|
||||||
const timeout = setTimeout(() => {
|
const timeout = setTimeout(() => {
|
||||||
reject("timeout");
|
reject("timeout");
|
||||||
@ -178,26 +172,6 @@ export function WSProvider({url, onmessage, children}) {
|
|||||||
data: data
|
data: data
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
const send = (uuid, code, type, data, resolve = () => {
|
|
||||||
}, reject = () => {
|
|
||||||
}) => {
|
|
||||||
if (isReadyRef.current) {
|
|
||||||
send2(uuid, code, type, data, resolve, reject);
|
|
||||||
}else {
|
|
||||||
let counter = 0;
|
|
||||||
const waitInterval = setInterval(() => {
|
|
||||||
if (isReadyRef.current) {
|
|
||||||
clearInterval(waitInterval);
|
|
||||||
send2(uuid, code, type, data, resolve, reject);
|
|
||||||
}
|
|
||||||
counter += 1;
|
|
||||||
if (counter >= 300) { // 30 seconds timeout
|
|
||||||
clearInterval(waitInterval);
|
|
||||||
reject("WebSocket is not connected");
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const ret = {isReady, dispatch, send, wait_length: callbackRef}
|
const ret = {isReady, dispatch, send, wait_length: callbackRef}
|
||||||
|
|||||||
@ -51,11 +51,9 @@ export function CompetitionEdit() {
|
|||||||
<Content data={data} refresh={refresh}/>
|
<Content data={data} refresh={refresh}/>
|
||||||
|
|
||||||
{data.id !== null && <button style={{marginBottom: "1.5em", width: "100%"}} className="btn btn-primary"
|
{data.id !== null && <button style={{marginBottom: "1.5em", width: "100%"}} className="btn btn-primary"
|
||||||
onClick={_ => navigate(`/competition/${data.id}/register?type=${data.registerMode}`)}>Voir/Modifier
|
onClick={_ => navigate(`/competition/${data.id}/register?type=${data.registerMode}`)}>Voir/Modifier les participants</button>}
|
||||||
les participants</button>}
|
|
||||||
|
|
||||||
{data.id !== null && (data.system === "SAFCA" || data.system === "INTERNAL") &&
|
{data.id !== null && data.system === "SAFCA" && <ContentSAFCA data2={data}/>}
|
||||||
<ContentSAFCAAndInternal data2={data} type={data.system}/>}
|
|
||||||
|
|
||||||
{data.id !== null && <>
|
{data.id !== null && <>
|
||||||
<div className="col" style={{textAlign: 'right', marginTop: '1em'}}>
|
<div className="col" style={{textAlign: 'right', marginTop: '1em'}}>
|
||||||
@ -74,12 +72,9 @@ export function CompetitionEdit() {
|
|||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
||||||
function ContentSAFCAAndInternal({data2, type = "SAFCA"}) {
|
function ContentSAFCA({data2}) {
|
||||||
const getDataPath = type === "SAFCA" ? `/competition/${data2.id}/safcaData` : `/competition/${data2.id}/internalData`
|
|
||||||
const setDataPath = type === "SAFCA" ? "/competition/safcaData" : "/competition/internalData"
|
|
||||||
|
|
||||||
const setLoading = useLoadingSwitcher()
|
const setLoading = useLoadingSwitcher()
|
||||||
const {data, error} = useFetch(getDataPath, setLoading, 1)
|
const {data, error} = useFetch(`/competition/${data2.id}/safcaData`, setLoading, 1)
|
||||||
|
|
||||||
const [state, dispatch] = useReducer(SimpleReducer, [])
|
const [state, dispatch] = useReducer(SimpleReducer, [])
|
||||||
const [state2, dispatch2] = useReducer(SimpleReducer, [])
|
const [state2, dispatch2] = useReducer(SimpleReducer, [])
|
||||||
@ -114,7 +109,7 @@ function ContentSAFCAAndInternal({data2, type = "SAFCA"}) {
|
|||||||
out['table'] = state2.map(d => d.data)
|
out['table'] = state2.map(d => d.data)
|
||||||
|
|
||||||
toast.promise(
|
toast.promise(
|
||||||
apiAxios.post(setDataPath, out),
|
apiAxios.post(`/competition/safcaData`, out),
|
||||||
{
|
{
|
||||||
pending: "Enregistrement des paramètres en cours",
|
pending: "Enregistrement des paramètres en cours",
|
||||||
success: "Paramètres enregistrée avec succès 🎉",
|
success: "Paramètres enregistrée avec succès 🎉",
|
||||||
@ -407,8 +402,7 @@ function Content({data}) {
|
|||||||
<li><strong>Configurer l'url de notification : </strong>afin que nous puissions recevoir une notification à
|
<li><strong>Configurer l'url de notification : </strong>afin que nous puissions recevoir une notification à
|
||||||
chaque inscription, il est nécessaire de configurer l'url de notification de votre compte HelloAsso pour
|
chaque inscription, il est nécessaire de configurer l'url de notification de votre compte HelloAsso pour
|
||||||
qu'il redirige vers "https://intra.ffsaf.fr/api/webhook/ha". Pour ce faire, depuis la page d'accueil de
|
qu'il redirige vers "https://intra.ffsaf.fr/api/webhook/ha". Pour ce faire, depuis la page d'accueil de
|
||||||
votre association sur HelloAsso, allez dans <strong>Mon compte</strong> >
|
votre association sur HelloAsso, allez dans <strong>Mon compte</strong> > <strong>Paramètres</strong> >
|
||||||
<strong>Paramètres</strong> >
|
|
||||||
<strong> Intégrations et API</strong> section Notification et copier-coller <strong>https://intra.ffsaf.fr/api/webhook/ha </strong>
|
<strong> Intégrations et API</strong> section Notification et copier-coller <strong>https://intra.ffsaf.fr/api/webhook/ha </strong>
|
||||||
dans le champ <strong>Mon URL de callback</strong> et enregister.
|
dans le champ <strong>Mon URL de callback</strong> et enregister.
|
||||||
<img src="/img/HA-help-4.png" alt="" className="img-fluid" style={{objectFit: "contain"}}/></li>
|
<img src="/img/HA-help-4.png" alt="" className="img-fluid" style={{objectFit: "contain"}}/></li>
|
||||||
|
|||||||
@ -38,7 +38,7 @@ export function CompetitionRegisterAdmin({source}) {
|
|||||||
}, [data, clubFilter, catFilter]);
|
}, [data, clubFilter, catFilter]);
|
||||||
|
|
||||||
const sendRegister = (new_state) => {
|
const sendRegister = (new_state) => {
|
||||||
return toast.promise(apiAxios.post(`/competition/${id}/register/${source}`, new_state), {
|
toast.promise(apiAxios.post(`/competition/${id}/register/${source}`, new_state), {
|
||||||
pending: "Recherche en cours", success: "Combattant trouvé et ajouté/mis à jour", error: {
|
pending: "Recherche en cours", success: "Combattant trouvé et ajouté/mis à jour", error: {
|
||||||
render({data}) {
|
render({data}) {
|
||||||
return data.response.data || "Combattant non trouvé"
|
return data.response.data || "Combattant non trouvé"
|
||||||
@ -153,9 +153,9 @@ function SearchMember({sendRegister}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sendRegister({
|
sendRegister({
|
||||||
licence: member.licence,
|
licence: member.licence.trim(),
|
||||||
fname: member.fname,
|
fname: member.fname.trim(),
|
||||||
lname: member.lname,
|
lname: member.lname.trim(),
|
||||||
weight: "",
|
weight: "",
|
||||||
overCategory: 0,
|
overCategory: 0,
|
||||||
lockEdit: false,
|
lockEdit: false,
|
||||||
@ -169,7 +169,7 @@ function SearchMember({sendRegister}) {
|
|||||||
const names = data.map(member => `${member.fname} ${member.lname}`.trim());
|
const names = data.map(member => `${member.fname} ${member.lname}`.trim());
|
||||||
names.sort((a, b) => a.localeCompare(b));
|
names.sort((a, b) => a.localeCompare(b));
|
||||||
setSuggestions(names);
|
setSuggestions(names);
|
||||||
}, [data]);
|
}, []);
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
{data ? <div className="row mb-3" style={{marginTop: "0.5em"}}>
|
{data ? <div className="row mb-3" style={{marginTop: "0.5em"}}>
|
||||||
@ -335,9 +335,9 @@ function Modal({sendRegister, modalState, setModalState, source}) {
|
|||||||
<form onSubmit={e => {
|
<form onSubmit={e => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
const new_state = {
|
const new_state = {
|
||||||
licence: Number.isInteger(licence) ? licence : licence.trim(),
|
licence: licence,
|
||||||
fname: fname.trim(),
|
fname: fname,
|
||||||
lname: lname.trim(),
|
lname: lname,
|
||||||
weight: weight,
|
weight: weight,
|
||||||
overCategory: cat,
|
overCategory: cat,
|
||||||
lockEdit: lockEdit,
|
lockEdit: lockEdit,
|
||||||
@ -350,10 +350,8 @@ function Modal({sendRegister, modalState, setModalState, source}) {
|
|||||||
new_state.country = country_
|
new_state.country = country_
|
||||||
new_state.genre = genre
|
new_state.genre = genre
|
||||||
}
|
}
|
||||||
sendRegister(new_state)
|
|
||||||
.then(() => {
|
|
||||||
setModalState(new_state)
|
setModalState(new_state)
|
||||||
})
|
sendRegister(new_state)
|
||||||
}}>
|
}}>
|
||||||
<div className="modal-header">
|
<div className="modal-header">
|
||||||
<h1 className="modal-title fs-5"
|
<h1 className="modal-title fs-5"
|
||||||
|
|||||||
@ -79,13 +79,6 @@ function MakeContent({data}) {
|
|||||||
href={`https://www.helloasso.com/associations/${data.data1}/evenements/${data.data2}`} target="_blank"
|
href={`https://www.helloasso.com/associations/${data.data1}/evenements/${data.data2}`} target="_blank"
|
||||||
rel="noopener noreferrer">{`https://www.helloasso.com/associations/${data.data1}/evenements/${data.data2}`}</a></p>
|
rel="noopener noreferrer">{`https://www.helloasso.com/associations/${data.data1}/evenements/${data.data2}`}</a></p>
|
||||||
}
|
}
|
||||||
{data.canEditRegisters &&
|
|
||||||
<div style={{marginTop: "0.5em"}}>
|
|
||||||
<button type="button" className="btn btn-primary"
|
|
||||||
onClick={_ => navigate("/competition/" + data.id + "/register")}>Inscription - mode administrateur
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@ -342,7 +342,7 @@ function CategoryHeader({cat, setCatId}) {
|
|||||||
}, [cats]);
|
}, [cats]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (cats && cats.length > 0 && (!cat || (cats && !cats.find(c => c.id === cat.id)))) {
|
if (cats && cats.length > 0 && !cat || (cats && !cats.find(c => c.id === cat.id))) {
|
||||||
setCatId(cats.sort((a, b) => a.name.localeCompare(b.name))[0].id);
|
setCatId(cats.sort((a, b) => a.name.localeCompare(b.name))[0].id);
|
||||||
} else if (cats && cats.length === 0) {
|
} else if (cats && cats.length === 0) {
|
||||||
setModal({});
|
setModal({});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user