diff --git a/authorization/pom.xml b/authorization/pom.xml
index 7c89015..1c33e3d 100644
--- a/authorization/pom.xml
+++ b/authorization/pom.xml
@@ -28,7 +28,13 @@
nimbus-jose-jwt
9.41.1
-
+
+
+
+ org.springframework.security
+ spring-security-oauth2-resource-server
+
+
org.springframework.security
spring-security-oauth2-jose
diff --git a/authorization/src/main/java/eu/solven/kumite/account/JwtUserContextHolder.java b/authorization/src/main/java/eu/solven/kumite/account/JwtUserContextHolder.java
new file mode 100644
index 0000000..7878426
--- /dev/null
+++ b/authorization/src/main/java/eu/solven/kumite/account/JwtUserContextHolder.java
@@ -0,0 +1,29 @@
+package eu.solven.kumite.account;
+
+import java.util.UUID;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.ReactiveSecurityContextHolder;
+import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
+
+import eu.solven.kumite.security.LoginRouteButNotAuthenticatedException;
+import reactor.core.publisher.Mono;
+
+public class JwtUserContextHolder implements IKumiteUserContextHolder {
+
+ @Override
+ public Mono authenticatedAccountId() {
+ return ReactiveSecurityContextHolder.getContext().map(securityContext -> {
+ Authentication authentication = securityContext.getAuthentication();
+
+ if (authentication instanceof JwtAuthenticationToken jwtAuth) {
+ UUID accountId = UUID.fromString(jwtAuth.getToken().getSubject());
+
+ return accountId;
+ } else {
+ throw new LoginRouteButNotAuthenticatedException("Expecting a JWT token");
+ }
+ });
+ }
+
+}
diff --git a/contest-core/pom.xml b/contest-core/pom.xml
index fd3c635..c18f3b1 100644
--- a/contest-core/pom.xml
+++ b/contest-core/pom.xml
@@ -27,24 +27,6 @@
spring-boot-starter-webflux
-
-
- org.springframework.security
- spring-security-core
-
-
-
-
- org.springframework.security
- spring-security-oauth2-resource-server
-
-
-
-
- org.springframework.security
- spring-security-oauth2-jose
-
-
org.springframework.boot
spring-boot-starter-test
diff --git a/contest-core/src/main/java/eu/solven/kumite/account/InMemoryUserRepository.java b/contest-core/src/main/java/eu/solven/kumite/account/InMemoryUserRepository.java
index 463409b..2bc7c91 100644
--- a/contest-core/src/main/java/eu/solven/kumite/account/InMemoryUserRepository.java
+++ b/contest-core/src/main/java/eu/solven/kumite/account/InMemoryUserRepository.java
@@ -5,19 +5,17 @@
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
-import org.springframework.beans.factory.InitializingBean;
-
-import eu.solven.kumite.account.fake_player.FakePlayerTokens;
+import eu.solven.kumite.account.fake_player.FakePlayer;
+import eu.solven.kumite.account.fake_player.RandomPlayer;
import eu.solven.kumite.player.IAccountPlayersRegistry;
import eu.solven.kumite.player.KumitePlayer;
import eu.solven.kumite.tools.IUuidGenerator;
-import eu.solven.kumite.tools.JdkUuidGenerator;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@AllArgsConstructor
@Slf4j
-public class InMemoryUserRepository implements IKumiteUserRepository, IKumiteUserRawRawRepository, InitializingBean {
+public class InMemoryUserRepository implements IKumiteUserRepository, IKumiteUserRawRawRepository {
final Map accountIdToUser = new ConcurrentHashMap<>();
final Map accountIdToRawRaw = new ConcurrentHashMap<>();
@@ -25,15 +23,6 @@ public class InMemoryUserRepository implements IKumiteUserRepository, IKumiteUse
final IAccountPlayersRegistry playersRegistry;
- @Override
- public void afterPropertiesSet() {
- KumiteUser fakeUser = FakePlayerTokens.fakeUser();
- KumiteUserRawRaw rawRaw = fakeUser.getRaw().getRawRaw();
-
- accountIdToRawRaw.put(fakeUser.getAccountId(), rawRaw);
- accountIdToUser.put(rawRaw, fakeUser);
- }
-
@Override
public Optional getUser(KumiteUserRawRaw accountId) {
return Optional.ofNullable(accountIdToUser.get(accountId));
@@ -56,7 +45,7 @@ public KumiteUser registerOrUpdate(KumiteUserRaw kumiteUserRaw) {
return accountIdToUser.compute(rawRaw, (k, alreadyIn) -> {
KumiteUser.KumiteUserBuilder kumiteUserBuilder = KumiteUser.builder().raw(kumiteUserRaw);
if (alreadyIn == null) {
- UUID accountId = uuidGenerator.randomUUID();
+ UUID accountId = generateAccountId(rawRaw);
KumitePlayer player = register(rawRaw, accountId);
@@ -72,6 +61,19 @@ public KumiteUser registerOrUpdate(KumiteUserRaw kumiteUserRaw) {
});
}
+ protected UUID generateAccountId(KumiteUserRawRaw rawRaw) {
+ return generateAccountId(uuidGenerator, rawRaw);
+ }
+
+ public static UUID generateAccountId(IUuidGenerator uuidGenerator, KumiteUserRawRaw rawRaw) {
+ if (rawRaw.equals(FakePlayer.user().getRaw().getRawRaw())) {
+ return FakePlayer.ACCOUNT_ID;
+ } else if (rawRaw.equals(RandomPlayer.user().getRaw().getRawRaw())) {
+ return RandomPlayer.ACCOUNT_ID;
+ }
+ return uuidGenerator.randomUUID();
+ }
+
private KumitePlayer register(KumiteUserRawRaw rawRaw, UUID accountId) {
UUID playerId = playersRegistry.generateMainPlayerId(accountId);
@@ -83,12 +85,4 @@ private KumitePlayer register(KumiteUserRawRaw rawRaw, UUID accountId) {
return player;
}
-
- public static InMemoryUserRepository forTests(IAccountPlayersRegistry playersRegistry) {
- InMemoryUserRepository inMemoryUserRepository =
- new InMemoryUserRepository(JdkUuidGenerator.INSTANCE, playersRegistry);
- inMemoryUserRepository.afterPropertiesSet();
- return inMemoryUserRepository;
- }
-
}
diff --git a/contest-core/src/main/java/eu/solven/kumite/board/BoardsRegistry.java b/contest-core/src/main/java/eu/solven/kumite/board/BoardsRegistry.java
index 75d740d..c6919b9 100644
--- a/contest-core/src/main/java/eu/solven/kumite/board/BoardsRegistry.java
+++ b/contest-core/src/main/java/eu/solven/kumite/board/BoardsRegistry.java
@@ -31,4 +31,10 @@ public IHasBoard makeDynamicBoardHolder(UUID contestId) {
public void updateBoard(UUID contestId, IKumiteBoard currentBoard) {
boardRepository.updateBoard(contestId, currentBoard);
}
+
+ public void forceGameover(UUID contestId) {
+// currentBoard.
+ // TODO Auto-generated method stub
+
+ }
}
diff --git a/contest-core/src/main/java/eu/solven/kumite/contest/ActiveContestGenerator.java b/contest-core/src/main/java/eu/solven/kumite/contest/ActiveContestGenerator.java
index ba9f25d..4c00c21 100644
--- a/contest-core/src/main/java/eu/solven/kumite/contest/ActiveContestGenerator.java
+++ b/contest-core/src/main/java/eu/solven/kumite/contest/ActiveContestGenerator.java
@@ -5,7 +5,7 @@
import java.util.UUID;
import java.util.random.RandomGenerator;
-import eu.solven.kumite.account.KumiteUser;
+import eu.solven.kumite.account.fake_player.RandomPlayer;
import eu.solven.kumite.app.IKumiteSpringProfiles;
import eu.solven.kumite.board.IKumiteBoard;
import eu.solven.kumite.game.GameSearchParameters;
@@ -51,7 +51,7 @@ public void makeContestsIfNoneJoinable() {
String contestName = "Auto-generated " + randomGenerator.nextInt(128);
ContestCreationMetadata constantMetadata = ContestCreationMetadata.fromGame(gameMetadata)
.name(contestName)
- .author(KumiteUser.SERVER_ACCOUNTID)
+ .author(RandomPlayer.ACCOUNT_ID)
.build();
Contest contest = contestsRegistry.registerContest(game, constantMetadata, initialBoard);
diff --git a/contest-core/src/main/java/eu/solven/kumite/contest/ContestHandler.java b/contest-core/src/main/java/eu/solven/kumite/contest/ContestHandler.java
index fb1ef7a..883b7d4 100644
--- a/contest-core/src/main/java/eu/solven/kumite/contest/ContestHandler.java
+++ b/contest-core/src/main/java/eu/solven/kumite/contest/ContestHandler.java
@@ -7,15 +7,13 @@
import java.util.stream.Collectors;
import org.springframework.http.MediaType;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.ReactiveSecurityContextHolder;
-import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
+import eu.solven.kumite.account.IKumiteUserContextHolder;
import eu.solven.kumite.app.KumiteJackson;
import eu.solven.kumite.app.webflux.api.KumiteHandlerHelper;
import eu.solven.kumite.board.IKumiteBoard;
@@ -23,7 +21,6 @@
import eu.solven.kumite.game.GameMetadata;
import eu.solven.kumite.game.GamesRegistry;
import eu.solven.kumite.game.IGame;
-import eu.solven.kumite.security.LoginRouteButNotAuthenticatedException;
import io.micrometer.common.util.StringUtils;
import lombok.Builder;
import lombok.NonNull;
@@ -47,6 +44,9 @@ public class ContestHandler {
@NonNull
final RandomGenerator randomGenerator;
+ @NonNull
+ final IKumiteUserContextHolder kumiteUser;
+
public Mono listContests(ServerRequest request) {
ContestSearchParametersBuilder parameters = ContestSearchParameters.builder();
@@ -74,23 +74,11 @@ public Mono listContests(ServerRequest request) {
}
// BEWARE we coupled the generation of a contest and its board. This may be poor design.
- public Mono generateContest(ServerRequest request) {
+ public Mono openContest(ServerRequest request) {
UUID gameId = KumiteHandlerHelper.uuid(request, "game_id");
IGame game = gamesRegistry.getGame(gameId);
- return ReactiveSecurityContextHolder.getContext().map(securityContext -> {
- Authentication authentication = securityContext.getAuthentication();
-
- if (authentication instanceof JwtAuthenticationToken jwtAuth) {
- // jwtAuth.ge
-
- UUID accountId = UUID.fromString(jwtAuth.getToken().getSubject());
-
- return accountId;
- } else {
- throw new LoginRouteButNotAuthenticatedException("Expecting a JWT token");
- }
- }).flatMap(authorAccountId -> {
+ return kumiteUser.authenticatedAccountId().flatMap(authorAccountId -> {
return request.bodyToMono(Map.class).flatMap(contestBody -> {
Map rawConstantMetadata = (Map) contestBody.get("constant_metadata");
@@ -151,4 +139,25 @@ private ContestCreationMetadata validateConstantMetadata(UUID authorAccountId,
return mergedContestMetadata;
}
+ public Mono deleteContest(ServerRequest request) {
+ UUID contestId = KumiteHandlerHelper.uuid(request, "contest_id");
+
+ return kumiteUser.authenticatedAccountId().flatMap(authorAccountId -> {
+ ContestCreationMetadata contest = contestsRegistry.contestsRepository.getById(contestId)
+ .orElseThrow(() -> new IllegalArgumentException("There is no contest for contestId=" + contestId));
+
+ if (!contest.getAuthor().equals(authorAccountId)) {
+ throw new IllegalArgumentException("Can not DELETE contestId=%s as its author is not you (but %s)"
+ .formatted(contestId, contest.getAuthor()));
+ }
+
+ contestsRegistry.deleteContest(contestId);
+
+ return ServerResponse.ok()
+ .contentType(MediaType.APPLICATION_JSON)
+ .body(BodyInserters.fromValue(Map.of("contestId", contestId, "author", authorAccountId)));
+ });
+
+ }
+
}
\ No newline at end of file
diff --git a/contest-core/src/main/java/eu/solven/kumite/contest/ContestsRegistry.java b/contest-core/src/main/java/eu/solven/kumite/contest/ContestsRegistry.java
index 45ad100..209ca51 100644
--- a/contest-core/src/main/java/eu/solven/kumite/contest/ContestsRegistry.java
+++ b/contest-core/src/main/java/eu/solven/kumite/contest/ContestsRegistry.java
@@ -127,4 +127,10 @@ public List searchContests(ContestSearchParameters search) {
return metaStream.collect(Collectors.toList());
}
+
+ public void deleteContest(UUID contestId) {
+ boardsRegistry.forceGameover(contestId);
+ contestPlayersRegistry.forceGameover(contestId);
+ contestsRepository.archive(contestId);
+ }
}
diff --git a/contest-core/src/main/java/eu/solven/kumite/contest/persistence/IContestsRepository.java b/contest-core/src/main/java/eu/solven/kumite/contest/persistence/IContestsRepository.java
index bcb71a7..0c7f7db 100644
--- a/contest-core/src/main/java/eu/solven/kumite/contest/persistence/IContestsRepository.java
+++ b/contest-core/src/main/java/eu/solven/kumite/contest/persistence/IContestsRepository.java
@@ -27,4 +27,6 @@ public interface IContestsRepository {
Stream> stream();
+ void archive(UUID contestId);
+
}
diff --git a/contest-core/src/main/java/eu/solven/kumite/contest/persistence/InMemoryContestRepository.java b/contest-core/src/main/java/eu/solven/kumite/contest/persistence/InMemoryContestRepository.java
index a85dc8e..3d626ea 100644
--- a/contest-core/src/main/java/eu/solven/kumite/contest/persistence/InMemoryContestRepository.java
+++ b/contest-core/src/main/java/eu/solven/kumite/contest/persistence/InMemoryContestRepository.java
@@ -36,4 +36,9 @@ public void clear() {
log.info("We reset {} contests", size);
uuidToContests.clear();
}
+
+ @Override
+ public void archive(UUID contestId) {
+ // TODO Should we remove the contest?
+ }
}
diff --git a/contest-core/src/main/java/eu/solven/kumite/player/ContendersFromBoard.java b/contest-core/src/main/java/eu/solven/kumite/player/ContendersFromBoard.java
index 7f95268..1f6d5a9 100644
--- a/contest-core/src/main/java/eu/solven/kumite/player/ContendersFromBoard.java
+++ b/contest-core/src/main/java/eu/solven/kumite/player/ContendersFromBoard.java
@@ -1,5 +1,6 @@
package eu.solven.kumite.player;
+import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;
@@ -51,4 +52,13 @@ public IHasPlayers makeDynamicHasPlayers(UUID contestId) {
}).collect(Collectors.toList());
}
+ @Override
+ public void gameover(UUID contestId) {
+ Optional board = boardRepository.getBoard(contestId);
+ if (board.isPresent()) {
+ // TODO Checkif the board is actually over
+ // board.get().
+ }
+ }
+
}
diff --git a/contest-core/src/main/java/eu/solven/kumite/player/ContestPlayersRegistry.java b/contest-core/src/main/java/eu/solven/kumite/player/ContestPlayersRegistry.java
index 8a49470..21ceeac 100644
--- a/contest-core/src/main/java/eu/solven/kumite/player/ContestPlayersRegistry.java
+++ b/contest-core/src/main/java/eu/solven/kumite/player/ContestPlayersRegistry.java
@@ -166,4 +166,9 @@ public PlayerContestStatus getPlayingPlayer(UUID playerId, Contest contestMetada
return playingPlayer;
}
+
+ public void forceGameover(UUID contestId) {
+ contestToViewingAccounts.remove(contestId);
+ contestPlayersRepository.gameover(contestId);
+ }
}
diff --git a/contest-core/src/main/java/eu/solven/kumite/player/IContendersRepository.java b/contest-core/src/main/java/eu/solven/kumite/player/IContendersRepository.java
index 71e7f3b..f2c0651 100644
--- a/contest-core/src/main/java/eu/solven/kumite/player/IContendersRepository.java
+++ b/contest-core/src/main/java/eu/solven/kumite/player/IContendersRepository.java
@@ -24,4 +24,6 @@ public interface IContendersRepository {
IHasPlayers makeDynamicHasPlayers(UUID contestId);
+ void gameover(UUID contestId);
+
}
diff --git a/contest-core/src/main/java/eu/solven/kumite/player/InMemoryContendersRepository.java b/contest-core/src/main/java/eu/solven/kumite/player/InMemoryContendersRepository.java
index d76e8ed..fb05a47 100644
--- a/contest-core/src/main/java/eu/solven/kumite/player/InMemoryContendersRepository.java
+++ b/contest-core/src/main/java/eu/solven/kumite/player/InMemoryContendersRepository.java
@@ -43,4 +43,9 @@ public boolean isContender(UUID contestId, UUID playerId) {
return viewContenders(contestId).stream().anyMatch(somePlayerId -> somePlayerId.equals(playerId));
}
+ @Override
+ public void gameover(UUID contestId) {
+ contestToContenders.remove(contestId);
+ }
+
}
diff --git a/contest-core/src/main/java/eu/solven/kumite/player/persistence/BijectiveAccountPlayersRegistry.java b/contest-core/src/main/java/eu/solven/kumite/player/persistence/BijectiveAccountPlayersRegistry.java
index 28004ed..6c4e15c 100644
--- a/contest-core/src/main/java/eu/solven/kumite/player/persistence/BijectiveAccountPlayersRegistry.java
+++ b/contest-core/src/main/java/eu/solven/kumite/player/persistence/BijectiveAccountPlayersRegistry.java
@@ -5,7 +5,8 @@
import java.util.List;
import java.util.UUID;
-import eu.solven.kumite.account.fake_player.FakePlayerTokens;
+import eu.solven.kumite.account.fake_player.FakePlayer;
+import eu.solven.kumite.account.fake_player.RandomPlayer;
import eu.solven.kumite.player.IAccountPlayersRegistry;
import eu.solven.kumite.player.IHasPlayers;
import eu.solven.kumite.player.KumitePlayer;
@@ -25,8 +26,10 @@ public final class BijectiveAccountPlayersRegistry implements IAccountPlayersReg
public void registerPlayer(KumitePlayer player) {
UUID accountId = player.getAccountId();
UUID playerId = player.getPlayerId();
- if (FakePlayerTokens.FAKE_ACCOUNT_ID.equals(accountId) && FakePlayerTokens.isFakePlayer(playerId)) {
+ if (FakePlayer.ACCOUNT_ID.equals(accountId) && FakePlayer.isFakePlayer(playerId)) {
log.info("Registering the fakeUser");
+ } else if (RandomPlayer.ACCOUNT_ID.equals(accountId) && RandomPlayer.isRandomPlayer(playerId)) {
+ log.info("Registering the randomuser");
} else if (playerId.equals(generateMainPlayerId(accountId))) {
log.info("Registering accountId={} playerId={}", accountId, playerId);
} else {
@@ -36,8 +39,10 @@ public void registerPlayer(KumitePlayer player) {
@Override
public UUID getAccountId(UUID playerId) {
- if (FakePlayerTokens.isFakePlayer(playerId)) {
- return FakePlayerTokens.FAKE_ACCOUNT_ID;
+ if (FakePlayer.isFakePlayer(playerId)) {
+ return FakePlayer.ACCOUNT_ID;
+ } else if (RandomPlayer.isRandomPlayer(playerId)) {
+ return RandomPlayer.ACCOUNT_ID;
}
return accountIdGivenPlayerId(playerId);
@@ -45,8 +50,11 @@ public UUID getAccountId(UUID playerId) {
@Override
public IHasPlayers makeDynamicHasPlayers(UUID accountId) {
- if (FakePlayerTokens.FAKE_ACCOUNT_ID.equals(accountId)) {
- List players = Arrays.asList(FakePlayerTokens.fakePlayer(0), FakePlayerTokens.fakePlayer(1));
+ if (FakePlayer.ACCOUNT_ID.equals(accountId)) {
+ List players = Arrays.asList(FakePlayer.fakePlayer(0), FakePlayer.fakePlayer(1));
+ return () -> players;
+ } else if (RandomPlayer.ACCOUNT_ID.equals(accountId)) {
+ List players = Arrays.asList(RandomPlayer.randomPlayer(0), RandomPlayer.randomPlayer(1));
return () -> players;
}
@@ -58,8 +66,10 @@ public IHasPlayers makeDynamicHasPlayers(UUID accountId) {
@Override
public UUID generateMainPlayerId(UUID accountId) {
- if (FakePlayerTokens.FAKE_ACCOUNT_ID.equals(accountId)) {
- return FakePlayerTokens.FAKE_PLAYER_ID1;
+ if (FakePlayer.ACCOUNT_ID.equals(accountId)) {
+ return FakePlayer.PLAYER_ID1;
+ } else if (RandomPlayer.ACCOUNT_ID.equals(accountId)) {
+ return RandomPlayer.PLAYERID_1;
}
return playerIdGivenAccountId(accountId);
diff --git a/contest-core/src/main/java/eu/solven/kumite/player/persistence/InMemoryAccountPlayersRegistry.java b/contest-core/src/main/java/eu/solven/kumite/player/persistence/InMemoryAccountPlayersRegistry.java
index 332e81e..cf022d5 100644
--- a/contest-core/src/main/java/eu/solven/kumite/player/persistence/InMemoryAccountPlayersRegistry.java
+++ b/contest-core/src/main/java/eu/solven/kumite/player/persistence/InMemoryAccountPlayersRegistry.java
@@ -7,7 +7,8 @@
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.stream.Collectors;
-import eu.solven.kumite.account.fake_player.FakePlayerTokens;
+import eu.solven.kumite.account.fake_player.FakePlayer;
+import eu.solven.kumite.account.fake_player.RandomPlayer;
import eu.solven.kumite.player.IAccountPlayersRegistry;
import eu.solven.kumite.player.IHasPlayers;
import eu.solven.kumite.player.KumitePlayer;
@@ -27,9 +28,6 @@ public final class InMemoryAccountPlayersRegistry implements IAccountPlayersRegi
public InMemoryAccountPlayersRegistry(IUuidGenerator uuidGenerator) {
this.uuidGenerator = uuidGenerator;
-
- registerPlayer(FakePlayerTokens.fakePlayer());
- registerPlayer(FakePlayerTokens.fakePlayer(1));
}
@Override
@@ -50,10 +48,6 @@ public void registerPlayer(KumitePlayer player) {
@Override
public UUID getAccountId(UUID playerId) {
- if (FakePlayerTokens.isFakePlayer(playerId)) {
- return FakePlayerTokens.FAKE_ACCOUNT_ID;
- }
-
UUID accountId = playerIdToAccountId.get(playerId);
if (accountId == null) {
throw new IllegalArgumentException("Unknown playerId: " + playerId);
@@ -72,6 +66,12 @@ public IHasPlayers makeDynamicHasPlayers(UUID accountId) {
@Override
public UUID generateMainPlayerId(UUID accountId) {
+ if (FakePlayer.ACCOUNT_ID.equals(accountId)) {
+ return FakePlayer.PLAYER_ID1;
+ } else if (RandomPlayer.ACCOUNT_ID.equals(accountId)) {
+ return RandomPlayer.PLAYERID_1;
+ }
+
return uuidGenerator.randomUUID();
}
}
diff --git a/contest-core/src/test/java/eu/solven/kumite/player/TestBijectiveAccountPlayersRegistry.java b/contest-core/src/test/java/eu/solven/kumite/player/TestBijectiveAccountPlayersRegistry.java
index 6a4cdca..79bb52b 100644
--- a/contest-core/src/test/java/eu/solven/kumite/player/TestBijectiveAccountPlayersRegistry.java
+++ b/contest-core/src/test/java/eu/solven/kumite/player/TestBijectiveAccountPlayersRegistry.java
@@ -6,7 +6,7 @@
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
-import eu.solven.kumite.account.fake_player.FakePlayerTokens;
+import eu.solven.kumite.account.fake_player.FakePlayer;
import eu.solven.kumite.player.persistence.BijectiveAccountPlayersRegistry;
public class TestBijectiveAccountPlayersRegistry {
@@ -14,10 +14,10 @@ public class TestBijectiveAccountPlayersRegistry {
@Test
public void testFakePlayer() {
- Assertions.assertThat(playersRegistry.getAccountId(FakePlayerTokens.FAKE_PLAYER_ID1))
- .isEqualTo(FakePlayerTokens.FAKE_ACCOUNT_ID);
- Assertions.assertThat(playersRegistry.getAccountId(FakePlayerTokens.FAKE_PLAYER_ID2))
- .isEqualTo(FakePlayerTokens.FAKE_ACCOUNT_ID);
+ Assertions.assertThat(playersRegistry.getAccountId(FakePlayer.PLAYER_ID1))
+ .isEqualTo(FakePlayer.ACCOUNT_ID);
+ Assertions.assertThat(playersRegistry.getAccountId(FakePlayer.PLAYER_ID2))
+ .isEqualTo(FakePlayer.ACCOUNT_ID);
}
@Test
@@ -38,16 +38,16 @@ public void testNormalPlayer() {
@Test
public void testHasPlayers_FakePlayers() {
List players =
- playersRegistry.makeDynamicHasPlayers(FakePlayerTokens.FAKE_ACCOUNT_ID).getPlayers();
+ playersRegistry.makeDynamicHasPlayers(FakePlayer.ACCOUNT_ID).getPlayers();
Assertions.assertThat(players)
.contains(KumitePlayer.builder()
- .playerId(FakePlayerTokens.FAKE_PLAYER_ID1)
- .accountId(FakePlayerTokens.FAKE_ACCOUNT_ID)
+ .playerId(FakePlayer.PLAYER_ID1)
+ .accountId(FakePlayer.ACCOUNT_ID)
.build())
.contains(KumitePlayer.builder()
- .playerId(FakePlayerTokens.FAKE_PLAYER_ID2)
- .accountId(FakePlayerTokens.FAKE_ACCOUNT_ID)
+ .playerId(FakePlayer.PLAYER_ID2)
+ .accountId(FakePlayer.ACCOUNT_ID)
.build())
.hasSize(2);
}
diff --git a/contest-core/src/test/java/eu/solven/kumite/player/TestInMemoryAccountPlayersRegistry.java b/contest-core/src/test/java/eu/solven/kumite/player/TestInMemoryAccountPlayersRegistry.java
index 50e382a..373a25f 100644
--- a/contest-core/src/test/java/eu/solven/kumite/player/TestInMemoryAccountPlayersRegistry.java
+++ b/contest-core/src/test/java/eu/solven/kumite/player/TestInMemoryAccountPlayersRegistry.java
@@ -5,34 +5,38 @@
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
-import eu.solven.kumite.account.fake_player.FakePlayerTokens;
+import eu.solven.kumite.account.fake_player.FakePlayer;
import eu.solven.kumite.player.persistence.InMemoryAccountPlayersRegistry;
import eu.solven.kumite.tools.JdkUuidGenerator;
public class TestInMemoryAccountPlayersRegistry {
IAccountPlayersRegistry playersRegistry = new InMemoryAccountPlayersRegistry(new JdkUuidGenerator());
+ private void registerFakePlayers() {
+ playersRegistry.registerPlayer(FakePlayer.fakePlayer());
+ playersRegistry.registerPlayer(FakePlayer.fakePlayer(1));
+ }
+
@Test
public void testFakePlayer() {
- Assertions.assertThat(playersRegistry.getAccountId(FakePlayerTokens.FAKE_PLAYER_ID1))
- .isEqualTo(FakePlayerTokens.FAKE_ACCOUNT_ID);
- Assertions.assertThat(playersRegistry.getAccountId(FakePlayerTokens.FAKE_PLAYER_ID2))
- .isEqualTo(FakePlayerTokens.FAKE_ACCOUNT_ID);
+ registerFakePlayers();
+
+ Assertions.assertThat(playersRegistry.getAccountId(FakePlayer.PLAYER_ID1)).isEqualTo(FakePlayer.ACCOUNT_ID);
+ Assertions.assertThat(playersRegistry.getAccountId(FakePlayer.PLAYER_ID2)).isEqualTo(FakePlayer.ACCOUNT_ID);
}
@Test
public void testHasPlayers_FakePlayers() {
- List players =
- playersRegistry.makeDynamicHasPlayers(FakePlayerTokens.FAKE_ACCOUNT_ID).getPlayers();
+ registerFakePlayers();
+
+ List players = playersRegistry.makeDynamicHasPlayers(FakePlayer.ACCOUNT_ID).getPlayers();
Assertions.assertThat(players)
+ .contains(
+ KumitePlayer.builder().playerId(FakePlayer.PLAYER_ID1).accountId(FakePlayer.ACCOUNT_ID).build())
.contains(KumitePlayer.builder()
- .playerId(FakePlayerTokens.FAKE_PLAYER_ID1)
- .accountId(FakePlayerTokens.FAKE_ACCOUNT_ID)
- .build())
- .contains(KumitePlayer.builder()
- .playerId(FakePlayerTokens.FAKE_PLAYER_ID2)
- .accountId(FakePlayerTokens.FAKE_ACCOUNT_ID)
+ .playerId(FakePlayer.PLAYER_ID2)
+ .accountId(FakePlayer.ACCOUNT_ID)
.build())
.hasSize(2);
}
diff --git a/js/src/main/resources/static/ui/js/kumite-contest-delete.js b/js/src/main/resources/static/ui/js/kumite-contest-delete.js
new file mode 100644
index 0000000..e61b995
--- /dev/null
+++ b/js/src/main/resources/static/ui/js/kumite-contest-delete.js
@@ -0,0 +1,38 @@
+import { ref, onMounted, onUnmounted } from "vue";
+
+import { mapState } from "pinia";
+import { useKumiteStore } from "./store.js";
+
+export default {
+ props: {
+ contestId: {
+ type: String,
+ required: true,
+ },
+ gameId: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ ...mapState(useKumiteStore, ["nbGameFetching", "nbContestFetching"]),
+ ...mapState(useKumiteStore, {
+ game(store) {
+ return store.games[this.gameId];
+ },
+ contest(store) {
+ return store.contests[this.contestId];
+ },
+ }),
+ },
+ setup(props) {
+ const store = useKumiteStore();
+
+ store.loadContestIfMissing(props.gameId, props.contestId);
+
+ return {};
+ },
+ template: /* HTML */ `
+
+ `,
+};
diff --git a/js/src/main/resources/static/ui/js/kumite-contest-header.js b/js/src/main/resources/static/ui/js/kumite-contest-header.js
index 1de9a91..6806d36 100644
--- a/js/src/main/resources/static/ui/js/kumite-contest-header.js
+++ b/js/src/main/resources/static/ui/js/kumite-contest-header.js
@@ -4,10 +4,12 @@ import { mapState } from "pinia";
import { useKumiteStore } from "./store.js";
import KumiteAccountRef from "./kumite-account-ref.js";
+import KumiteContestDelete from "./kumite-contest-delete.js";
export default {
components: {
KumiteAccountRef,
+ KumiteContestDelete,
},
props: {
contestId: {
@@ -93,6 +95,9 @@ export default {
- author:
- created: {{contest.constantMetadata.created}}
+ -
+
+
`,
diff --git a/monolith/src/test/java/eu/solven/kumite/app/it/TestRandomGamingLogic.java b/monolith/src/test/java/eu/solven/kumite/app/it/TestRandomGamingLogic.java
index ae48aed..bf7e61e 100644
--- a/monolith/src/test/java/eu/solven/kumite/app/it/TestRandomGamingLogic.java
+++ b/monolith/src/test/java/eu/solven/kumite/app/it/TestRandomGamingLogic.java
@@ -20,7 +20,7 @@
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;
-import eu.solven.kumite.account.fake_player.FakePlayerTokens;
+import eu.solven.kumite.account.fake_player.RandomPlayer;
import eu.solven.kumite.app.IKumiteSpringProfiles;
import eu.solven.kumite.app.KumiteContestServerApplication;
import eu.solven.kumite.app.KumiteWebclientServerProperties;
@@ -42,7 +42,7 @@
@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = KumiteContestServerApplication.class,
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
-@ActiveProfiles({ IKumiteSpringProfiles.P_UNSAFE, IKumiteSpringProfiles.P_INMEMORY, IKumiteSpringProfiles.P_FAKEUSER })
+@ActiveProfiles({ IKumiteSpringProfiles.P_UNSAFE, IKumiteSpringProfiles.P_INMEMORY })
@TestPropertySource(properties = { "kumite.random.seed=123",
"kumite.player.wait_duration_if_no_move" + "=PT0.001S",
@@ -59,7 +59,7 @@ public class TestRandomGamingLogic {
@Test
public void testOptimization() {
- UUID playerId = FakePlayerTokens.FAKE_PLAYER_ID1;
+ UUID playerId = RandomPlayer.PLAYERID_1;
KumiteWebclientServerProperties properties = KumiteWebclientServerProperties.forTests(env, randomServerPort);
KumiteWebclientServer kumiteServer = KumiteWebclientServer.fromProperties(properties);
@@ -93,7 +93,7 @@ public void test1v1TurnBased() throws InterruptedException {
IGamingLogic kumitePlayer = new RandomGamingLogic(env, kumiteServer);
for (int iPlayer = 0; iPlayer < nbPlayers; iPlayer++) {
- UUID playerId = FakePlayerTokens.fakePlayerId(iPlayer);
+ UUID playerId = RandomPlayer.randomPlayerId(iPlayer);
executorService.execute(() -> {
try {
diff --git a/monolith/src/test/java/eu/solven/kumite/app/it/TestRandomGamingLogicRedis.java b/monolith/src/test/java/eu/solven/kumite/app/it/TestRandomGamingLogicRedis.java
index db31ff7..6543d15 100644
--- a/monolith/src/test/java/eu/solven/kumite/app/it/TestRandomGamingLogicRedis.java
+++ b/monolith/src/test/java/eu/solven/kumite/app/it/TestRandomGamingLogicRedis.java
@@ -21,7 +21,7 @@
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;
-import eu.solven.kumite.account.fake_player.FakePlayerTokens;
+import eu.solven.kumite.account.fake_player.RandomPlayer;
import eu.solven.kumite.app.IKumiteSpringProfiles;
import eu.solven.kumite.app.KumiteContestServerApplication;
import eu.solven.kumite.app.KumiteWebclientServerProperties;
@@ -44,7 +44,7 @@
@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = KumiteContestServerApplication.class,
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
-@ActiveProfiles({ IKumiteSpringProfiles.P_UNSAFE, IKumiteSpringProfiles.P_REDIS, IKumiteSpringProfiles.P_FAKEUSER })
+@ActiveProfiles({ IKumiteSpringProfiles.P_UNSAFE, IKumiteSpringProfiles.P_REDIS })
@TestPropertySource(properties = { "kumite.random.seed=123",
"kumite.player.wait_duration_if_no_move" + "=PT0.001S",
KumiteWebclientServerProperties.KEY_PLAYER_CONTESTBASEURL + "=http://localhost:LocalServerPort",
@@ -65,7 +65,7 @@ public class TestRandomGamingLogicRedis {
@Test
public void testOptimization() {
- UUID playerId = FakePlayerTokens.FAKE_PLAYER_ID1;
+ UUID playerId = RandomPlayer.PLAYERID_1;
KumiteWebclientServerProperties properties = KumiteWebclientServerProperties.forTests(env, randomServerPort);
IKumiteServer kumiteServer = KumiteWebclientServer.fromProperties(properties);
@@ -96,7 +96,7 @@ public void test1v1TurnBased() throws InterruptedException {
IGamingLogic kumitePlayer = new RandomGamingLogic(env, kumiteServer);
for (int iPlayer = 0; iPlayer < nbPlayers; iPlayer++) {
- UUID playerId = FakePlayerTokens.fakePlayerId(iPlayer);
+ UUID playerId = RandomPlayer.randomPlayerId(iPlayer);
executorService.execute(() -> {
try {
diff --git a/monolith/src/test/java/eu/solven/kumite/app/it/TestTSPLifecycleThroughRouter.java b/monolith/src/test/java/eu/solven/kumite/app/it/TestTSPLifecycleThroughRouter.java
index 4272eb4..477d680 100644
--- a/monolith/src/test/java/eu/solven/kumite/app/it/TestTSPLifecycleThroughRouter.java
+++ b/monolith/src/test/java/eu/solven/kumite/app/it/TestTSPLifecycleThroughRouter.java
@@ -14,7 +14,7 @@
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;
-import eu.solven.kumite.account.fake_player.FakePlayerTokens;
+import eu.solven.kumite.account.fake_player.RandomPlayer;
import eu.solven.kumite.app.IKumiteSpringProfiles;
import eu.solven.kumite.app.KumiteContestServerApplication;
import eu.solven.kumite.app.KumiteWebclientServerProperties;
@@ -37,7 +37,7 @@
@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = KumiteContestServerApplication.class,
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
-@ActiveProfiles({ IKumiteSpringProfiles.P_UNSAFE, IKumiteSpringProfiles.P_INMEMORY, IKumiteSpringProfiles.P_FAKEUSER })
+@ActiveProfiles({ IKumiteSpringProfiles.P_UNSAFE, IKumiteSpringProfiles.P_INMEMORY })
@TestPropertySource(properties = { "kumite.random.seed=123",
"kumite.player.wait_duration_if_no_move" + "=PT0.001S",
KumiteWebclientServerProperties.KEY_PLAYER_CONTESTBASEURL + "=http://localhost:LocalServerPort" })
@@ -53,7 +53,7 @@ public class TestTSPLifecycleThroughRouter {
@Test
public void testSinglePlayer() {
- UUID playerId = FakePlayerTokens.FAKE_PLAYER_ID1;
+ UUID playerId = RandomPlayer.PLAYERID_1;
KumiteWebclientServerProperties properties = KumiteWebclientServerProperties.forTests(env, randomServerPort);
IKumiteServer kumiteServer = KumiteWebclientServer.fromProperties(properties);
diff --git a/player/src/main/java/eu/solven/kumite/app/KumiteWebclientServerProperties.java b/player/src/main/java/eu/solven/kumite/app/KumiteWebclientServerProperties.java
index 89d909b..c914f62 100644
--- a/player/src/main/java/eu/solven/kumite/app/KumiteWebclientServerProperties.java
+++ b/player/src/main/java/eu/solven/kumite/app/KumiteWebclientServerProperties.java
@@ -3,7 +3,8 @@
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
-import eu.solven.kumite.account.fake_player.FakePlayerTokens;
+import eu.solven.kumite.account.fake_player.FakePlayer;
+import eu.solven.kumite.account.fake_player.RandomPlayer;
import eu.solven.kumite.login.RefreshTokenWrapper;
import eu.solven.kumite.oauth2.authorizationserver.KumiteTokenService;
import eu.solven.kumite.tools.IUuidGenerator;
@@ -20,6 +21,7 @@ public class KumiteWebclientServerProperties {
public static final String ENV_REFRESH_TOKEN = "kumite.player.refresh_token";
public static final String PLACEHOLDER_GENERATEFAKEPLAYER = "GENERATE_FAKEUSER";
+ public static final String PLACEHOLDER_GENERATERANDOMPLAYER = "GENERATE_RANDOMUSER";
String baseUrl;
String refreshToken;
@@ -36,8 +38,16 @@ public static String loadRefreshToken(Environment env, IUuidGenerator uuidGenera
log.info("Generating on-the-fly a fakeUser refreshToken");
}
KumiteTokenService kumiteTokenService = new KumiteTokenService(env, uuidGenerator);
- RefreshTokenWrapper wrappedRefreshToken = kumiteTokenService
- .wrapInJwtRefreshToken(FakePlayerTokens.fakeUser(), FakePlayerTokens.fakePlayers());
+ RefreshTokenWrapper wrappedRefreshToken =
+ kumiteTokenService.wrapInJwtRefreshToken(FakePlayer.user(), FakePlayer.fakePlayers());
+ refreshToken = wrappedRefreshToken.getRefreshToken();
+ } else if (KumiteWebclientServerProperties.PLACEHOLDER_GENERATERANDOMPLAYER.equals(refreshToken)) {
+ {
+ log.info("Generating on-the-fly a fakeUser refreshToken");
+ }
+ KumiteTokenService kumiteTokenService = new KumiteTokenService(env, uuidGenerator);
+ RefreshTokenWrapper wrappedRefreshToken =
+ kumiteTokenService.wrapInJwtRefreshToken(RandomPlayer.user(), RandomPlayer.randomPlayers());
refreshToken = wrappedRefreshToken.getRefreshToken();
}
return refreshToken;
@@ -46,7 +56,7 @@ public static String loadRefreshToken(Environment env, IUuidGenerator uuidGenera
public static KumiteWebclientServerProperties forTests(Environment env, int randomServerPort) {
String refreshToken = loadRefreshToken(env,
JdkUuidGenerator.INSTANCE,
- KumiteWebclientServerProperties.PLACEHOLDER_GENERATEFAKEPLAYER);
+ KumiteWebclientServerProperties.PLACEHOLDER_GENERATERANDOMPLAYER);
// https://github.com/spring-projects/spring-boot/issues/5077
String baseUrl = env.getRequiredProperty(KEY_PLAYER_CONTESTBASEURL)
diff --git a/player/src/test/java/eu/solven/kumite/app/TestParseFakePlayer.java b/player/src/test/java/eu/solven/kumite/app/TestParseFakePlayer.java
index 0b86686..1b362f7 100644
--- a/player/src/test/java/eu/solven/kumite/app/TestParseFakePlayer.java
+++ b/player/src/test/java/eu/solven/kumite/app/TestParseFakePlayer.java
@@ -13,6 +13,7 @@
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;
+import eu.solven.kumite.account.fake_player.RandomPlayer;
import lombok.extern.slf4j.Slf4j;
@ExtendWith(SpringExtension.class)
@@ -21,11 +22,11 @@
// Enables generation on-the-fly on refreshToken
IKumiteSpringProfiles.P_UNSAFE_OAUTH2,
// Enables playing as fakeUser
- IKumiteSpringProfiles.P_FAKEUSER,
+ // IKumiteSpringProfiles.P_FAKEUSER,
IKumiteSpringProfiles.P_UNSAFE_PLAYER })
@TestPropertySource(properties = { KumiteWebclientServerProperties.KEY_PLAYER_CONTESTBASEURL + "=someUrl",
KumiteWebclientServerProperties.ENV_REFRESH_TOKEN + "="
- + KumiteWebclientServerProperties.PLACEHOLDER_GENERATEFAKEPLAYER })
+ + KumiteWebclientServerProperties.PLACEHOLDER_GENERATERANDOMPLAYER })
@Slf4j
public class TestParseFakePlayer implements IKumiteSpringProfiles {
@@ -43,8 +44,8 @@ public void testPlayerIdFromAccessToken() {
Set playerIds = conf.playerIdFromRefreshToken(kumiteWebclientServerProperties);
Assertions.assertThat(playerIds)
- .contains(UUID.fromString("11111111-1111-1111-1111-111111111111"))
- .contains(UUID.fromString("11111111-1111-1111-1111-222222222222"))
+ .contains(RandomPlayer.randomPlayer(0).getPlayerId())
+ .contains(RandomPlayer.randomPlayer(1).getPlayerId())
.hasSize(2);
}
}
diff --git a/public/src/main/java/eu/solven/kumite/account/KumiteUser.java b/public/src/main/java/eu/solven/kumite/account/KumiteUser.java
index fb4ea57..383a879 100644
--- a/public/src/main/java/eu/solven/kumite/account/KumiteUser.java
+++ b/public/src/main/java/eu/solven/kumite/account/KumiteUser.java
@@ -21,9 +21,6 @@
@Jacksonized
@Slf4j
public class KumiteUser {
- // Used to create contests
- public static final UUID SERVER_ACCOUNTID = UUID.fromString("FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF");
-
// Multiple Users may be attached to the same account (e.g. by using different OAuth2 providers)
@NonNull
UUID accountId;
diff --git a/public/src/main/java/eu/solven/kumite/account/fake_player/FakePlayerTokens.java b/public/src/main/java/eu/solven/kumite/account/fake_player/FakePlayer.java
similarity index 61%
rename from public/src/main/java/eu/solven/kumite/account/fake_player/FakePlayerTokens.java
rename to public/src/main/java/eu/solven/kumite/account/fake_player/FakePlayer.java
index 1091877..bf43709 100644
--- a/public/src/main/java/eu/solven/kumite/account/fake_player/FakePlayerTokens.java
+++ b/public/src/main/java/eu/solven/kumite/account/fake_player/FakePlayer.java
@@ -17,52 +17,52 @@
*
*/
@Slf4j
-public class FakePlayerTokens {
+public class FakePlayer {
// IKumiteSpringProfiles.P_DEFAULT_FAKE_USER
- public static final UUID FAKE_ACCOUNT_ID = UUID.fromString("11111111-1111-1111-1111-000000000000");
- public static final UUID FAKE_PLAYER_ID1 = UUID.fromString("11111111-1111-1111-1111-111111111111");
- public static final UUID FAKE_PLAYER_ID2 = UUID.fromString("11111111-1111-1111-1111-222222222222");
+ public static final UUID ACCOUNT_ID = UUID.fromString("11111111-1111-1111-1111-000000000000");
+ public static final UUID PLAYER_ID1 = UUID.fromString("11111111-1111-1111-1111-111111111111");
+ public static final UUID PLAYER_ID2 = UUID.fromString("11111111-1111-1111-1111-222222222222");
public static UUID fakePlayerId(int playerIndex) {
if (playerIndex == 0) {
- return FAKE_PLAYER_ID1;
+ return PLAYER_ID1;
} else if (playerIndex == 1) {
- return FAKE_PLAYER_ID2;
+ return PLAYER_ID2;
} else {
throw new IllegalArgumentException("There is no fakePlayer for playerIndex=" + playerIndex);
}
}
public static boolean isFakePlayer(UUID playerId) {
- if (FAKE_PLAYER_ID1.equals(playerId) || FAKE_PLAYER_ID2.equals(playerId)) {
+ if (PLAYER_ID1.equals(playerId) || PLAYER_ID2.equals(playerId)) {
return true;
} else {
return false;
}
}
- public static KumiteUser fakeUser() {
- KumiteUserRawRaw rawRaw = KumiteUserRawRaw.builder().providerId("fakeProviderId").sub("fakeSub").build();
+ public static KumiteUser user() {
+ KumiteUserRawRaw rawRaw = KumiteUserRawRaw.builder().providerId("kumite").sub("fakeSub").build();
KumiteUserRaw raw = KumiteUserRaw.builder()
.rawRaw(rawRaw)
.username("fakeUsername")
.email("fake@fake")
.name("Fake User")
.build();
- return KumiteUser.builder().accountId(FAKE_ACCOUNT_ID).playerId(FAKE_PLAYER_ID1).raw(raw).build();
+ return KumiteUser.builder().accountId(ACCOUNT_ID).playerId(PLAYER_ID1).raw(raw).build();
}
public static KumitePlayer fakePlayer() {
- return KumitePlayer.builder().playerId(FAKE_PLAYER_ID1).accountId(FAKE_ACCOUNT_ID).build();
+ return KumitePlayer.builder().playerId(PLAYER_ID1).accountId(ACCOUNT_ID).build();
}
public static KumitePlayer fakePlayer(int i) {
- return KumitePlayer.builder().playerId(fakePlayerId(i)).accountId(FAKE_ACCOUNT_ID).build();
+ return KumitePlayer.builder().playerId(fakePlayerId(i)).accountId(ACCOUNT_ID).build();
}
public static Set fakePlayers() {
- return Set.of(FakePlayerTokens.FAKE_PLAYER_ID1, FakePlayerTokens.FAKE_PLAYER_ID2);
+ return Set.of(FakePlayer.PLAYER_ID1, FakePlayer.PLAYER_ID2);
}
}
diff --git a/public/src/main/java/eu/solven/kumite/account/fake_player/RandomPlayer.java b/public/src/main/java/eu/solven/kumite/account/fake_player/RandomPlayer.java
new file mode 100644
index 0000000..954e554
--- /dev/null
+++ b/public/src/main/java/eu/solven/kumite/account/fake_player/RandomPlayer.java
@@ -0,0 +1,67 @@
+package eu.solven.kumite.account.fake_player;
+
+import java.util.Set;
+import java.util.UUID;
+
+import eu.solven.kumite.account.KumiteUser;
+import eu.solven.kumite.account.KumiteUserRaw;
+import eu.solven.kumite.account.KumiteUserRawRaw;
+import eu.solven.kumite.player.KumitePlayer;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * Various tools specific to the RandomPlayer. This player is useful to generate activity even for a PRD contest-server,
+ * circumventing the need for an actual login flow, with an external login provider.
+ *
+ * @author Benoit Lacelle
+ *
+ */
+@Slf4j
+public class RandomPlayer {
+
+ public static final UUID ACCOUNT_ID = UUID.fromString("FFFFFFFF-FFFF-FFFF-FFFF-000000000000");
+ public static final UUID PLAYERID_1 = UUID.fromString("FFFFFFFF-FFFF-FFFF-FFFF-111111111111");
+ public static final UUID RANDOM_PLAYERID2 = UUID.fromString("FFFFFFFF-FFFF-FFFF-FFFF-222222222222");
+
+ public static UUID randomPlayerId(int playerIndex) {
+ if (playerIndex == 0) {
+ return PLAYERID_1;
+ } else if (playerIndex == 1) {
+ return RANDOM_PLAYERID2;
+ } else {
+ throw new IllegalArgumentException("There is no randomPlayer for playerIndex=" + playerIndex);
+ }
+ }
+
+ public static boolean isRandomPlayer(UUID playerId) {
+ if (PLAYERID_1.equals(playerId) || RANDOM_PLAYERID2.equals(playerId)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public static KumiteUser user() {
+ KumiteUserRawRaw rawRaw = KumiteUserRawRaw.builder().providerId("kumite").sub("randomSub").build();
+ KumiteUserRaw raw = KumiteUserRaw.builder()
+ .rawRaw(rawRaw)
+ .username("randomUsername")
+ .email("random@random")
+ .name("Random User")
+ .build();
+ return KumiteUser.builder().accountId(ACCOUNT_ID).playerId(PLAYERID_1).raw(raw).build();
+ }
+
+ public static KumitePlayer randomPlayer() {
+ return KumitePlayer.builder().playerId(PLAYERID_1).accountId(ACCOUNT_ID).build();
+ }
+
+ public static KumitePlayer randomPlayer(int i) {
+ return KumitePlayer.builder().playerId(randomPlayerId(i)).accountId(ACCOUNT_ID).build();
+ }
+
+ public static Set randomPlayers() {
+ return Set.of(RandomPlayer.PLAYERID_1, RandomPlayer.RANDOM_PLAYERID2);
+ }
+
+}
diff --git a/redis/src/main/java/eu/solven/kumite/contest/persistence/RedisContestRepository.java b/redis/src/main/java/eu/solven/kumite/contest/persistence/RedisContestRepository.java
index 64a33a7..b51d452 100644
--- a/redis/src/main/java/eu/solven/kumite/contest/persistence/RedisContestRepository.java
+++ b/redis/src/main/java/eu/solven/kumite/contest/persistence/RedisContestRepository.java
@@ -77,4 +77,9 @@ public Stream> stream() {
.map(contestId -> Map.entry(contestId, getById(contestId).orElse(ContestCreationMetadata.empty())))
.filter(e -> !e.getValue().getGameId().equals(IGameMetadataConstants.EMPTY));
}
+
+ @Override
+ public void archive(UUID contestId) {
+ // Do not remove, as TTL will do its job in due-time
+ }
}
diff --git a/redis/src/main/java/eu/solven/kumite/user/RedisUserRepository.java b/redis/src/main/java/eu/solven/kumite/user/RedisUserRepository.java
index f0dcf52..a3914d7 100644
--- a/redis/src/main/java/eu/solven/kumite/user/RedisUserRepository.java
+++ b/redis/src/main/java/eu/solven/kumite/user/RedisUserRepository.java
@@ -8,10 +8,10 @@
import eu.solven.kumite.account.IKumiteUserRawRawRepository;
import eu.solven.kumite.account.IKumiteUserRepository;
+import eu.solven.kumite.account.InMemoryUserRepository;
import eu.solven.kumite.account.KumiteUser;
import eu.solven.kumite.account.KumiteUserRaw;
import eu.solven.kumite.account.KumiteUserRawRaw;
-import eu.solven.kumite.account.fake_player.FakePlayerTokens;
import eu.solven.kumite.player.IAccountPlayersRegistry;
import eu.solven.kumite.player.KumitePlayer;
import eu.solven.kumite.redis.RepositoryKey;
@@ -103,11 +103,8 @@ public KumiteUser registerOrUpdate(KumiteUserRaw kumiteUserRaw) {
return getUser(rawRaw).orElseThrow(() -> new IllegalStateException("No user through we just registered one"));
}
- private UUID generateAccountId(KumiteUserRawRaw rawRaw) {
- if (rawRaw.equals(FakePlayerTokens.fakeUser().getRaw().getRawRaw())) {
- return FakePlayerTokens.FAKE_ACCOUNT_ID;
- }
- return uuidGenerator.randomUUID();
+ protected UUID generateAccountId(KumiteUserRawRaw rawRaw) {
+ return InMemoryUserRepository.generateAccountId(uuidGenerator, rawRaw);
}
}
diff --git a/server/pom.xml b/server/pom.xml
index 66e01ed..bc7caa6 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -39,11 +39,6 @@
spring-boot-starter-oauth2-client
-
- org.springframework.boot
- spring-boot-starter-oauth2-resource-server
-
-
org.springframework.boot
diff --git a/server/src/main/java/eu/solven/kumite/app/InjectKumiteAccountsConfig.java b/server/src/main/java/eu/solven/kumite/app/InjectKumiteAccountsConfig.java
new file mode 100644
index 0000000..0917bd6
--- /dev/null
+++ b/server/src/main/java/eu/solven/kumite/app/InjectKumiteAccountsConfig.java
@@ -0,0 +1,37 @@
+package eu.solven.kumite.app;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+
+import eu.solven.kumite.account.KumiteUsersRegistry;
+import eu.solven.kumite.account.fake_player.FakePlayer;
+import eu.solven.kumite.account.fake_player.RandomPlayer;
+import eu.solven.kumite.player.IAccountPlayersRegistry;
+import lombok.extern.slf4j.Slf4j;
+
+@Configuration
+@Slf4j
+public class InjectKumiteAccountsConfig {
+
+ @Profile(IKumiteSpringProfiles.P_FAKEUSER)
+ @Bean
+ public Void initFakePlayer(KumiteUsersRegistry usersRegistry, IAccountPlayersRegistry accountPlayersRegistry) {
+ log.info("Registering the {} account and players", IKumiteSpringProfiles.P_FAKEUSER);
+
+ usersRegistry.registerOrUpdate(FakePlayer.user().getRaw());
+ accountPlayersRegistry.registerPlayer(FakePlayer.fakePlayer(1));
+
+ return null;
+ }
+
+ @Bean
+ public Void initRandomPlayer(KumiteUsersRegistry usersRegistry, IAccountPlayersRegistry accountPlayersRegistry) {
+ log.info("Registering the random account and players");
+
+ usersRegistry.registerOrUpdate(RandomPlayer.user().getRaw());
+ accountPlayersRegistry.registerPlayer(RandomPlayer.randomPlayer(1));
+
+ return null;
+ }
+}
diff --git a/server/src/main/java/eu/solven/kumite/app/KumiteServerComponentsConfiguration.java b/server/src/main/java/eu/solven/kumite/app/KumiteServerComponentsConfiguration.java
index 6e49a3c..3fa106b 100644
--- a/server/src/main/java/eu/solven/kumite/app/KumiteServerComponentsConfiguration.java
+++ b/server/src/main/java/eu/solven/kumite/app/KumiteServerComponentsConfiguration.java
@@ -6,10 +6,8 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
-import org.springframework.context.annotation.Profile;
import eu.solven.kumite.account.KumiteUsersRegistry;
-import eu.solven.kumite.account.fake_player.FakePlayerTokens;
import eu.solven.kumite.app.persistence.InMemoryKumiteConfiguration;
import eu.solven.kumite.app.persistence.RedisKumiteConfiguration;
import eu.solven.kumite.board.BoardHandler;
@@ -45,6 +43,7 @@
PlayerMovesHandler.class,
InjectDefaultGamesConfig.class,
+ InjectKumiteAccountsConfig.class,
ContendersFromBoard.class,
@@ -63,14 +62,4 @@ public BoardLifecycleManager boardLifecycleManager(BoardsRegistry boardRegistry,
return new BoardLifecycleManager(boardRegistry, contestPlayersRegistry, boardEvolutionExecutor);
}
-
- @Profile(IKumiteSpringProfiles.P_FAKEUSER)
- @Bean
- public Void initFakePlayer(KumiteUsersRegistry usersRegistry) {
- log.info("Registering the {} account and players", IKumiteSpringProfiles.P_FAKEUSER);
-
- usersRegistry.registerOrUpdate(FakePlayerTokens.fakeUser().getRaw());
-
- return null;
- }
}
diff --git a/server/src/main/java/eu/solven/kumite/app/webflux/api/KumiteApiRouter.java b/server/src/main/java/eu/solven/kumite/app/webflux/api/KumiteApiRouter.java
index 5d367b4..90b5d6e 100644
--- a/server/src/main/java/eu/solven/kumite/app/webflux/api/KumiteApiRouter.java
+++ b/server/src/main/java/eu/solven/kumite/app/webflux/api/KumiteApiRouter.java
@@ -77,9 +77,10 @@ public RouterFunction apiRoutes(PlayerVerifierFilterFunction pla
.GET(json("/contests"),
contestSearchHandler::listContests,
ops -> ops.operationId("searchContest").parameter(gameId))
- .POST(json("/contests"),
- contestSearchHandler::generateContest,
- ops -> ops.operationId("publishContest"))
+ .POST(json("/contests"), contestSearchHandler::openContest, ops -> ops.operationId("publishContest"))
+ .DELETE(json("/contests"),
+ contestSearchHandler::openContest,
+ ops -> ops.operationId("deleteContest").parameter(contestId))
.GET(json("/board"),
boardHandler::getBoard,
@@ -114,8 +115,6 @@ public RouterFunction apiRoutes(PlayerVerifierFilterFunction pla
// webhooksHandler::dropWebhooks,
// ops -> ops.operationId("deleteWebhook"))
- .filter(playerVerifierFilterFunction, ops -> {
- })
.build();
}
diff --git a/server/src/main/java/eu/solven/kumite/app/webflux/api/KumiteLoginController.java b/server/src/main/java/eu/solven/kumite/app/webflux/api/KumiteLoginController.java
index dda35d6..e6e418e 100644
--- a/server/src/main/java/eu/solven/kumite/app/webflux/api/KumiteLoginController.java
+++ b/server/src/main/java/eu/solven/kumite/app/webflux/api/KumiteLoginController.java
@@ -15,7 +15,11 @@
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
+import org.springframework.security.core.context.ReactiveSecurityContextHolder;
+import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.oauth2.client.registration.InMemoryReactiveClientRegistrationRepository;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.user.OAuth2User;
@@ -30,7 +34,6 @@
import eu.solven.kumite.account.KumiteUser;
import eu.solven.kumite.account.KumiteUserRawRaw;
import eu.solven.kumite.account.KumiteUsersRegistry;
-import eu.solven.kumite.account.fake_player.FakePlayerTokens;
import eu.solven.kumite.account.login.IKumiteTestConstants;
import eu.solven.kumite.app.IKumiteSpringProfiles;
import eu.solven.kumite.oauth2.authorizationserver.KumiteTokenService;
@@ -38,6 +41,7 @@
import eu.solven.kumite.player.KumitePlayer;
import eu.solven.kumite.security.LoginRouteButNotAuthenticatedException;
import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Mono;
/**
@@ -49,6 +53,7 @@
@RestController
@RequestMapping("/api/login/v1")
@AllArgsConstructor
+@Slf4j
public class KumiteLoginController {
public static final String PROVIDERID_GITHUB = "github";
@Deprecated
@@ -88,12 +93,12 @@ public class KumiteLoginController {
@GetMapping("/html")
public ResponseEntity> loginpage(@AuthenticationPrincipal OAuth2User oauth2User) {
String url;
- if (env.acceptsProfiles(Profiles.of(IKumiteSpringProfiles.P_FAKEUSER))) {
+ if (oauth2User != null) {
+ url = "login?success";
+ } else if (env.acceptsProfiles(Profiles.of(IKumiteSpringProfiles.P_FAKEUSER))) {
url = "login?" + IKumiteSpringProfiles.P_FAKEUSER;
- } else if (oauth2User == null) {
- url = "login";
} else {
- url = "login?success";
+ url = "login";
}
// Spring-OAuth2-Login returns FOUND in case current user is not authenticated: let's follow this choice is=n
@@ -103,19 +108,26 @@ public ResponseEntity> loginpage(@AuthenticationPrincipal OAuth2User oauth2Use
// @PreAuthorize("isAuthenticated()")
@GetMapping("/user")
- public Mono user(@AuthenticationPrincipal Mono oauth2User) {
- if (env.acceptsProfiles(Profiles.of(IKumiteSpringProfiles.P_FAKEUSER))) {
- return Mono.just(usersRegistry.getUser(FakePlayerTokens.FAKE_ACCOUNT_ID));
- } else if (oauth2User == null) {
- // Happens if this route is called without authentication
- return Mono.error(() -> new LoginRouteButNotAuthenticatedException("Lack of OAuth2 user"));
- } else {
- return oauth2User.map(o -> {
- KumiteUser user = userFromOAuth2(o);
+ public Mono user() {
+ return ReactiveSecurityContextHolder.getContext().map(sc -> {
+ Authentication authentication = sc.getAuthentication();
+
+ if (authentication instanceof UsernamePasswordAuthenticationToken usernameToken) {
+ // This happens on BASIC auth (for fakePlayer)
+ return userFromUsername(usernameToken);
+ } else if (authentication instanceof OAuth2AuthenticationToken oauth2Token) {
+ // This happens on OAuth2 auth (e.g. Github login)
+ return userFromOAuth2(oauth2Token.getPrincipal());
+ } else {
+ throw new LoginRouteButNotAuthenticatedException("Lack of authentication");
+ }
+ }).switchIfEmpty(Mono.error(() -> new LoginRouteButNotAuthenticatedException("No user")));
+ }
- return user;
- }).switchIfEmpty(Mono.error(() -> new LoginRouteButNotAuthenticatedException("No user")));
- }
+ private KumiteUser userFromUsername(UsernamePasswordAuthenticationToken usernameToken) {
+ UUID accountId = UUID.fromString(usernameToken.getName());
+ KumiteUser user = usersRegistry.getUser(accountId);
+ return user;
}
private KumiteUser userFromOAuth2(OAuth2User o) {
@@ -152,10 +164,9 @@ private String guessProviderId(OAuth2User o) {
}
@GetMapping("/oauth2/token")
- public Mono> token(@AuthenticationPrincipal Mono oauth2User,
- @RequestParam(name = "player_id", required = false) String rawPlayerId,
+ public Mono> token(@RequestParam(name = "player_id", required = false) String rawPlayerId,
@RequestParam(name = "refresh_token", defaultValue = "false") boolean requestRefreshToken) {
- return user(oauth2User).map(user -> {
+ return user().map(user -> {
if (requestRefreshToken) {
// TODO Restrict if `rawPlayerId` is provided.
if (!StringUtils.isEmpty(rawPlayerId)) {
@@ -164,11 +175,13 @@ public Mono> token(@AuthenticationPrincipal Mono oauth2User,
List players = playersRegistry.makeDynamicHasPlayers(user.getAccountId()).getPlayers();
// Beware this would not allow playerIds generated after the refresh_token creation
Set playerIds = players.stream().map(KumitePlayer::getPlayerId).collect(Collectors.toSet());
+ log.info("Generating an refresh_token for accountId={} playerIds={}", user.getAccountId(), playerIds);
return kumiteTokenService.wrapInJwtRefreshToken(user, playerIds);
} else {
UUID playerId =
KumiteHandlerHelper.optUuid(Optional.ofNullable(rawPlayerId)).orElse(user.getPlayerId());
checkValidPlayerId(user, playerId);
+ log.info("Generating an access_token for accountId={} playerId={}", user.getAccountId(), playerId);
return kumiteTokenService.wrapInJwtAccessToken(user, playerId);
}
});
diff --git a/server/src/main/java/eu/solven/kumite/security/KumiteSecurity.java b/server/src/main/java/eu/solven/kumite/security/KumiteSecurity.java
index 17d1d9a..375d272 100644
--- a/server/src/main/java/eu/solven/kumite/security/KumiteSecurity.java
+++ b/server/src/main/java/eu/solven/kumite/security/KumiteSecurity.java
@@ -8,6 +8,7 @@
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.WebExceptionHandler;
+import eu.solven.kumite.account.JwtUserContextHolder;
import eu.solven.kumite.app.IKumiteSpringProfiles;
import eu.solven.kumite.app.webflux.KumiteWebExceptionHandler;
import eu.solven.kumite.app.webflux.api.KumiteLoginController;
@@ -30,6 +31,8 @@
KumiteResourceServerConfiguration.class,
KumiteTokenService.class,
+ JwtUserContextHolder.class,
+
})
@Slf4j
public class KumiteSecurity {
@@ -68,10 +71,10 @@ public Void checkSpringProfilesConsistency(Environment env) {
return null;
}
-// @Bean
-// WebFilter kumiteExceptionRoutingWebFilter() {
-// return new KumiteExceptionRoutingWebFilter();
-// }
+ // @Bean
+ // WebFilter kumiteExceptionRoutingWebFilter() {
+ // return new KumiteExceptionRoutingWebFilter();
+ // }
@Bean
WebExceptionHandler kumiteWebExceptionHandler() {
diff --git a/server/src/main/java/eu/solven/kumite/security/SocialWebFluxSecurity.java b/server/src/main/java/eu/solven/kumite/security/SocialWebFluxSecurity.java
index f0d10e7..aa1d5c6 100644
--- a/server/src/main/java/eu/solven/kumite/security/SocialWebFluxSecurity.java
+++ b/server/src/main/java/eu/solven/kumite/security/SocialWebFluxSecurity.java
@@ -1,6 +1,8 @@
package eu.solven.kumite.security;
import java.net.URI;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.context.annotation.Bean;
@@ -10,19 +12,25 @@
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
+import org.springframework.security.authentication.UserDetailsRepositoryReactiveAuthenticationManager;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
+import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder;
import org.springframework.security.oauth2.server.resource.web.server.BearerTokenServerAuthenticationEntryPoint;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.authentication.RedirectServerAuthenticationSuccessHandler;
import org.springframework.security.web.server.authentication.logout.RedirectServerLogoutSuccessHandler;
+import org.springframework.security.web.server.context.WebSessionServerSecurityContextRepository;
import org.springframework.security.web.server.csrf.WebSessionServerCsrfTokenRepository;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers;
import com.nimbusds.jwt.JWT;
+import eu.solven.kumite.account.fake_player.FakePlayer;
import eu.solven.kumite.app.IKumiteSpringProfiles;
import eu.solven.kumite.oauth2.resourceserver.KumiteResourceServerConfiguration;
import eu.solven.kumite.security.oauth2.KumiteOAuth2UserService;
@@ -47,11 +55,13 @@ public class SocialWebFluxSecurity {
public SecurityWebFilterChain configureUi(ServerProperties serverProperties,
ServerHttpSecurity http,
Environment env) {
- boolean isSsl = serverProperties.getSsl() != null && serverProperties.getSsl().isEnabled();
- ReactiveAuthenticationManager ram = auth -> {
- throw new IllegalStateException();
- };
+ boolean isFakeUser = env.acceptsProfiles(Profiles.of(IKumiteSpringProfiles.P_FAKEUSER));
+ if (isFakeUser) {
+ log.warn("{}=true", IKumiteSpringProfiles.P_FAKEUSER);
+ } else {
+ log.info("{}=false", IKumiteSpringProfiles.P_FAKEUSER);
+ }
return http
// We restrict the scope of this UI securityFilterChain to UI routes
@@ -123,7 +133,11 @@ public SecurityWebFilterChain configureUi(ServerProperties serverProperties,
// `/html/login` has to be synced with the SPA login route
.formLogin(login -> {
- String loginPage = "/html/login".formatted(isSsl ? "s" : "");
+ ReactiveAuthenticationManager ram = auth -> {
+ throw new IllegalStateException();
+ };
+
+ String loginPage = "/html/login";
login.loginPage(loginPage)
// Required not to get an NPE at `.build()`
.authenticationManager(ram);
@@ -132,10 +146,34 @@ public SecurityWebFilterChain configureUi(ServerProperties serverProperties,
// https://docs.spring.io/spring-security/reference/servlet/oauth2/client/authorization-grants.html
// https://stackoverflow.com/questions/74242738/how-to-logout-from-oauth-signed-in-web-app-with-github
.oauth2Login(oauth2 -> {
- String loginSuccess = "/html/login?success".formatted(isSsl ? "s" : "");
+ String loginSuccess = "/html/login?success";
oauth2.authenticationSuccessHandler(new RedirectServerAuthenticationSuccessHandler(loginSuccess));
})
+ .httpBasic(basic -> {
+ Map userDetails = new ConcurrentHashMap<>();
+
+ UserDetails fakeUser = User.builder()
+ .username(FakePlayer.ACCOUNT_ID.toString())
+ // `{noop}` relates with `PasswordEncoderFactories.createDelegatingPasswordEncoder()`
+ .password("{noop}" + "no_password")
+ .roles(IKumiteSpringProfiles.P_FAKEUSER)
+ .build();
+
+ userDetails.put(fakeUser.getUsername(), fakeUser);
+
+ UserDetailsRepositoryReactiveAuthenticationManager ram =
+ new UserDetailsRepositoryReactiveAuthenticationManager(
+ new MapReactiveUserDetailsService(userDetails));
+
+ if (isFakeUser) {
+ basic.authenticationManager(ram)
+ .securityContextRepository(new WebSessionServerSecurityContextRepository());
+ } else {
+ basic.disable();
+ }
+ })
+
.logout(logout -> {
RedirectServerLogoutSuccessHandler logoutSuccessHandler = new RedirectServerLogoutSuccessHandler();
// We need to redirect to a 2XX URL, and not a 3XX URL, as Fetch API can not intercept redirections.
@@ -161,8 +199,8 @@ public SecurityWebFilterChain configureApi(ServerHttpSecurity http,
Environment env,
ReactiveJwtDecoder jwtDecoder) {
- boolean fakeUser = env.acceptsProfiles(Profiles.of(IKumiteSpringProfiles.P_FAKEUSER));
- if (fakeUser) {
+ boolean isFakeUser = env.acceptsProfiles(Profiles.of(IKumiteSpringProfiles.P_FAKEUSER));
+ if (isFakeUser) {
log.warn("{}=true", IKumiteSpringProfiles.P_FAKEUSER);
} else {
log.info("{}=false", IKumiteSpringProfiles.P_FAKEUSER);
@@ -195,7 +233,7 @@ public SecurityWebFilterChain configureApi(ServerHttpSecurity http,
.permitAll()
// If fakeUser==true, we allow the reset route (for integration tests)
- .pathMatchers(fakeUser ? "/api/v1/clear" : "nonono")
+ .pathMatchers(isFakeUser ? "/api/v1/clear" : "nonono")
.permitAll()
// The rest needs to be authenticated
diff --git a/server/src/test/java/eu/solven/kumite/account/fake_player/RunFakePlayerToken.java b/server/src/test/java/eu/solven/kumite/account/fake_player/RunFakePlayerToken.java
index 21fe6bf..bb4f796 100644
--- a/server/src/test/java/eu/solven/kumite/account/fake_player/RunFakePlayerToken.java
+++ b/server/src/test/java/eu/solven/kumite/account/fake_player/RunFakePlayerToken.java
@@ -48,8 +48,8 @@ public static void main(String[] args) {
@Bean
public Void generateFakePlayerToken(KumiteTokenService tokenService) {
- String accessToken = tokenService.generateAccessToken(FakePlayerTokens.fakeUser(),
- Set.of(FakePlayerTokens.FAKE_PLAYER_ID1, FakePlayerTokens.FAKE_PLAYER_ID2),
+ String accessToken = tokenService.generateAccessToken(FakePlayer.user(),
+ Set.of(FakePlayer.PLAYER_ID1, FakePlayer.PLAYER_ID2),
Duration.ofDays(365),
false);
diff --git a/server/src/test/java/eu/solven/kumite/app/it/TestKumiteApiRouter.java b/server/src/test/java/eu/solven/kumite/app/it/TestKumiteApiRouter.java
index dddc5d6..0d0df3b 100644
--- a/server/src/test/java/eu/solven/kumite/app/it/TestKumiteApiRouter.java
+++ b/server/src/test/java/eu/solven/kumite/app/it/TestKumiteApiRouter.java
@@ -14,7 +14,7 @@
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.reactive.server.WebTestClient;
-import eu.solven.kumite.account.fake_player.FakePlayerTokens;
+import eu.solven.kumite.account.fake_player.FakePlayer;
import eu.solven.kumite.app.IKumiteSpringProfiles;
import eu.solven.kumite.app.KumiteContestServerApplication;
import eu.solven.kumite.app.webflux.KumiteWebExceptionHandler;
@@ -46,8 +46,8 @@ public class TestKumiteApiRouter {
KumiteTokenService tokenService;
protected String generateAccessToken() {
- return tokenService.generateAccessToken(FakePlayerTokens.fakeUser(),
- Set.of(FakePlayerTokens.FAKE_PLAYER_ID1),
+ return tokenService.generateAccessToken(FakePlayer.user(),
+ Set.of(FakePlayer.PLAYER_ID1),
Duration.ofMinutes(1),
false);
}
diff --git a/server/src/test/java/eu/solven/kumite/app/it/TestKumiteRouterSpringConfig.java b/server/src/test/java/eu/solven/kumite/app/it/TestKumiteRouterSpringConfig.java
index 6cadb3d..5365589 100644
--- a/server/src/test/java/eu/solven/kumite/app/it/TestKumiteRouterSpringConfig.java
+++ b/server/src/test/java/eu/solven/kumite/app/it/TestKumiteRouterSpringConfig.java
@@ -5,13 +5,17 @@
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
+import eu.solven.kumite.account.JwtUserContextHolder;
import eu.solven.kumite.app.KumiteServerComponentsConfiguration;
import eu.solven.kumite.app.webflux.KumiteWebFluxConfiguration;
import eu.solven.kumite.app.webflux.api.GreetingHandler;
import lombok.extern.slf4j.Slf4j;
@ExtendWith(SpringExtension.class)
-@SpringBootTest(classes = { KumiteWebFluxConfiguration.class, KumiteServerComponentsConfiguration.class, },
+@SpringBootTest(
+ classes = { KumiteWebFluxConfiguration.class,
+ KumiteServerComponentsConfiguration.class,
+ JwtUserContextHolder.class, },
webEnvironment = SpringBootTest.WebEnvironment.MOCK)
@Slf4j
public class TestKumiteRouterSpringConfig {
diff --git a/server/src/test/java/eu/solven/kumite/app/it/security/KumiteServerSecurityApplication.java b/server/src/test/java/eu/solven/kumite/app/it/security/KumiteServerSecurityApplication.java
index 93acca8..406c18d 100644
--- a/server/src/test/java/eu/solven/kumite/app/it/security/KumiteServerSecurityApplication.java
+++ b/server/src/test/java/eu/solven/kumite/app/it/security/KumiteServerSecurityApplication.java
@@ -11,6 +11,7 @@
import eu.solven.kumite.account.InMemoryUserRepository;
import eu.solven.kumite.account.KumiteUsersRegistry;
+import eu.solven.kumite.app.InjectKumiteAccountsConfig;
import eu.solven.kumite.app.webflux.PlayerVerifierFilterFunction;
import eu.solven.kumite.app.webflux.api.AccessTokenHandler;
import eu.solven.kumite.app.webflux.api.GreetingHandler;
@@ -40,6 +41,8 @@
// IAccountPlayersRegistry is needed as security often checks the players of an account
BijectiveAccountPlayersRegistry.class,
+ InjectKumiteAccountsConfig.class,
+
})
public class KumiteServerSecurityApplication {
diff --git a/server/src/test/java/eu/solven/kumite/app/it/security/TestSecurity_WithFakeUser.java b/server/src/test/java/eu/solven/kumite/app/it/security/TestSecurity_WithFakeUser.java
new file mode 100644
index 0000000..eebc7c4
--- /dev/null
+++ b/server/src/test/java/eu/solven/kumite/app/it/security/TestSecurity_WithFakeUser.java
@@ -0,0 +1,80 @@
+package eu.solven.kumite.app.it.security;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import eu.solven.kumite.account.fake_player.FakePlayer;
+import eu.solven.kumite.app.IKumiteSpringProfiles;
+import eu.solven.kumite.app.KumiteJackson;
+import eu.solven.kumite.app.webflux.api.KumiteLoginController;
+import eu.solven.kumite.login.AccessTokenWrapper;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * OAuth2 enables logging-in a subset of APIs, especially the login APIs.
+ *
+ * @author Benoit Lacelle
+ *
+ */
+@ExtendWith(SpringExtension.class)
+@ActiveProfiles({ IKumiteSpringProfiles.P_UNSAFE, IKumiteSpringProfiles.P_FAKEUSER })
+@Slf4j
+public class TestSecurity_WithFakeUser extends TestSecurity_WithOAuth2User {
+
+ @Test
+ @Override
+ public void testLoginAccessToken() {
+ log.debug("About {}", KumiteLoginController.class);
+
+ webTestClient
+
+ .get()
+ .uri("/api/login/v1/oauth2/token")
+ .accept(MediaType.APPLICATION_JSON)
+ .header(HttpHeaders.AUTHORIZATION,
+ "Basic " + HttpHeaders.encodeBasicAuth(FakePlayer.ACCOUNT_ID.toString(),
+ "no_password",
+ StandardCharsets.UTF_8))
+ .exchange()
+
+ .expectStatus()
+ .isOk()
+ .expectBody(AccessTokenWrapper.class)
+ .value(token -> {
+ Map asMap = KumiteJackson.objectMapper().convertValue(token, Map.class);
+
+ Assertions.assertThat(asMap)
+ .containsKey("access_token")
+ .containsEntry("token_type", "Bearer")
+ .containsEntry("player_id", FakePlayer.PLAYER_ID1.toString())
+ .containsEntry("expires_in", 3600L)
+ .hasSize(4);
+ });
+ }
+
+ @Test
+ public void testLoginAccessToken_invalidUser() {
+ log.debug("About {}", KumiteLoginController.class);
+
+ webTestClient
+
+ .get()
+ .uri("/api/login/v1/oauth2/token")
+ .accept(MediaType.APPLICATION_JSON)
+ .header(HttpHeaders.AUTHORIZATION,
+ "Basic " + HttpHeaders
+ .encodeBasicAuth("someUnknownUser", "no_password", StandardCharsets.UTF_8))
+ .exchange()
+
+ .expectStatus()
+ .isUnauthorized();
+ }
+}
\ No newline at end of file
diff --git a/server/src/test/java/eu/solven/kumite/app/it/security/TestSecurity_WithJwtUser.java b/server/src/test/java/eu/solven/kumite/app/it/security/TestSecurity_WithJwtUser.java
index 007b8e6..9f71c33 100644
--- a/server/src/test/java/eu/solven/kumite/app/it/security/TestSecurity_WithJwtUser.java
+++ b/server/src/test/java/eu/solven/kumite/app/it/security/TestSecurity_WithJwtUser.java
@@ -21,7 +21,7 @@
import org.springframework.test.web.reactive.server.StatusAssertions;
import org.springframework.test.web.reactive.server.WebTestClient;
-import eu.solven.kumite.account.fake_player.FakePlayerTokens;
+import eu.solven.kumite.account.fake_player.RandomPlayer;
import eu.solven.kumite.app.IKumiteSpringProfiles;
import eu.solven.kumite.app.webflux.KumiteWebExceptionHandler;
import eu.solven.kumite.app.webflux.api.AccessTokenHandler;
@@ -56,15 +56,15 @@ public class TestSecurity_WithJwtUser {
KumiteTokenService tokenService;
protected String generateAccessToken() {
- return tokenService.generateAccessToken(FakePlayerTokens.fakeUser(),
- Set.of(FakePlayerTokens.FAKE_PLAYER_ID1),
+ return tokenService.generateAccessToken(RandomPlayer.user(),
+ Set.of(RandomPlayer.PLAYERID_1),
Duration.ofMinutes(1),
false);
}
protected String generateRefreshToken() {
- return tokenService.generateAccessToken(FakePlayerTokens.fakeUser(),
- Set.of(FakePlayerTokens.FAKE_PLAYER_ID1),
+ return tokenService.generateAccessToken(RandomPlayer.user(),
+ Set.of(RandomPlayer.PLAYERID_1),
Duration.ofMinutes(1),
true);
}
@@ -274,7 +274,7 @@ public void testMakeRefreshToken() {
// We need an oauth2 user, not a jwt user
expectStatus.isUnauthorized().expectBody(Map.class).value(bodyAsMap -> {
- Assertions.assertThat(bodyAsMap).containsEntry("error_message", "Lack of OAuth2 user").hasSize(1);
+ Assertions.assertThat(bodyAsMap).containsEntry("error_message", "No user").hasSize(1);
});
}
@@ -285,7 +285,7 @@ public void testRefreshTokenToAccessToken() {
log.debug("About {}", AccessTokenHandler.class);
StatusAssertions expectStatus = webTestClient.get()
- .uri("/api/v1/oauth2/token?player_id=11111111-1111-1111-1111-111111111111")
+ .uri("/api/v1/oauth2/token?player_id=" + RandomPlayer.PLAYERID_1)
.header(HttpHeaders.AUTHORIZATION, "Bearer " + generateRefreshToken())
.accept(MediaType.APPLICATION_JSON)
.exchange()
diff --git a/server/src/test/java/eu/solven/kumite/app/it/security/TestSecurity_WithOAuth2User.java b/server/src/test/java/eu/solven/kumite/app/it/security/TestSecurity_WithOAuth2User.java
index 8853636..1040a36 100644
--- a/server/src/test/java/eu/solven/kumite/app/it/security/TestSecurity_WithOAuth2User.java
+++ b/server/src/test/java/eu/solven/kumite/app/it/security/TestSecurity_WithOAuth2User.java
@@ -49,14 +49,15 @@
@ActiveProfiles({ IKumiteSpringProfiles.P_UNSAFE, })
@Slf4j
// https://stackoverflow.com/questions/73881370/mocking-oauth2-client-with-webtestclient-for-servlet-applications-results-in-nul
-@AutoConfigureWebTestClient
+// https://stackoverflow.com/questions/56784289/autoconfigurewebtestclienttimeout-600000-has-no-effect
+@AutoConfigureWebTestClient(timeout = "PT10M")
@WithMockUser
public class TestSecurity_WithOAuth2User {
// Spring Boot will create a `WebTestClient` for you,
// already configure and ready to issue requests against "localhost:RANDOM_PORT"
@Autowired
- private WebTestClient webTestClient;
+ WebTestClient webTestClient;
@Autowired
KumiteOAuth2UserService oauth2UserService;
diff --git a/server/src/test/java/eu/solven/kumite/app/webflux/api/TestKumiteLoginController.java b/server/src/test/java/eu/solven/kumite/app/webflux/api/TestKumiteLoginController.java
index ca2b954..08fb6dc 100644
--- a/server/src/test/java/eu/solven/kumite/app/webflux/api/TestKumiteLoginController.java
+++ b/server/src/test/java/eu/solven/kumite/app/webflux/api/TestKumiteLoginController.java
@@ -10,7 +10,7 @@
import eu.solven.kumite.account.InMemoryUserRepository;
import eu.solven.kumite.account.KumiteUsersRegistry;
-import eu.solven.kumite.account.fake_player.FakePlayerTokens;
+import eu.solven.kumite.account.fake_player.FakePlayer;
import eu.solven.kumite.oauth2.IKumiteOAuth2Constants;
import eu.solven.kumite.oauth2.authorizationserver.KumiteTokenService;
import eu.solven.kumite.player.IAccountPlayersRegistry;
@@ -54,7 +54,7 @@ public class TestKumiteLoginController {
public void testPlayer_invalid() {
Assertions
.assertThatThrownBy(
- () -> controller.checkValidPlayerId(FakePlayerTokens.fakeUser(), uuidGenerator.randomUUID()))
+ () -> controller.checkValidPlayerId(FakePlayer.user(), uuidGenerator.randomUUID()))
.isInstanceOf(IllegalArgumentException.class);
}
}
diff --git a/server/src/test/java/eu/solven/kumite/user/TestInMemoryUserRepository.java b/server/src/test/java/eu/solven/kumite/user/TestInMemoryUserRepository.java
index 4702673..4163789 100644
--- a/server/src/test/java/eu/solven/kumite/user/TestInMemoryUserRepository.java
+++ b/server/src/test/java/eu/solven/kumite/user/TestInMemoryUserRepository.java
@@ -6,20 +6,53 @@
import org.junit.jupiter.api.Test;
import eu.solven.kumite.account.InMemoryUserRepository;
+import eu.solven.kumite.account.KumiteUser;
import eu.solven.kumite.account.KumiteUserRawRaw;
-import eu.solven.kumite.account.fake_player.FakePlayerTokens;
+import eu.solven.kumite.account.fake_player.FakePlayer;
+import eu.solven.kumite.account.fake_player.RandomPlayer;
+import eu.solven.kumite.account.login.IKumiteTestConstants;
import eu.solven.kumite.player.persistence.BijectiveAccountPlayersRegistry;
+import eu.solven.kumite.tools.JdkUuidGenerator;
public class TestInMemoryUserRepository {
BijectiveAccountPlayersRegistry playersRegistry = new BijectiveAccountPlayersRegistry();
+ InMemoryUserRepository userRepository = new InMemoryUserRepository(JdkUuidGenerator.INSTANCE, playersRegistry);
@Test
- public void testFakeAccount() {
- InMemoryUserRepository userRepository = InMemoryUserRepository.forTests(playersRegistry);
+ public void testRegisterUser() {
+ KumiteUser user = userRepository.registerOrUpdate(IKumiteTestConstants.userRaw());
- Optional optRawRaw = userRepository.getUser(FakePlayerTokens.FAKE_ACCOUNT_ID);
+ Optional optRawRaw = userRepository.getUser(user.getAccountId());
+ Assertions.assertThat(optRawRaw).isPresent().contains(user.getRaw().getRawRaw());
+ }
- Assertions.assertThat(optRawRaw).isPresent();
+ @Test
+ public void testFakeUser() {
+ // Not present by default
+ {
+ Optional optRawRaw = userRepository.getUser(FakePlayer.ACCOUNT_ID);
+ Assertions.assertThat(optRawRaw).isEmpty();
+ }
+
+ KumiteUser user = userRepository.registerOrUpdate(FakePlayer.user().getRaw());
+ Assertions.assertThat(user.getAccountId()).isEqualTo(FakePlayer.ACCOUNT_ID);
+
+ Optional optRawRaw = userRepository.getUser(user.getAccountId());
+ Assertions.assertThat(optRawRaw).isPresent().contains(user.getRaw().getRawRaw());
+ }
+ @Test
+ public void testRandomUser() {
+ // Not present by default
+ {
+ Optional optRawRaw = userRepository.getUser(RandomPlayer.ACCOUNT_ID);
+ Assertions.assertThat(optRawRaw).isEmpty();
+ }
+
+ KumiteUser user = userRepository.registerOrUpdate(RandomPlayer.user().getRaw());
+ Assertions.assertThat(user.getAccountId()).isEqualTo(RandomPlayer.ACCOUNT_ID);
+
+ Optional optRawRaw = userRepository.getUser(user.getAccountId());
+ Assertions.assertThat(optRawRaw).isPresent().contains(user.getRaw().getRawRaw());
}
}
diff --git a/tools/pom.xml b/tools/pom.xml
index 4f3bd07..f9532bb 100644
--- a/tools/pom.xml
+++ b/tools/pom.xml
@@ -19,6 +19,12 @@
5.1.0
+
+
+ io.projectreactor
+ reactor-core
+
+
org.springframework
diff --git a/tools/src/main/java/eu/solven/kumite/account/IKumiteUserContextHolder.java b/tools/src/main/java/eu/solven/kumite/account/IKumiteUserContextHolder.java
new file mode 100644
index 0000000..bb1b051
--- /dev/null
+++ b/tools/src/main/java/eu/solven/kumite/account/IKumiteUserContextHolder.java
@@ -0,0 +1,15 @@
+package eu.solven.kumite.account;
+
+import java.util.UUID;
+
+import reactor.core.publisher.Mono;
+
+/**
+ * Give access to the authenticated user.
+ *
+ * @author Benoit Lacelle
+ *
+ */
+public interface IKumiteUserContextHolder {
+ Mono authenticatedAccountId();
+}