diff --git a/src/main/java/no/josefushighscore/controller/GameController.java b/src/main/java/no/josefushighscore/controller/GameController.java new file mode 100644 index 0000000..3d53b2d --- /dev/null +++ b/src/main/java/no/josefushighscore/controller/GameController.java @@ -0,0 +1,38 @@ +package no.josefushighscore.controller; + +import no.josefushighscore.dto.ScoreDto; +import no.josefushighscore.exception.InvalidJwtAuthenticationException; +import no.josefushighscore.service.GameService; +import no.josefushighscore.service.UserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.web.bind.annotation.*; + +import static org.springframework.http.ResponseEntity.ok; + +@RestController +@RequestMapping("/game") +public class GameController { + + + @Autowired + private UserService userService; + + @Autowired + private GameService gameService; + + @PreAuthorize("hasRole('ROLE_USER')") + @GetMapping("/id") + public ResponseEntity getGameId(@AuthenticationPrincipal UserDetails userDetails) throws InvalidJwtAuthenticationException { + return ok(gameService.getGameDetails(userDetails.getUsername())); + } + + @PreAuthorize("hasRole('ROLE_USER')") + @PostMapping("/score") + public ResponseEntity postScore(@AuthenticationPrincipal UserDetails userDetails, @RequestBody ScoreDto scoreDto) throws InvalidJwtAuthenticationException { + return ok(gameService.updateScore(userDetails.getUsername(), scoreDto)); + } +} diff --git a/src/main/java/no/josefushighscore/dto/GameDto.java b/src/main/java/no/josefushighscore/dto/GameDto.java new file mode 100644 index 0000000..0c0fda8 --- /dev/null +++ b/src/main/java/no/josefushighscore/dto/GameDto.java @@ -0,0 +1,6 @@ +package no.josefushighscore.dto; + +public class GameDto { + + +} diff --git a/src/main/java/no/josefushighscore/dto/ScoreDto.java b/src/main/java/no/josefushighscore/dto/ScoreDto.java new file mode 100644 index 0000000..83f806c --- /dev/null +++ b/src/main/java/no/josefushighscore/dto/ScoreDto.java @@ -0,0 +1,34 @@ +package no.josefushighscore.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class ScoreDto { + + @JsonProperty("score") + private String score; + @JsonProperty("gameId") + private String gameId; + + // Constructors + public ScoreDto() { + // Default constructor + } + + public ScoreDto(String score, String gameId) { + this.score = score; + this.gameId = gameId; + } + + public String getScore() { + return score; + } + + + public String getGameId() { + return gameId; + } + + + +} + diff --git a/src/main/java/no/josefushighscore/model/Game.java b/src/main/java/no/josefushighscore/model/Game.java index 39a039a..dbe2222 100644 --- a/src/main/java/no/josefushighscore/model/Game.java +++ b/src/main/java/no/josefushighscore/model/Game.java @@ -18,11 +18,11 @@ public class Game { Long gameId; @ManyToOne - @JoinColumn(name = "scoreId") - private Score score; + @JoinColumn(name = "`scoreId`") + private Score scoreId; - @ManyToOne - @JoinColumn(name = "userId") + @OneToOne + @JoinColumn(name = "`userId`") private User user; @Column(name="`created_at`") @@ -31,10 +31,58 @@ public class Game { @Column(name="`updated_at`") LocalDate updatedAt; - public Game(Score score, User user, Long gameId) { - this.score = score; + @Column(name="`game_end_time`") + LocalDate gameEndTime; + + public LocalDate getGameEndTime() { + return gameEndTime; + } + + public void setGameEndTime(LocalDate gameEndTime) { + this.gameEndTime = gameEndTime; + } + + public Game(User user) { this.user = user; + } + + public Long getGameId() { + return gameId; + } + + public void setGameId(Long gameId) { this.gameId = gameId; } + public Score getScoreId() { + return scoreId; + } + + public void setScoreId(Score scoreId) { + this.scoreId = scoreId; + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public LocalDate getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDate createdAt) { + this.createdAt = createdAt; + } + + public LocalDate getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(LocalDate updatedAt) { + this.updatedAt = updatedAt; + } } diff --git a/src/main/java/no/josefushighscore/model/Score.java b/src/main/java/no/josefushighscore/model/Score.java index 5c25bad..bdb1a7e 100644 --- a/src/main/java/no/josefushighscore/model/Score.java +++ b/src/main/java/no/josefushighscore/model/Score.java @@ -1,39 +1,88 @@ package no.josefushighscore.model; -import lombok.Data; -import lombok.NoArgsConstructor; - import jakarta.persistence.*; -import java.time.LocalDate; + +import java.time.LocalDateTime; + @Entity -@Table(name="`score`") -@Data -@NoArgsConstructor +@Table(name = "`score`") public class Score { + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name="`score_id`") - Long scoreId; + @Column(name = "`score_id`") + private Long scoreId; - @Column(name="`score`") - Long score; + @Column(name = "`score`", nullable = false) + private Long score; - @OneToOne - @JoinColumn(name = "username") - private User user; + @Column(name = "`created_at`", nullable = false) + private LocalDateTime createdAt; - @Column(name="`created_at`") - LocalDate createdAt; + @Column(name = "`updated_at`", nullable = false) + private LocalDateTime updatedAt; - @Column(name="`updated_at`") - LocalDate updatedAt; + @Column(name="`game_id`", unique = true) + private Long game_id; - public Score(Long score, User user, Long scoreId) { + public void setGame_id(Long game_id) { + this.game_id = game_id; + } + + // Constructors + public Score() { + // Default constructor + } + + public Score(Long score, LocalDateTime createdAt, LocalDateTime updatedAt) { this.score = score; - this.user = user; + this.createdAt = createdAt; + this.updatedAt = updatedAt; + } + + // Getters and Setters + public Long getScoreId() { + return scoreId; + } + + public void setScoreId(Long scoreId) { this.scoreId = scoreId; } + public Long getScore() { + return score; + } + + public void setScore(Long score) { + this.score = score; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } + public LocalDateTime getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(LocalDateTime updatedAt) { + this.updatedAt = updatedAt; + } + + + @Override + public String toString() { + return "Score{" + + "scoreId=" + scoreId + + ", score=" + score + + ", createdAt=" + createdAt + + ", updatedAt=" + updatedAt + + ", game_id=" + game_id + + '}'; + } } diff --git a/src/main/java/no/josefushighscore/register/GameRegister.java b/src/main/java/no/josefushighscore/register/GameRegister.java new file mode 100644 index 0000000..79cf97c --- /dev/null +++ b/src/main/java/no/josefushighscore/register/GameRegister.java @@ -0,0 +1,14 @@ +package no.josefushighscore.register; + +import no.josefushighscore.model.Game; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface GameRegister extends JpaRepository { + + Optional findLatestByUser_UserId(Long userId); + Optional findByGameId(Long gameId); +} diff --git a/src/main/java/no/josefushighscore/register/ScoreRegister.java b/src/main/java/no/josefushighscore/register/ScoreRegister.java new file mode 100644 index 0000000..604a077 --- /dev/null +++ b/src/main/java/no/josefushighscore/register/ScoreRegister.java @@ -0,0 +1,7 @@ +package no.josefushighscore.register; + +import no.josefushighscore.model.Score; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ScoreRegister extends JpaRepository { +} diff --git a/src/main/java/no/josefushighscore/service/GameService.java b/src/main/java/no/josefushighscore/service/GameService.java new file mode 100644 index 0000000..7aaf14e --- /dev/null +++ b/src/main/java/no/josefushighscore/service/GameService.java @@ -0,0 +1,76 @@ +package no.josefushighscore.service; + +import no.josefushighscore.dto.ScoreDto; +import no.josefushighscore.model.Game; +import no.josefushighscore.model.Score; +import no.josefushighscore.model.User; +import no.josefushighscore.register.GameRegister; +import no.josefushighscore.register.ScoreRegister; +import no.josefushighscore.register.UserRegister; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.Optional; + +@Service +public class GameService { + + private final GameRegister gameRegister; + private final UserRegister userRegister; + private final ScoreRegister scoreRegister; + + private final Logger LOG = LoggerFactory.getLogger(GameService.class); + + public GameService (GameRegister gameRegister, UserRegister userRegister, ScoreRegister scoreRegister) { + this.gameRegister = gameRegister; + this.userRegister = userRegister; + this.scoreRegister = scoreRegister; + } + + public Game getGameDetails(String username) { + Optional currentUser = userRegister.findByUsername(username); + Game game = new Game(); + game.setUser(currentUser.orElseThrow( + () -> new UsernameNotFoundException("Username " + username + " not found"))); + game.setCreatedAt(LocalDate.now()); + game.setGameEndTime(LocalDate.now()); + gameRegister.save(game); + + return game; + } + + public Score updateScore(String username, ScoreDto scoreDto) { + + Optional currentGame = this.gameRegister.findByGameId(Long.valueOf(scoreDto.getGameId())); + + LOG.info("current game is {} for username: {}", currentGame.orElseThrow().getGameId(), username); + Score score = new Score(); + score.setScore(Long.valueOf(scoreDto.getScore())); + score.setCreatedAt(LocalDateTime.now()); + score.setGame_id(Long.valueOf(scoreDto.getGameId())); + LOG.info("updating score: {} gameId: {}", scoreDto.getScore(), scoreDto.getGameId()); + this.scoreRegister.save(score); + + Game updatedGame = currentGame + .map(game -> { + game.setScoreId(score); + return this.gameRegister.save(game); + }) + .orElse(null); // Or throw an exception, or handle the absence in another way + + if (updatedGame != null) { + // Game was found and updated + } else { + // Game was not found + } + + + return score; + } + + +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 8fadd83..fd3b49b 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -60,10 +60,10 @@ logging: level: org: springframework: - web: INFO - security: INFO + web: DEBUG + security: DEBUG hibernate: - SQL: debug + SQL: DEBUG type: descriptor: sql: trace diff --git a/src/main/resources/db/migration/V0_1_3__add_game_end_time_to_josefushighscore_game.sql b/src/main/resources/db/migration/V0_1_3__add_game_end_time_to_josefushighscore_game.sql new file mode 100644 index 0000000..be5ef68 --- /dev/null +++ b/src/main/resources/db/migration/V0_1_3__add_game_end_time_to_josefushighscore_game.sql @@ -0,0 +1 @@ +ALTER TABLE josefushighscore.game ADD COLUMN IF NOT EXISTS game_end_time timestamp without time zone NOT NULL; \ No newline at end of file diff --git a/src/main/resources/db/migration/V0_1_4__add_game_id_to_josefushighscore_score.sql b/src/main/resources/db/migration/V0_1_4__add_game_id_to_josefushighscore_score.sql new file mode 100644 index 0000000..9408c21 --- /dev/null +++ b/src/main/resources/db/migration/V0_1_4__add_game_id_to_josefushighscore_score.sql @@ -0,0 +1,12 @@ +-- Add game_id column to Score table in josefushighscore schema +ALTER TABLE josefushighscore."score" ADD COLUMN IF NOT EXISTS game_id bigint; + +-- Add foreign key constraint if it doesn't exist +DO $$ +BEGIN + IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_score_game_id') THEN + ALTER TABLE josefushighscore."score" ADD CONSTRAINT fk_score_game_id + FOREIGN KEY (game_id) + REFERENCES josefushighscore.game(game_id); + END IF; +END $$; \ No newline at end of file