diff --git a/README.md b/README.md
index 4405632..880a6b5 100644
--- a/README.md
+++ b/README.md
@@ -1 +1 @@
-# Flight Advisor Service ![GitHub release (latest by date)](https://img.shields.io/github/v/release/mohamed-taman/Flight-Advisor) [![Release Codename](https://img.shields.io/badge/codename-Advisor_4.0-yellow.svg)](https://github.com/mohamed-taman/Flight-Advisor/releases) [![Twitter Follow](https://img.shields.io/twitter/follow/_tamanm?label=follow%20me&style=social)](https://twitter.com/_tamanm)
Flight advisor Service is a set of APIs for primarily finding the cheapest flight from city A to
city B based on price, and as a result it's returning all the trip information alongside the
distance(s).
## System Functionality
- This project is developing a layered monolith **Spring Boot** based project (with the latest
version **3.1.0-M2**), on Java 20, and with an embedded database mode.
- This project is an OAuth2 based project, using JWT token to secure endpoints. So you need to register first to continue using the system.
- The functionality is reached based on user role, and there are three roles in the system.
- **Admin**: user is a predefined user (*admin@traveladvisor.com/Admin1234*).
- Admin needs to log-in first through `/login` API to get their token to contact the system.
- This user can upload airports and flight routes.
- Admin manages cities by adding, updating, or deleting them.
- Actually, the admin can do anything in the system.
- **Client**: Clients should register first before using the system through `/register` public API.
- After successful registration, they can then use the public `/login` API to get a token to contact the system successfully.
- Client can use all read API calls.
- Clients can add, manage their comments for a city, add, update, delete their comments, and see other comments.
- Client can get the cheapest flight by calling `/cities/travel` API and provide airport codes for [from the city] and [to the city].
- **Public**: it is not a role, but anonymous users use APIs under public.
- Use `/login` API call to log-in to the system, supplying the username and password. Then
you will
get a valid JWT token.
- Use `/register` API call to register as a client to use the system functionalities
related to the client, otherwise for he will receive *Not Authorized*.
## Getting started
### Project Management
1. I have used GitHub projects to manage my tasks in the **Flight-Advisor** project. [Project Link](https://github.com/mohamed-taman/Flight-Advisor/projects/1).
2. All MVP tasks are assigned to the **Flight Advisor API MVP** Milestone. [Milestone Link](https://github.com/mohamed-taman/Flight-Advisor/milestone/1?closed=1).
3. I used pull requests to manage and close assigned tasks. [Tasks Link](https://github.com/mohamed-taman/Flight-Advisor/issues?q=is%3Aclosed).
4. Finally, I have added releases to manage small features sprints until the final release v1.0. [Releases Link](https://github.com/mohamed-taman/Flight-Advisor/releases).
5. Have a look at opened issues for future enhancements. [Opened Issues](https://github.com/mohamed-taman/Flight-Advisor/issues?q=is%3Aopen).
### System components Structure
Let's explain first the system layers structure to understand its components:
```
Flight-Advisor --> Parent folder.
|- docs --> Contains system images.
|- data --> Contains Airports and routes files.
|- frontend --> Contains the frontend UI project.
|- src/main/java - org.siriusxi.htec.fa (package)
|- FlightAdvisorApplication.java --> The main starting point of the application.
|- api --> Contains All REST API controllers that receive requests from the client,
to process that request, and finally, return appropriate responses.
It contains all request and response DTOs.
|- repository --> All the database entities CRUD management services.
|- domain --> Domain contains all the database modeled entities.
|- infra --> Contains all the configurations, exceptions, security management,
support utilities, and dto<-->entities mappers, for the system support.
|- service --> Contains all the system business login,
receives calls from Controllers, call repository to retrieve and manage data,
then process them to return back to the controllers.
```
Now, as we have learned about different system layers and components, so it is the time then to
play, let's play.
## Playing With Flight Advisor Service
First things first, you need to download the following pieces of software to have fun with
the project:
### Required software
The following are the initially required software pieces:
1. **Maven**: it can be downloaded from https://maven.apache.org/download.cgi#.
2. **Git**: it can be downloaded from https://git-scm.com/downloads.
3. **Java 18.0.0**: it can be downloaded from https://www.oracle.com/java/technologies/downloads/#java18.
4. **Node.js 17.8+**: Latest features, and it can be downloaded from https://nodejs.
org/en/download/current/.
5. **Angular CLI 12.2+**: Install it with the following command:
`npm install -g @angular/cli@latest`
Follow the installation guide for each software, on provided website link and check your software
versions from the command line to verify that they are all installed correctly.
### Cloning It
Now it is the time to open **terminal** or **git bash** command line, and then clone the project under any of your favorite places with the following command:
```bash
> git clone https://github.com/mohamed-taman/Flight-Advisor.git
```
### Using an IDE
I recommend that you work with your Java code using an IDE that supports the development of Spring Boot applications such as **Spring Tool Suite** or **IntelliJ IDEA Community | Ultimate Edition**.
All you have to do is fire up your favorite IDE **->** open or import the parent folder `Flight-Advisor,` and everything will be ready for you.
### Building & Running The System
To build and run Flight Advisor (FA) system components, run the following command:
#### Building FA Components
##### FA backend
```bash
👻 [mtaman]:Flight-Advisor ~~ ./mvnw clean package
```
Now you should expect output like this:
```JavaScript
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- maven-jar-plugin:3.2.0:jar (default-jar) @ flight-advisor ---
[INFO] Building jar: /Flight-Advisor/target/flight-advisor-3.0.jar
[INFO]
[INFO] --- spring-boot-maven-plugin:2.4.0:repackage (repackage) @ flight-advisor ---
[INFO] Replacing main artifact with repackaged archive
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 14.620 s
[INFO] Finished at: 2022-04-13T13:40:50+01:00
[INFO] -----------------------------------------------------------------------
```
##### FA frontend
```bash
👻 [mtaman]:Flight-Advisor ~~ cd frontend
👻 [mtaman]:frontend ~~ npm install && ng build
```
Now you should expect output like this:
```JavaScript
removed 1 package and audited 1521 packages in 6.658s
85 packages are looking for funding
run `npm fund` for details
found 6 vulnerabilities (3 low, 1 moderate, 1 high, 1 critical)
run `npm audit fix` to fix them, or `npm audit` for details
✔ Browser application bundle generation complete.
✔ Copying assets complete.
✔ Index html generation complete.
Initial Chunk Files | Names | Size
vendor.js | vendor | 4.37 MB
scripts.js | scripts | 153.22 kB
polyfills.js | polyfills | 149.77 kB
styles.css | styles | 142.28 kB
main.js | main | 13.32 kB
runtime.js | runtime | 6.15 kB
| Initial Total | 4.83 MB
Build at: 2022-04-13T18:30:00.555Z - Hash: ccf039ad034c30696fdb - Time: 8608ms
```
#### Running the System
Now it's the time to run the system, and it's straightforward, just hit the following commands:
##### FA backend
```bash
👻 [mtaman]:Flight-Advisor ~~ java --enable-preview -jar ./target/*.jar \
👻 [mtaman]:Flight-Advisor ~+ --spring.profiles.active=prod
```
Or
```bash
👻 [mtaman]:Flight-Advisor ~~ ./mvnw spring-boot:run \
👻 [mtaman]:Flight-Advisor ~+ -Dspring-boot.run.jvmArguments="--enable-preview" \
👻 [mtaman]:Flight-Advisor ~+ -Dspring-boot.run.arguments="--spring.profiles.active=prod"
```
**Flight Advisor backend service** will run, with embedded H2 **database** that will be created
under `db` folder and then the `flightDB.mv.db` file, and you should expect an output like this:
```javascript
2022-04-13 13:56:16.587 INFO 2981 --- [ restartedMain] o.s.b.a.h2.H2ConsoleAutoConfiguration:
H2 console available at '/db-console'.
Database available at 'jdbc:h2:./db/flightDB'
2022-04-13 13:56:18.081 INFO 2981 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer:
Tomcat started on port(s): 8090 (http) with
context path 'api/v1/flight/service'
2022-04-13 13:56:18.581 INFO 2981 --- [ restartedMain] o.s.h.f.F.AppStartupRunner:
Congratulations, Flight Advisor Application, is Up & Running :)
```
##### FA frontend
```bash
👻 [mtaman]:frontend ~~ npm start
```
**Flight Advisor UI** will run, and you should expect an output like this:
```javascript
** Angular Live Development Server is listening on localhost:4200,
open your browser on http://localhost:4200/ **
✔ Compiled successfully.
```
### Access Flight Advisor System APIs
You can play and test `Flight Advisor` APIs throughout its **OpenAPI** interface.
1. Go to the landing page at the following URL [http://localhost:8090/api/v1/flight/service/]
(http://localhost:8090/api/v1/flight/service/).
2. Follow the link on the page, and you should see the following:
![System APIs](docs/images/SystemAPI.png)
3. More beautifully with its UI at [http://localhost:4200/](http://localhost:4200/), and you
expect this view for login:
![ClientLogin page](docs/images/FA-Login.png)
And this view after login, to travel:
![System APIs](docs/images/FA-Travel.png)
#### System Behaviour
1. First, if you want to upload airports or routes (in the data folder) using the **Files upload Management** section:
1. You need to log-in with the provided admin username/password to the `public/login` endpoint.
2. On a successful login, the response will contain an authorization token; copy it.
3. Click on the Authorize button and paste it in the only field out there, `value,` then click the `Authorize` button.
4. Now, all locks are closed, and you can use the secured APIs.
2. If you are a new client and want to access the system, you need first to register through the `/public/register` endpoint. Then follow previous point **1.1**.
3. When uploading the Airports file, countries and cities will be created automatically.
4. All search parameters are case-insensitive, and the system use like search by default.
5. To add a city, you need a country, so from the **country management** section, you can search for the country you want.
6. To manage comments, you need a city, so from the **city management** section, you can get all cities or search for a specific city.
7. You can search for all airports for a specific city to know their codes, so you can use travel service.
8. Use travel service to search for the cheapest flight from city to city, for example traveling from **CAI** (*Cairo International Airport, Egypt*) to **LAX** (*Los Angeles, USA*) the following results will be returned:
```JSON
[
{
"start": {
"airport": "Cairo International Airport",
"city": "Cairo",
"country": "Egypt",
"iata": "CAI"
},
"through": [
{
"airport": "Lester B. Pearson International Airport",
"city": "Toronto",
"country": "Canada",
"iata": "YYZ"
}
],
"end": {
"airport": "Los Angeles International Airport",
"city": "Los Angeles",
"country": "United States",
"iata": "LAX"
},
"price": {
"total": 62.17,
"currency": "US"
},
"distance": {
"total": 12722.2,
"in": "KM"
}
}
]
```
### Access Flight Advisor System Database
You can access database through it online console from the following URL
[http://localhost:8090/api/v1/flight/service/db-console/]
(http://localhost:8090/api/v1/flight/service/db-console/) with the following properties:
- Driver class: `org.h2.Driver`
- JDBC URL: `jdbc:h2:./db/flightDB`
- user: `sa`
- password: `Admin1234`
![System DB](docs/images/SystemDB.png)
Hit test, and it should show a green bar for successful settings. So hit the **Connect** button and explore all data.
### Stopping The System
Just press the `CTRL+C` keys on the terminal.
### Closing The Story
Finally, I hope you enjoyed the application and find it useful. If you would like to enhance, please open **PR**, and yet give it a 🌟.
## The End
Happy Coding 😊
## License
Copyright (C) 2023 Mohamed Taman, Licensed under the **MIT License**.
\ No newline at end of file
+# Flight Advisor Service ![GitHub release (latest by date)](https://img.shields.io/github/v/release/mohamed-taman/Flight-Advisor) [![Release Codename](https://img.shields.io/badge/codename-Advisor_Fresh_5.0-yellow.svg)](https://github.com/mohamed-taman/Flight-Advisor/releases) [![Twitter Follow](https://img.shields.io/twitter/follow/_tamanm?label=follow%20me&style=social)](https://twitter.com/_tamanm)
Flight Advisor Service is a set of APIs for primarily finding the cheapest flight from city A to
City B is based on price, and as a result, it returns all the trip information alongside the
distance(s).
> This service is a great example of migrating spring boot from the older version **2.7.x** to **3.1.x**. You can check the changes from commit changes of each version release (as code) or release notes as information.
## System Functionality
- This project is developing a layered monolith **Spring Boot** based project (with the latest
version **3.1.0-RC1**), on **Java 20**, and with an embedded database mode.
- This OAuth2-based project uses a JWT token to secure endpoints and a refresh token to get a new JWT token without login.
- Therefore, you need to register first to continue using the system.
- The functionality is reached based on user roles, and the system has three roles.
- **Admin**: user is a predefined user (*admin@traveladvisor.com/Admin1234*).
- Admin needs to log-in first through `/signin` API to get their token to contact the system.
- This user can upload airports and flight routes.
- Admin manages cities by adding, updating, or deleting them.
- Actually, the admin can do anything in the system.
- **Client**: Clients should register before using the system through `/signup` public API.
- After successful registration, they can use the public `/signin` API to get a token to contact the system successfully.
- Client can use all read API calls.
- Clients can add, manage their comments for a city, add, update, delete their comments, and see other comments.
- Client can get the cheapest flight by calling `/cities/travel` API and providing airport codes for [**from the city**] and [**to the city**].
- **Public**: it is not a role, but anonymous users use APIs under public.
- Use `/signin` API call to log-in to the system, supplying the username and password. Then you will get a valid JWT token with a longer living refresh token.
- Use `/signout` to logout from the system.
- Use `/change_password` to change your current password so you will be logged-out, and you need to log-in again to access the system.
- Use `/refresh_token` when your access token is expired to get new JWT access and refresh the token with the previous not expired refresh token without login into the system again.
- Use `/signup` API call to register as a client to use the system functionalities related to the client; otherwise, the client will receive *Not Authorized*.
## Getting started
### Project Management
1. I have used GitHub projects to manage my tasks in the **Flight-Advisor** project. [Project Link](https://github.com/mohamed-taman/Flight-Advisor/projects/1).
2. All MVP tasks are assigned to the **Flight Advisor API MVP** Milestone. [Milestone Link](https://github.com/mohamed-taman/Flight-Advisor/milestone/1?closed=1).
3. I used pull requests to manage and close assigned tasks. [Tasks Link](https://github.com/mohamed-taman/Flight-Advisor/issues?q=is%3Aclosed).
4. Finally, I have added releases to manage small feature sprints until the final release, v1.0. [Releases Link](https://github.com/mohamed-taman/Flight-Advisor/releases).
5. Have a look at open issues for future enhancements. [Opened Issues](https://github.com/mohamed-taman/Flight-Advisor/issues?q=is%3Aopen).
### System components Structure
Let's first explain the system layers structure to understand its components:
```
Flight-Advisor --> Parent folder.
|- docs --> Contains system images.
|- data --> Contains Airports and routes files.
|- frontend --> Contains the frontend UI project.
|- src/main/java - org.siriusxi.fa (package)
|- FlightAdvisorApplication.java --> The main starting point of the application.
|- api --> Contains All REST API controllers that receive requests from the client
to process that request and, finally, return appropriate responses.
It contains all request and response DTOs.
|- repository --> All the database entities CRUD management services.
|- domain --> Domain contains all the database-modeled entities.
|- infra --> Contains all the configurations, exceptions, security management,
support utilities, and dto <--> entities mappers for the system support.
|- service --> Contains all the system business login,
receives calls from Controllers, calls the repository to retrieve and manage data,
then processes them to return to the controllers.
```
Now, as we have learned about different system layers and components, so it is time then to
play, let's play.
## Playing With Flight Advisor Service
First things first, you need to download the following pieces of software to have fun with
the project:
### Required software
The following are the initially required software pieces:
1. **Maven**: it can be downloaded from https://maven.apache.org/download.cgi#.
2. **Git**: it can be downloaded from https://git-scm.com/downloads.
3. **Java 20.0.1**: it can be downloaded from https://www.oracle.com/java/technologies/downloads/#java20.
4. **Node.js 17.8+**: Latest features, can be downloaded from https://nodejs.org/en/download/current/.
5. **Angular CLI 12.2+**: Install it with the following command:
`npm install -g @angular/cli@latest`
Follow the installation guide for each software on provided website link and check your software
versions from the command line to verify that they are all installed correctly.
### Cloning It
Now it is the time to open **terminal** or **git bash** command line, and then clone the project under any of your favorite places with the following command:
```bash
> git clone https://github.com/mohamed-taman/Flight-Advisor.git
```
### Using an IDE
I recommend that you work with your Java code using an IDE that supports the development of Spring Boot applications such as **Spring Tool Suite** or **IntelliJ IDEA Community | Ultimate Edition**.
All you have to do is fire up your favorite IDE **->** open or import the parent folder `Flight-Advisor,` everything will be ready for you.
### Building & Running The System
To build and run Flight Advisor (FA) system components, run the following command:
#### Building FA Components
##### FA backend
```bash
👻 [mtaman]:Flight-Advisor ~~ ./mvnw clean package
```
Now you should expect output like this:
```JavaScript
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- maven-jar-plugin:3.2.0:jar (default-jar) @ flight-advisor ---
[INFO] Building jar: /Flight-Advisor/target/flight-advisor-3.0.jar
[INFO]
[INFO] --- spring-boot-maven-plugin:2.4.0:repackage (repackage) @ flight-advisor ---
[INFO] Replacing main artifact with repackaged archive
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 14.620 s
[INFO] Finished at: 2022-04-13T13:40:50+01:00
[INFO] -----------------------------------------------------------------------
```
##### FA frontend
```bash
👻 [mtaman]:Flight-Advisor ~~ cd frontend
👻 [mtaman]:frontend ~~ npm install && ng build
```
Now you should expect output like this:
```JavaScript
removed 1 package and audited 1521 packages in 6.658s
85 packages are looking for funding
run `npm fund` for details
found 6 vulnerabilities (3 low, 1 moderate, 1 high, 1 critical)
run `npm audit fix` to fix them, or `npm audit` for details
✔ Browser application bundle generation complete.
✔ Copying assets complete.
✔ Index html generation complete.
Initial Chunk Files | Names | Size
vendor.js | vendor | 4.37 MB
scripts.js | scripts | 153.22 kB
polyfills.js | polyfills | 149.77 kB
styles.css | styles | 142.28 kB
main.js | main | 13.32 kB
runtime.js | runtime | 6.15 kB
| Initial Total | 4.83 MB
Build at: 2022-04-13T18:30:00.555Z - Hash: ccf039ad034c30696fdb - Time: 8608ms
```
#### Running the System
Now it's the time to run the system, and it's straightforward, just hit the following commands:
##### FA backend
```bash
👻 [mtaman]:Flight-Advisor ~~ java --enable-preview -jar ./target/*.jar \
👻 [mtaman]:Flight-Advisor ~+ --spring.profiles.active=prod
```
Or
```bash
👻 [mtaman]:Flight-Advisor ~~ ./mvnw spring-boot:run \
👻 [mtaman]:Flight-Advisor ~+ -Dspring-boot.run.jvmArguments="--enable-preview" \
👻 [mtaman]:Flight-Advisor ~+ -Dspring-boot.run.arguments="--spring.profiles.active=prod"
```
**Flight Advisor backend service** will run, with embedded H2 **database** that will be created
under `db` folder and then the `flightDB.mv.db` file, and you should expect an output like this:
```javascript
2022-04-13 13:56:16.587 INFO 2981 --- [ restartedMain] o.s.b.a.h2.H2ConsoleAutoConfiguration:
H2 console available at '/db-console'.
Database available at 'jdbc:h2:./db/flightDB'
2022-04-13 13:56:18.081 INFO 2981 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer:
Tomcat started on port(s): 8090 (http) with
context path 'api/v1/flight/service'
2022-04-13 13:56:18.581 INFO 2981 --- [ restartedMain] o.s.h.f.F.AppStartupRunner:
Congratulations, Flight Advisor Application, is Up & Running :)
```
##### FA frontend
```bash
👻 [mtaman]:frontend ~~ npm start
```
**Flight Advisor UI** will run, and you should expect an output like this:
```javascript
** Angular Live Development Server is listening on localhost:4200,
open your browser on http://localhost:4200/ **
✔ Compiled successfully.
```
### Access Flight Advisor System APIs
You can play and test `Flight Advisor` APIs throughout its **OpenAPI** interface.
1. Go to the landing page at the following URL [http://localhost:8090/api/v1/flight/service/]
(http://localhost:8090/api/v1/flight/service/).
2. Follow the link on the page, and you should see the following:
![System APIs](docs/images/SystemAPI.png)
3. More beautifully with its UI at [http://localhost:4200/](http://localhost:4200/), and you
expect this view for login:
![ClientLogin page](docs/images/FA-Login.png)
And this view after login, to travel:
![System APIs](docs/images/FA-Travel.png)
#### System Behaviour
1. First, if you want to upload airports or routes (in the data folder) using the **Files upload Management** section:
1. Log-in with the provided admin username/password to the `auth/signin` endpoint.
2. On successful login, the response will contain an authorization token; copy it.
3. Click on the Authorize button and paste it into the only field out there, `value,` then click the `Authorize` button.
4. All locks are closed, and you can use the secured APIs.
2. If you are a new client and want to access the system, you must first register through the `/auth/signup` endpoint. Then follow the previous point **1.1**.
3. When uploading the Airports file, countries and cities will be created automatically.
4. All search parameters are case-insensitive, and the system uses a `like` search by default.
5. To add a city, you need a country, so from the **country management** section, you can search for the country you want.
6. To manage comments, you need a city, so from the **city management** section, you can get all cities or search for a specific city.
7. You can search for all airports in a specific city to know their codes so that you can use travel services.
8. Use a travel service to search for the cheapest flight from city to city, for example traveling from **CAI** (*Cairo International Airport, Egypt*) to **LAX** (*Los Angeles, USA*); the following results will be returned:
```JSON
[
{
"start": {
"airport": "Cairo International Airport",
"city": "Cairo",
"country": "Egypt",
"iata": "CAI"
},
"through": [
{
"airport": "Lester B. Pearson International Airport",
"city": "Toronto",
"country": "Canada",
"iata": "YYZ"
}
],
"end": {
"airport": "Los Angeles International Airport",
"city": "Los Angeles",
"country": "United States",
"iata": "LAX"
},
"price": {
"total": 62.17,
"currency": "US"
},
"distance": {
"total": 12722.2,
"in": "KM"
}
}
]
```
### Access Flight Advisor System Database
You can access the database through its online console from the following URL
[http://localhost:8090/api/v1/flight/service/db-console/]
(http://localhost:8090/api/v1/flight/service/db-console/) with the following properties:
- Driver class: `org.h2.Driver`
- JDBC URL: `jdbc:h2:./db/flightDB`
- user: `sa`
- password: `Admin1234`
![System DB](docs/images/SystemDB.png)
Hit test, and it should show a green bar for successful settings. So hit the **Connect** button and explore all data.
### Stopping The System
Just press the `CTRL+C` keys on the terminal.
### Closing The Story
Finally, I hope you enjoyed the application and found it useful. If you would like to enhance it, please open **PR**, and yet give it a 🌟.
## The End
Happy Coding 😊
## License
Copyright (C) 2023 Mohamed Taman, Licensed under the **MIT License**.
\ No newline at end of file
diff --git a/docs/images/SystemAPI.png b/docs/images/SystemAPI.png
index d35d19c..b44c359 100644
Binary files a/docs/images/SystemAPI.png and b/docs/images/SystemAPI.png differ
diff --git a/pom.xml b/pom.xml
index ce2f02e..1ce0b33 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,13 +6,13 @@
org.springframework.boot
spring-boot-starter-parent
- 3.1.0-M2
+ 3.1.0-RC2
- org.siriusxi.htec
+ org.siriusxi.fa
flight-advisor
- 3.0
+ 5.0
Flight Advisor API
Flight Advisor API Spring Boot based Application.
jar
@@ -58,10 +58,10 @@
- 20
- 20
- 20
20
+ ${java.version}
+ ${java.version}
+ ${java.version}
UTF-8
UTF-8
@@ -69,7 +69,7 @@
3.0.0
3.0.0
0.11.5
- 1.5.3.Final
+ 1.5.4.Final
2.1.0
5.7.1
1.0.1
@@ -114,6 +114,12 @@
org.springdoc
springdoc-openapi-starter-webmvc-ui
${org.springdoc.version}
+
+
+ org.yaml
+ snakeyaml
+
+
@@ -180,8 +186,7 @@
${org.mapstruct.version}
-
+
com.opencsv
opencsv
diff --git a/src/main/java/org/siriusxi/htec/fa/FlightAdvisorApplication.java b/src/main/java/org/siriusxi/fa/FlightAdvisorApplication.java
similarity index 95%
rename from src/main/java/org/siriusxi/htec/fa/FlightAdvisorApplication.java
rename to src/main/java/org/siriusxi/fa/FlightAdvisorApplication.java
index 5d1cc96..1352eaa 100644
--- a/src/main/java/org/siriusxi/htec/fa/FlightAdvisorApplication.java
+++ b/src/main/java/org/siriusxi/fa/FlightAdvisorApplication.java
@@ -1,4 +1,4 @@
-package org.siriusxi.htec.fa;
+package org.siriusxi.fa;
import lombok.extern.log4j.Log4j2;
import org.springframework.boot.ApplicationRunner;
diff --git a/src/main/java/org/siriusxi/fa/api/controller/AuthController.java b/src/main/java/org/siriusxi/fa/api/controller/AuthController.java
new file mode 100644
index 0000000..c7dba6a
--- /dev/null
+++ b/src/main/java/org/siriusxi/fa/api/controller/AuthController.java
@@ -0,0 +1,212 @@
+package org.siriusxi.fa.api.controller;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.security.SecurityRequirement;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.validation.Valid;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.log4j.Log4j2;
+import org.siriusxi.fa.api.model.request.AuthRequest;
+import org.siriusxi.fa.api.model.request.ChangePasswordRequest;
+import org.siriusxi.fa.api.model.request.CreateUserRequest;
+import org.siriusxi.fa.api.model.request.TokenRefreshRequest;
+import org.siriusxi.fa.api.model.response.TokenRefreshResponse;
+import org.siriusxi.fa.api.model.response.UserResponse;
+import org.siriusxi.fa.domain.User;
+import org.siriusxi.fa.infra.exception.NotAllowedException;
+import org.siriusxi.fa.infra.exception.RefreshTokenException;
+import org.siriusxi.fa.service.UserService;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.HttpClientErrorException;
+
+import java.util.Optional;
+
+import static org.siriusxi.fa.infra.security.jwt.JwtTokenHelper.generateJwtToken;
+import static org.springframework.http.HttpStatus.UNAUTHORIZED;
+
+/**
+ * Authentication controller used to handle users authentication.
+ *
+ * @author Mohamed Taman
+ * @version 1.0
+ */
+
+@Log4j2
+@Tag(name = "Authentication",
+ description = "A set of public APIs, for managing user authentication, and the registration.")
+@RestController
+@RequestMapping("auth")
+@RequiredArgsConstructor
+public class AuthController {
+
+ private final AuthenticationManager authenticationManager;
+ private final UserService userService;
+
+ @Operation(description = """
+ An API call to authenticate user before using the system,
+ and if successful a valid token is returned.
+ """)
+ @PostMapping(value = "signin")
+ public ResponseEntity authenticate(@RequestBody @Valid AuthRequest request) {
+ try {
+ var authenticate = this.authenticationManager
+ .authenticate(new UsernamePasswordAuthenticationToken(
+ request.username(),
+ request.password()));
+
+ User user = (User) authenticate.getPrincipal();
+
+ // Generate refresh token
+ user = this.userService.generateRefreshToken(user);
+
+ return ResponseEntity.ok()
+ .header(HttpHeaders.AUTHORIZATION,
+ generateJwtToken(
+ user.getId(),
+ user.getUsername()))
+ .body(this.userService.mapper().toView(user));
+ } catch (BadCredentialsException ex) {
+ throw new HttpClientErrorException(UNAUTHORIZED, UNAUTHORIZED.getReasonPhrase());
+ }
+ }
+
+ @Operation(description = """
+ An API call, to register the user,
+ to be able to authenticate and use the system.
+ """)
+ @PostMapping(value = "signup")
+ public UserResponse register(@RequestBody @Valid CreateUserRequest userRequest) {
+
+ log.debug("User to be created: {}", userRequest);
+ return this.userService.create(userRequest);
+ }
+
+
+ /**
+ *
+ * +--------+ +---------------+
+ * | |--(A)------- Authorization Grant --------->| |
+ * | | | |
+ * | |<-(B)----------- Access Token -------------| |
+ * | | & Refresh Token | |
+ * | | | |
+ * | | +----------+ | |
+ * | |--(C)---- Access Token ---->| | | |
+ * | | | | | |
+ * | |<-(D)- Protected Resource --| Resource | | Authorization |
+ * | Client | | Server | | Server |
+ * | |--(E)---- Access Token ---->| | | |
+ * | | | | | |
+ * | |<-(F)- Invalid Token Error -| | | |
+ * | | +----------+ | |
+ * | | | |
+ * | |--(G)----------- Refresh Token ----------->| |
+ * | | | |
+ * | |<-(H)----------- Access Token -------------| |
+ * +--------+ & Optional Refresh Token +---------------+
+ *
+ *
+ * - (A) The client requests an access token by authenticating with the
+ * authorization server and presenting an authorization grant.
+ *
+ * - (B) The authorization server authenticates the client and validates
+ * the authorization grant, and if valid, issues an access token
+ * and a refresh token.
+ *
+ * - (C) The client makes a protected resource request to the resource
+ * server by presenting the access token.
+ *
+ * - (D) The resource server validates the access token, and if valid,
+ * serves the request.
+ *
+ * - (E) Steps (C) and (D) repeat until the access token expires. If the
+ * client knows the access token expired, it skips to step (G);
+ * otherwise, it makes another protected resource request.
+ *
+ * - (F) Since the access token is invalid, the resource server returns
+ * an invalid token error.
+ *
+ * - (G) The client requests a new access token by authenticating with
+ * the authorization server and presenting the refresh token. The
+ * client authentication requirements are based on the client type
+ * and on the authorization server policies.
+ *
+ * - (H) The authorization server authenticates the client and validates
+ * the refresh token, and if valid, issues a new access token (and,
+ * optionally, a new refresh token).
+ *
+ *
+ * @param tokenRefreshRequest the request for generating a new token, and refresh token.
+ * @return the new access token, and a new refresh token if not expired.
+ */
+ @Operation(description = """
+ An API call, to refresh user JWT token without signing again,
+ to be able to continue be authenticated and use the system.
+ """)
+ @PostMapping(value = "refresh_token")
+ public TokenRefreshResponse refreshToken(@RequestBody @Valid TokenRefreshRequest tokenRefreshRequest) {
+ log.debug("Token to be Refreshed: {}", tokenRefreshRequest);
+
+ return this.userService
+ .findByRefreshToken(tokenRefreshRequest.refreshToken())
+ .map(this.userService::verifyRefreshTokenExpiration)
+ .map(this.userService::generateRefreshToken)
+ .map(user ->
+ new TokenRefreshResponse(generateJwtToken(
+ user.getId(),
+ user.getUsername()), user.getRefreshToken().toString())
+ )
+ .orElseThrow(() -> new RefreshTokenException(tokenRefreshRequest.refreshToken(), "Invalid refresh token, can't generate a new one!"));
+ }
+
+ @Operation(description = """
+ An API call, to logout the user,
+ But has to re-authenticate again to access the system.
+ """,
+ security = {@SecurityRequirement(name = "bearer-key")})
+ @PostMapping("/signout")
+ public ResponseEntity logoutUser() {
+ getUserFromSecurityContext()
+ .ifPresentOrElse(user -> {
+ this.userService.invalidateRefreshTokenById(user.getId());
+ SecurityContextHolder.getContext().setAuthentication(null);
+ }, () -> {
+ throw new NotAllowedException("Can't logout, please signin!");
+ });
+
+ return ResponseEntity.ok("Logged out successful!");
+ }
+
+ @Operation(description = """
+ An API call, to change user password,
+ But user has to re-authenticate again to access the system with new password.
+ """,
+ security = {@SecurityRequirement(name = "bearer-key")})
+ @PostMapping("/change_password")
+ public ResponseEntity changePassword(@RequestBody @Valid ChangePasswordRequest changePassRequest) {
+ getUserFromSecurityContext()
+ .ifPresentOrElse(user -> {
+ this.userService.updatePassword(user.getId(), changePassRequest);
+ SecurityContextHolder.getContext().setAuthentication(null);
+ }, () -> {
+ throw new NotAllowedException("Can't change password, please signin!");
+ });
+
+ return ResponseEntity.ok("Password changed successful!");
+ }
+
+ private Optional getUserFromSecurityContext() {
+ var auth = SecurityContextHolder.getContext().getAuthentication();
+ return auth != null && auth.getPrincipal() instanceof User user ? Optional.of(user) : Optional.empty();
+ }
+
+}
diff --git a/src/main/java/org/siriusxi/htec/fa/api/controller/CityController.java b/src/main/java/org/siriusxi/fa/api/controller/CityController.java
similarity index 56%
rename from src/main/java/org/siriusxi/htec/fa/api/controller/CityController.java
rename to src/main/java/org/siriusxi/fa/api/controller/CityController.java
index 0aca0fa..dd991f1 100644
--- a/src/main/java/org/siriusxi/htec/fa/api/controller/CityController.java
+++ b/src/main/java/org/siriusxi/fa/api/controller/CityController.java
@@ -1,4 +1,4 @@
-package org.siriusxi.htec.fa.api.controller;
+package org.siriusxi.fa.api.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@@ -10,17 +10,17 @@
import jakarta.validation.constraints.Size;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
-import org.siriusxi.htec.fa.api.model.request.CommentUpSrtRequest;
-import org.siriusxi.htec.fa.api.model.request.CreateCityRequest;
-import org.siriusxi.htec.fa.api.model.request.SearchAirportRequest;
-import org.siriusxi.htec.fa.api.model.request.SearchCityRequest;
-import org.siriusxi.htec.fa.api.model.response.AirportView;
-import org.siriusxi.htec.fa.api.model.response.CityView;
-import org.siriusxi.htec.fa.api.model.response.CommentView;
-import org.siriusxi.htec.fa.api.model.response.TripView;
-import org.siriusxi.htec.fa.domain.User;
-import org.siriusxi.htec.fa.service.CityMgmtService;
-import org.siriusxi.htec.fa.service.TravelService;
+import org.siriusxi.fa.api.model.request.CommentUpSrtRequest;
+import org.siriusxi.fa.api.model.request.CreateCityRequest;
+import org.siriusxi.fa.api.model.request.SearchAirportRequest;
+import org.siriusxi.fa.api.model.request.SearchCityRequest;
+import org.siriusxi.fa.api.model.response.AirportResponse;
+import org.siriusxi.fa.api.model.response.CityResponse;
+import org.siriusxi.fa.api.model.response.CommentResponse;
+import org.siriusxi.fa.api.model.response.TripResponse;
+import org.siriusxi.fa.domain.User;
+import org.siriusxi.fa.service.CityMgmtService;
+import org.siriusxi.fa.service.TravelService;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
@@ -35,6 +35,7 @@
@Log4j2
@Tag(name = "City Management",
description = "A set of authorized APIs, for getting and managing system cities.")
+@SecurityRequirement(name = "bearer-key")
@RestController
@RequestMapping("cities")
@RequiredArgsConstructor
@@ -44,22 +45,20 @@ public class CityController {
private final TravelService travelService;
@Operation(summary = "Get all cities.",
- description = "Get city or all cities. You can limit the # of returned comments.",
- security = {@SecurityRequirement(name = "bearer-key")})
+ description = "Get city or all cities. You can limit the # of returned comments.")
@GetMapping
- public List getAllCities(@RequestParam(defaultValue = "0")
- @Min(0) @Max(Integer.MAX_VALUE) int cLimit) {
- return cityMgmtService.searchCities(new SearchCityRequest(""), cLimit);
+ public List getAllCities(@RequestParam(defaultValue = "0")
+ @Min(0) @Max(Integer.MAX_VALUE) int cLimit) {
+ return this.cityMgmtService.searchCities(new SearchCityRequest(""), cLimit);
}
@Operation(summary = "Search all cities by name.",
- description = "Find city or all cities by name. You can limit the # of returned comments.",
- security = {@SecurityRequirement(name = "bearer-key")})
+ description = "Find city or all cities by name. You can limit the # of returned comments.")
@PostMapping("search")
- public List searchCities(@RequestParam(defaultValue = "0")
- @Min(0) @Max(Integer.MAX_VALUE) int cLimit,
- @RequestBody @Valid SearchCityRequest request) {
- return cityMgmtService.searchCities(request, cLimit);
+ public List searchCities(@RequestParam(defaultValue = "0")
+ @Min(0) @Max(Integer.MAX_VALUE) int cLimit,
+ @RequestBody @Valid SearchCityRequest request) {
+ return this.cityMgmtService.searchCities(request, cLimit);
}
@@ -70,20 +69,18 @@ public List searchCities(@RequestParam(defaultValue = "0")
1. by its id if it is already exist in the system, or
2. by country name if not exist, then the system will \
creat the country and attach it to the city.
- """,
- security = {@SecurityRequirement(name = "bearer-key")})
+ """)
@PostMapping
- public CityView createCity(@RequestBody @Valid CreateCityRequest request) {
- return cityMgmtService.addCity(request);
+ public CityResponse createCity(@RequestBody @Valid CreateCityRequest request) {
+ return this.cityMgmtService.addCity(request);
}
@Operation(summary = "Exited! and wanna travel.",
- description = "Find the cheapest trip from source country to a destination country.",
- security = {@SecurityRequirement(name = "bearer-key")})
+ description = "Find the cheapest trip from source country to a destination country.")
@GetMapping("travel")
- public List travel(@RequestParam @Size(min = 3) String from,
- @RequestParam @Size(min = 3) String to) {
+ public List travel(@RequestParam @Size(min = 3) String from,
+ @RequestParam @Size(min = 3) String to) {
if (from.isBlank() || to.isBlank())
throw new IllegalArgumentException("""
@@ -95,7 +92,7 @@ public List travel(@RequestParam @Size(min = 3) String from,
throw new IllegalArgumentException(String.format(
"You are traveling from and to the same destination [%s]", to));
- return travelService
+ return this.travelService
.travel(from.trim().toUpperCase(), to.trim().toUpperCase());
}
@@ -103,24 +100,22 @@ public List travel(@RequestParam @Size(min = 3) String from,
Airport Management
*/
@Operation(summary = "Find city airports.",
- description = "Find all airports for a specific city.",
- security = {@SecurityRequirement(name = "bearer-key")})
+ description = "Find all airports for a specific city.")
@PostMapping("{id}/airports")
- public List searchAirports(@Parameter(description = "City Id")
- @PathVariable(name = "id")
- @Min(1) @Max(Integer.MAX_VALUE) int cityId,
- @RequestBody @Valid SearchAirportRequest request) {
- return cityMgmtService.searchAirports(request, cityId);
+ public List searchAirports(@Parameter(description = "City Id")
+ @PathVariable(name = "id")
+ @Min(1) @Max(Integer.MAX_VALUE) int cityId,
+ @RequestBody @Valid SearchAirportRequest request) {
+ return this.cityMgmtService.searchAirports(request, cityId);
}
@Operation(summary = "Get all airports by a any name.",
- description = "Find all airports by airport, city or country name.",
- security = {@SecurityRequirement(name = "bearer-key")})
+ description = "Find all airports by airport, city or country name.")
@GetMapping("/airports")
- public List searchForCityOrCountryAirports(
+ public List searchForCityOrCountryAirports(
@Parameter(description = "Airport, city or country name")
@RequestParam @Size(min = 1) String name) {
- return travelService.findAirportsForCityOrCountry(name);
+ return this.travelService.findAirportsForCityOrCountry(name);
}
/*
@@ -129,20 +124,18 @@ public List searchForCityOrCountryAirports(
//Add comment
@Operation(summary = "Add a city comment.",
- description = "Wanna add a comment to a city you have visited.",
- security = {@SecurityRequirement(name = "bearer-key")})
+ description = "Wanna add a comment to a city you have visited.")
@PostMapping("{id}/comments")
- public CommentView addComment(@Parameter(description = "City Id")
- @PathVariable(name = "id")
- @Min(1) @Max(Integer.MAX_VALUE) int cityId,
- @RequestBody @Valid CommentUpSrtRequest request) {
- return cityMgmtService.addComment(getCurrentLoginUser(), cityId, request);
+ public CommentResponse addComment(@Parameter(description = "City Id")
+ @PathVariable(name = "id")
+ @Min(1) @Max(Integer.MAX_VALUE) int cityId,
+ @RequestBody @Valid CommentUpSrtRequest request) {
+ return this.cityMgmtService.addComment(getCurrentLoginUser(), cityId, request);
}
//update comment
@Operation(summary = "Update my city comment.",
- description = "Wanna change your comment to a city you have visited.",
- security = {@SecurityRequirement(name = "bearer-key")})
+ description = "Wanna change your comment to a city you have visited.")
@PutMapping("{id}/comments/{cid}")
public void updateComment(@Parameter(description = "City Id")
@PathVariable(name = "id")
@@ -152,20 +145,19 @@ public void updateComment(@Parameter(description = "City Id")
@Min(1) @Max(Integer.MAX_VALUE) int commentId,
@RequestBody @Valid CommentUpSrtRequest request) {
- cityMgmtService.updateComment(getCurrentLoginUser(), cityId, commentId, request);
+ this.cityMgmtService.updateComment(getCurrentLoginUser(), cityId, commentId, request);
}
//Delete comment
@Operation(summary = "Delete my city comment.",
- description = "Changed your mind, don't like your comment then delete it.",
- security = {@SecurityRequirement(name = "bearer-key")})
+ description = "Changed your mind, don't like your comment then delete it.")
@DeleteMapping("{id}/comments/{cid}")
public void deleteComment(@Parameter(description = "City Id") @PathVariable(name = "id")
@Min(1) @Max(Integer.MAX_VALUE) int cityId,
@Parameter(description = "Comment Id") @PathVariable("cid")
@Min(1) @Max(Integer.MAX_VALUE) int commentId) {
- cityMgmtService.deleteComment(getCurrentLoginUser(), cityId, commentId);
+ this.cityMgmtService.deleteComment(getCurrentLoginUser(), cityId, commentId);
}
private User getCurrentLoginUser() {
diff --git a/src/main/java/org/siriusxi/htec/fa/api/controller/CountryController.java b/src/main/java/org/siriusxi/fa/api/controller/CountryController.java
similarity index 57%
rename from src/main/java/org/siriusxi/htec/fa/api/controller/CountryController.java
rename to src/main/java/org/siriusxi/fa/api/controller/CountryController.java
index 683f83b..d839816 100644
--- a/src/main/java/org/siriusxi/htec/fa/api/controller/CountryController.java
+++ b/src/main/java/org/siriusxi/fa/api/controller/CountryController.java
@@ -1,4 +1,4 @@
-package org.siriusxi.htec.fa.api.controller;
+package org.siriusxi.fa.api.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
@@ -6,9 +6,9 @@
import jakarta.validation.constraints.NotBlank;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
-import org.siriusxi.htec.fa.api.model.response.CountryView;
-import org.siriusxi.htec.fa.infra.mapper.CountryMapper;
-import org.siriusxi.htec.fa.repository.CountryRepository;
+import org.siriusxi.fa.api.model.response.CountryResponse;
+import org.siriusxi.fa.infra.mapper.CountryMapper;
+import org.siriusxi.fa.repository.CountryRepository;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@@ -17,16 +17,16 @@
import java.util.Set;
/**
- * City controller used to handle cities API functions.
+ * Country controller used to handle countries API functions.
*
* @author Mohamed Taman
* @version 1.0
*/
-// TODO: Add Swagger documentation
@Log4j2
@Tag(name = "Country Management",
description = "A set of authorized APIs, for getting and managing system countries.")
+@SecurityRequirement(name = "bearer-key")
@RestController
@RequestMapping("countries")
@RequiredArgsConstructor
@@ -35,19 +35,21 @@ public class CountryController {
private final CountryRepository countryRepository;
private final CountryMapper mapper;
- @Operation(security = {@SecurityRequirement(name = "bearer-key")})
+ @Operation(summary = "Get all countries.",
+ description = "Get Country or all countries.")
@GetMapping
- public Set getAllCountries() {
- return mapper
- .toViews(countryRepository
+ public Set getAllCountries() {
+ return this.mapper
+ .toViews(this.countryRepository
.findAllByNameIgnoreCaseIsLike("%%"));
}
- @Operation(security = {@SecurityRequirement(name = "bearer-key")})
+ @Operation(summary = "Search all countries by name.",
+ description = "Find country or all countries by name.")
@GetMapping("search")
- public Set searchCountries(@RequestParam @NotBlank String name) {
- return mapper
- .toViews(countryRepository
+ public Set searchCountries(@RequestParam @NotBlank String name) {
+ return this.mapper
+ .toViews(this.countryRepository
.findAllByNameIgnoreCaseIsLike("%" + name + "%"));
}
diff --git a/src/main/java/org/siriusxi/htec/fa/api/controller/FileUploadController.java b/src/main/java/org/siriusxi/fa/api/controller/FileUploadController.java
similarity index 86%
rename from src/main/java/org/siriusxi/htec/fa/api/controller/FileUploadController.java
rename to src/main/java/org/siriusxi/fa/api/controller/FileUploadController.java
index 0e8669c..5ff2790 100644
--- a/src/main/java/org/siriusxi/htec/fa/api/controller/FileUploadController.java
+++ b/src/main/java/org/siriusxi/fa/api/controller/FileUploadController.java
@@ -1,4 +1,4 @@
-package org.siriusxi.htec.fa.api.controller;
+package org.siriusxi.fa.api.controller;
import com.opencsv.bean.BeanVerifier;
import com.opencsv.bean.CsvToBean;
@@ -12,17 +12,17 @@
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
-import org.siriusxi.htec.fa.api.model.upload.airport.AirportDto;
-import org.siriusxi.htec.fa.api.model.upload.airport.verifer.AirportBeanVerifier;
-import org.siriusxi.htec.fa.api.model.upload.route.RouteDto;
-import org.siriusxi.htec.fa.api.model.upload.route.verifer.RouteBeanVerifier;
-import org.siriusxi.htec.fa.domain.Country;
-import org.siriusxi.htec.fa.infra.mapper.AirportMapper;
-import org.siriusxi.htec.fa.infra.mapper.RouteMapper;
-import org.siriusxi.htec.fa.repository.AirportRepository;
-import org.siriusxi.htec.fa.repository.CityRepository;
-import org.siriusxi.htec.fa.repository.CountryRepository;
-import org.siriusxi.htec.fa.repository.RouteRepository;
+import org.siriusxi.fa.api.model.upload.airport.AirportDto;
+import org.siriusxi.fa.api.model.upload.airport.verifer.AirportBeanVerifier;
+import org.siriusxi.fa.api.model.upload.route.RouteDto;
+import org.siriusxi.fa.api.model.upload.route.verifer.RouteBeanVerifier;
+import org.siriusxi.fa.domain.Country;
+import org.siriusxi.fa.infra.mapper.AirportMapper;
+import org.siriusxi.fa.infra.mapper.RouteMapper;
+import org.siriusxi.fa.repository.AirportRepository;
+import org.siriusxi.fa.repository.CityRepository;
+import org.siriusxi.fa.repository.CountryRepository;
+import org.siriusxi.fa.repository.RouteRepository;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
@@ -49,6 +49,7 @@
description = """
A set of authorized file management APIs, used to feed the system with data
files like airports and routes.""")
+@SecurityRequirement(name = "bearer-key")
@RestController
@RequestMapping(value = "upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@RequiredArgsConstructor
@@ -62,7 +63,6 @@ public class FileUploadController {
private final AirportMapper airportMapper;
@Operation(summary = "Upload file that contains flights airports.",
- security = {@SecurityRequirement(name = "bearer-key")},
responses = {
@ApiResponse(responseCode = "200",
description = "OK; File is uploaded and parsed successfully.",
@@ -92,22 +92,22 @@ public ResponseEntity uploadAirports(@Parameter(name = "file", required
3. Map Airport Dto to Airport model.
4. Return all airports as list to be saved to DB.
*/
- airportRepository.saveAll(
+ this.airportRepository.saveAll(
airports
.stream()// Save countries and cities to database
.map(airportDto -> {
- Country country = countryRepository
+ Country country = this.countryRepository
.findOrSaveBy(airportDto.getCountry());
airportDto.setCountryId(country.getId());
- airportDto.setCityId(cityRepository
+ airportDto.setCityId(this.cityRepository
.findOrSaveBy(country, airportDto.getCity())
.getId());
// then converting to
- return airportMapper.toModel(airportDto);
+ return this.airportMapper.toModel(airportDto);
})
// Then collect them to list
.toList());
@@ -123,7 +123,6 @@ public ResponseEntity uploadAirports(@Parameter(name = "file", required
}
@Operation(summary = "Upload file that contains flights routes.",
- security = {@SecurityRequirement(name = "bearer-key")},
responses = {
@ApiResponse(responseCode = "200",
description = "OK; File is uploaded and parsed successfully.",
@@ -144,7 +143,7 @@ public ResponseEntity uploadRoutes(@Parameter(name = "file", required =
if (file.isEmpty())
return new ResponseEntity<>("Please upload a valid file.", BAD_REQUEST);
- else if (airportRepository.count() == 0) {
+ else if (this.airportRepository.count() == 0) {
return new ResponseEntity<>("""
"Can't upload flight routes, system doesn't has Airports defined.
Please upload airport file, to feed the system with airports."
@@ -162,16 +161,16 @@ else if (airportRepository.count() == 0) {
1. Convert to Route model.
2. Save routes in DB.
*/
- routeRepository
+ this.routeRepository
.saveAll(routes
.stream()
// filter routes doesn't exists
.filter(dto ->
- airportRepository
+ this.airportRepository
.findById(dto.getSrcAirportId()).isPresent() &&
- airportRepository.findById(dto.getDestAirportId()).isPresent())
+ this.airportRepository.findById(dto.getDestAirportId()).isPresent())
// converting to
- .map(routeMapper::toModel)
+ .map(this.routeMapper::toModel)
// Then collect them to list
.toList());
diff --git a/src/main/java/org/siriusxi/htec/fa/api/model/request/AuthRequest.java b/src/main/java/org/siriusxi/fa/api/model/request/AuthRequest.java
similarity index 89%
rename from src/main/java/org/siriusxi/htec/fa/api/model/request/AuthRequest.java
rename to src/main/java/org/siriusxi/fa/api/model/request/AuthRequest.java
index 6000b4c..b16a7e7 100644
--- a/src/main/java/org/siriusxi/htec/fa/api/model/request/AuthRequest.java
+++ b/src/main/java/org/siriusxi/fa/api/model/request/AuthRequest.java
@@ -1,4 +1,4 @@
-package org.siriusxi.htec.fa.api.model.request;
+package org.siriusxi.fa.api.model.request;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/src/main/java/org/siriusxi/fa/api/model/request/ChangePasswordRequest.java b/src/main/java/org/siriusxi/fa/api/model/request/ChangePasswordRequest.java
new file mode 100644
index 0000000..f1fd278
--- /dev/null
+++ b/src/main/java/org/siriusxi/fa/api/model/request/ChangePasswordRequest.java
@@ -0,0 +1,7 @@
+package org.siriusxi.fa.api.model.request;
+
+import jakarta.validation.constraints.NotBlank;
+
+public record ChangePasswordRequest(@NotBlank String newPassword,
+ @NotBlank String newPasswordAgain) {
+}
diff --git a/src/main/java/org/siriusxi/htec/fa/api/model/request/CommentUpSrtRequest.java b/src/main/java/org/siriusxi/fa/api/model/request/CommentUpSrtRequest.java
similarity index 88%
rename from src/main/java/org/siriusxi/htec/fa/api/model/request/CommentUpSrtRequest.java
rename to src/main/java/org/siriusxi/fa/api/model/request/CommentUpSrtRequest.java
index 66b2ec5..2cc767e 100644
--- a/src/main/java/org/siriusxi/htec/fa/api/model/request/CommentUpSrtRequest.java
+++ b/src/main/java/org/siriusxi/fa/api/model/request/CommentUpSrtRequest.java
@@ -1,4 +1,4 @@
-package org.siriusxi.htec.fa.api.model.request;
+package org.siriusxi.fa.api.model.request;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/src/main/java/org/siriusxi/htec/fa/api/model/request/CreateCityRequest.java b/src/main/java/org/siriusxi/fa/api/model/request/CreateCityRequest.java
similarity index 93%
rename from src/main/java/org/siriusxi/htec/fa/api/model/request/CreateCityRequest.java
rename to src/main/java/org/siriusxi/fa/api/model/request/CreateCityRequest.java
index 1e5ea75..44463ff 100644
--- a/src/main/java/org/siriusxi/htec/fa/api/model/request/CreateCityRequest.java
+++ b/src/main/java/org/siriusxi/fa/api/model/request/CreateCityRequest.java
@@ -1,4 +1,4 @@
-package org.siriusxi.htec.fa.api.model.request;
+package org.siriusxi.fa.api.model.request;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/src/main/java/org/siriusxi/htec/fa/api/model/request/CreateUserRequest.java b/src/main/java/org/siriusxi/fa/api/model/request/CreateUserRequest.java
similarity index 94%
rename from src/main/java/org/siriusxi/htec/fa/api/model/request/CreateUserRequest.java
rename to src/main/java/org/siriusxi/fa/api/model/request/CreateUserRequest.java
index e5d5b74..6a4e040 100644
--- a/src/main/java/org/siriusxi/htec/fa/api/model/request/CreateUserRequest.java
+++ b/src/main/java/org/siriusxi/fa/api/model/request/CreateUserRequest.java
@@ -1,4 +1,4 @@
-package org.siriusxi.htec.fa.api.model.request;
+package org.siriusxi.fa.api.model.request;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/src/main/java/org/siriusxi/htec/fa/api/model/request/SearchAirportRequest.java b/src/main/java/org/siriusxi/fa/api/model/request/SearchAirportRequest.java
similarity index 86%
rename from src/main/java/org/siriusxi/htec/fa/api/model/request/SearchAirportRequest.java
rename to src/main/java/org/siriusxi/fa/api/model/request/SearchAirportRequest.java
index da658e3..09a41df 100644
--- a/src/main/java/org/siriusxi/htec/fa/api/model/request/SearchAirportRequest.java
+++ b/src/main/java/org/siriusxi/fa/api/model/request/SearchAirportRequest.java
@@ -1,4 +1,4 @@
-package org.siriusxi.htec.fa.api.model.request;
+package org.siriusxi.fa.api.model.request;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/src/main/java/org/siriusxi/htec/fa/api/model/request/SearchCityRequest.java b/src/main/java/org/siriusxi/fa/api/model/request/SearchCityRequest.java
similarity index 83%
rename from src/main/java/org/siriusxi/htec/fa/api/model/request/SearchCityRequest.java
rename to src/main/java/org/siriusxi/fa/api/model/request/SearchCityRequest.java
index d81be8e..f7e5b83 100644
--- a/src/main/java/org/siriusxi/htec/fa/api/model/request/SearchCityRequest.java
+++ b/src/main/java/org/siriusxi/fa/api/model/request/SearchCityRequest.java
@@ -1,4 +1,4 @@
-package org.siriusxi.htec.fa.api.model.request;
+package org.siriusxi.fa.api.model.request;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/src/main/java/org/siriusxi/fa/api/model/request/TokenRefreshRequest.java b/src/main/java/org/siriusxi/fa/api/model/request/TokenRefreshRequest.java
new file mode 100644
index 0000000..c65c715
--- /dev/null
+++ b/src/main/java/org/siriusxi/fa/api/model/request/TokenRefreshRequest.java
@@ -0,0 +1,6 @@
+package org.siriusxi.fa.api.model.request;
+
+import jakarta.validation.constraints.NotBlank;
+
+public record TokenRefreshRequest(@NotBlank String refreshToken) {
+}
diff --git a/src/main/java/org/siriusxi/fa/api/model/response/AirportResponse.java b/src/main/java/org/siriusxi/fa/api/model/response/AirportResponse.java
new file mode 100644
index 0000000..fd61144
--- /dev/null
+++ b/src/main/java/org/siriusxi/fa/api/model/response/AirportResponse.java
@@ -0,0 +1,20 @@
+package org.siriusxi.fa.api.model.response;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
+
+public record AirportResponse(@JsonInclude(NON_NULL)
+ @JsonProperty Integer id,
+ @JsonProperty String airport,
+ @JsonProperty String city,
+ @JsonProperty String country,
+ @JsonInclude(NON_NULL)
+ @JsonProperty String iata,
+ @JsonInclude(NON_NULL)
+ @JsonProperty String icao) {
+}
+
+
+
diff --git a/src/main/java/org/siriusxi/fa/api/model/response/CityResponse.java b/src/main/java/org/siriusxi/fa/api/model/response/CityResponse.java
new file mode 100644
index 0000000..4054b30
--- /dev/null
+++ b/src/main/java/org/siriusxi/fa/api/model/response/CityResponse.java
@@ -0,0 +1,17 @@
+package org.siriusxi.fa.api.model.response;
+
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.List;
+
+import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
+
+public record CityResponse(@JsonProperty int id,
+ @JsonProperty String name,
+ @JsonProperty String country,
+ @JsonProperty String description,
+ @JsonInclude(NON_NULL)
+ @JsonProperty List comments) {
+}
diff --git a/src/main/java/org/siriusxi/htec/fa/api/model/response/CommentView.java b/src/main/java/org/siriusxi/fa/api/model/response/CommentResponse.java
similarity index 55%
rename from src/main/java/org/siriusxi/htec/fa/api/model/response/CommentView.java
rename to src/main/java/org/siriusxi/fa/api/model/response/CommentResponse.java
index c13843e..9c7ab9f 100644
--- a/src/main/java/org/siriusxi/htec/fa/api/model/response/CommentView.java
+++ b/src/main/java/org/siriusxi/fa/api/model/response/CommentResponse.java
@@ -1,4 +1,4 @@
-package org.siriusxi.htec.fa.api.model.response;
+package org.siriusxi.fa.api.model.response;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
@@ -9,10 +9,10 @@
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
@JsonPropertyOrder({"id", "comment", "by", "createdAt", "updatedAt"})
-public record CommentView(@JsonProperty int id,
- @JsonProperty String comment,
- @JsonProperty String by,
- @JsonProperty("createdAt") LocalDateTime createdAt,
- @JsonInclude(NON_NULL)
+public record CommentResponse(@JsonProperty int id,
+ @JsonProperty String comment,
+ @JsonProperty String by,
+ @JsonProperty("createdAt") LocalDateTime createdAt,
+ @JsonInclude(NON_NULL)
@JsonProperty("updatedAt") LocalDateTime updatedAt) {
}
diff --git a/src/main/java/org/siriusxi/fa/api/model/response/CountryResponse.java b/src/main/java/org/siriusxi/fa/api/model/response/CountryResponse.java
new file mode 100644
index 0000000..4a1355e
--- /dev/null
+++ b/src/main/java/org/siriusxi/fa/api/model/response/CountryResponse.java
@@ -0,0 +1,8 @@
+package org.siriusxi.fa.api.model.response;
+
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public record CountryResponse(@JsonProperty int id,
+ @JsonProperty String name) {
+}
diff --git a/src/main/java/org/siriusxi/fa/api/model/response/TokenRefreshResponse.java b/src/main/java/org/siriusxi/fa/api/model/response/TokenRefreshResponse.java
new file mode 100644
index 0000000..ba0606a
--- /dev/null
+++ b/src/main/java/org/siriusxi/fa/api/model/response/TokenRefreshResponse.java
@@ -0,0 +1,6 @@
+package org.siriusxi.fa.api.model.response;
+
+public record TokenRefreshResponse(
+ String accessToken,
+ String refreshToken) {
+}
\ No newline at end of file
diff --git a/src/main/java/org/siriusxi/htec/fa/api/model/response/TripView.java b/src/main/java/org/siriusxi/fa/api/model/response/TripResponse.java
similarity index 72%
rename from src/main/java/org/siriusxi/htec/fa/api/model/response/TripView.java
rename to src/main/java/org/siriusxi/fa/api/model/response/TripResponse.java
index 25ea819..fd955c4 100644
--- a/src/main/java/org/siriusxi/htec/fa/api/model/response/TripView.java
+++ b/src/main/java/org/siriusxi/fa/api/model/response/TripResponse.java
@@ -1,4 +1,4 @@
-package org.siriusxi.htec.fa.api.model.response;
+package org.siriusxi.fa.api.model.response;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
@@ -7,11 +7,11 @@
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
-public record TripView(
- @JsonProperty AirportView start,
+public record TripResponse(
+ @JsonProperty AirportResponse start,
@JsonInclude(NON_NULL)
- @JsonProperty List through,
- @JsonProperty AirportView end,
+ @JsonProperty List through,
+ @JsonProperty AirportResponse end,
@JsonProperty Price price,
@JsonProperty Distance distance) {
diff --git a/src/main/java/org/siriusxi/fa/api/model/response/UserResponse.java b/src/main/java/org/siriusxi/fa/api/model/response/UserResponse.java
new file mode 100644
index 0000000..ea78541
--- /dev/null
+++ b/src/main/java/org/siriusxi/fa/api/model/response/UserResponse.java
@@ -0,0 +1,43 @@
+package org.siriusxi.fa.api.model.response;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL;
+
+@JsonInclude(NON_NULL)
+public record UserResponse(@JsonProperty String id,
+ @JsonProperty String username,
+ @JsonProperty String firstName,
+ @JsonProperty String lastName,
+ @JsonProperty String[] authorities,
+ @JsonProperty String refreshToken) {
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ UserResponse userResponse = (UserResponse) o;
+ return Objects.equals(this.id, userResponse.id) &&
+ Objects.equals(this.username, userResponse.username) &&
+ Objects.equals(this.firstName, userResponse.firstName) &&
+ Objects.equals(this.lastName, userResponse.lastName) &&
+ Objects.equals(this.refreshToken, userResponse.refreshToken) &&
+ Arrays.equals(this.authorities, userResponse.authorities);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = Objects.hash(this.id, this.username, this.firstName, this.lastName, this.refreshToken);
+ result = 31 * result + Arrays.hashCode(this.authorities);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName().concat(" { id= %s, username= %s, firstName= %s, lastName= %s , authorities= %s, refreshToken= %s }")
+ .formatted(this.id, this.username, this.firstName, this.lastName, Arrays.toString(this.authorities), this.refreshToken);
+ }
+}
diff --git a/src/main/java/org/siriusxi/htec/fa/api/model/upload/airport/AirportDto.java b/src/main/java/org/siriusxi/fa/api/model/upload/airport/AirportDto.java
similarity index 87%
rename from src/main/java/org/siriusxi/htec/fa/api/model/upload/airport/AirportDto.java
rename to src/main/java/org/siriusxi/fa/api/model/upload/airport/AirportDto.java
index 9c4d257..8dcf398 100644
--- a/src/main/java/org/siriusxi/htec/fa/api/model/upload/airport/AirportDto.java
+++ b/src/main/java/org/siriusxi/fa/api/model/upload/airport/AirportDto.java
@@ -1,9 +1,9 @@
-package org.siriusxi.htec.fa.api.model.upload.airport;
+package org.siriusxi.fa.api.model.upload.airport;
import com.opencsv.bean.CsvBindByPosition;
import com.opencsv.bean.processor.PreAssignmentProcessor;
import lombok.Data;
-import org.siriusxi.htec.fa.api.model.upload.converter.ConvertUnwantedStringsToDefault;
+import org.siriusxi.fa.api.model.upload.converter.ConvertUnwantedStringsToDefault;
import java.math.BigDecimal;
@@ -13,56 +13,56 @@
**/
@Data
public class AirportDto {
-
+
@PreAssignmentProcessor(processor = ConvertUnwantedStringsToDefault.class, paramString = "0")
@CsvBindByPosition(position = 0)
private int airportId;
-
+
@CsvBindByPosition(position = 1)
private String name;
-
+
@CsvBindByPosition(position = 2)
private String city;
-
+
@CsvBindByPosition(position = 3)
private String country;
-
+
@PreAssignmentProcessor(processor = ConvertUnwantedStringsToDefault.class)
@CsvBindByPosition(position = 4)
private String iata;
-
+
@PreAssignmentProcessor(processor = ConvertUnwantedStringsToDefault.class)
@CsvBindByPosition(position = 5)
private String icao;
-
+
@CsvBindByPosition(position = 6)
private BigDecimal latitude;
-
+
@CsvBindByPosition(position = 7)
private BigDecimal longitude;
-
+
@CsvBindByPosition(position = 8)
private short altitude;
-
+
@PreAssignmentProcessor(processor = ConvertUnwantedStringsToDefault.class,
- paramString = "-99.9")
+ paramString = "-99.9")
@CsvBindByPosition(position = 9)
private float timezone;
-
+
@PreAssignmentProcessor(processor = ConvertUnwantedStringsToDefault.class, paramString = "U")
@CsvBindByPosition(position = 10)
private String dst;
-
+
@PreAssignmentProcessor(processor = ConvertUnwantedStringsToDefault.class, paramString = "U")
@CsvBindByPosition(position = 11)
private String tz;
-
+
@CsvBindByPosition(position = 12)
private String type;
-
+
@CsvBindByPosition(position = 13)
private String dataSource;
-
+
// Used for Airport Model mapping of country and city
private int cityId;
private int countryId;
diff --git a/src/main/java/org/siriusxi/htec/fa/api/model/upload/airport/verifer/AirportBeanVerifier.java b/src/main/java/org/siriusxi/fa/api/model/upload/airport/verifer/AirportBeanVerifier.java
similarity index 68%
rename from src/main/java/org/siriusxi/htec/fa/api/model/upload/airport/verifer/AirportBeanVerifier.java
rename to src/main/java/org/siriusxi/fa/api/model/upload/airport/verifer/AirportBeanVerifier.java
index 0b66a71..7666d8b 100644
--- a/src/main/java/org/siriusxi/htec/fa/api/model/upload/airport/verifer/AirportBeanVerifier.java
+++ b/src/main/java/org/siriusxi/fa/api/model/upload/airport/verifer/AirportBeanVerifier.java
@@ -1,7 +1,7 @@
-package org.siriusxi.htec.fa.api.model.upload.airport.verifer;
+package org.siriusxi.fa.api.model.upload.airport.verifer;
import com.opencsv.bean.BeanVerifier;
-import org.siriusxi.htec.fa.api.model.upload.airport.AirportDto;
+import org.siriusxi.fa.api.model.upload.airport.AirportDto;
public class AirportBeanVerifier implements BeanVerifier {
@Override
diff --git a/src/main/java/org/siriusxi/htec/fa/api/model/upload/converter/ConvertUnwantedStringsToDefault.java b/src/main/java/org/siriusxi/fa/api/model/upload/converter/ConvertUnwantedStringsToDefault.java
similarity index 79%
rename from src/main/java/org/siriusxi/htec/fa/api/model/upload/converter/ConvertUnwantedStringsToDefault.java
rename to src/main/java/org/siriusxi/fa/api/model/upload/converter/ConvertUnwantedStringsToDefault.java
index b5263ff..86b905a 100644
--- a/src/main/java/org/siriusxi/htec/fa/api/model/upload/converter/ConvertUnwantedStringsToDefault.java
+++ b/src/main/java/org/siriusxi/fa/api/model/upload/converter/ConvertUnwantedStringsToDefault.java
@@ -1,4 +1,4 @@
-package org.siriusxi.htec.fa.api.model.upload.converter;
+package org.siriusxi.fa.api.model.upload.converter;
import com.opencsv.bean.processor.StringProcessor;
@@ -11,13 +11,13 @@ public String processString(String value) {
if (value == null || value.isBlank() ||
value.equalsIgnoreCase("\\N") ||
value.equalsIgnoreCase("N")) {
- return defaultValue;
+ return this.defaultValue;
}
return value;
}
@Override
public void setParameterString(String value) {
- defaultValue = value;
+ this.defaultValue = value;
}
}
diff --git a/src/main/java/org/siriusxi/htec/fa/api/model/upload/route/RouteDto.java b/src/main/java/org/siriusxi/fa/api/model/upload/route/RouteDto.java
similarity index 90%
rename from src/main/java/org/siriusxi/htec/fa/api/model/upload/route/RouteDto.java
rename to src/main/java/org/siriusxi/fa/api/model/upload/route/RouteDto.java
index 260b0c4..87493ab 100644
--- a/src/main/java/org/siriusxi/htec/fa/api/model/upload/route/RouteDto.java
+++ b/src/main/java/org/siriusxi/fa/api/model/upload/route/RouteDto.java
@@ -1,9 +1,9 @@
-package org.siriusxi.htec.fa.api.model.upload.route;
+package org.siriusxi.fa.api.model.upload.route;
import com.opencsv.bean.CsvBindByPosition;
import com.opencsv.bean.processor.PreAssignmentProcessor;
import lombok.Data;
-import org.siriusxi.htec.fa.api.model.upload.converter.ConvertUnwantedStringsToDefault;
+import org.siriusxi.fa.api.model.upload.converter.ConvertUnwantedStringsToDefault;
/**
* @author Mohamed Taman
diff --git a/src/main/java/org/siriusxi/htec/fa/api/model/upload/route/verifer/RouteBeanVerifier.java b/src/main/java/org/siriusxi/fa/api/model/upload/route/verifer/RouteBeanVerifier.java
similarity index 72%
rename from src/main/java/org/siriusxi/htec/fa/api/model/upload/route/verifer/RouteBeanVerifier.java
rename to src/main/java/org/siriusxi/fa/api/model/upload/route/verifer/RouteBeanVerifier.java
index 652263f..16d5081 100644
--- a/src/main/java/org/siriusxi/htec/fa/api/model/upload/route/verifer/RouteBeanVerifier.java
+++ b/src/main/java/org/siriusxi/fa/api/model/upload/route/verifer/RouteBeanVerifier.java
@@ -1,7 +1,7 @@
-package org.siriusxi.htec.fa.api.model.upload.route.verifer;
+package org.siriusxi.fa.api.model.upload.route.verifer;
import com.opencsv.bean.BeanVerifier;
-import org.siriusxi.htec.fa.api.model.upload.route.RouteDto;
+import org.siriusxi.fa.api.model.upload.route.RouteDto;
public class RouteBeanVerifier implements BeanVerifier {
@Override
diff --git a/src/main/java/org/siriusxi/htec/fa/domain/Airport.java b/src/main/java/org/siriusxi/fa/domain/Airport.java
similarity index 93%
rename from src/main/java/org/siriusxi/htec/fa/domain/Airport.java
rename to src/main/java/org/siriusxi/fa/domain/Airport.java
index 5f3e9fb..df26352 100644
--- a/src/main/java/org/siriusxi/htec/fa/domain/Airport.java
+++ b/src/main/java/org/siriusxi/fa/domain/Airport.java
@@ -1,4 +1,4 @@
-package org.siriusxi.htec.fa.domain;
+package org.siriusxi.fa.domain;
import jakarta.persistence.Basic;
import jakarta.persistence.Column;
@@ -34,70 +34,88 @@
@Table(catalog = "FLIGHTDB", schema = "PUBLIC")
@Getter
@Setter
-@NoArgsConstructor
+@NoArgsConstructor(force = true)
@RequiredArgsConstructor
public class Airport implements Serializable {
@Serial
private static final long serialVersionUID = 6913599167936010779L;
+
@Id
@Basic(optional = false)
@Column(name = "AIRPORT_ID", nullable = false)
private Integer airportId;
+
@NonNull
@Basic(optional = false)
@Column(nullable = false)
private String name;
+
@NonNull
@Basic(optional = false)
@Column(name = "CITY", nullable = false, length = 100)
private String cityName;
+
@NonNull
@Basic(optional = false)
@Column(name = "COUNTRY", nullable = false, length = 100)
private String countryName;
+
@Column(length = 3)
private String iata;
+
@Column(length = 4)
private String icao;
+
@NonNull
@Basic(optional = false)
@Column(nullable = false, precision = 12, scale = 6)
private BigDecimal latitude;
+
@NonNull
@Basic(optional = false)
@Column(nullable = false, precision = 12, scale = 6)
private BigDecimal longitude;
+
@NonNull
private Integer altitude;
+
@NonNull
private Float timezone;
+
@NonNull
@Enumerated(STRING)
@Basic(optional = false)
@Column(nullable = false)
private Dst dst;
+
@NonNull
@Column(length = 50)
private String tz;
+
@NonNull
@Basic(optional = false)
@Column(nullable = false, length = 50)
private String type;
+
@NonNull
@Basic(optional = false)
@Column(name = "DATA_SOURCE", nullable = false)
private String dataSource;
+
@OneToMany(mappedBy = "destinationAirport", fetch = LAZY)
@ToString.Exclude
private List destinationRoutes;
+
@OneToMany(mappedBy = "sourceAirport", fetch = LAZY)
@ToString.Exclude
private List sourceRoutes;
+
@JoinColumn(name = "CITY_ID", referencedColumnName = "ID", nullable = false)
@ManyToOne(optional = false, fetch = LAZY)
@ToString.Exclude
private City city;
+
@JoinColumn(name = "COUNTRY_ID", referencedColumnName = "ID", nullable = false)
@ManyToOne(optional = false, fetch = LAZY)
@ToString.Exclude
@@ -113,12 +131,12 @@ public boolean equals(Object o) {
if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o))
return false;
- return Objects.equals(airportId, ((Airport) o).airportId);
+ return Objects.equals(this.airportId, ((Airport) o).airportId);
}
@Override
public int hashCode() {
- return Objects.hash(latitude, longitude, altitude);
+ return Objects.hash(this.latitude, this.longitude, this.altitude);
}
public enum Dst {
diff --git a/src/main/java/org/siriusxi/htec/fa/domain/City.java b/src/main/java/org/siriusxi/fa/domain/City.java
similarity index 84%
rename from src/main/java/org/siriusxi/htec/fa/domain/City.java
rename to src/main/java/org/siriusxi/fa/domain/City.java
index 9ada762..a503adc 100644
--- a/src/main/java/org/siriusxi/htec/fa/domain/City.java
+++ b/src/main/java/org/siriusxi/fa/domain/City.java
@@ -1,4 +1,4 @@
-package org.siriusxi.htec.fa.domain;
+package org.siriusxi.fa.domain;
import jakarta.persistence.Basic;
import jakarta.persistence.Column;
@@ -34,12 +34,12 @@
@Table(catalog = "FLIGHTDB", schema = "PUBLIC")
@Getter
@Setter
-@NoArgsConstructor
+@NoArgsConstructor(force = true)
@RequiredArgsConstructor
public class City implements Serializable {
@Serial
- private static final long serialVersionUID = 1322727266984495327L;
+ private static final long serialVersionUID = 7744039479941701650L;
@Id
@GeneratedValue(strategy = IDENTITY)
@@ -58,11 +58,11 @@ public class City implements Serializable {
@OneToMany(cascade = ALL, mappedBy = "city", fetch = LAZY)
@ToString.Exclude
- private List comments;
+ private transient List comments;
@OneToMany(cascade = ALL, mappedBy = "city", fetch = LAZY)
@ToString.Exclude
- private List airports;
+ private transient List airports;
@NonNull
@JoinColumn(name = "COUNTRY_ID", referencedColumnName = "ID", nullable = false)
@@ -85,11 +85,11 @@ public boolean equals(Object o) {
if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o))
return false;
- return Objects.equals(id, ((City) o).id);
+ return Objects.equals(this.id, ((City) o).id);
}
@Override
public int hashCode() {
- return Objects.hash(id, name, description, comments, airports, country);
+ return Objects.hash(this.id, this.name, this.description, this.comments, this.airports, this.country);
}
}
diff --git a/src/main/java/org/siriusxi/htec/fa/domain/Comment.java b/src/main/java/org/siriusxi/fa/domain/Comment.java
similarity index 84%
rename from src/main/java/org/siriusxi/htec/fa/domain/Comment.java
rename to src/main/java/org/siriusxi/fa/domain/Comment.java
index 58a9eb7..cb9ec01 100644
--- a/src/main/java/org/siriusxi/htec/fa/domain/Comment.java
+++ b/src/main/java/org/siriusxi/fa/domain/Comment.java
@@ -1,4 +1,4 @@
-package org.siriusxi.htec.fa.domain;
+package org.siriusxi.fa.domain;
import jakarta.persistence.Basic;
import jakarta.persistence.Column;
@@ -33,12 +33,12 @@
@Table(name = "CITY_COMMENT", catalog = "FLIGHTDB", schema = "PUBLIC")
@Getter
@Setter
-@NoArgsConstructor
+@NoArgsConstructor(force = true)
@RequiredArgsConstructor
public class Comment implements Serializable {
@Serial
- private static final long serialVersionUID = -4628882357786781599L;
+ private static final long serialVersionUID = 3792430609269167831L;
@Id
@NonNull
@@ -74,7 +74,7 @@ public String toString() {
return """
Comment{id= %d, comment= %s, createdAt= %s, \
updatedOn= %s, city= "%s", user= %s }"""
- .formatted(id, comment, createdAt, updatedAt, city.getName(), user.getUserUuid());
+ .formatted(this.id, this.comment, this.createdAt, this.updatedAt, this.city.getName(), this.user.getUserUuid());
}
@Override
@@ -83,11 +83,11 @@ public boolean equals(Object o) {
if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o))
return false;
- return Objects.equals(id, ((Comment) o).id);
+ return Objects.equals(this.id, ((Comment) o).id);
}
@Override
public int hashCode() {
- return Objects.hash(id, comment, createdAt, updatedAt, city, user);
+ return Objects.hash(this.id, this.comment, this.createdAt, this.updatedAt, this.city, this.user);
}
}
diff --git a/src/main/java/org/siriusxi/htec/fa/domain/Country.java b/src/main/java/org/siriusxi/fa/domain/Country.java
similarity index 82%
rename from src/main/java/org/siriusxi/htec/fa/domain/Country.java
rename to src/main/java/org/siriusxi/fa/domain/Country.java
index 5788565..4d7f7fa 100644
--- a/src/main/java/org/siriusxi/htec/fa/domain/Country.java
+++ b/src/main/java/org/siriusxi/fa/domain/Country.java
@@ -1,4 +1,4 @@
-package org.siriusxi.htec.fa.domain;
+package org.siriusxi.fa.domain;
import jakarta.persistence.Basic;
import jakarta.persistence.Column;
@@ -33,27 +33,31 @@
@Getter
@Setter
@ToString
-@NoArgsConstructor
+@NoArgsConstructor(force = true)
@RequiredArgsConstructor
public class Country implements Serializable {
@Serial
- private static final long serialVersionUID = -9057344199173138205L;
+ private static final long serialVersionUID = 7665467979286278572L;
+
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(nullable = false)
private Integer id;
+
@NonNull
@Basic(optional = false)
@Column(nullable = false, length = 100)
private String name;
+
@OneToMany(cascade = ALL, mappedBy = "country", fetch = LAZY)
@ToString.Exclude
- private List airports;
+ private transient List airports;
+
@OneToMany(cascade = ALL, mappedBy = "country", fetch = LAZY)
@ToString.Exclude
- private List cities;
+ private transient List cities;
public Country(Integer id) {
this.id = id;
@@ -65,11 +69,11 @@ public boolean equals(Object o) {
if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o))
return false;
Country country = (Country) o;
- return Objects.equals(id, country.id);
+ return Objects.equals(this.id, country.id);
}
@Override
public int hashCode() {
- return Objects.hash(id, name, airports, cities);
+ return Objects.hash(this.id, this.name, this.airports, this.cities);
}
}
diff --git a/src/main/java/org/siriusxi/htec/fa/domain/Role.java b/src/main/java/org/siriusxi/fa/domain/Role.java
similarity index 87%
rename from src/main/java/org/siriusxi/htec/fa/domain/Role.java
rename to src/main/java/org/siriusxi/fa/domain/Role.java
index 1019a09..86a93e2 100644
--- a/src/main/java/org/siriusxi/htec/fa/domain/Role.java
+++ b/src/main/java/org/siriusxi/fa/domain/Role.java
@@ -1,4 +1,4 @@
-package org.siriusxi.htec.fa.domain;
+package org.siriusxi.fa.domain;
import jakarta.persistence.Basic;
import jakarta.persistence.Column;
@@ -30,7 +30,7 @@ public class Role implements GrantedAuthority {
public static final String ADMIN = "ADMIN";
@Serial
- private static final long serialVersionUID = 3353780708738749971L;
+ private static final long serialVersionUID = 5369984016984936492L;
@EmbeddedId
protected RolePK rolePK;
@@ -51,11 +51,11 @@ public boolean equals(Object o) {
if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o))
return false;
Role role = (Role) o;
- return Objects.equals(rolePK, role.rolePK);
+ return Objects.equals(this.rolePK, role.rolePK);
}
@Override
public int hashCode() {
- return Objects.hash(rolePK);
+ return Objects.hash(this.rolePK);
}
}
diff --git a/src/main/java/org/siriusxi/htec/fa/domain/RolePK.java b/src/main/java/org/siriusxi/fa/domain/RolePK.java
similarity index 73%
rename from src/main/java/org/siriusxi/htec/fa/domain/RolePK.java
rename to src/main/java/org/siriusxi/fa/domain/RolePK.java
index 6d732ce..529513a 100644
--- a/src/main/java/org/siriusxi/htec/fa/domain/RolePK.java
+++ b/src/main/java/org/siriusxi/fa/domain/RolePK.java
@@ -1,4 +1,4 @@
-package org.siriusxi.htec.fa.domain;
+package org.siriusxi.fa.domain;
import jakarta.persistence.Basic;
import jakarta.persistence.Column;
@@ -11,6 +11,7 @@
import lombok.ToString;
import org.hibernate.Hibernate;
+import java.io.Serial;
import java.io.Serializable;
import java.util.Objects;
@@ -18,10 +19,14 @@
@Getter
@Setter
@ToString
-@NoArgsConstructor
+@NoArgsConstructor(force = true)
@RequiredArgsConstructor
public class RolePK implements Serializable {
-
+
+
+ @Serial
+ private static final long serialVersionUID = 7751515991605761066L;
+
@NonNull
@Basic(optional = false)
@Column(name = "USER_ID", nullable = false)
@@ -38,12 +43,12 @@ public boolean equals(Object o) {
if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o))
return false;
RolePK rolePK = (RolePK) o;
- return Objects.equals(userId, rolePK.userId)
- && Objects.equals(authority, rolePK.authority);
+ return Objects.equals(this.userId, rolePK.userId)
+ && Objects.equals(this.authority, rolePK.authority);
}
@Override
public int hashCode() {
- return Objects.hash(userId, authority);
+ return Objects.hash(this.userId, this.authority);
}
}
diff --git a/src/main/java/org/siriusxi/htec/fa/domain/Route.java b/src/main/java/org/siriusxi/fa/domain/Route.java
similarity index 94%
rename from src/main/java/org/siriusxi/htec/fa/domain/Route.java
rename to src/main/java/org/siriusxi/fa/domain/Route.java
index 760e595..4e871ed 100644
--- a/src/main/java/org/siriusxi/htec/fa/domain/Route.java
+++ b/src/main/java/org/siriusxi/fa/domain/Route.java
@@ -1,4 +1,4 @@
-package org.siriusxi.htec.fa.domain;
+package org.siriusxi.fa.domain;
import jakarta.persistence.Column;
import jakarta.persistence.EmbeddedId;
@@ -33,7 +33,7 @@
public class Route implements Serializable {
@Serial
- private static final long serialVersionUID = 8818845493466966108L;
+ private static final long serialVersionUID = -4190697799834880387L;
@EmbeddedId
protected RoutePK routePK;
diff --git a/src/main/java/org/siriusxi/htec/fa/domain/RoutePK.java b/src/main/java/org/siriusxi/fa/domain/RoutePK.java
similarity index 73%
rename from src/main/java/org/siriusxi/htec/fa/domain/RoutePK.java
rename to src/main/java/org/siriusxi/fa/domain/RoutePK.java
index 05fdf7d..040c9fe 100644
--- a/src/main/java/org/siriusxi/htec/fa/domain/RoutePK.java
+++ b/src/main/java/org/siriusxi/fa/domain/RoutePK.java
@@ -1,4 +1,4 @@
-package org.siriusxi.htec.fa.domain;
+package org.siriusxi.fa.domain;
import jakarta.persistence.Basic;
import jakarta.persistence.Column;
@@ -11,6 +11,7 @@
import lombok.ToString;
import org.hibernate.Hibernate;
+import java.io.Serial;
import java.io.Serializable;
import java.util.Objects;
@@ -18,9 +19,12 @@
@Getter
@Setter
@ToString
-@NoArgsConstructor
+@NoArgsConstructor(force = true)
@RequiredArgsConstructor
public class RoutePK implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = -3409091883135162258L;
@NonNull
@Basic(optional = false)
@@ -38,12 +42,12 @@ public boolean equals(Object o) {
if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o))
return false;
RoutePK routePK = (RoutePK) o;
- return Objects.equals(source, routePK.source)
- && Objects.equals(destination, routePK.destination);
+ return Objects.equals(this.source, routePK.source)
+ && Objects.equals(this.destination, routePK.destination);
}
@Override
public int hashCode() {
- return Objects.hash(source, destination);
+ return Objects.hash(this.source, this.destination);
}
}
diff --git a/src/main/java/org/siriusxi/htec/fa/domain/User.java b/src/main/java/org/siriusxi/fa/domain/User.java
similarity index 69%
rename from src/main/java/org/siriusxi/htec/fa/domain/User.java
rename to src/main/java/org/siriusxi/fa/domain/User.java
index 1e0bc52..3c7ea14 100644
--- a/src/main/java/org/siriusxi/htec/fa/domain/User.java
+++ b/src/main/java/org/siriusxi/fa/domain/User.java
@@ -1,30 +1,14 @@
-package org.siriusxi.htec.fa.domain;
-
-import jakarta.persistence.Basic;
-import jakarta.persistence.Column;
-import jakarta.persistence.Entity;
-import jakarta.persistence.GeneratedValue;
-import jakarta.persistence.GenerationType;
-import jakarta.persistence.Id;
-import jakarta.persistence.JoinColumn;
-import jakarta.persistence.OneToMany;
-import jakarta.persistence.Table;
-import jakarta.persistence.UniqueConstraint;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.NonNull;
-import lombok.RequiredArgsConstructor;
-import lombok.Setter;
-import lombok.ToString;
+package org.siriusxi.fa.domain;
+
+import jakarta.persistence.*;
+import lombok.*;
import org.hibernate.Hibernate;
import org.springframework.security.core.userdetails.UserDetails;
import java.io.Serial;
import java.io.Serializable;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
+import java.time.Instant;
+import java.util.*;
import static jakarta.persistence.CascadeType.ALL;
import static jakarta.persistence.FetchType.EAGER;
@@ -38,18 +22,20 @@
*/
@Entity
@Table(name = "users",
- catalog = "FLIGHTDB",
- schema = "PUBLIC",
- uniqueConstraints = {
- @UniqueConstraint(columnNames = {"USER_UUID"}),
- @UniqueConstraint(columnNames = {"USERNAME"})
- })
+ catalog = "FLIGHTDB",
+ schema = "PUBLIC",
+ uniqueConstraints = {
+ @UniqueConstraint(columnNames = {"USER_UUID"}),
+ @UniqueConstraint(columnNames = {"USERNAME"}),
+ @UniqueConstraint(columnNames = {"REFRESH_TOKEN"})
+ })
@Getter
@Setter
@NoArgsConstructor(force = true)
@RequiredArgsConstructor
+@ToString
public class User implements UserDetails, Serializable {
-
+
@Serial
private static final long serialVersionUID = 5666668516577592568L;
@@ -60,9 +46,9 @@ public class User implements UserDetails, Serializable {
private Integer id;
@Basic(optional = false)
- @Column(name = "USER_UUID", nullable = false, updatable = false)
+ @Column(name = "USER_UUID", columnDefinition = "UUID", nullable = false, updatable = false)
@ToString.Exclude
- private String userUuid;
+ private UUID userUuid;
@NonNull
@Basic(optional = false)
@@ -86,6 +72,14 @@ public class User implements UserDetails, Serializable {
@ToString.Exclude
private String password;
+ @Basic(optional = false)
+ @Column(name = "REFRESH_TOKEN", columnDefinition = "UUID")
+ private UUID refreshToken;
+
+ @Basic(optional = false)
+ @Column(name = "TOKEN_EXPIRY_DATE")
+ private Instant tokenExpiryDate;
+
@OneToMany(cascade = ALL, mappedBy = "user", fetch = LAZY)
@ToString.Exclude
private List comments;
@@ -98,57 +92,57 @@ public class User implements UserDetails, Serializable {
@ToString.Exclude
private boolean enabled = true;
-
+
public User(Integer id) {
this.id = id;
}
-
+
public void setAuthorities(Set roles) {
for (Role role : roles) {
role.setRolePK(new RolePK(this.getId(), role.getAuthority()));
this.authorities.add(role);
}
}
-
+
public void setAuthorities(String... authorities) {
for (String authority : authorities)
this.authorities.add(new Role(new RolePK(this.getId(), authority)));
}
-
+
public String getFullName() {
return getFirstName()
- .concat(" ")
- .concat(getLastName());
+ .concat(" ")
+ .concat(getLastName());
}
-
+
@Override
public boolean isAccountNonExpired() {
return isEnabled();
}
-
+
@Override
public boolean isAccountNonLocked() {
return isEnabled();
}
-
+
@Override
public boolean isCredentialsNonExpired() {
return isEnabled();
}
-
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o))
return false;
User user = (User) o;
- return Objects.equals(id, user.id);
+ return Objects.equals(this.id, user.id);
}
-
+
@Override
public int hashCode() {
return Objects.hash(
- id, userUuid, firstName, lastName, username,
- password, comments, authorities, enabled);
+ this.id, this.userUuid, this.firstName, this.lastName, this.username,
+ this.password, this.comments, this.authorities, this.enabled, this.refreshToken);
}
}
diff --git a/src/main/java/org/siriusxi/htec/fa/domain/vo/RouteView.java b/src/main/java/org/siriusxi/fa/domain/vo/RouteView.java
similarity index 66%
rename from src/main/java/org/siriusxi/htec/fa/domain/vo/RouteView.java
rename to src/main/java/org/siriusxi/fa/domain/vo/RouteView.java
index 3d79c16..f0f04d7 100644
--- a/src/main/java/org/siriusxi/htec/fa/domain/vo/RouteView.java
+++ b/src/main/java/org/siriusxi/fa/domain/vo/RouteView.java
@@ -1,4 +1,4 @@
-package org.siriusxi.htec.fa.domain.vo;
+package org.siriusxi.fa.domain.vo;
public record RouteView(String source, String destination, double price) {
}
diff --git a/src/main/java/org/siriusxi/fa/infra/UuidUtil.java b/src/main/java/org/siriusxi/fa/infra/UuidUtil.java
new file mode 100644
index 0000000..94b9003
--- /dev/null
+++ b/src/main/java/org/siriusxi/fa/infra/UuidUtil.java
@@ -0,0 +1,17 @@
+package org.siriusxi.fa.infra;
+
+import lombok.experimental.UtilityClass;
+
+import java.util.UUID;
+
+@UtilityClass
+public class UuidUtil {
+
+ public UUID newUuid() {
+ return UUID.randomUUID();
+ }
+
+ public UUID uuidFrom(String uuid) {
+ return UUID.fromString(uuid);
+ }
+}
diff --git a/src/main/java/org/siriusxi/htec/fa/infra/algorithm/distance/DistanceAlgorithm.java b/src/main/java/org/siriusxi/fa/infra/algorithm/distance/DistanceAlgorithm.java
similarity index 96%
rename from src/main/java/org/siriusxi/htec/fa/infra/algorithm/distance/DistanceAlgorithm.java
rename to src/main/java/org/siriusxi/fa/infra/algorithm/distance/DistanceAlgorithm.java
index da49baf..a13e105 100644
--- a/src/main/java/org/siriusxi/htec/fa/infra/algorithm/distance/DistanceAlgorithm.java
+++ b/src/main/java/org/siriusxi/fa/infra/algorithm/distance/DistanceAlgorithm.java
@@ -1,4 +1,4 @@
-package org.siriusxi.htec.fa.infra.algorithm.distance;
+package org.siriusxi.fa.infra.algorithm.distance;
/**
* A distance Algorithm interface to represent different calculations algorithms type
@@ -76,7 +76,7 @@ enum MeasureType {
}
public double getValue() {
- return value;
+ return this.value;
}
}
diff --git a/src/main/java/org/siriusxi/htec/fa/infra/algorithm/distance/HaversineAlgorithm.java b/src/main/java/org/siriusxi/fa/infra/algorithm/distance/HaversineAlgorithm.java
similarity index 92%
rename from src/main/java/org/siriusxi/htec/fa/infra/algorithm/distance/HaversineAlgorithm.java
rename to src/main/java/org/siriusxi/fa/infra/algorithm/distance/HaversineAlgorithm.java
index d54c27f..5c90c27 100644
--- a/src/main/java/org/siriusxi/htec/fa/infra/algorithm/distance/HaversineAlgorithm.java
+++ b/src/main/java/org/siriusxi/fa/infra/algorithm/distance/HaversineAlgorithm.java
@@ -1,4 +1,4 @@
-package org.siriusxi.htec.fa.infra.algorithm.distance;
+package org.siriusxi.fa.infra.algorithm.distance;
import static java.lang.Math.asin;
import static java.lang.Math.cos;
@@ -14,7 +14,7 @@
* The Haversine formula calculates the shortest distance between two points on a sphere
* using their latitudes and longitudes measured along the surface.
*
- * Source: Wikipedia
+ * Source: Wikipedia
*
* @author Mohamed Taman
* @apiNote It is important for use in navigation.
@@ -55,6 +55,7 @@ public double calculate(Point first, Point second, MeasureType measure) {
/**
* {@inheritDoc}
*/
+ @Override
public double calculate(Point first, Point second) {
return calculate(first, second, null);
}
diff --git a/src/main/java/org/siriusxi/htec/fa/infra/algorithm/distance/OrthodromicAlgorithm.java b/src/main/java/org/siriusxi/fa/infra/algorithm/distance/OrthodromicAlgorithm.java
similarity index 97%
rename from src/main/java/org/siriusxi/htec/fa/infra/algorithm/distance/OrthodromicAlgorithm.java
rename to src/main/java/org/siriusxi/fa/infra/algorithm/distance/OrthodromicAlgorithm.java
index e0f01cd..5ac3051 100644
--- a/src/main/java/org/siriusxi/htec/fa/infra/algorithm/distance/OrthodromicAlgorithm.java
+++ b/src/main/java/org/siriusxi/fa/infra/algorithm/distance/OrthodromicAlgorithm.java
@@ -1,4 +1,4 @@
-package org.siriusxi.htec.fa.infra.algorithm.distance;
+package org.siriusxi.fa.infra.algorithm.distance;
import static java.lang.Math.asin;
import static java.lang.Math.cos;
@@ -64,6 +64,7 @@ public double calculate(Point first, Point second, MeasureType measure) {
/**
* {@inheritDoc}
*/
+ @Override
public double calculate(Point first, Point second) {
return calculate(first, second, null);
}
diff --git a/src/main/java/org/siriusxi/htec/fa/infra/algorithm/distance/Point.java b/src/main/java/org/siriusxi/fa/infra/algorithm/distance/Point.java
similarity index 76%
rename from src/main/java/org/siriusxi/htec/fa/infra/algorithm/distance/Point.java
rename to src/main/java/org/siriusxi/fa/infra/algorithm/distance/Point.java
index df3c987..a399a39 100644
--- a/src/main/java/org/siriusxi/htec/fa/infra/algorithm/distance/Point.java
+++ b/src/main/java/org/siriusxi/fa/infra/algorithm/distance/Point.java
@@ -1,4 +1,4 @@
-package org.siriusxi.htec.fa.infra.algorithm.distance;
+package org.siriusxi.fa.infra.algorithm.distance;
/**
* Point value class to represent a point as latitude and longitude.
diff --git a/src/main/java/org/siriusxi/htec/fa/infra/config/GlobalExceptionHandler.java b/src/main/java/org/siriusxi/fa/infra/config/GlobalExceptionHandler.java
similarity index 83%
rename from src/main/java/org/siriusxi/htec/fa/infra/config/GlobalExceptionHandler.java
rename to src/main/java/org/siriusxi/fa/infra/config/GlobalExceptionHandler.java
index 00aab1d..8e8ded4 100644
--- a/src/main/java/org/siriusxi/htec/fa/infra/config/GlobalExceptionHandler.java
+++ b/src/main/java/org/siriusxi/fa/infra/config/GlobalExceptionHandler.java
@@ -1,12 +1,13 @@
-package org.siriusxi.htec.fa.infra.config;
+package org.siriusxi.fa.infra.config;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonRootName;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.ValidationException;
import lombok.extern.log4j.Log4j2;
-import org.siriusxi.htec.fa.infra.exception.NotAllowedException;
-import org.siriusxi.htec.fa.infra.exception.NotFoundException;
+import org.siriusxi.fa.infra.exception.NotAllowedException;
+import org.siriusxi.fa.infra.exception.NotFoundException;
+import org.siriusxi.fa.infra.exception.RefreshTokenException;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
@@ -40,7 +41,7 @@ public ResponseEntity> handleNotFoundException(
HttpServletRequest request,
NotFoundException ex) {
- log.error("NotFoundException {}\n", request.getRequestURI(), ex);
+ log.error("NotFoundException {} \n", request.getRequestURI(), ex);
return ResponseEntity
.status(NOT_FOUND)
@@ -53,7 +54,7 @@ public ResponseEntity> handleNotFoundException(
handleNotAllowedException(HttpServletRequest request,
NotAllowedException ex) {
- log.error("NotAllowedException {}\n", request.getRequestURI(), ex);
+ log.error("NotAllowedException {} \n", request.getRequestURI(), ex);
return ResponseEntity
.status(NOT_ACCEPTABLE)
@@ -66,7 +67,7 @@ public ResponseEntity> handleNotFoundException(
handleIllegalArgumentException(HttpServletRequest request,
IllegalArgumentException ex) {
- log.error("IllegalArgumentException {} \n\n {}",
+ log.error("IllegalArgumentException {} \n {}",
request.getRequestURI(), ex.getMessage());
return ResponseEntity
@@ -83,7 +84,7 @@ public ResponseEntity> handleNotFoundException(
handleValidationException(HttpServletRequest request,
ValidationException ex) {
- log.error("ValidationException {}\n", request.getRequestURI(), ex);
+ log.error("ValidationException {} \n", request.getRequestURI(), ex);
return ResponseEntity
.badRequest()
@@ -98,7 +99,7 @@ public ResponseEntity> handleNotFoundException(
handleMissingServletRequestParameterException(HttpServletRequest request,
MissingServletRequestParameterException ex) {
- log.error("handleMissingServletRequestParameterException {}\n", request.getRequestURI(), ex);
+ log.error("handleMissingServletRequestParameterException {} \n", request.getRequestURI(), ex);
return ResponseEntity
.badRequest()
@@ -132,7 +133,7 @@ public ResponseEntity> handleNotFoundException(
handleMethodArgumentNotValidException(HttpServletRequest request,
MethodArgumentNotValidException ex) {
- log.error("handleMethodArgumentNotValidException {}\n", request.getRequestURI(), ex);
+ log.error("handleMethodArgumentNotValidException {} \n", request.getRequestURI(), ex);
List