From 66e5d730dd7c0aeb045fab2a1c22cec6414659f9 Mon Sep 17 00:00:00 2001 From: csimonis Date: Wed, 23 Apr 2025 13:39:49 +0200 Subject: [PATCH 01/21] refactor: reorganize import statements and clean up code --- frontend/src/app/app.config.ts | 2 +- frontend/src/app/feature/deposit/deposit.component.ts | 10 +++++----- .../app/feature/game/blackjack/blackjack.component.ts | 4 ++-- .../animated-number/animated-number.component.ts | 4 ++-- .../components/game-info/game-info.component.ts | 2 +- .../components/game-result/game-result.component.ts | 2 +- .../components/playing-card/playing-card.component.ts | 4 ++-- .../game/blackjack/services/blackjack.service.ts | 4 ++-- frontend/src/app/feature/home/home.component.html | 3 --- frontend/src/app/feature/landing/landing.component.ts | 2 +- .../transaction-history.component.ts | 9 +-------- frontend/src/app/model/Transaction.ts | 1 - .../components/confirmation/confirmation.component.ts | 4 ++-- .../app/shared/components/footer/footer.component.ts | 4 ++-- .../app/shared/components/navbar/navbar.component.ts | 9 +-------- 15 files changed, 23 insertions(+), 41 deletions(-) diff --git a/frontend/src/app/app.config.ts b/frontend/src/app/app.config.ts index 671a717..d6ac35a 100644 --- a/frontend/src/app/app.config.ts +++ b/frontend/src/app/app.config.ts @@ -6,7 +6,7 @@ import { routes } from './app.routes'; import { provideHttpClient, withInterceptors } from '@angular/common/http'; import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; import { OAuthStorage, provideOAuthClient } from 'angular-oauth2-oidc'; -import { httpInterceptor } from './shared/interceptor/http.interceptor'; +import { httpInterceptor } from '@shared/interceptor/http.interceptor'; export const appConfig: ApplicationConfig = { providers: [ diff --git a/frontend/src/app/feature/deposit/deposit.component.ts b/frontend/src/app/feature/deposit/deposit.component.ts index 834a2e4..8768bbe 100644 --- a/frontend/src/app/feature/deposit/deposit.component.ts +++ b/frontend/src/app/feature/deposit/deposit.component.ts @@ -1,18 +1,18 @@ import { + AfterViewInit, ChangeDetectionStrategy, + ChangeDetectorRef, Component, ElementRef, EventEmitter, inject, Input, + OnChanges, + OnDestroy, OnInit, Output, - ViewChild, - AfterViewInit, - OnDestroy, - OnChanges, SimpleChanges, - ChangeDetectorRef, + ViewChild, } from '@angular/core'; import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; import { loadStripe, Stripe } from '@stripe/stripe-js'; diff --git a/frontend/src/app/feature/game/blackjack/blackjack.component.ts b/frontend/src/app/feature/game/blackjack/blackjack.component.ts index 370b535..3e58e25 100644 --- a/frontend/src/app/feature/game/blackjack/blackjack.component.ts +++ b/frontend/src/app/feature/game/blackjack/blackjack.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, inject, signal, OnInit } from '@angular/core'; +import { ChangeDetectionStrategy, Component, inject, OnInit, signal } from '@angular/core'; import { CommonModule } from '@angular/common'; import { Router } from '@angular/router'; import { PlayingCardComponent } from './components/playing-card/playing-card.component'; @@ -6,7 +6,7 @@ import { DealerHandComponent } from './components/dealer-hand/dealer-hand.compon import { PlayerHandComponent } from './components/player-hand/player-hand.component'; import { GameControlsComponent } from './components/game-controls/game-controls.component'; import { GameInfoComponent } from './components/game-info/game-info.component'; -import { Card, BlackjackGame } from '@blackjack/models/blackjack.model'; +import { BlackjackGame, Card } from '@blackjack/models/blackjack.model'; import { BlackjackService } from '@blackjack/services/blackjack.service'; import { HttpErrorResponse } from '@angular/common/http'; import { GameResultComponent } from '@blackjack/components/game-result/game-result.component'; diff --git a/frontend/src/app/feature/game/blackjack/components/animated-number/animated-number.component.ts b/frontend/src/app/feature/game/blackjack/components/animated-number/animated-number.component.ts index 25ea0e4..7d78871 100644 --- a/frontend/src/app/feature/game/blackjack/components/animated-number/animated-number.component.ts +++ b/frontend/src/app/feature/game/blackjack/components/animated-number/animated-number.component.ts @@ -1,12 +1,12 @@ import { + AfterViewInit, ChangeDetectionStrategy, Component, + ElementRef, Input, OnChanges, SimpleChanges, - ElementRef, ViewChild, - AfterViewInit, } from '@angular/core'; import { CommonModule, CurrencyPipe } from '@angular/common'; import { CountUp } from 'countup.js'; diff --git a/frontend/src/app/feature/game/blackjack/components/game-info/game-info.component.ts b/frontend/src/app/feature/game/blackjack/components/game-info/game-info.component.ts index ecd1fad..644fb22 100644 --- a/frontend/src/app/feature/game/blackjack/components/game-info/game-info.component.ts +++ b/frontend/src/app/feature/game/blackjack/components/game-info/game-info.component.ts @@ -5,8 +5,8 @@ import { Input, OnChanges, Output, - SimpleChanges, signal, + SimpleChanges, } from '@angular/core'; import { CommonModule, CurrencyPipe } from '@angular/common'; import { FormGroup, ReactiveFormsModule } from '@angular/forms'; diff --git a/frontend/src/app/feature/game/blackjack/components/game-result/game-result.component.ts b/frontend/src/app/feature/game/blackjack/components/game-result/game-result.component.ts index b841ee8..74d02e4 100644 --- a/frontend/src/app/feature/game/blackjack/components/game-result/game-result.component.ts +++ b/frontend/src/app/feature/game/blackjack/components/game-result/game-result.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, Input, Output, EventEmitter } from '@angular/core'; +import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core'; import { CommonModule, CurrencyPipe } from '@angular/common'; import { animate, style, transition, trigger } from '@angular/animations'; import { GameState } from '../../enum/gameState'; diff --git a/frontend/src/app/feature/game/blackjack/components/playing-card/playing-card.component.ts b/frontend/src/app/feature/game/blackjack/components/playing-card/playing-card.component.ts index 8ae8824..0fbbb5a 100644 --- a/frontend/src/app/feature/game/blackjack/components/playing-card/playing-card.component.ts +++ b/frontend/src/app/feature/game/blackjack/components/playing-card/playing-card.component.ts @@ -1,9 +1,9 @@ import { + AfterViewInit, ChangeDetectionStrategy, Component, - Input, - AfterViewInit, ElementRef, + Input, OnChanges, SimpleChanges, } from '@angular/core'; diff --git a/frontend/src/app/feature/game/blackjack/services/blackjack.service.ts b/frontend/src/app/feature/game/blackjack/services/blackjack.service.ts index ca3f218..5e43dc7 100644 --- a/frontend/src/app/feature/game/blackjack/services/blackjack.service.ts +++ b/frontend/src/app/feature/game/blackjack/services/blackjack.service.ts @@ -1,6 +1,6 @@ -import { Injectable, inject } from '@angular/core'; +import { inject, Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; -import { Observable, catchError } from 'rxjs'; +import { catchError, Observable } from 'rxjs'; import { BlackjackGame } from '@blackjack/models/blackjack.model'; @Injectable({ diff --git a/frontend/src/app/feature/home/home.component.html b/frontend/src/app/feature/home/home.component.html index e03bed8..dc8ee59 100644 --- a/frontend/src/app/feature/home/home.component.html +++ b/frontend/src/app/feature/home/home.component.html @@ -91,9 +91,6 @@ [isOpen]="isTransactionModalOpen" (closeEventEmitter)="closeTransactionModal()" /> - diff --git a/frontend/src/app/feature/landing/landing.component.ts b/frontend/src/app/feature/landing/landing.component.ts index 62fa25e..915547f 100644 --- a/frontend/src/app/feature/landing/landing.component.ts +++ b/frontend/src/app/feature/landing/landing.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, OnInit, OnDestroy } from '@angular/core'; +import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core'; import { NgFor } from '@angular/common'; import { NavbarComponent } from '@shared/components/navbar/navbar.component'; diff --git a/frontend/src/app/feature/transaction-history/transaction-history.component.ts b/frontend/src/app/feature/transaction-history/transaction-history.component.ts index 0bef06d..e69c995 100644 --- a/frontend/src/app/feature/transaction-history/transaction-history.component.ts +++ b/frontend/src/app/feature/transaction-history/transaction-history.component.ts @@ -1,11 +1,4 @@ -import { - ChangeDetectionStrategy, - Component, - EventEmitter, - inject, - Input, - Output, -} from '@angular/core'; +import { ChangeDetectionStrategy, Component, EventEmitter, inject, Input, Output } from '@angular/core'; import { TransactionService } from '@service/transaction.service'; import { Observable } from 'rxjs'; import { AsyncPipe, CurrencyPipe, DatePipe, NgForOf, NgIf } from '@angular/common'; diff --git a/frontend/src/app/model/Transaction.ts b/frontend/src/app/model/Transaction.ts index 2a57559..d3bccf1 100644 --- a/frontend/src/app/model/Transaction.ts +++ b/frontend/src/app/model/Transaction.ts @@ -1,5 +1,4 @@ export interface Transaction { - id: string; status: string; amount: number; createdAt: string; diff --git a/frontend/src/app/shared/components/confirmation/confirmation.component.ts b/frontend/src/app/shared/components/confirmation/confirmation.component.ts index 8bc884a..9ce91ba 100644 --- a/frontend/src/app/shared/components/confirmation/confirmation.component.ts +++ b/frontend/src/app/shared/components/confirmation/confirmation.component.ts @@ -1,12 +1,12 @@ import { + AfterViewInit, Component, ElementRef, EventEmitter, Input, + OnDestroy, Output, ViewChild, - AfterViewInit, - OnDestroy, } from '@angular/core'; import { ModalAnimationService } from '@shared/services/modal-animation.service'; import gsap from 'gsap'; diff --git a/frontend/src/app/shared/components/footer/footer.component.ts b/frontend/src/app/shared/components/footer/footer.component.ts index 1c3b309..2cb56e1 100644 --- a/frontend/src/app/shared/components/footer/footer.component.ts +++ b/frontend/src/app/shared/components/footer/footer.component.ts @@ -1,7 +1,7 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; -import { faMoneyBillTransfer, faCreditCard, faWallet } from '@fortawesome/free-solid-svg-icons'; -import { faPaypal, faGooglePay, faApplePay } from '@fortawesome/free-brands-svg-icons'; +import { faCreditCard, faMoneyBillTransfer, faWallet } from '@fortawesome/free-solid-svg-icons'; +import { faApplePay, faGooglePay, faPaypal } from '@fortawesome/free-brands-svg-icons'; @Component({ selector: 'app-footer', diff --git a/frontend/src/app/shared/components/navbar/navbar.component.ts b/frontend/src/app/shared/components/navbar/navbar.component.ts index 6bbeeb9..3b7ee00 100644 --- a/frontend/src/app/shared/components/navbar/navbar.component.ts +++ b/frontend/src/app/shared/components/navbar/navbar.component.ts @@ -1,11 +1,4 @@ -import { - ChangeDetectionStrategy, - Component, - inject, - OnInit, - OnDestroy, - signal, -} from '@angular/core'; +import { ChangeDetectionStrategy, Component, inject, OnDestroy, OnInit, signal } from '@angular/core'; import { RouterModule } from '@angular/router'; import { AuthService } from '../../../service/auth.service'; import { CurrencyPipe } from '@angular/common'; From 6f3f3791c3506796397cca5976a775d5d8ac6aca Mon Sep 17 00:00:00 2001 From: csimonis Date: Wed, 23 Apr 2025 13:39:55 +0200 Subject: [PATCH 02/21] refactor: remove unused imports and clean up code --- .../java/de/szut/casino/CasinoApplication.java | 10 ---------- .../casino/blackjack/BlackJackGameRepository.java | 4 ---- .../szut/casino/blackjack/BlackJackService.java | 1 - .../de/szut/casino/deposit/DepositController.java | 6 ++++-- .../de/szut/casino/deposit/TransactionEntity.java | 1 - .../szut/casino/deposit/TransactionService.java | 1 - .../de/szut/casino/deposit/WebhookController.java | 15 +++++---------- .../de/szut/casino/lootboxes/LootBoxEntity.java | 6 ------ .../de/szut/casino/lootboxes/RewardEntity.java | 1 - .../java/de/szut/casino/user/UserController.java | 8 ++++---- .../user/transaction/TransactionController.java | 4 ---- 11 files changed, 13 insertions(+), 44 deletions(-) diff --git a/backend/src/main/java/de/szut/casino/CasinoApplication.java b/backend/src/main/java/de/szut/casino/CasinoApplication.java index 68e2ebe..8c99f02 100644 --- a/backend/src/main/java/de/szut/casino/CasinoApplication.java +++ b/backend/src/main/java/de/szut/casino/CasinoApplication.java @@ -1,20 +1,10 @@ package de.szut.casino; -import de.szut.casino.lootboxes.LootBoxEntity; -import de.szut.casino.lootboxes.LootBoxRepository; -import de.szut.casino.lootboxes.RewardEntity; -import de.szut.casino.lootboxes.RewardRepository; -import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - @SpringBootApplication public class CasinoApplication { diff --git a/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameRepository.java b/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameRepository.java index d25a180..aafea4f 100644 --- a/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameRepository.java +++ b/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameRepository.java @@ -1,12 +1,8 @@ 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 index 158e32c..cb31352 100644 --- a/backend/src/main/java/de/szut/casino/blackjack/BlackJackService.java +++ b/backend/src/main/java/de/szut/casino/blackjack/BlackJackService.java @@ -7,7 +7,6 @@ import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.util.List; -import java.util.Optional; import java.util.Random; @Service diff --git a/backend/src/main/java/de/szut/casino/deposit/DepositController.java b/backend/src/main/java/de/szut/casino/deposit/DepositController.java index cdf883d..dbfe449 100644 --- a/backend/src/main/java/de/szut/casino/deposit/DepositController.java +++ b/backend/src/main/java/de/szut/casino/deposit/DepositController.java @@ -8,7 +8,6 @@ import de.szut.casino.deposit.dto.AmountDto; import de.szut.casino.deposit.dto.SessionIdDto; import de.szut.casino.user.UserEntity; import de.szut.casino.user.UserRepository; -import de.szut.casino.user.UserService; import de.szut.casino.user.dto.KeycloakUserDto; import jakarta.validation.Valid; import org.springframework.beans.factory.annotation.Value; @@ -16,7 +15,10 @@ import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; +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 org.springframework.web.client.RestTemplate; import java.util.Optional; diff --git a/backend/src/main/java/de/szut/casino/deposit/TransactionEntity.java b/backend/src/main/java/de/szut/casino/deposit/TransactionEntity.java index c98d1cd..7c43af9 100644 --- a/backend/src/main/java/de/szut/casino/deposit/TransactionEntity.java +++ b/backend/src/main/java/de/szut/casino/deposit/TransactionEntity.java @@ -5,7 +5,6 @@ import jakarta.persistence.*; import lombok.Getter; import lombok.Setter; -import java.math.BigDecimal; import java.util.Date; @Setter diff --git a/backend/src/main/java/de/szut/casino/deposit/TransactionService.java b/backend/src/main/java/de/szut/casino/deposit/TransactionService.java index b5ddfd2..2cfc19e 100644 --- a/backend/src/main/java/de/szut/casino/deposit/TransactionService.java +++ b/backend/src/main/java/de/szut/casino/deposit/TransactionService.java @@ -7,7 +7,6 @@ import de.szut.casino.user.UserEntity; import de.szut.casino.user.UserRepository; import org.springframework.stereotype.Service; -import java.util.Objects; import java.util.Optional; @Service diff --git a/backend/src/main/java/de/szut/casino/deposit/WebhookController.java b/backend/src/main/java/de/szut/casino/deposit/WebhookController.java index be90a48..dba9041 100644 --- a/backend/src/main/java/de/szut/casino/deposit/WebhookController.java +++ b/backend/src/main/java/de/szut/casino/deposit/WebhookController.java @@ -1,26 +1,21 @@ package de.szut.casino.deposit; -import com.fasterxml.jackson.core.JsonProcessingException; - import com.stripe.Stripe; -import com.stripe.exception.SignatureVerificationException; import com.stripe.exception.StripeException; -import com.stripe.model.*; +import com.stripe.model.Event; import com.stripe.model.checkout.Session; import com.stripe.net.Webhook; -import com.stripe.param.checkout.SessionRetrieveParams; -import de.szut.casino.user.UserEntity; -import de.szut.casino.user.UserRepository; import jakarta.annotation.PostConstruct; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; +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.Objects; -import java.util.Optional; @RestController public class WebhookController { diff --git a/backend/src/main/java/de/szut/casino/lootboxes/LootBoxEntity.java b/backend/src/main/java/de/szut/casino/lootboxes/LootBoxEntity.java index eb5b93a..8a3e9a9 100644 --- a/backend/src/main/java/de/szut/casino/lootboxes/LootBoxEntity.java +++ b/backend/src/main/java/de/szut/casino/lootboxes/LootBoxEntity.java @@ -1,15 +1,9 @@ package de.szut.casino.lootboxes; -import com.fasterxml.jackson.annotation.JsonBackReference; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonManagedReference; -import de.szut.casino.blackjack.CardEntity; import jakarta.persistence.*; -import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import org.hibernate.annotations.SQLRestriction; import java.math.BigDecimal; import java.util.ArrayList; diff --git a/backend/src/main/java/de/szut/casino/lootboxes/RewardEntity.java b/backend/src/main/java/de/szut/casino/lootboxes/RewardEntity.java index c69390c..1abd2df 100644 --- a/backend/src/main/java/de/szut/casino/lootboxes/RewardEntity.java +++ b/backend/src/main/java/de/szut/casino/lootboxes/RewardEntity.java @@ -1,7 +1,6 @@ package de.szut.casino.lootboxes; import com.fasterxml.jackson.annotation.JsonBackReference; -import com.fasterxml.jackson.annotation.JsonManagedReference; import jakarta.persistence.*; import lombok.Getter; import lombok.NoArgsConstructor; 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 031d56a..c2ad0d0 100644 --- a/backend/src/main/java/de/szut/casino/user/UserController.java +++ b/backend/src/main/java/de/szut/casino/user/UserController.java @@ -1,14 +1,14 @@ package de.szut.casino.user; +import de.szut.casino.user.dto.CreateUserDto; +import de.szut.casino.user.dto.GetUserDto; +import jakarta.validation.Valid; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import de.szut.casino.user.dto.CreateUserDto; -import de.szut.casino.user.dto.GetUserDto; -import jakarta.validation.Valid; -import lombok.extern.slf4j.Slf4j; @Slf4j @RestController diff --git a/backend/src/main/java/de/szut/casino/user/transaction/TransactionController.java b/backend/src/main/java/de/szut/casino/user/transaction/TransactionController.java index 61805b0..10061fa 100644 --- a/backend/src/main/java/de/szut/casino/user/transaction/TransactionController.java +++ b/backend/src/main/java/de/szut/casino/user/transaction/TransactionController.java @@ -1,7 +1,5 @@ package de.szut.casino.user.transaction; -import de.szut.casino.deposit.TransactionEntity; -import de.szut.casino.user.transaction.dto.GetTransactionDto; import de.szut.casino.user.transaction.dto.UserTransactionsDto; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; @@ -10,8 +8,6 @@ import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import java.util.List; - @RestController public class TransactionController { From 0cc8ff50aa73f56ad09a64a0d847f0bac6bdb1e7 Mon Sep 17 00:00:00 2001 From: csimonis Date: Wed, 23 Apr 2025 13:43:12 +0200 Subject: [PATCH 03/21] style: format import statements for readability --- .../transaction-history/transaction-history.component.ts | 9 ++++++++- .../src/app/shared/components/navbar/navbar.component.ts | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/feature/transaction-history/transaction-history.component.ts b/frontend/src/app/feature/transaction-history/transaction-history.component.ts index e69c995..0bef06d 100644 --- a/frontend/src/app/feature/transaction-history/transaction-history.component.ts +++ b/frontend/src/app/feature/transaction-history/transaction-history.component.ts @@ -1,4 +1,11 @@ -import { ChangeDetectionStrategy, Component, EventEmitter, inject, Input, Output } from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + EventEmitter, + inject, + Input, + Output, +} from '@angular/core'; import { TransactionService } from '@service/transaction.service'; import { Observable } from 'rxjs'; import { AsyncPipe, CurrencyPipe, DatePipe, NgForOf, NgIf } from '@angular/common'; diff --git a/frontend/src/app/shared/components/navbar/navbar.component.ts b/frontend/src/app/shared/components/navbar/navbar.component.ts index 3b7ee00..6cc6f56 100644 --- a/frontend/src/app/shared/components/navbar/navbar.component.ts +++ b/frontend/src/app/shared/components/navbar/navbar.component.ts @@ -1,4 +1,11 @@ -import { ChangeDetectionStrategy, Component, inject, OnDestroy, OnInit, signal } from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + inject, + OnDestroy, + OnInit, + signal, +} from '@angular/core'; import { RouterModule } from '@angular/router'; import { AuthService } from '../../../service/auth.service'; import { CurrencyPipe } from '@angular/common'; From 4f377e1e87fc354afd784e44ef90109b09eb5a0e Mon Sep 17 00:00:00 2001 From: csimonis Date: Wed, 23 Apr 2025 14:27:47 +0200 Subject: [PATCH 04/21] feat(ci): add deployment workflow and update Dockerfile --- .gitea/workflows/deploy.yml | 20 +++++++++++ backend/.docker/Dockerfile | 10 +++--- .../src/main/resources/application.properties | 34 +++++++++---------- 3 files changed, 42 insertions(+), 22 deletions(-) create mode 100644 .gitea/workflows/deploy.yml diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml new file mode 100644 index 0000000..82de965 --- /dev/null +++ b/.gitea/workflows/deploy.yml @@ -0,0 +1,20 @@ +name: Deploy +on: + push: + branches: + - "feat/deployment" +# paths: +# - "backend/**" + +jobs: + build-image: + runs-on: ubuntu-latest + name: Build Docker Image + steps: + - uses: actions/checkout@v4 + - name: Build Image + run: docker buildx build -f .docker/Dockerfile -t git.kjan.de/SZUT/casino-backend:latest . + - name: Login + run: echo ${DOCKER_PASS} | docker login git.kjan.de --username ${DOCKER_USER} --password-stdin + - name Push + run: docker push git.kja.de/SZUT/casino-backend:latest diff --git a/backend/.docker/Dockerfile b/backend/.docker/Dockerfile index d6df4f7..cbb743f 100644 --- a/backend/.docker/Dockerfile +++ b/backend/.docker/Dockerfile @@ -1,17 +1,17 @@ -FROM gradle:jdk22 AS builder +FROM gradle:jdk23 AS builder WORKDIR /app -COPY gradlew build.gradle.kts settings.gradle.kts ./ +COPY gradlew build.gradle.kts settings.gradle.kts config ./ COPY gradle gradle RUN chmod +x gradlew -RUN ./gradlew dependencies +RUN gradle dependencies COPY src src -RUN ./gradlew clean build -x test +RUN gradle clean build -x test -x checkstyleMain -x checkstyleTest -x compileTestJava -FROM openjdk:22-jdk-slim +FROM openjdk:23-jdk-slim AS runtime WORKDIR /app COPY --from=builder /app/build/libs/*.jar app.jar diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 4c56a9d..bb8a4be 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -1,17 +1,17 @@ -spring.datasource.url=jdbc:postgresql://${DB_HOST:localhost}:5432/postgresdb -spring.datasource.username=postgres_user -spring.datasource.password=postgres_pass -server.port=8080 +spring.datasource.url=jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5432}/${DB_NAME:postgresdb} +spring.datasource.username=${DB_USER:postgres_user} +spring.datasource.password=${DB_PASS:postgres_pass} +server.port=${HTTP_PORT:8080} spring.jpa.hibernate.ddl-auto=update stripe.secret.key=${STRIPE_SECRET_KEY:sk_test_51QrePYIvCfqz7ANgqam8rEwWcMeKiLOof3j6SCMgu2sl4sESP45DJxca16mWcYo1sQaiBv32CMR6Z4AAAGQPCJo300ubuZKO8I} -stripe.webhook.secret=whsec_746b6a488665f6057118bdb4a2b32f4916f16c277109eeaed5e8f8e8b81b8c15 -app.frontend-host=http://localhost:4200 +stripe.webhook.secret=${STRIPE_WEBHOOK_SECRET:whsec_746b6a488665f6057118bdb4a2b32f4916f16c277109eeaed5e8f8e8b81b8c15} +app.frontend-host=${FE_URL:http://localhost:4200} -spring.application.name=lf12_starter +spring.application.name=casino #client registration configuration -spring.security.oauth2.client.registration.authentik.client-id=MDqjm1kcWKuZfqHJXjxwAV20i44aT7m4VhhTL3Nm -spring.security.oauth2.client.registration.authentik.client-secret=GY2F8te6iAVYt1TNAUVLzWZEXb6JoMNp6chbjqaXNq4gS5xTDL54HqBiAlV1jFKarN28LQ7FUsYX4SbwjfEhZhgeoKuBnZKjR9eiu7RawnGgxIK9ffvUfMkjRxnmiGI5 +spring.security.oauth2.client.registration.authentik.client-id=${AUTH_CLIENT_ID:MDqjm1kcWKuZfqHJXjxwAV20i44aT7m4VhhTL3Nm} +spring.security.oauth2.client.registration.authentik.client-secret=${AUTH_CLIENT_SECRET:GY2F8te6iAVYt1TNAUVLzWZEXb6JoMNp6chbjqaXNq4gS5xTDL54HqBiAlV1jFKarN28LQ7FUsYX4SbwjfEhZhgeoKuBnZKjR9eiu7RawnGgxIK9ffvUfMkjRxnmiGI5} spring.security.oauth2.client.registration.authentik.provider=authentik spring.security.oauth2.client.registration.authentik.client-name=Authentik spring.security.oauth2.client.registration.authentik.scope=openid,email,profile @@ -20,16 +20,16 @@ spring.security.oauth2.client.registration.authentik.authorization-grant-type=au spring.security.oauth2.client.registration.authentik.redirect-uri={baseUrl}/login/oauth2/code/{registrationId} # Provider settings -spring.security.oauth2.client.provider.authentik.issuer-uri=https://oauth.simonis.lol/application/o/casino-dev/ -spring.security.oauth2.client.provider.authentik.authorization-uri=https://oauth.simonis.lol/application/o/authorize/ -spring.security.oauth2.client.provider.authentik.token-uri=https://oauth.simonis.lol/application/o/token/ -spring.security.oauth2.client.provider.authentik.user-info-uri=https://oauth.simonis.lol/application/o/userinfo/ -spring.security.oauth2.client.provider.authentik.jwk-set-uri=https://oauth.simonis.lol/application/o/casino-dev/jwks/ -spring.security.oauth2.client.provider.authentik.user-name-attribute=preferred_username +spring.security.oauth2.client.provider.authentik.issuer-uri=${AUTH_PROVIDER_ISSUER:https://oauth.simonis.lol/application/o/casino-dev/} +spring.security.oauth2.client.provider.authentik.authorization-uri=${AUTH_PROVIDER_AUTHORIZE_URI:https://oauth.simonis.lol/application/o/authorize/} +spring.security.oauth2.client.provider.authentik.token-uri=${AUTH_PROVIDER_TOKEN_URI:https://oauth.simonis.lol/application/o/token/} +spring.security.oauth2.client.provider.authentik.user-info-uri=${AUTH_PROVIDER_USERINFO_URI:https://oauth.simonis.lol/application/o/userinfo/} +spring.security.oauth2.client.provider.authentik.jwk-set-uri=${AUTH_PROVIDER_JWKS_URI:https://oauth.simonis.lol/application/o/casino-dev/jwks/} +spring.security.oauth2.client.provider.authentik.user-name-attribute=${AUTH_PROVIDER_NAME_ATTR:preferred_username} # Resource server config -spring.security.oauth2.resourceserver.jwt.issuer-uri=https://oauth.simonis.lol/application/o/casino-dev/ -spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://oauth.simonis.lol/application/o/casino-dev/jwks/ +spring.security.oauth2.resourceserver.jwt.issuer-uri=${AUTH_JWT_ISSUER_URI:https://oauth.simonis.lol/application/o/casino-dev}/ +spring.security.oauth2.resourceserver.jwt.jwk-set-uri=${AUTH_JWT_JWT_SET_URI:https://oauth.simonis.lol/application/o/casino-dev/jwks/} #OIDC provider configuration: logging.level.org.springframework.security=DEBUG From 25b7e90517f7d900675777b9491dbf90f0cf2ce9 Mon Sep 17 00:00:00 2001 From: csimonis Date: Wed, 23 Apr 2025 14:33:11 +0200 Subject: [PATCH 05/21] build: update Dockerfile path in deploy workflow --- .gitea/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 82de965..39b999e 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -13,7 +13,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Build Image - run: docker buildx build -f .docker/Dockerfile -t git.kjan.de/SZUT/casino-backend:latest . + run: docker buildx build -f backend/.docker/Dockerfile -t git.kjan.de/SZUT/casino-backend:latest backend - name: Login run: echo ${DOCKER_PASS} | docker login git.kjan.de --username ${DOCKER_USER} --password-stdin - name Push From 1c58db60d3376d2d20ef7dc161e6ab153da63b02 Mon Sep 17 00:00:00 2001 From: csimonis Date: Wed, 23 Apr 2025 14:37:58 +0200 Subject: [PATCH 06/21] style(deploy.yml): fix indentation in deploy workflow steps --- .gitea/workflows/deploy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 39b999e..1d73ddb 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -16,5 +16,5 @@ jobs: run: docker buildx build -f backend/.docker/Dockerfile -t git.kjan.de/SZUT/casino-backend:latest backend - name: Login run: echo ${DOCKER_PASS} | docker login git.kjan.de --username ${DOCKER_USER} --password-stdin - - name Push - run: docker push git.kja.de/SZUT/casino-backend:latest + - name: Push + run: docker push git.kjan.de/SZUT/casino-backend:latest From 44b68528e3ff483751bd66760360eaf9bd867912 Mon Sep 17 00:00:00 2001 From: csimonis Date: Wed, 23 Apr 2025 14:38:30 +0200 Subject: [PATCH 07/21] ci: fix casing in deploy workflow for image tags --- .gitea/workflows/deploy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 1d73ddb..60cb483 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -13,8 +13,8 @@ jobs: steps: - uses: actions/checkout@v4 - name: Build Image - run: docker buildx build -f backend/.docker/Dockerfile -t git.kjan.de/SZUT/casino-backend:latest backend + run: docker buildx build -f backend/.docker/Dockerfile -t git.kjan.de/szut/casino-backend:latest backend - name: Login run: echo ${DOCKER_PASS} | docker login git.kjan.de --username ${DOCKER_USER} --password-stdin - name: Push - run: docker push git.kjan.de/SZUT/casino-backend:latest + run: docker push git.kjan.de/szut/casino-backend:latest From 3b2ce7e772ed1046d83f2cb51f8f9080265b6b30 Mon Sep 17 00:00:00 2001 From: csimonis Date: Thu, 24 Apr 2025 12:08:04 +0200 Subject: [PATCH 08/21] chore: test --- .gitea/workflows/deploy.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 60cb483..112aa0b 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -15,6 +15,10 @@ jobs: - name: Build Image run: docker buildx build -f backend/.docker/Dockerfile -t git.kjan.de/szut/casino-backend:latest backend - name: Login - run: echo ${DOCKER_PASS} | docker login git.kjan.de --username ${DOCKER_USER} --password-stdin + uses: actions/login + with: + registry: git.kjan.de + username: ${DOCKER_USER} + password: ${DOCKER_PASS} - name: Push run: docker push git.kjan.de/szut/casino-backend:latest From af005ce01939c458379bccb93750a42643dc3bd0 Mon Sep 17 00:00:00 2001 From: csimonis Date: Thu, 24 Apr 2025 12:10:19 +0200 Subject: [PATCH 09/21] ci: update login action to use secrets for credentials --- .gitea/workflows/deploy.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 112aa0b..026357c 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -15,10 +15,10 @@ jobs: - name: Build Image run: docker buildx build -f backend/.docker/Dockerfile -t git.kjan.de/szut/casino-backend:latest backend - name: Login - uses: actions/login + uses: docker/login-action@v3 with: registry: git.kjan.de - username: ${DOCKER_USER} - password: ${DOCKER_PASS} + username: ${{ secrets.DOCKER_USER }} + password: ${{ secrets.DOCKER_PASS }} - name: Push run: docker push git.kjan.de/szut/casino-backend:latest From 41124af20e1ddaffd41e0f24c7c2378e2e59c4dd Mon Sep 17 00:00:00 2001 From: csimonis Date: Thu, 24 Apr 2025 12:11:06 +0200 Subject: [PATCH 10/21] ci: update deployment workflow for main branch --- .gitea/workflows/deploy.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 026357c..c6942ba 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -2,16 +2,17 @@ name: Deploy on: push: branches: - - "feat/deployment" -# paths: -# - "backend/**" + - "main" + paths: + - "backend/**" jobs: build-image: runs-on: ubuntu-latest name: Build Docker Image steps: - - uses: actions/checkout@v4 + - name: Checkout + uses: actions/checkout@v4 - name: Build Image run: docker buildx build -f backend/.docker/Dockerfile -t git.kjan.de/szut/casino-backend:latest backend - name: Login From 7a0dd0593b3f0629c82171ab8a09ebab9c30c713 Mon Sep 17 00:00:00 2001 From: Phan Huy Tran Date: Thu, 24 Apr 2025 11:00:32 +0200 Subject: [PATCH 11/21] feat: implement slots api route --- .../blackjack/BlackJackGameController.java | 30 ++--- .../blackjack/dto/CreateBlackJackGameDto.java | 16 --- .../casino/deposit/TransactionService.java | 4 +- .../de/szut/casino/shared/dto/BetDto.java | 18 +++ .../casino/shared/service/BalanceService.java | 36 +++++ .../de/szut/casino/slots/SlotController.java | 50 +++++++ .../de/szut/casino/slots/SlotService.java | 127 ++++++++++++++++++ .../java/de/szut/casino/slots/SpinResult.java | 24 ++++ .../java/de/szut/casino/slots/Symbol.java | 35 +++++ .../java/de/szut/casino/user/UserEntity.java | 28 +++- 10 files changed, 326 insertions(+), 42 deletions(-) delete mode 100644 backend/src/main/java/de/szut/casino/blackjack/dto/CreateBlackJackGameDto.java create mode 100644 backend/src/main/java/de/szut/casino/shared/dto/BetDto.java create mode 100644 backend/src/main/java/de/szut/casino/shared/service/BalanceService.java create mode 100644 backend/src/main/java/de/szut/casino/slots/SlotController.java create mode 100644 backend/src/main/java/de/szut/casino/slots/SlotService.java create mode 100644 backend/src/main/java/de/szut/casino/slots/SpinResult.java create mode 100644 backend/src/main/java/de/szut/casino/slots/Symbol.java diff --git a/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameController.java b/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameController.java index c89f3ef..c9d5c26 100644 --- a/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameController.java +++ b/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameController.java @@ -1,6 +1,7 @@ package de.szut.casino.blackjack; -import de.szut.casino.blackjack.dto.CreateBlackJackGameDto; +import de.szut.casino.shared.dto.BetDto; +import de.szut.casino.shared.service.BalanceService; import de.szut.casino.user.UserEntity; import de.szut.casino.user.UserService; import jakarta.validation.Valid; @@ -9,19 +10,18 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.math.BigDecimal; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; +import java.util.*; @Slf4j @RestController public class BlackJackGameController { + private final BalanceService balanceService; private final UserService userService; private final BlackJackService blackJackService; - public BlackJackGameController(UserService userService, BlackJackService blackJackService) { + public BlackJackGameController(BalanceService balanceService, UserService userService, BlackJackService blackJackService) { + this.balanceService = balanceService; this.blackJackService = blackJackService; this.userService = userService; } @@ -112,7 +112,7 @@ public class BlackJackGameController { } @PostMapping("/blackjack/start") - public ResponseEntity createBlackJackGame(@RequestBody @Valid CreateBlackJackGameDto createBlackJackGameDto, @RequestHeader("Authorization") String token) { + public ResponseEntity createBlackJackGame(@RequestBody @Valid BetDto betDto, @RequestHeader("Authorization") String token) { Optional optionalUser = userService.getCurrentUser(token); if (optionalUser.isEmpty()) { @@ -120,21 +120,11 @@ public class BlackJackGameController { } 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 (!this.balanceService.hasFunds(user, betDto)) { + return ResponseEntity.badRequest().body(Collections.singletonMap("error", "Insufficient funds")); } - 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)); + return ResponseEntity.ok(blackJackService.createBlackJackGame(user, betDto.getBetAmount())); } } 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/deposit/TransactionService.java b/backend/src/main/java/de/szut/casino/deposit/TransactionService.java index 2cfc19e..7a7c48e 100644 --- a/backend/src/main/java/de/szut/casino/deposit/TransactionService.java +++ b/backend/src/main/java/de/szut/casino/deposit/TransactionService.java @@ -7,6 +7,8 @@ import de.szut.casino.user.UserEntity; import de.szut.casino.user.UserRepository; import org.springframework.stereotype.Service; +import java.math.BigDecimal; +import java.util.Objects; import java.util.Optional; @Service @@ -54,7 +56,7 @@ public class TransactionService { UserEntity user = transaction.getUser(); Long amountTotal = checkoutSession.getAmountTotal(); if (amountTotal != null) { - user.addBalance(amountTotal); + user.addBalance(BigDecimal.valueOf(amountTotal).movePointLeft(2)); } userRepository.save(user); diff --git a/backend/src/main/java/de/szut/casino/shared/dto/BetDto.java b/backend/src/main/java/de/szut/casino/shared/dto/BetDto.java new file mode 100644 index 0000000..a910a03 --- /dev/null +++ b/backend/src/main/java/de/szut/casino/shared/dto/BetDto.java @@ -0,0 +1,18 @@ +package de.szut.casino.shared.dto; + +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +import java.math.BigDecimal; + +@Getter +@Setter +@AllArgsConstructor +public class BetDto { + @NotNull(message = "Bet amount cannot be null") + @Positive(message = "Bet amount must be positive") + private BigDecimal betAmount; +} diff --git a/backend/src/main/java/de/szut/casino/shared/service/BalanceService.java b/backend/src/main/java/de/szut/casino/shared/service/BalanceService.java new file mode 100644 index 0000000..40e6caa --- /dev/null +++ b/backend/src/main/java/de/szut/casino/shared/service/BalanceService.java @@ -0,0 +1,36 @@ +package de.szut.casino.shared.service; + +import de.szut.casino.shared.dto.BetDto; +import de.szut.casino.user.UserEntity; +import de.szut.casino.user.UserRepository; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; + +@Service +public class BalanceService { + private UserRepository userRepository; + + public BalanceService(UserRepository userRepository) { + this.userRepository = userRepository; + } + + public boolean hasFunds(UserEntity user, BetDto betDto) { + BigDecimal balance = user.getBalance(); + BigDecimal betAmount = betDto.getBetAmount(); + + return betAmount.compareTo(balance) <= 0; + } + + public void addFunds(UserEntity user, BigDecimal amount) { + user.addBalance(amount); + + this.userRepository.save(user); + } + + public void subtractFunds(UserEntity user, BigDecimal amount) { + user.subtractBalance(amount); + + this.userRepository.save(user); + } +} diff --git a/backend/src/main/java/de/szut/casino/slots/SlotController.java b/backend/src/main/java/de/szut/casino/slots/SlotController.java new file mode 100644 index 0000000..5d11430 --- /dev/null +++ b/backend/src/main/java/de/szut/casino/slots/SlotController.java @@ -0,0 +1,50 @@ +package de.szut.casino.slots; + +import de.szut.casino.shared.dto.BetDto; +import de.szut.casino.shared.service.BalanceService; +import de.szut.casino.user.UserEntity; +import de.szut.casino.user.UserService; +import jakarta.validation.Valid; +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.util.Collections; +import java.util.Optional; + +@RestController +public class SlotController { + private final UserService userService; + private final BalanceService balanceService; + private final SlotService slotService; + + public SlotController(UserService userService, BalanceService balanceService, SlotService slotService) { + this.userService = userService; + this.balanceService = balanceService; + this.slotService = slotService; + } + + @PostMapping("/slots/spin") + public ResponseEntity spinSlots(@RequestBody @Valid BetDto betDto, @RequestHeader("Authorization") String token) { + Optional optionalUser = userService.getCurrentUser(token); + + if (optionalUser.isEmpty()) { + return ResponseEntity.notFound().build(); + } + + UserEntity user = optionalUser.get(); + + if (!this.balanceService.hasFunds(user, betDto)) { + return ResponseEntity.badRequest().body(Collections.singletonMap("error", "Insufficient funds")); + } + + SpinResult spinResult = this.slotService.handleSpinResult( + betDto.getBetAmount(), + user + ); + + return ResponseEntity.ok(spinResult); + } +} \ No newline at end of file diff --git a/backend/src/main/java/de/szut/casino/slots/SlotService.java b/backend/src/main/java/de/szut/casino/slots/SlotService.java new file mode 100644 index 0000000..cd5a814 --- /dev/null +++ b/backend/src/main/java/de/szut/casino/slots/SlotService.java @@ -0,0 +1,127 @@ +package de.szut.casino.slots; + +import de.szut.casino.shared.service.BalanceService; +import de.szut.casino.user.UserEntity; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Random; + +@Service +public class SlotService { + private final int REEL_LENGTH = 60; + private static final int SEVEN_COUNT = 4; + private static final int BAR_COUNT = 20; + private static final int CHERRY_COUNT = 36; + + private final List FIRST_REEL = new ArrayList<>(REEL_LENGTH); + private final List SECOND_REEL = new ArrayList<>(REEL_LENGTH); + private final List THIRD_REEL = new ArrayList<>(REEL_LENGTH); + + private final BalanceService balanceService; + + public SlotService(BalanceService balanceService) { + this.balanceService = balanceService; + + initReels(); + } + + public SpinResult handleSpinResult( + BigDecimal betAmount, + UserEntity user + ) { + Random random = new Random(); + + int index1 = random.nextInt(REEL_LENGTH); + int index2 = random.nextInt(REEL_LENGTH); + int index3 = random.nextInt(REEL_LENGTH); + + Symbol symbol1 = FIRST_REEL.get(index1); + Symbol symbol2 = SECOND_REEL.get(index2); + Symbol symbol3 = THIRD_REEL.get(index3); + + boolean isWin = symbol1.equals(symbol2) && symbol1.equals(symbol3); + + SpinResult spinResult = new SpinResult(); + + if (isWin) { + BigDecimal winAmount = betAmount.multiply(symbol1.getPayoutMultiplier()); + this.balanceService.addFunds(user, winAmount); + + spinResult.setStatus("win"); + spinResult.setAmount(winAmount); + spinResult.setWin(true); + } else { + this.balanceService.subtractFunds(user, betAmount); + + spinResult.setStatus("lose"); + spinResult.setAmount(betAmount); + spinResult.setWin(false); + } + + buildResultMatrix(spinResult, index1, index2, index3); + + return spinResult; + } + + public void buildResultMatrix(SpinResult spinResult, int index1, int index2, int index3) { + List> resultMatrix = new ArrayList<>(3); + for (int i = 0; i < 3; i++) { + resultMatrix.add(new ArrayList<>(3)); + } + + resultMatrix.get(0).add(getSymbolAt(FIRST_REEL, index1 - 1)); + resultMatrix.get(1).add(getSymbolAt(FIRST_REEL, index1)); + resultMatrix.get(2).add(getSymbolAt(FIRST_REEL, index1 + 1)); + + resultMatrix.get(0).add(getSymbolAt(SECOND_REEL, index2 - 1)); + resultMatrix.get(1).add(getSymbolAt(SECOND_REEL, index2)); + resultMatrix.get(2).add(getSymbolAt(SECOND_REEL, index2 + 1)); + + resultMatrix.get(0).add(getSymbolAt(THIRD_REEL, index3 - 1)); + resultMatrix.get(1).add(getSymbolAt(THIRD_REEL, index3)); + resultMatrix.get(2).add(getSymbolAt(THIRD_REEL, index3 + 1)); + + spinResult.setResultMatrix(resultMatrix); + } + + private void initReels() { + List reelStrip = new ArrayList<>(REEL_LENGTH); + + for (int i = 0; i < CHERRY_COUNT; i++) { + Symbol CHERRY = new Symbol("cherry", new BigDecimal(5)); + reelStrip.add(CHERRY); + } + + for (int i = 0; i < BAR_COUNT; i++) { + Symbol BAR = new Symbol("bar", new BigDecimal(10)); + reelStrip.add(BAR); + } + + for (int i = 0; i < SEVEN_COUNT; i++) { + Symbol SEVEN = new Symbol("seven", new BigDecimal(85)); + reelStrip.add(SEVEN); + } + + FIRST_REEL.addAll(reelStrip); + SECOND_REEL.addAll(reelStrip); + THIRD_REEL.addAll(reelStrip); + + Collections.shuffle(FIRST_REEL); + Collections.shuffle(SECOND_REEL); + Collections.shuffle(THIRD_REEL); + } + + private Symbol getSymbolAt(List reel, int index) { + int effectiveIndex = index % REEL_LENGTH; + + if (effectiveIndex < 0) { + effectiveIndex += REEL_LENGTH; + } + + return reel.get(effectiveIndex); + } +} diff --git a/backend/src/main/java/de/szut/casino/slots/SpinResult.java b/backend/src/main/java/de/szut/casino/slots/SpinResult.java new file mode 100644 index 0000000..6263e9b --- /dev/null +++ b/backend/src/main/java/de/szut/casino/slots/SpinResult.java @@ -0,0 +1,24 @@ +package de.szut.casino.slots; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.math.BigDecimal; +import java.util.List; + +@Getter +@Setter +@NoArgsConstructor +public class SpinResult { + public SpinResult(String status, BigDecimal amount, boolean isWin) { + this.status = status; + this.amount = amount; + this.isWin = isWin; + } + + private String status; + private BigDecimal amount; + private boolean isWin; + private List> resultMatrix; +} diff --git a/backend/src/main/java/de/szut/casino/slots/Symbol.java b/backend/src/main/java/de/szut/casino/slots/Symbol.java new file mode 100644 index 0000000..806d14b --- /dev/null +++ b/backend/src/main/java/de/szut/casino/slots/Symbol.java @@ -0,0 +1,35 @@ +package de.szut.casino.slots; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.math.BigDecimal; + +@Getter +@Setter +@AllArgsConstructor +public class Symbol { + private String name; + private BigDecimal payoutMultiplier; + + @Override + public boolean equals(Object other) { + if (!(other instanceof Symbol that)) { + return false; + } + + return this.name.equals(that.name) && this.payoutMultiplier.equals(that.payoutMultiplier); + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 37 + this.name.hashCode(); + hashCode = hashCode * 37 + this.payoutMultiplier.hashCode(); + + return hashCode; + } +} diff --git a/backend/src/main/java/de/szut/casino/user/UserEntity.java b/backend/src/main/java/de/szut/casino/user/UserEntity.java index 67fc1ae..03f4a34 100644 --- a/backend/src/main/java/de/szut/casino/user/UserEntity.java +++ b/backend/src/main/java/de/szut/casino/user/UserEntity.java @@ -31,13 +31,31 @@ public class UserEntity { this.balance = balance; } - public void addBalance(long amountInCents) { - BigDecimal amountToAdd = BigDecimal.valueOf(amountInCents).movePointLeft(2); + public void addBalance(BigDecimal amountToAdd) { + if (amountToAdd == null || amountToAdd.compareTo(BigDecimal.ZERO) <= 0) { + return; + } if (this.balance == null) { - this.balance = amountToAdd; - } else { - this.balance = this.balance.add(amountToAdd); + this.balance = BigDecimal.ZERO; } + + this.balance = this.balance.add(amountToAdd); + } + + public void subtractBalance(BigDecimal amountToSubtract) { + if (amountToSubtract == null || amountToSubtract.compareTo(BigDecimal.ZERO) <= 0) { + throw new IllegalArgumentException("Amount to subtract must be positive."); + } + + if (this.balance == null) { + this.balance = BigDecimal.ZERO; + } + + if (this.balance.compareTo(amountToSubtract) < 0) { + throw new IllegalStateException("Insufficient funds to subtract " + amountToSubtract); + } + + this.balance = this.balance.subtract(amountToSubtract); } } From a26aeab86ab417f002699a8195f19daac7809bcf Mon Sep 17 00:00:00 2001 From: Phan Huy Tran Date: Thu, 24 Apr 2025 12:04:26 +0200 Subject: [PATCH 12/21] feat: refactor and balance winnings --- .../de/szut/casino/slots/SlotController.java | 2 +- .../de/szut/casino/slots/SlotService.java | 149 ++++++++++-------- 2 files changed, 81 insertions(+), 70 deletions(-) diff --git a/backend/src/main/java/de/szut/casino/slots/SlotController.java b/backend/src/main/java/de/szut/casino/slots/SlotController.java index 5d11430..59f3135 100644 --- a/backend/src/main/java/de/szut/casino/slots/SlotController.java +++ b/backend/src/main/java/de/szut/casino/slots/SlotController.java @@ -40,7 +40,7 @@ public class SlotController { return ResponseEntity.badRequest().body(Collections.singletonMap("error", "Insufficient funds")); } - SpinResult spinResult = this.slotService.handleSpinResult( + SpinResult spinResult = this.slotService.spin( betDto.getBetAmount(), user ); diff --git a/backend/src/main/java/de/szut/casino/slots/SlotService.java b/backend/src/main/java/de/szut/casino/slots/SlotService.java index cd5a814..0bc543f 100644 --- a/backend/src/main/java/de/szut/casino/slots/SlotService.java +++ b/backend/src/main/java/de/szut/casino/slots/SlotService.java @@ -12,107 +12,118 @@ import java.util.Random; @Service public class SlotService { - private final int REEL_LENGTH = 60; - private static final int SEVEN_COUNT = 4; - private static final int BAR_COUNT = 20; - private static final int CHERRY_COUNT = 36; + private final int REEL_LENGTH = 32; - private final List FIRST_REEL = new ArrayList<>(REEL_LENGTH); - private final List SECOND_REEL = new ArrayList<>(REEL_LENGTH); - private final List THIRD_REEL = new ArrayList<>(REEL_LENGTH); + private final int SEVEN_COUNT = 1; + private final int BAR_COUNT = 4; + private final int BELL_COUNT = 7; + private final int CHERRY_COUNT = 11; + private final int BLANK_COUNT = 9; + private final Symbol SEVEN = new Symbol("seven", new BigDecimal("1000")); + private final Symbol BAR = new Symbol("bar", new BigDecimal("85")); + private final Symbol BELL = new Symbol("bell", new BigDecimal("40")); + private final Symbol CHERRY = new Symbol("cherry", new BigDecimal("10")); + private final Symbol BLANK = new Symbol("blank", new BigDecimal("0")); + + private final List firstReel; + private final List secondReel; + private final List thirdReel; + + private final Random random; private final BalanceService balanceService; public SlotService(BalanceService balanceService) { + this.random = new Random(); this.balanceService = balanceService; - initReels(); + List reelStrip = createReelStrip(); + this.firstReel = shuffleReel(reelStrip); + this.secondReel = shuffleReel(reelStrip); + this.thirdReel = shuffleReel(reelStrip); } - public SpinResult handleSpinResult( - BigDecimal betAmount, - UserEntity user - ) { - Random random = new Random(); + public SpinResult spin(BigDecimal betAmount, UserEntity user) { + int index1 = this.random.nextInt(REEL_LENGTH); + int index2 = this.random.nextInt(REEL_LENGTH); + int index3 = this.random.nextInt(REEL_LENGTH); - int index1 = random.nextInt(REEL_LENGTH); - int index2 = random.nextInt(REEL_LENGTH); - int index3 = random.nextInt(REEL_LENGTH); - - Symbol symbol1 = FIRST_REEL.get(index1); - Symbol symbol2 = SECOND_REEL.get(index2); - Symbol symbol3 = THIRD_REEL.get(index3); + Symbol symbol1 = getSymbolAt(this.firstReel, index1); + Symbol symbol2 = getSymbolAt(this.secondReel, index2); + Symbol symbol3 = getSymbolAt(this.thirdReel, index3); boolean isWin = symbol1.equals(symbol2) && symbol1.equals(symbol3); - SpinResult spinResult = new SpinResult(); - - if (isWin) { - BigDecimal winAmount = betAmount.multiply(symbol1.getPayoutMultiplier()); - this.balanceService.addFunds(user, winAmount); - - spinResult.setStatus("win"); - spinResult.setAmount(winAmount); - spinResult.setWin(true); - } else { - this.balanceService.subtractFunds(user, betAmount); - - spinResult.setStatus("lose"); - spinResult.setAmount(betAmount); - spinResult.setWin(false); - } - + SpinResult spinResult = processResult(betAmount, user, isWin, symbol1); buildResultMatrix(spinResult, index1, index2, index3); return spinResult; } - public void buildResultMatrix(SpinResult spinResult, int index1, int index2, int index3) { + private SpinResult processResult(BigDecimal betAmount, UserEntity user, boolean isWin, Symbol winSymbol) { + BigDecimal resultAmount; + String status; + + if (isWin) { + resultAmount = betAmount.multiply(winSymbol.getPayoutMultiplier()); + status = "win"; + this.balanceService.addFunds(user, resultAmount); + } else { + resultAmount = betAmount; + status = "lose"; + this.balanceService.subtractFunds(user, betAmount); + } + + SpinResult spinResult = new SpinResult(); + spinResult.setStatus(status); + spinResult.setAmount(resultAmount); + spinResult.setWin(isWin); + + return spinResult; + } + + private void buildResultMatrix(SpinResult spinResult, int index1, int index2, int index3) { List> resultMatrix = new ArrayList<>(3); + for (int i = 0; i < 3; i++) { resultMatrix.add(new ArrayList<>(3)); } - resultMatrix.get(0).add(getSymbolAt(FIRST_REEL, index1 - 1)); - resultMatrix.get(1).add(getSymbolAt(FIRST_REEL, index1)); - resultMatrix.get(2).add(getSymbolAt(FIRST_REEL, index1 + 1)); + resultMatrix.getFirst().add(getSymbolAt(this.firstReel, index1 - 1)); + resultMatrix.getFirst().add(getSymbolAt(this.secondReel, index2 - 1)); + resultMatrix.getFirst().add(getSymbolAt(this.thirdReel, index3 - 1)); - resultMatrix.get(0).add(getSymbolAt(SECOND_REEL, index2 - 1)); - resultMatrix.get(1).add(getSymbolAt(SECOND_REEL, index2)); - resultMatrix.get(2).add(getSymbolAt(SECOND_REEL, index2 + 1)); + resultMatrix.get(1).add(getSymbolAt(this.firstReel, index1)); + resultMatrix.get(1).add(getSymbolAt(this.secondReel, index2)); + resultMatrix.get(1).add(getSymbolAt(this.thirdReel, index3)); - resultMatrix.get(0).add(getSymbolAt(THIRD_REEL, index3 - 1)); - resultMatrix.get(1).add(getSymbolAt(THIRD_REEL, index3)); - resultMatrix.get(2).add(getSymbolAt(THIRD_REEL, index3 + 1)); + resultMatrix.getLast().add(getSymbolAt(this.firstReel, index1 + 1)); + resultMatrix.getLast().add(getSymbolAt(this.secondReel, index2 + 1)); + resultMatrix.getLast().add(getSymbolAt(this.thirdReel, index3 + 1)); spinResult.setResultMatrix(resultMatrix); } - private void initReels() { + private List shuffleReel(List reelStrip) { + Collections.shuffle(reelStrip, this.random); + + return reelStrip; + } + + private List createReelStrip() { List reelStrip = new ArrayList<>(REEL_LENGTH); + addSymbolsToStrip(reelStrip, CHERRY, CHERRY_COUNT); + addSymbolsToStrip(reelStrip, BELL, BELL_COUNT); + addSymbolsToStrip(reelStrip, BAR, BAR_COUNT); + addSymbolsToStrip(reelStrip, SEVEN, SEVEN_COUNT); + addSymbolsToStrip(reelStrip, BLANK, BLANK_COUNT); + return reelStrip; + } - for (int i = 0; i < CHERRY_COUNT; i++) { - Symbol CHERRY = new Symbol("cherry", new BigDecimal(5)); - reelStrip.add(CHERRY); + private void addSymbolsToStrip(List strip, Symbol symbol, int count) { + for (int i = 0; i < count; i++) { + strip.add(symbol); } - - for (int i = 0; i < BAR_COUNT; i++) { - Symbol BAR = new Symbol("bar", new BigDecimal(10)); - reelStrip.add(BAR); - } - - for (int i = 0; i < SEVEN_COUNT; i++) { - Symbol SEVEN = new Symbol("seven", new BigDecimal(85)); - reelStrip.add(SEVEN); - } - - FIRST_REEL.addAll(reelStrip); - SECOND_REEL.addAll(reelStrip); - THIRD_REEL.addAll(reelStrip); - - Collections.shuffle(FIRST_REEL); - Collections.shuffle(SECOND_REEL); - Collections.shuffle(THIRD_REEL); } private Symbol getSymbolAt(List reel, int index) { From 29732e63b95063fcfea5e5a36e13bb9010736bab Mon Sep 17 00:00:00 2001 From: Phan Huy Tran Date: Thu, 24 Apr 2025 12:06:55 +0200 Subject: [PATCH 13/21] refactor: balance in favor of the house --- backend/src/main/java/de/szut/casino/slots/SlotService.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/de/szut/casino/slots/SlotService.java b/backend/src/main/java/de/szut/casino/slots/SlotService.java index 0bc543f..39ebeab 100644 --- a/backend/src/main/java/de/szut/casino/slots/SlotService.java +++ b/backend/src/main/java/de/szut/casino/slots/SlotService.java @@ -14,11 +14,12 @@ import java.util.Random; public class SlotService { private final int REEL_LENGTH = 32; + // 98% RTP private final int SEVEN_COUNT = 1; private final int BAR_COUNT = 4; private final int BELL_COUNT = 7; - private final int CHERRY_COUNT = 11; - private final int BLANK_COUNT = 9; + private final int CHERRY_COUNT = 10; + private final int BLANK_COUNT = 10; private final Symbol SEVEN = new Symbol("seven", new BigDecimal("1000")); private final Symbol BAR = new Symbol("bar", new BigDecimal("85")); From c93c386469b80465b6aacd92a3a59811a63f2902 Mon Sep 17 00:00:00 2001 From: Phan Huy Tran Date: Thu, 24 Apr 2025 12:09:52 +0200 Subject: [PATCH 14/21] style: bruh --- backend/src/main/java/de/szut/casino/slots/SlotController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/de/szut/casino/slots/SlotController.java b/backend/src/main/java/de/szut/casino/slots/SlotController.java index 59f3135..8f98b1d 100644 --- a/backend/src/main/java/de/szut/casino/slots/SlotController.java +++ b/backend/src/main/java/de/szut/casino/slots/SlotController.java @@ -47,4 +47,4 @@ public class SlotController { return ResponseEntity.ok(spinResult); } -} \ No newline at end of file +} From f01f6f6477c456fb77350dfbf30191850d9e1618 Mon Sep 17 00:00:00 2001 From: Phan Huy Tran Date: Thu, 24 Apr 2025 12:14:02 +0200 Subject: [PATCH 15/21] chore: rebase --- .../src/main/java/de/szut/casino/deposit/TransactionService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/src/main/java/de/szut/casino/deposit/TransactionService.java b/backend/src/main/java/de/szut/casino/deposit/TransactionService.java index 7a7c48e..fceb27b 100644 --- a/backend/src/main/java/de/szut/casino/deposit/TransactionService.java +++ b/backend/src/main/java/de/szut/casino/deposit/TransactionService.java @@ -8,7 +8,6 @@ import de.szut.casino.user.UserRepository; import org.springframework.stereotype.Service; import java.math.BigDecimal; -import java.util.Objects; import java.util.Optional; @Service From 0f96b284db526e92a1bed8ada2ed073b2e4fd12c Mon Sep 17 00:00:00 2001 From: Jan K9f Date: Thu, 24 Apr 2025 12:19:55 +0200 Subject: [PATCH 16/21] feat(ci): add build-image job to release workflow --- .gitea/workflows/release.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 05e146d..3e7b00e 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -31,3 +31,28 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} + build-image: + needs: release + runs-on: ubuntu-latest + name: Build Docker Image + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Ensure full history is available + - name: Extract tag + run: | + TAG=$(git describe --tags --abbrev=0) + echo "TAG=$TAG" >> $GITHUB_ENV + - name: Checkout + uses: actions/checkout@v4 + - name: Build Image + run: docker buildx build -f backend/.docker/Dockerfile -t git.kjan.de/szut/casino-backend:${{ env.TAG }} -t git.kjan.de/szut/casino-backend:latest backend + - name: Login + uses: docker/login-action@v3 + with: + registry: git.kjan.de + username: ${{ secrets.DOCKER_USER }} + password: ${{ secrets.DOCKER_PASS }} + - name: Push + run: docker push git.kjan.de/szut/casino-backend:latest From d9324ee7f03c3f6d7fd6ae3aae789a5330b5864b Mon Sep 17 00:00:00 2001 From: Jan K9f Date: Thu, 24 Apr 2025 12:23:31 +0200 Subject: [PATCH 17/21] build(workflow): update Docker build and push actions --- .gitea/workflows/release.yml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 3e7b00e..e38a5a7 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -46,13 +46,18 @@ jobs: echo "TAG=$TAG" >> $GITHUB_ENV - name: Checkout uses: actions/checkout@v4 - - name: Build Image - run: docker buildx build -f backend/.docker/Dockerfile -t git.kjan.de/szut/casino-backend:${{ env.TAG }} -t git.kjan.de/szut/casino-backend:latest backend - name: Login uses: docker/login-action@v3 with: registry: git.kjan.de username: ${{ secrets.DOCKER_USER }} password: ${{ secrets.DOCKER_PASS }} - - name: Push - run: docker push git.kjan.de/szut/casino-backend:latest + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: backend/ + file: backend/.docker/Dockerfile + push: true + tags: | + git.kjan.de/szut/casino-backend:latest + git.kjan.de/szut/casino-backend:${{ env.TAG }} From d2560c60493c06dd8270b7036b7168a06894aaf1 Mon Sep 17 00:00:00 2001 From: Jan K9f Date: Thu, 24 Apr 2025 12:24:27 +0200 Subject: [PATCH 18/21] chore: remove deploy workflow configuration file --- .gitea/workflows/deploy.yml | 25 ------------------------- 1 file changed, 25 deletions(-) delete mode 100644 .gitea/workflows/deploy.yml diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml deleted file mode 100644 index c6942ba..0000000 --- a/.gitea/workflows/deploy.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Deploy -on: - push: - branches: - - "main" - paths: - - "backend/**" - -jobs: - build-image: - runs-on: ubuntu-latest - name: Build Docker Image - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Build Image - run: docker buildx build -f backend/.docker/Dockerfile -t git.kjan.de/szut/casino-backend:latest backend - - name: Login - uses: docker/login-action@v3 - with: - registry: git.kjan.de - username: ${{ secrets.DOCKER_USER }} - password: ${{ secrets.DOCKER_PASS }} - - name: Push - run: docker push git.kjan.de/szut/casino-backend:latest From 36237874f74a704653a91a76e213c8d2ec471187 Mon Sep 17 00:00:00 2001 From: csimonis Date: Thu, 24 Apr 2025 14:23:17 +0200 Subject: [PATCH 19/21] feat(docker): add Docker configuration for frontend app --- frontend/.docker/Dockerfile | 23 ++++++++++++++++++++++ frontend/.docker/casino.conf | 19 ++++++++++++++++++ frontend/.docker/entrypoint.sh | 7 +++++++ frontend/.dockerignore | 15 +++++++++++++++ frontend/angular.json | 2 +- frontend/docker/docker-compose.yml | 31 ------------------------------ 6 files changed, 65 insertions(+), 32 deletions(-) create mode 100644 frontend/.docker/Dockerfile create mode 100644 frontend/.docker/casino.conf create mode 100755 frontend/.docker/entrypoint.sh create mode 100644 frontend/.dockerignore delete mode 100644 frontend/docker/docker-compose.yml diff --git a/frontend/.docker/Dockerfile b/frontend/.docker/Dockerfile new file mode 100644 index 0000000..494c91f --- /dev/null +++ b/frontend/.docker/Dockerfile @@ -0,0 +1,23 @@ +FROM oven/bun:debian AS build +WORKDIR /app + +RUN apt-get update -y && apt-get install nodejs -y + +ENV NODE_ENV=production + +COPY package.json bun.lock ./ +RUN bun install --frozen-lockfile + +COPY . . +RUN bun run build + +FROM nginx:alpine AS production + +RUN rm /etc/nginx/conf.d/default.conf +COPY .docker/casino.conf /etc/nginx/templates/nginx.conf.template +COPY .docker/entrypoint.sh /docker-entrypoint.d/40-custom-config-env.sh + +COPY --from=build /app/dist/casino /usr/share/nginx/html + +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] diff --git a/frontend/.docker/casino.conf b/frontend/.docker/casino.conf new file mode 100644 index 0000000..40b9613 --- /dev/null +++ b/frontend/.docker/casino.conf @@ -0,0 +1,19 @@ +server { + listen 80; + root /usr/share/nginx/html/browser; + index index.html; + + location / { + try_files $uri $uri/ /index.html; + add_header Cache-Control "no-cache"; + } + + location /backend/ { + proxy_pass http://${BACKEND_HOST}:${BACKEND_PORT}/; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + } +} diff --git a/frontend/.docker/entrypoint.sh b/frontend/.docker/entrypoint.sh new file mode 100755 index 0000000..3842b5a --- /dev/null +++ b/frontend/.docker/entrypoint.sh @@ -0,0 +1,7 @@ +#!/bin/sh +# Default values if not provided +: ${BACKEND_HOST:=localhost} +: ${BACKEND_PORT:=8080} + +envsubst '$BACKEND_HOST $BACKEND_PORT' < /etc/nginx/templates/nginx.conf.template > /etc/nginx/conf.d/default.conf +exec nginx -g 'daemon off;' diff --git a/frontend/.dockerignore b/frontend/.dockerignore new file mode 100644 index 0000000..4e10341 --- /dev/null +++ b/frontend/.dockerignore @@ -0,0 +1,15 @@ +node_modules +dist +.angular +.git +.github +.vscode +.idea +*.md +!README.md +.DS_Store +.env* +npm-debug.log* +yarn-debug.log* +yarn-error.log* +bun-debug.log* \ No newline at end of file diff --git a/frontend/angular.json b/frontend/angular.json index f7a1430..a9f9a84 100644 --- a/frontend/angular.json +++ b/frontend/angular.json @@ -13,7 +13,7 @@ "build": { "builder": "@angular-devkit/build-angular:application", "options": { - "outputPath": "dist/lf10-starter2024", + "outputPath": "dist/casino", "index": "src/index.html", "browser": "src/main.ts", "tsConfig": "tsconfig.app.json", diff --git a/frontend/docker/docker-compose.yml b/frontend/docker/docker-compose.yml deleted file mode 100644 index 2123d63..0000000 --- a/frontend/docker/docker-compose.yml +++ /dev/null @@ -1,31 +0,0 @@ -version: '3' - -volumes: - employee_postgres_data: - driver: local - -services: - postgres-employee: - container_name: postgres_employee - image: postgres:17.4 - volumes: - - employee_postgres_data:/var/lib/postgresql/data - environment: - POSTGRES_DB: employee_db - POSTGRES_USER: employee - POSTGRES_PASSWORD: secret - ports: - - "5432:5432" - - employee: - container_name: employee - image: berndheidemann/employee-management-service:1.1.3 - # image: berndheidemann/employee-management-service_without_keycloak:1.1 - environment: - spring.datasource.url: jdbc:postgresql://postgres-employee:5432/employee_db - spring.datasource.username: employee - spring.datasource.password: secret - ports: - - "8089:8089" - depends_on: - - postgres-employee From 40e1ae5f87e610975a1cff1c2b838b9e85ca437d Mon Sep 17 00:00:00 2001 From: csimonis Date: Thu, 24 Apr 2025 14:25:10 +0200 Subject: [PATCH 20/21] chore(workflow): rename build-image and add frontend build --- .gitea/workflows/release.yml | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index e38a5a7..1dc9476 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -31,10 +31,10 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} - build-image: + build-backend-image: needs: release runs-on: ubuntu-latest - name: Build Docker Image + name: Build Backend Image steps: - name: Checkout uses: actions/checkout@v4 @@ -61,3 +61,34 @@ jobs: tags: | git.kjan.de/szut/casino-backend:latest git.kjan.de/szut/casino-backend:${{ env.TAG }} + +build-frontend-image: + needs: release + runs-on: ubuntu-latest + name: Build Frontend Image + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Ensure full history is available + - name: Extract tag + run: | + TAG=$(git describe --tags --abbrev=0) + echo "TAG=$TAG" >> $GITHUB_ENV + - name: Checkout + uses: actions/checkout@v4 + - name: Login + uses: docker/login-action@v3 + with: + registry: git.kjan.de + username: ${{ secrets.DOCKER_USER }} + password: ${{ secrets.DOCKER_PASS }} + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: frontend/ + file: frontend/.docker/Dockerfile + push: true + tags: | + git.kjan.de/szut/casino-frontend:latest + git.kjan.de/szut/casino-frontend:${{ env.TAG }} From 27473ef5b50d8aeb6407fd33a77b184b36281f2c Mon Sep 17 00:00:00 2001 From: csimonis Date: Thu, 24 Apr 2025 14:28:19 +0200 Subject: [PATCH 21/21] ci: update job name in release workflow configuration --- .gitea/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 1dc9476..7e76ef6 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -62,7 +62,7 @@ jobs: git.kjan.de/szut/casino-backend:latest git.kjan.de/szut/casino-backend:${{ env.TAG }} -build-frontend-image: + build-frontend-image: needs: release runs-on: ubuntu-latest name: Build Frontend Image