Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
AliRizaAynaci committed Oct 1, 2024
2 parents b690b03 + be0d7e6 commit 1d7e71f
Show file tree
Hide file tree
Showing 23 changed files with 469 additions and 11 deletions.
84 changes: 84 additions & 0 deletions .github/workflows/app.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
name: Flight Reservation CI/CD Pipeline

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
build:
runs-on: ubuntu-latest

services:
postgres:
image: postgres:13
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
POSTGRES_DB: flightreservation
ports:
- 5432:5432
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5

steps:
- uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
cache: maven
- name: Cache Maven dependencies
uses: actions/cache@v3
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- name: Build with Maven
run: mvn -B clean package
- name: Archive Production Artifact
uses: actions/upload-artifact@v3
with:
name: package
path: target/*.jar

test:
runs-on: ubuntu-latest
needs: build

services:
postgres:
image: postgres:13
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
POSTGRES_DB: flightreservation
ports:
- 5432:5432
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5

steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
cache: maven
- name: Cache Maven dependencies
uses: actions/cache@v3
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- name: Run Tests with Maven
run: mvn -B verify
- name: Archive Test Reports
uses: actions/upload-artifact@v3
with:
name: test-reports
path: target/surefire-reports
14 changes: 14 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM openjdk:17-jdk-slim AS build

COPY pom.xml mvnw ./
COPY .mvn .mvn
RUN ./mvnw dependency:resolve

COPY src src
RUN ./mvnw package -DskipTests

FROM openjdk:17-jdk-slim
WORKDIR /flightreservation
COPY --from=build target/*.jar flightreservation.jar

ENTRYPOINT ["java", "-jar", "flightreservation.jar"]
26 changes: 26 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
version: '3.9'

services:
app:
image: 'flightreservation'
build:
context: .
dockerfile: Dockerfile
container_name: flightreservation
ports:
- "8080:8080"
environment:
- SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/flightreservation
- SPRING_DATASOURCE_USERNAME=postgres
- SPRING_DATASOURCE_PASSWORD=password
depends_on:
- db

db:
image: postgres:13-alpine
container_name: postgres
environment:
- POSTGRES_DB=flightreservation
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=password
- POSTGRES_HOST_AUTH_METHOD=trust
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,17 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
.csrf(csrf -> csrf.disable())
.sessionManagement(sessionManagement -> sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(authorizeRequests -> authorizeRequests
.requestMatchers("/swagger-ui/**", "/v3/api-docs/**", "/swagger-resources/**").permitAll()
.requestMatchers("/api/users/login", "/api/users/register").permitAll()
.requestMatchers("/api/flights/search").permitAll()
.requestMatchers(HttpMethod.POST, "/api/bookings/create").permitAll()
.requestMatchers(HttpMethod.GET, "/api/users").hasRole("ADMIN")
.requestMatchers(HttpMethod.GET, "/api/users/{id}").hasRole("ADMIN")
.requestMatchers(HttpMethod.PUT, "/api/users/{id}").hasRole("ADMIN")
.requestMatchers(HttpMethod.DELETE, "/api/users/{id}").hasRole("ADMIN")
.requestMatchers(HttpMethod.POST, "/api/flights/addFlights").hasRole("ADMIN")
.requestMatchers(HttpMethod.DELETE, "/api/flights/{id}").hasRole("ADMIN")
.requestMatchers(HttpMethod.PUT, "/api/flights/{id}").hasRole("ADMIN")
.anyRequest().authenticated()
)
.addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.flightreservation.controller;

import com.flightreservation.dto.BookingCreateDTO;
import com.flightreservation.dto.BookingDTO;
import com.flightreservation.exception.BusinessRuleException;
import com.flightreservation.exception.FlightNotFoundException;
import com.flightreservation.exception.UserNotFoundException;
import com.flightreservation.service.BookingService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/bookings")
public class BookingController {

private final BookingService bookingService;

public BookingController(BookingService bookingService) {
this.bookingService = bookingService;
}

@PostMapping("/create")
public ResponseEntity<BookingDTO> createBooking(@RequestBody BookingCreateDTO bookingCreateDTO) {
try {
BookingDTO booking = bookingService.createBooking(bookingCreateDTO);
return ResponseEntity.ok(booking);
} catch (FlightNotFoundException | UserNotFoundException | BusinessRuleException e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
}
}

@PreAuthorize("hasRole('ADMIN')")
@GetMapping
public ResponseEntity<List<BookingDTO>> getAllBookings() {
List<BookingDTO> bookings = bookingService.getAllBookings();
return ResponseEntity.ok(bookings);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.flightreservation.controller;

import com.flightreservation.dto.FlightDTO;
import com.flightreservation.model.entity.Flight;
import com.flightreservation.service.FlightService;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDate;
import java.util.List;

@RestController
@RequestMapping("/api/flights")
public class FlightController {

private final FlightService flightService;

public FlightController(FlightService flightService) {
this.flightService = flightService;
}

@GetMapping("/search")
public ResponseEntity<List<FlightDTO>> searchFlights(@RequestParam("departure") String departureAirport,
@RequestParam("arrival") String arrivalAirport) {
List<FlightDTO> flights = flightService.searchFlights(departureAirport, arrivalAirport);
return ResponseEntity.ok(flights);
}

@PreAuthorize("hasRole('ADMIN')")
@PostMapping("/addFlights")
public ResponseEntity<Flight> addFlight(@RequestBody FlightDTO flightDTO) {
Flight flight = flightService.addFlight(flightDTO);
return ResponseEntity.ok(flight);
}

@PreAuthorize("hasRole('ADMIN')")
@PutMapping("/{id}")
public ResponseEntity<Flight> updateFlight(@PathVariable Long id, @RequestBody FlightDTO flightDTO) {
Flight flight = flightService.updateFlight(id, flightDTO);
return ResponseEntity.ok(flight);
}

@PreAuthorize("hasRole('ADMIN')")
@DeleteMapping("/{id}")
public ResponseEntity<String> deleteFlight(@PathVariable Long id) {
flightService.deleteFlight(id);
return ResponseEntity.ok("Flight with id " + id + " has been successfully deleted.");
}
}
12 changes: 12 additions & 0 deletions src/main/java/com/flightreservation/controller/UserController.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@
import com.flightreservation.service.UserService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/users")
public class UserController {
Expand All @@ -30,9 +33,18 @@ public ResponseEntity<String> login(@RequestBody UserLoginDTO userLoginDTO) {
return ResponseEntity.ok(jwtToken);
}

@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
User user = userService.getUserById(id);
return ResponseEntity.ok(user);
}

@PreAuthorize("hasRole('ADMIN')")
@GetMapping
public ResponseEntity<List<User>> getAllUsers() {
List<User> users = userService.getAllUsers();
return ResponseEntity.ok(users);
}

}
6 changes: 3 additions & 3 deletions src/main/java/com/flightreservation/dto/BookingCreateDTO.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
public class BookingCreateDTO {

private String flightNumber;
private String name;
private String email;
private String phoneNumber;
private String passengerName;
private String passengerEmail;
private String passengerPhone;
}
4 changes: 2 additions & 2 deletions src/main/java/com/flightreservation/dto/BookingDTO.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ public class BookingDTO {
private String bookingNumber;
private String flightNumber;
private String passengerName;
private String email;
private String phoneNumber;
private String passengerEmail;
private String passengerPhone;
}
1 change: 1 addition & 0 deletions src/main/java/com/flightreservation/dto/FlightDTO.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
public class FlightDTO {

private String flightNumber;
private int capacity;
private String departureAirport;
private String arrivalAirport;
private LocalDateTime departureDate;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import org.modelmapper.ModelMapper;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class BookingConverter {

Expand All @@ -22,4 +24,6 @@ public BookingDTO convertToDto(Booking booking) {
public Booking convertToEntity(BookingCreateDTO bookingDTO) {
return modelMapper.map(bookingDTO, Booking.class);
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ public FlightConverter(ModelMapper modelMapper) {
public FlightDTO convertToDto(Flight flight) {
return modelMapper.map(flight, FlightDTO.class);
}

public Flight convertToEntity(FlightDTO flightDTO) {
return modelMapper.map(flightDTO, Flight.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.flightreservation.exception;

public class BookingException extends RuntimeException {

public BookingException(String s) {
super(s);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.flightreservation.exception;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(HttpStatus.NOT_FOUND)
public class FlightNotFoundException extends RuntimeException {

public FlightNotFoundException(String s) {
super(s);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.flightreservation.exception;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(HttpStatus.NOT_FOUND)
public class UserNotFoundException extends RuntimeException {

public UserNotFoundException(String s) {
super(s);
}
}
10 changes: 4 additions & 6 deletions src/main/java/com/flightreservation/model/entity/Booking.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.flightreservation.model.entity;

import com.fasterxml.jackson.annotation.JsonBackReference;
import jakarta.persistence.*;
import lombok.Data;

Expand All @@ -12,14 +13,11 @@ public class Booking {
private Long id;
private String bookingNumber;

@ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@ManyToOne(fetch = FetchType.LAZY)
@JsonBackReference
private User user;

@ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@ManyToOne(fetch = FetchType.EAGER)
private Flight flight;

private String passengerName;
private String passengerEmail;
private String passengerPhoneNumber;

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public class Flight {
private Long id;

private String flightNumber;
private int capacity;
private String departureAirport;
private String arrivalAirport;
private LocalDateTime departureDate;
Expand Down
Loading

0 comments on commit 1d7e71f

Please sign in to comment.