diff --git a/docs/src/07_deployment_view.adoc b/docs/src/07_deployment_view.adoc index 521e3efd..08de22f5 100644 --- a/docs/src/07_deployment_view.adoc +++ b/docs/src/07_deployment_view.adoc @@ -11,15 +11,15 @@ Our application is containerized using Docker, enabling us to deploy the entire _**Overview Diagram:**_ The infrastructure features a single Docker container that hosts the Java Spring Boot application. This container communicates with external services, such as the Wikidata API, to fetch data in real-time and generate game questions. -.Motivation:: +.Motivation The primary motivation behind using Docker for deployment is to streamline the development and deployment processes. By containerizing the application, we reduce discrepancies between environments, making it easier to develop, test, and deploy with confidence. -.Quality and/or Performance Features:: +.Quality and/or Performance Features - **Portability:** Docker containers can run on any system that has Docker installed, reducing environment-specific bugs. - **Scalability:** While we start with a single container, the setup can be easily scaled using Docker Compose or Docker Swarm if the need arises. - **Efficiency:** Docker utilizes resources more efficiently than traditional VMs, allowing for faster startup times and lower overhead. -.Mapping of Building Blocks to Infrastructure:: +.Mapping of Building Blocks to Infrastructure - **Web Server/Application (.jar file):** Packaged within a Docker container, it includes all necessary dependencies to run independently across any Docker-supported platform. - **External APIs (e.g., Wikidata API):** Accessed over the network, these APIs provide dynamic content for the game. @@ -29,23 +29,35 @@ At this level, we describe the Docker container configuration that encapsulates ==== _Docker Container_ -Our Docker container is built from a Java base image, which is then layered with our application’s `.jar` file. This setup encapsulates the entire runtime environment required for our application. +Our app's Docker container is built from a Java base image, which is then layered with our application’s `.jar` file. -.Diagram: Docker Container Setup:: +In addition to the Spring boot standalone file, we also use the official `MySQL` server docker container image brought by DockerHub. This is our database server and it is used to store the game data, such as user scores, questions, etc. and all the other persistent data. + +This setup encapsulates the entire runtime environment required for our application, and does not require extensive configuration. + +.Diagram: Docker Container Setup [plantuml,"Docker Container Setup",png] ---- @startuml -rectangle "Docker Container" { - node "Java Spring Boot App (.jar)" as App - database "Web Server (Embedded)" as WebServer +rectangle "Docker compose" { + rectangle "App's Docker Container" { + node "Java Spring Boot App (.jar)" as App + database "Web Server (Embedded)" as WebServer + } + + rectangle "MySQL Server Container" { + database "MySQL Server" as MySQL + } } cloud "Wikidata API" as API +App --> MySQL : Store game data +MySQL --> App : Fetch game data App --> API : Fetch questions App ..> WebServer : Server application @enduml ---- -.Explanation:_ -This diagram illustrates the internal structure of our Docker container. It shows the Java Spring Boot application, including the embedded web server, packaged as a `.jar` file. The application interacts with external APIs, like the Wikidata API, to retrieve data necessary for generating game questions. The containerized approach ensures that the application can be deployed consistently across any environment that supports Docker. \ No newline at end of file +.Explanation: +This diagram illustrates the internal structure of our Docker containers structure. It shows the Java Spring Boot application, including the embedded web server, packaged as a `.jar` file and the MySQL server. The application interacts with external APIs, like the Wikidata API, to retrieve data necessary for generating game questions. The containerized approach ensures that the application can be deployed consistently across any environment that supports Docker. \ No newline at end of file diff --git a/docs/src/08_concepts.adoc b/docs/src/08_concepts.adoc index 30611946..b228f3ff 100644 --- a/docs/src/08_concepts.adoc +++ b/docs/src/08_concepts.adoc @@ -7,7 +7,200 @@ The following concepts provide a foundation for the design and implementation of === Domain Model -The domain model for our game includes entities such as `Question`, `Category`, `Player`, and `GameSession`. These are crucial for representing the game's data and logic. The model serves as the basis for interactions within the application and between the application and the database. +The domain model for our game includes entities such as `Question`, `Category`, `Player`, `Role`, and `GameSession`. These are crucial for representing the game's data and logic. The model serves as the basis for interactions within the application and between the application and the database. + + +[plantuml, domain-model, svg, subs="attributes", subs="methods"] +---- +@startuml +class Question { + - id: Long + - question: String + - correctAnswer: String + - incorrectAnswers: List + - category: Category + - difficulty: String + - type: String + - updatedAt: LocalDateTime + + getId(): Long + + getQuestion(): String + + getCorrectAnswer(): String + + getIncorrectAnswers(): List + + getCategory(): Category + + getDifficulty(): String + + getType(): String + + getUpdatedAt(): LocalDateTime +} + +class Category { + - id: Long + - name: String + + getName(): String + + getId(): Long + + setName(name: String): void + + setId(id: Long): void +} + +class Player { + - id: Long + - username: String + - email: String + - password: String + - passwordConfirm : String + - roles: Set + + getId(): Long + + getUsername(): String + + getEmail(): String + + getPassword(): String + + getPasswordConfirm(): String + + getRoles(): Set + + setUsername(username: String): void + + setEmail(email: String): void + + setPassword(password: String): void + + setPasswordConfirm(passwordConfirm: String): void + + setRoles(roles: Set): void + + setId(id: Long): void +} + +class GameSession { + - id: Long + - player: Player + - correctQuestions: Integer + - totalQuestions: Integer + - createdAt: LocalDateTime + - updatedAt: LocalDateTime + + getPlayer(): Player + + getScore(): Integer + + getCreatedAt(): LocalDateTime + + getUpdatedAt(): LocalDateTime + + getCorrectQuestions(): Integer + + getTotalQuestions(): Integer + + addQuestion(correct: boolean): void + + setPlayer(player: Player): void + + setScore(score: Integer): void + + setCreatedAt(createdAt: LocalDateTime): void + + setUpdatedAt(updatedAt: LocalDateTime): void + + setCorrectQuestions(correctQuestions: Integer): void + + setTotalQuestions(totalQuestions: Integer): void +} + +class Role { + - id: Long + - name: String + + getId(): Long + + getName(): String + + setId(id: Long): void + + setName(name: String): void +} + +interface PlayerService { + + addNewPlayer(playerDto: PlayerDto): Player + + getUsers(): List + + getUser(id: Long): Optional + + getUserByUsername(username: String): Optional + + getUserByEmail(email: String): Optional +} + +interface RoleService { + + addRole(roleDto: RoleDto): Role + + getRoles(): List + + getRole(name: String): Role +} + +class PlayerServiceImpl { + - playerRepository: PlayerRepository + - roleService: RoleService + + addNewPlayer(playerDto: PlayerDto): Player + + getUsers(): List + + getUser(id: Long): Optional + + getUserByUsername(username: String): Optional + + getUserByEmail(email: String): Optional +} + +class RoleServiceImpl { + - roleRepository: RoleRepository + + addRole(roleDto: RoleDto): Role + + getRoles(): List + + getRole(name: String): Role +} + +interface CrudRepository { + + save(entity: T): T + + findById(id: ID): Optional + + findAll(): List +} + +interface PlayerRepository { + + findByUsername(username: String): Optional + + findByEmail(email: String): Optional +} + +interface RoleRepository { + + findByName(name: String): Role +} + +class PlayerDto { + + username: String + + email: String + + password: String + + passwordConfirm: String + + roles: String[] +} + +class RoleDto { + + name: String +} + +Question "1" *- "1" Category +GameSession "*" *-- "1" Player +Role "*" - "*" Player +PlayerService <|.. PlayerServiceImpl +RoleService <|.. RoleServiceImpl +PlayerService ..> Player +RoleService ..> Role +PlayerService ..> PlayerDto +PlayerServiceImpl ..> PlayerRepository +RoleServiceImpl .> RoleRepository +RoleService ..> RoleDto +PlayerRepository --|> CrudRepository +RoleRepository -|> CrudRepository +@enduml +---- + +[plantuml, domain-model-2, svg] +---- +@startuml +class WiqEs04bApplication { + + main(args: String[]): void +} +class CustomErrorController { + + error(model: Model, webRequest: HttpServletRequest): String +} + +class HomeController { + + home(model: Model): String +} + +class PlayersController { + + showRegistrationForm(model: Model): String + + registerUserAccount(user: PlayerDto, result: BindingResult, model: Model): String + + showLoginForm(model: Model, error: String, session: HttpSession): String + + home(model: Model, principal: Principal): String +} + +class SecurityConfig { + + passwordEncoder(): PasswordEncoder + + filterChain(http: HttpSecurity): SecurityFilterChain + + configureGlobal(auth: AuthenticationManagerBuilder): void + + isAuthenticated(): boolean +} + +class CustomAuthenticationFailureHandler { + + onAuthenticationFailure(request: HttpServletRequest, response: HttpServletResponse, exception: AuthenticationException): void +} + +@enduml +---- === Hexagonal Architecture @@ -23,16 +216,16 @@ We use JPA for data persistence to abstract and handle all database operations, .Explanation: JPA enables us to map our domain objects to the database schema with ease, providing a clear layer of abstraction that simplifies data persistence and retrieval while ensuring our application remains agnostic of the underlying database technology. -=== Logging with Log4j and System.out +=== Logging with Slf4j and System.out -For monitoring runtime behavior and troubleshooting, the project utilizes Log4j and System.out for logging. While Log4j offers more sophisticated logging capabilities, System.out is used for straightforward, immediate console output. +For monitoring runtime behavior and troubleshooting, the project utilizes Slf4j, bundled with Sprint Boot, and System.out for logging. While Slf4j offers more sophisticated logging capabilities, System.out is used for straightforward, immediate console output. .Explanation: -Log4j is configured to capture various levels of output, which can be directed to multiple destinations such as console, files, or even remote logging servers. For simplicity and immediacy during development or less complex deployment scenarios, System.out is employed for logging output directly to the console. +Slf4j is configured to capture various levels of output, which can be directed to multiple destinations such as console, files, or even remote logging servers. For simplicity and immediacy during development or less complex deployment scenarios, System.out is employed for logging output directly to the console. === Security -Security is a key concern, ensuring that user data and game integrity are protected. We implement standard security practices at various levels within the application. +Security is a key concern, ensuring that user data and game integrity are protected. We implement standard security practices at various levels within the application .Explanation: This includes securing the web layer with Spring Security, encrypting sensitive data, and protecting against common web vulnerabilities. @@ -54,6 +247,5 @@ Our CI/CD pipeline automates the process of integrating code changes, building t === Scalability Designing for scalability, the application can accommodate an increasing number of users and interactions without performance degradation. - .Explanation: Scalable solutions such as Docker containers allow the application to be deployed in a distributed environment, where resources can be adjusted based on demand. \ No newline at end of file