diff --git a/backend/requests/blackjack.http b/backend/requests/blackjack.http deleted file mode 100644 index ea20985..0000000 --- a/backend/requests/blackjack.http +++ /dev/null @@ -1,7 +0,0 @@ -POST http://localhost:8080/blackjack/start -Authorization: Bearer {{token}} -Content-Type: application/json - -{ - "betAmount": 1.01 -} diff --git a/backend/requests/getBearerToken.http b/backend/requests/getBearerToken.http index 791c3a2..afdea20 100644 --- a/backend/requests/getBearerToken.http +++ b/backend/requests/getBearerToken.http @@ -1,6 +1,6 @@ POST http://localhost:9090/realms/LF12/protocol/openid-connect/token Content-Type: application/x-www-form-urlencoded -grant_type=password&client_id=lf12&username=lf12_test_user&password=secret&scope=openid +grant_type=password&client_id=lf12&username=lf12_test_user&password=secret > {% client.global.set("token", response.body.access_token); %} \ No newline at end of file diff --git a/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameController.java b/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameController.java deleted file mode 100644 index 0aab2cb..0000000 --- a/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameController.java +++ /dev/null @@ -1,57 +0,0 @@ -package de.szut.casino.blackjack; - -import de.szut.casino.blackjack.dto.CreateBlackJackGameDto; -import de.szut.casino.user.UserEntity; -import de.szut.casino.user.UserService; -import jakarta.validation.Valid; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RestController; - -import java.math.BigDecimal; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; - -@Slf4j -@RestController -public class BlackJackGameController { - - private final UserService userService; - private final BlackJackService blackJackService; - - public BlackJackGameController(UserService userService, BlackJackService blackJackService) { - this.blackJackService = blackJackService; - this.userService = userService; - } - - @PostMapping("/blackjack/start") - public ResponseEntity createBlackJackGame(@RequestBody @Valid CreateBlackJackGameDto createBlackJackGameDto, @RequestHeader("Authorization") String token) { - Optional optionalUser = userService.getCurrentUser(token); - - if (optionalUser.isEmpty()) { - return ResponseEntity.notFound().build(); - } - - UserEntity user = optionalUser.get(); - BigDecimal balance = user.getBalance(); - BigDecimal betAmount = createBlackJackGameDto.getBetAmount(); - - if (betAmount.compareTo(BigDecimal.ZERO) <= 0) { - Map errorResponse = new HashMap<>(); - errorResponse.put("error", "Invalid bet amount"); - return ResponseEntity.badRequest().body(errorResponse); - } - - if (betAmount.compareTo(balance) > 0) { - Map errorResponse = new HashMap<>(); - errorResponse.put("error", "Insufficient funds"); - return ResponseEntity.badRequest().body(errorResponse); - } - - return ResponseEntity.ok(blackJackService.createBlackJackGame(user, betAmount)); - } -} diff --git a/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameEntity.java b/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameEntity.java deleted file mode 100644 index e3380a7..0000000 --- a/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameEntity.java +++ /dev/null @@ -1,46 +0,0 @@ -package de.szut.casino.blackjack; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonManagedReference; -import de.szut.casino.user.UserEntity; -import jakarta.persistence.*; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.List; - -@Entity -@Getter -@Setter -@AllArgsConstructor -@NoArgsConstructor -public class BlackJackGameEntity { - @Id - @GeneratedValue - private Long id; - - @ManyToOne - @JoinColumn(name = "user_id", nullable = false) - @JsonIgnore - private UserEntity user; - - // Expose UserID to JSON output - public Long getUserId() { - return user != null ? user.getId() : null; - } - - private String state; - private BigDecimal bet; - - @OneToMany(mappedBy = "game", cascade = CascadeType.ALL, orphanRemoval = true) - @JsonManagedReference - private List playerCards = new ArrayList<>(); - - @OneToMany(mappedBy = "game", cascade = CascadeType.ALL, orphanRemoval = true) - @JsonManagedReference - private List dealerCards = new ArrayList<>(); -} diff --git a/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameRepository.java b/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameRepository.java deleted file mode 100644 index d25a180..0000000 --- a/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameRepository.java +++ /dev/null @@ -1,12 +0,0 @@ -package de.szut.casino.blackjack; - -import de.szut.casino.user.UserEntity; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.stereotype.Service; - -import java.util.Optional; - -@Service -public interface BlackJackGameRepository extends JpaRepository { -} diff --git a/backend/src/main/java/de/szut/casino/blackjack/BlackJackService.java b/backend/src/main/java/de/szut/casino/blackjack/BlackJackService.java deleted file mode 100644 index ba5e7d1..0000000 --- a/backend/src/main/java/de/szut/casino/blackjack/BlackJackService.java +++ /dev/null @@ -1,50 +0,0 @@ -package de.szut.casino.blackjack; - -import de.szut.casino.user.UserEntity; -import de.szut.casino.user.UserRepository; -import org.springframework.stereotype.Service; - -import java.math.BigDecimal; -import java.util.Random; - -@Service -public class BlackJackService { - private final BlackJackGameRepository blackJackGameRepository; - private final UserRepository userRepository; - - public BlackJackService(BlackJackGameRepository blackJackGameRepository, UserRepository userRepository) { - this.blackJackGameRepository = blackJackGameRepository; - this.userRepository = userRepository; - } - - private final Random random = new Random(); - - public BlackJackGameEntity createBlackJackGame(UserEntity user, BigDecimal betAmount) { - BlackJackGameEntity game = new BlackJackGameEntity(); - game.setUser(user); - game.setBet(betAmount); - - for (int i = 0; i < 2; i++) { - CardEntity playerCard = createRandomCard(game); - game.getPlayerCards().add(playerCard); - } - - CardEntity dealerCard = createRandomCard(game); - game.getDealerCards().add(dealerCard); - - user.setBalance(user.getBalance().subtract(betAmount)); - - userRepository.save(user); - blackJackGameRepository.save(game); - - return game; - } - - private CardEntity createRandomCard(BlackJackGameEntity game) { - CardEntity card = new CardEntity(); - card.setGame(game); - card.setSuit(Suit.values()[random.nextInt(Suit.values().length)]); - card.setRank(Rank.values()[random.nextInt(Rank.values().length)]); - return card; - } -} diff --git a/backend/src/main/java/de/szut/casino/blackjack/CardEntity.java b/backend/src/main/java/de/szut/casino/blackjack/CardEntity.java deleted file mode 100644 index 8026d72..0000000 --- a/backend/src/main/java/de/szut/casino/blackjack/CardEntity.java +++ /dev/null @@ -1,33 +0,0 @@ -package de.szut.casino.blackjack; - - -import com.fasterxml.jackson.annotation.JsonBackReference; -import com.fasterxml.jackson.annotation.JsonIgnore; -import jakarta.persistence.*; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -@Entity -@Getter -@Setter -@AllArgsConstructor -@NoArgsConstructor -public class CardEntity { - @Id - @GeneratedValue - @JsonIgnore - private Long id; - - @ManyToOne - @JoinColumn(name = "game_id", nullable = false) - @JsonBackReference - private BlackJackGameEntity game; - - @Enumerated(EnumType.STRING) - private Suit suit; - - @Enumerated(EnumType.STRING) - private Rank rank; -} diff --git a/backend/src/main/java/de/szut/casino/blackjack/Rank.java b/backend/src/main/java/de/szut/casino/blackjack/Rank.java deleted file mode 100644 index 8f9a3b8..0000000 --- a/backend/src/main/java/de/szut/casino/blackjack/Rank.java +++ /dev/null @@ -1,31 +0,0 @@ -package de.szut.casino.blackjack; - -import lombok.Getter; - -@Getter -public enum Rank { - TWO("2", "Two", 2), - THREE("3", "Three", 3), - FOUR("4", "Four", 4), - FIVE("5", "Five", 5), - SIX("6", "Six", 6), - SEVEN("7", "Seven", 7), - EIGHT("8", "Eight", 8), - NINE("9", "Nine", 9), - TEN("10", "Ten", 10), - JACK("J", "Jack", 10), - QUEEN("Q", "Queen", 10), - KING("K", "King", 10), - ACE("A", "Ace", 11); - - private final String symbol; - private final String displayName; - private final int value; - - Rank(String symbol, String displayName, int value) { - this.symbol = symbol; - this.displayName = displayName; - this.value = value; - } - -} diff --git a/backend/src/main/java/de/szut/casino/blackjack/Suit.java b/backend/src/main/java/de/szut/casino/blackjack/Suit.java deleted file mode 100644 index 8ee80a9..0000000 --- a/backend/src/main/java/de/szut/casino/blackjack/Suit.java +++ /dev/null @@ -1,20 +0,0 @@ -package de.szut.casino.blackjack; - -import lombok.Getter; - -@Getter -public enum Suit { - HEARTS("H", "Hearts"), - DIAMONDS("D", "Diamonds"), - CLUBS("C", "Clubs"), - SPADES("S", "Spades"); - - private final String symbol; - private final String displayName; - - Suit(String symbol, String displayName) { - this.symbol = symbol; - this.displayName = displayName; - } - -} diff --git a/backend/src/main/java/de/szut/casino/blackjack/dto/CreateBlackJackGameDto.java b/backend/src/main/java/de/szut/casino/blackjack/dto/CreateBlackJackGameDto.java deleted file mode 100644 index e5b0c97..0000000 --- a/backend/src/main/java/de/szut/casino/blackjack/dto/CreateBlackJackGameDto.java +++ /dev/null @@ -1,16 +0,0 @@ -package de.szut.casino.blackjack.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -import java.math.BigDecimal; - -@Getter -@Setter -@AllArgsConstructor -@NoArgsConstructor -public class CreateBlackJackGameDto { - private BigDecimal betAmount; -} diff --git a/backend/src/main/java/de/szut/casino/user/UserController.java b/backend/src/main/java/de/szut/casino/user/UserController.java index 3750c8b..4d232ac 100644 --- a/backend/src/main/java/de/szut/casino/user/UserController.java +++ b/backend/src/main/java/de/szut/casino/user/UserController.java @@ -44,7 +44,7 @@ public class UserController { @GetMapping("/user") public ResponseEntity getCurrentUser(@RequestHeader("Authorization") String token) { - GetUserDto userData = userService.getCurrentUserAsDto(token); + GetUserDto userData = userService.getCurrentUser(token); if (userData == null) { return ResponseEntity.notFound().build(); diff --git a/backend/src/main/java/de/szut/casino/user/UserService.java b/backend/src/main/java/de/szut/casino/user/UserService.java index 36569e6..724962e 100644 --- a/backend/src/main/java/de/szut/casino/user/UserService.java +++ b/backend/src/main/java/de/szut/casino/user/UserService.java @@ -38,7 +38,7 @@ public class UserService { return user.map(userEntity -> mappingService.mapToGetUserDto(userEntity)).orElse(null); } - public GetUserDto getCurrentUserAsDto(String token) { + public GetUserDto getCurrentUser(String token) { KeycloakUserDto userData = getKeycloakUserInfo(token); if (userData == null) { @@ -47,15 +47,7 @@ public class UserService { Optional user = this.userRepository.findOneByKeycloakId(userData.getSub()); return user.map(userEntity -> mappingService.mapToGetUserDto(userEntity)).orElse(null); - } - public Optional getCurrentUser(String token) { - KeycloakUserDto userData = getKeycloakUserInfo(token); - - if (userData == null) { - return Optional.empty(); - } - return this.userRepository.findOneByKeycloakId(userData.getSub()); } private KeycloakUserDto getKeycloakUserInfo(String token) { diff --git a/backend/src/test/java/de/szut/casino/user/UserControllerTest.java b/backend/src/test/java/de/szut/casino/user/UserControllerTest.java new file mode 100644 index 0000000..2addb43 --- /dev/null +++ b/backend/src/test/java/de/szut/casino/user/UserControllerTest.java @@ -0,0 +1,122 @@ +package de.szut.casino.user; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import de.szut.casino.user.dto.CreateUserDto; +import de.szut.casino.user.dto.GetUserDto; + +@WebMvcTest(UserController.class) +@AutoConfigureMockMvc(addFilters = false) +public class UserControllerTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @MockBean + private UserService userService; + + private GetUserDto getUserDto; + private CreateUserDto createUserDto; + private UserEntity testUser; + private final String TEST_ID = "test-id-123"; + private final String AUTH_TOKEN = "Bearer test-token"; + + @BeforeEach + void setUp() { + getUserDto = new GetUserDto(); + getUserDto.setKeycloakId(TEST_ID); + getUserDto.setUsername("testuser"); + + testUser = new UserEntity(); + testUser.setKeycloakId(TEST_ID); + testUser.setUsername("testuser"); + + createUserDto = new CreateUserDto(); + createUserDto.setKeycloakId(TEST_ID); + createUserDto.setUsername("testuser"); + } + + @Test + void getUserByIdSuccess() throws Exception { + when(userService.exists(TEST_ID)).thenReturn(true); + when(userService.getUser(TEST_ID)).thenReturn(getUserDto); + + mockMvc.perform(get("/user/" + TEST_ID)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.keycloakId").value(TEST_ID)) + .andExpect(jsonPath("$.username").value("testuser")); + } + + @Test + void getUserByIdNotFound() throws Exception { + when(userService.exists(TEST_ID)).thenReturn(false); + + mockMvc.perform(get("/user/" + TEST_ID)) + .andExpect(status().isNotFound()); + } + + @Test + void createUserSuccess() throws Exception { + when(userService.exists(TEST_ID)).thenReturn(false); + when(userService.createUser(any(CreateUserDto.class))).thenReturn(testUser); + + mockMvc.perform(post("/user") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(createUserDto))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.keycloakId").value(TEST_ID)) + .andExpect(jsonPath("$.username").value("testuser")); + } + + @Test + void createUserAlreadyExists() throws Exception { + when(userService.exists(TEST_ID)).thenReturn(true); + + mockMvc.perform(post("/user") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(createUserDto))) + .andExpect(status().isFound()) + .andExpect(header().string("Location", "/user/" + TEST_ID)); + } + + @Test + void getCurrentUserSuccess() throws Exception { + when(userService.getCurrentUser(AUTH_TOKEN)).thenReturn(getUserDto); + + mockMvc.perform(get("/user") + .header("Authorization", AUTH_TOKEN)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.keycloakId").value(TEST_ID)) + .andExpect(jsonPath("$.username").value("testuser")); + } + + @Test + void getCurrentUserNotFound() throws Exception { + when(userService.getCurrentUser(anyString())).thenReturn(null); + + mockMvc.perform(get("/user") + .header("Authorization", AUTH_TOKEN)) + .andExpect(status().isNotFound()); + } +} \ No newline at end of file