├── .github └── workflows │ └── ci-backend.yml ├── .gitignore ├── carRental ├── HELP.md ├── Makefile ├── docker-compose.yaml ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── amigoscode │ │ │ └── chohort2 │ │ │ └── carRental │ │ │ ├── CarRentalApplication.java │ │ │ ├── abstracts │ │ │ ├── AbstractAddress.java │ │ │ ├── AbstractAuditingEntity.java │ │ │ ├── EntityMapper.java │ │ │ └── repository │ │ │ │ ├── CRJpaRepository.java │ │ │ │ └── CRJpaRepositoryImp.java │ │ │ ├── annotation │ │ │ └── TransactionalService.java │ │ │ ├── auth │ │ │ ├── AuthController.java │ │ │ ├── AuthService.java │ │ │ └── LoginVM.java │ │ │ ├── authority │ │ │ ├── Authority.java │ │ │ ├── AuthorityConstants.java │ │ │ ├── AuthorityRepository.java │ │ │ └── AuthorityService.java │ │ │ ├── brand │ │ │ ├── Brand.java │ │ │ ├── BrandController.java │ │ │ ├── BrandDTO.java │ │ │ ├── BrandMapper.java │ │ │ ├── BrandRepository.java │ │ │ └── BrandService.java │ │ │ ├── brandModel │ │ │ ├── BrandModel.java │ │ │ ├── BrandModelController.java │ │ │ ├── BrandModelDTO.java │ │ │ ├── BrandModelMapper.java │ │ │ ├── BrandModelRepository.java │ │ │ └── BrandModelService.java │ │ │ ├── car │ │ │ ├── Car.java │ │ │ ├── CarController.java │ │ │ ├── CarDTO.java │ │ │ ├── CarMapper.java │ │ │ ├── CarRepository.java │ │ │ ├── CarService.java │ │ │ └── VM │ │ │ │ ├── CarSearchByProviderUserVM.java │ │ │ │ ├── CarSearchVM.java │ │ │ │ └── CarVM.java │ │ │ ├── carBooking │ │ │ ├── CarBooking.java │ │ │ ├── CarBookingController.java │ │ │ ├── CarBookingDTO.java │ │ │ ├── CarBookingMapper.java │ │ │ ├── CarBookingRepository.java │ │ │ └── CarBookingService.java │ │ │ ├── carProvider │ │ │ ├── CarProvider.java │ │ │ ├── CarProviderController.java │ │ │ ├── CarProviderDTO.java │ │ │ ├── CarProviderMapper.java │ │ │ ├── CarProviderRepository.java │ │ │ ├── CarProviderService.java │ │ │ └── VM │ │ │ │ └── CarProviderVM.java │ │ │ ├── carProviderAddress │ │ │ ├── CarProviderAddress.java │ │ │ ├── CarProviderAddressController.java │ │ │ ├── CarProviderAddressDTO.java │ │ │ ├── CarProviderAddressMapper.java │ │ │ ├── CarProviderAddressRepository.java │ │ │ └── CarProviderAddressService.java │ │ │ ├── carProviderCoupon │ │ │ ├── CarProviderCoupon.java │ │ │ ├── CarProviderCouponController.java │ │ │ ├── CarProviderCouponDTO.java │ │ │ ├── CarProviderCouponMapper.java │ │ │ ├── CarProviderCouponRepository.java │ │ │ ├── CarProviderCouponService.java │ │ │ └── VM │ │ │ │ ├── CarProviderCouponAvailabilityVM.java │ │ │ │ └── CarProviderCouponVM.java │ │ │ ├── carProviderUser │ │ │ ├── CarProviderUser.java │ │ │ ├── CarProviderUserController.java │ │ │ ├── CarProviderUserDTO.java │ │ │ ├── CarProviderUserMapper.java │ │ │ ├── CarProviderUserRepository.java │ │ │ └── CarProviderUserService.java │ │ │ ├── carUser │ │ │ ├── CarUser.java │ │ │ ├── CarUserController.java │ │ │ ├── CarUserDTO.java │ │ │ ├── CarUserMapper.java │ │ │ ├── CarUserRepository.java │ │ │ └── CarUserService.java │ │ │ ├── city │ │ │ ├── City.java │ │ │ ├── CityController.java │ │ │ ├── CityDTO.java │ │ │ ├── CityMapper.java │ │ │ ├── CityRepository.java │ │ │ └── CityService.java │ │ │ ├── config │ │ │ ├── CustomStringDeserializer.java │ │ │ └── audit │ │ │ │ ├── AuditConfig.java │ │ │ │ └── SystemAudit.java │ │ │ ├── constants │ │ │ ├── Constants.java │ │ │ ├── ErrorConstants.java │ │ │ └── LoggingConstants.java │ │ │ ├── country │ │ │ ├── Country.java │ │ │ ├── CountryController.java │ │ │ ├── CountryDTO.java │ │ │ ├── CountryMapper.java │ │ │ ├── CountryRepository.java │ │ │ └── CountryService.java │ │ │ ├── driverLicense │ │ │ ├── DriverLicense.java │ │ │ ├── DriverLicenseController.java │ │ │ ├── DriverLicenseDTO.java │ │ │ ├── DriverLicenseMapper.java │ │ │ ├── DriverLicenseRepository.java │ │ │ ├── DriverLicenseService.java │ │ │ └── VM │ │ │ │ └── DriverLicenseVM.java │ │ │ ├── exception │ │ │ ├── ApiExceptionHandler.java │ │ │ ├── ApiExceptionResponse.java │ │ │ └── ApiRequestException.java │ │ │ ├── logging │ │ │ ├── AbstractAspect.java │ │ │ ├── ControllerLoggingAspect.java │ │ │ ├── DataAccessLoggingAspect.java │ │ │ └── ServiceLoggingAspect.java │ │ │ ├── lookupCode │ │ │ ├── LookupCode.java │ │ │ ├── LookupCodeController.java │ │ │ ├── LookupCodeDTO.java │ │ │ ├── LookupCodeMapper.java │ │ │ ├── LookupCodeRepository.java │ │ │ ├── LookupCodeService.java │ │ │ └── LookupCodes.java │ │ │ ├── registration │ │ │ ├── RegistrationController.java │ │ │ ├── RegistrationService.java │ │ │ └── VM │ │ │ │ ├── CarProviderRegistrationVM.java │ │ │ │ ├── ClientRegistrationVM.java │ │ │ │ └── UserRegistrationVM.java │ │ │ ├── security │ │ │ ├── CorsConfig.java │ │ │ ├── PasswordEncoderConfig.java │ │ │ ├── SecurityConfig.java │ │ │ ├── SecurityFilterChainConfig.java │ │ │ ├── SecurityUtils.java │ │ │ ├── UserDetailsServiceImpl.java │ │ │ └── jwt │ │ │ │ ├── JWTAuthFilter.java │ │ │ │ └── JWTUtil.java │ │ │ ├── specification │ │ │ ├── CarSearchSpecification.java │ │ │ └── Util.java │ │ │ ├── user │ │ │ ├── User.java │ │ │ ├── UserController.java │ │ │ ├── UserDTO.java │ │ │ ├── UserMapper.java │ │ │ ├── UserRepository.java │ │ │ └── UserService.java │ │ │ ├── userAddress │ │ │ ├── UserAddress.java │ │ │ ├── UserAddressController.java │ │ │ ├── UserAddressDTO.java │ │ │ ├── UserAddressMapper.java │ │ │ ├── UserAddressRepository.java │ │ │ └── UserAddressServices.java │ │ │ ├── userNotification │ │ │ ├── UserNotification.java │ │ │ ├── UserNotificationController.java │ │ │ ├── UserNotificationDTO.java │ │ │ ├── UserNotificationMapper.java │ │ │ ├── UserNotificationRepository.java │ │ │ └── UserNotificationService.java │ │ │ └── validation │ │ │ └── Validator.java │ └── resources │ │ ├── application-dev.yml │ │ ├── application-prod.yml │ │ ├── application.yml │ │ └── db │ │ └── changelog │ │ ├── 0.0.0.1 │ │ ├── 000000000000_initial.xml │ │ ├── 202306211212._added_entity_LookupCode.xml │ │ ├── 202306211213_insert_LookupCode.xml │ │ ├── 202306212035_added_entity_Car.xml │ │ ├── 202306212059_added_entity_brand.xml │ │ ├── 202306212060_added_entity_brand_model.xml │ │ ├── 202306212135_added_entity_Car_Provider.xml │ │ ├── 202306221751_added_entity_UserAddress.xml │ │ ├── 202306221800_added_constraints_UserAddress.xml │ │ ├── 202306222016_added_entity_Driver_License.xml │ │ ├── 202306231445_added_fk_car_car_provider.xml │ │ ├── 202306231451_added_sequence_brand.xml │ │ ├── 202306231500_add_fk_brand_model_brand.xml │ │ ├── 202306231530_added_fk_constraints_driver_license.xml │ │ ├── 202306240441_added_entity_Car_Provider_User.xml │ │ ├── 202306240449_added_fk_constraints_car_provider_user.xml │ │ ├── 202306261435_added_entity_Car_Provider_Coupon.xml │ │ ├── 202306261441_added_fk_constraints_car_provider_coupon.xml │ │ ├── 202306271523_added_entity_Country.xml │ │ ├── 202306271544_added_entity_City.xml │ │ ├── 202306271718_added_fk_constraints_city__country_id.xml │ │ ├── 202306271755_added_fk_constraints_user_address__city_id.xml │ │ ├── 202306271811_added_fk_constraints_car_provider_address.xml │ │ ├── 202306271820_added_entity_Car_Provider_Address.xml │ │ ├── 202306281333_added_entity_Car_User.xml │ │ ├── 202306281336_added_fk_constraints_car_user__car_id.xml │ │ ├── 202306281347_added_entity_User_Notification.xml │ │ ├── 202306281356_added_entity_Car_Booking.xml │ │ ├── 202306281358_added_fk_constraints_user_notification.xml │ │ ├── 202306281401_added_fk_constraints_car_booking.xml │ │ ├── 202306291216_insert_Authorities.xml │ │ ├── 202307041630_insert_Brands.xml │ │ └── 202307041635_insert_BrandModels.xml │ │ ├── dateTimeStamp_Example_entity_EntityName.xml │ │ └── master.xml │ └── test │ ├── java │ └── com │ │ └── amigoscode │ │ └── chohort2 │ │ └── carRental │ │ ├── AbstractTestContainer.java │ │ ├── auth │ │ └── AuthControllerIT.java │ │ ├── car │ │ └── CarServiceTest.java │ │ ├── coupon │ │ └── CarProviderCouponControllerIT.java │ │ └── registration │ │ ├── RegistrationControllerIT.java │ │ └── RegistrationServiceTest.java │ └── resources │ └── application-test.yml └── infrastructure ├── Makefile ├── modules ├── aws_budgeting │ ├── budget.tf │ └── variables.tf └── aws_org_ous │ ├── accounts.tf │ ├── organizational_units.tf │ ├── outputs.tf │ ├── terraform.tf │ └── varibales.tf └── organization ├── aws-dev-s3-state ├── s3.tf └── variables.tf ├── aws-organization ├── backends3.tf ├── budget.tf ├── iam.tf ├── identity_center_ex_sso.tf ├── main.tf ├── organization.tf ├── organization_ou.tf ├── provider.tf ├── scp.tf └── variables.tf ├── aws-prod-s3-state ├── s3.tf └── variables.tf ├── aws-sandbox-s3-state ├── s3.tf └── variables.tf └── aws-staging-s3-state ├── s3.tf └── variables.tf /.github/workflows/ci-backend.yml: -------------------------------------------------------------------------------- 1 | 2 | name: Java CI with Maven 3 | 4 | on: 5 | push: 6 | branches: ["main", "ci"] 7 | pull_request: 8 | branches: [ "main" ] 9 | env: 10 | JAVA_VERSION: 17 11 | JAVA_DISTRO: temurin 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | defaults: 16 | run: 17 | working-directory: ./carRental 18 | steps: 19 | - uses: actions/checkout@v3 20 | - name: Set up JDK ${{env.JAVA_VERSION}} 21 | uses: actions/setup-java@v3 22 | with: 23 | java-version: ${{env.JAVA_VERSION}} 24 | distribution: ${{env.JAVA_DISTRO}} 25 | cache: maven 26 | - name: Build with Maven 27 | run: mvn clean package install -ntp 28 | # # Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive 29 | # - name: Update dependency graph 30 | # uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6 -------------------------------------------------------------------------------- /carRental/HELP.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | ### Reference Documentation 4 | For further reference, please consider the following sections: 5 | 6 | * [Official Apache Maven documentation](https://maven.apache.org/guides/index.html) 7 | * [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/3.1.0/maven-plugin/reference/html/) 8 | * [Create an OCI image](https://docs.spring.io/spring-boot/docs/3.1.0/maven-plugin/reference/html/#build-image) 9 | * [Spring Boot Testcontainers support](https://docs.spring.io/spring-boot/docs/3.1.0/reference/html/features.html#features.testing.testcontainers) 10 | * [Testcontainers Postgres Module Reference Guide](https://www.testcontainers.org/modules/databases/postgres/) 11 | * [Spring Web](https://docs.spring.io/spring-boot/docs/3.1.0/reference/htmlsingle/#web) 12 | * [Spring Data JPA](https://docs.spring.io/spring-boot/docs/3.1.0/reference/htmlsingle/#data.sql.jpa-and-spring-data) 13 | * [Validation](https://docs.spring.io/spring-boot/docs/3.1.0/reference/htmlsingle/#io.validation) 14 | * [Liquibase Migration](https://docs.spring.io/spring-boot/docs/3.1.0/reference/htmlsingle/#howto.data-initialization.migration-tool.liquibase) 15 | * [Spring REST Docs](https://docs.spring.io/spring-restdocs/docs/current/reference/html5/) 16 | * [Testcontainers](https://www.testcontainers.org/) 17 | * [Spring Reactive Web](https://docs.spring.io/spring-boot/docs/3.1.0/reference/htmlsingle/#web.reactive) 18 | 19 | ### Guides 20 | The following guides illustrate how to use some features concretely: 21 | 22 | * [Building a RESTful Web Service](https://spring.io/guides/gs/rest-service/) 23 | * [Serving Web Content with Spring MVC](https://spring.io/guides/gs/serving-web-content/) 24 | * [Building REST services with Spring](https://spring.io/guides/tutorials/rest/) 25 | * [Accessing Data with JPA](https://spring.io/guides/gs/accessing-data-jpa/) 26 | * [Validation](https://spring.io/guides/gs/validating-form-input/) 27 | * [Building a Reactive RESTful Web Service](https://spring.io/guides/gs/reactive-rest-service/) 28 | 29 | -------------------------------------------------------------------------------- /carRental/Makefile: -------------------------------------------------------------------------------- 1 | SHELL:=/bin/bash 2 | .ONESHELL: 3 | check-yes: 4 | @echo -en "${DANGER}Are you sure? [y/N] " && read ans && [ $${ans:-N} == y ] 5 | dbd: 6 | docker-compose down && docker-compose rm -fs 7 | dbu: 8 | docker-compose up -d 9 | dsp: 10 | docker system prune 11 | dnp: 12 | docker network prune 13 | mcp: 14 | mvn clean package 15 | untrack-iml: 16 | find ./ -name $(_EXTENSION) | xargs 17 | find ./ -name $(_EXTENSION) -exec git rm --cache --dry-run {} | xargs printf $(_DANGER) "" \; 18 | make check-yes && find ./ -name $(_EXTENSION) -exec git rm --cache {} \; 19 | 20 | _SUCCESS := "\033[32m[%s]\033[0m %s\n" 21 | SUCCESS := '\033[0;32m' 22 | _DANGER := "\033[31m[%s]\033[0m %s\n" 23 | DANGER := '\033[0;31m' 24 | _EXTENSION := "*.iml" -------------------------------------------------------------------------------- /carRental/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | services: 3 | temp-car-db: 4 | container_name: temp-car-db 5 | image: postgres:alpine 6 | environment: 7 | POSTGRES_USER: postgres 8 | POSTGRES_PASSWORD: 123 9 | POSTGRES_DB: postgres 10 | PGDATA: /data/postgres 11 | POSTGRES_INITDB_ARGS: "--auth-host=scram-sha-256 --auth-local=scram-sha-256" 12 | ports: 13 | - "5432:5432" 14 | networks: 15 | - car-db-network 16 | restart: unless-stopped 17 | 18 | const-car-db: 19 | container_name: const-car-db 20 | image: postgres:alpine 21 | environment: 22 | POSTGRES_USER: postgres 23 | POSTGRES_PASSWORD: 123 24 | POSTGRES_DB: postgres 25 | PGDATA: /data/postgres 26 | POSTGRES_INITDB_ARGS: "--auth-host=scram-sha-256 --auth-local=scram-sha-256" 27 | volumes: 28 | - postgres_data:/data/postgres 29 | ports: 30 | - "5434:5432" 31 | networks: 32 | - car-db-network 33 | restart: unless-stopped 34 | 35 | networks: 36 | car-db-network: 37 | driver: bridge 38 | 39 | volumes: 40 | postgres_data: {} 41 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/CarRentalApplication.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.repository.CRJpaRepositoryImp; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 7 | 8 | @SpringBootApplication 9 | @EnableJpaRepositories(repositoryBaseClass = CRJpaRepositoryImp.class) 10 | public class CarRentalApplication { 11 | 12 | public static void main(String[] args) { 13 | 14 | SpringApplication.run(CarRentalApplication.class, args); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/abstracts/AbstractAddress.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.abstracts; 2 | 3 | import jakarta.persistence.Column; 4 | import jakarta.persistence.MappedSuperclass; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | import lombok.experimental.Accessors; 8 | 9 | @MappedSuperclass 10 | @Setter 11 | @Getter 12 | @Accessors(chain = true) 13 | public abstract class AbstractAddress extends AbstractAuditingEntity { 14 | 15 | 16 | 17 | @Column(name = "city_id") 18 | protected Long cityId; 19 | 20 | @Column(name = "location") 21 | protected String location; 22 | 23 | @Column(name = "postal_code") 24 | protected String postalCode; 25 | 26 | 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/abstracts/AbstractAuditingEntity.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.abstracts; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import jakarta.persistence.Column; 5 | import jakarta.persistence.EntityListeners; 6 | import jakarta.persistence.MappedSuperclass; 7 | import org.springframework.data.annotation.CreatedBy; 8 | import org.springframework.data.annotation.CreatedDate; 9 | import org.springframework.data.annotation.LastModifiedBy; 10 | import org.springframework.data.annotation.LastModifiedDate; 11 | import org.springframework.data.jpa.domain.support.AuditingEntityListener; 12 | 13 | import java.io.Serializable; 14 | import java.time.LocalDateTime; 15 | 16 | @MappedSuperclass 17 | @EntityListeners(value = {AuditingEntityListener.class}) 18 | public abstract class AbstractAuditingEntity implements Serializable { 19 | 20 | @CreatedBy 21 | @Column(name = "created_by", updatable = false, nullable = false) 22 | @JsonIgnore 23 | private String createdBy; 24 | 25 | @CreatedDate 26 | @Column(name = "created_date", updatable = false, nullable = false) 27 | @JsonIgnore 28 | private LocalDateTime createdDate; 29 | 30 | @LastModifiedBy 31 | @Column(name = "last_modified_by") 32 | @JsonIgnore 33 | private String lastModifiedBy; 34 | 35 | @LastModifiedDate 36 | @Column(name = "last_modified_date") 37 | @JsonIgnore 38 | private LocalDateTime lastModifiedDate; 39 | 40 | 41 | @Column(name = "is_deleted") 42 | @JsonIgnore 43 | private boolean isDeleted = false; 44 | 45 | 46 | public String getCreatedBy() { 47 | return createdBy; 48 | } 49 | 50 | public void setCreatedBy(String createdBy) { 51 | this.createdBy = createdBy; 52 | } 53 | 54 | public LocalDateTime getCreatedDate() { 55 | return createdDate; 56 | } 57 | 58 | public void setCreatedDate(LocalDateTime createdDate) { 59 | this.createdDate = createdDate; 60 | } 61 | 62 | public String getLastModifiedBy() { 63 | return lastModifiedBy; 64 | } 65 | 66 | public void setLastModifiedBy(String lastModifiedBy) { 67 | this.lastModifiedBy = lastModifiedBy; 68 | } 69 | 70 | public LocalDateTime getLastModifiedDate() { 71 | return lastModifiedDate; 72 | } 73 | 74 | public void setLastModifiedDate(LocalDateTime lastModifiedDate) { 75 | this.lastModifiedDate = lastModifiedDate; 76 | } 77 | 78 | public boolean isDeleted() { 79 | return isDeleted; 80 | } 81 | 82 | public void setDeleted(boolean deleted) { 83 | this.isDeleted = deleted; 84 | } 85 | } 86 | 87 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/abstracts/EntityMapper.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.abstracts; 2 | 3 | 4 | import java.util.List; 5 | 6 | public interface EntityMapper { 7 | 8 | E toEntity(D dto); 9 | 10 | D toDto(E entity); 11 | 12 | 13 | List toEntity(List dto); 14 | 15 | List toDto(List entity); 16 | 17 | } 18 | 19 | 20 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/abstracts/repository/CRJpaRepository.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.abstracts.repository; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.AbstractAuditingEntity; 4 | import jakarta.validation.constraints.NotNull; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.data.repository.NoRepositoryBean; 7 | 8 | import java.io.Serializable; 9 | 10 | @NoRepositoryBean 11 | public interface CRJpaRepository extends JpaRepository { 12 | 13 | @Override 14 | default void delete(@NotNull T entity) { 15 | entity.setDeleted(true); 16 | save(entity); 17 | } 18 | 19 | @Override 20 | default void deleteById(@NotNull ID id) { 21 | findById(id).ifPresent(data -> { 22 | data.setDeleted(true); 23 | save(data); 24 | }); 25 | } 26 | 27 | @Override 28 | default void deleteAll() { 29 | 30 | } 31 | 32 | @Override 33 | default void deleteAllById(@NotNull Iterable ids) { 34 | ids.forEach(this::deleteById); 35 | } 36 | 37 | @Override 38 | default void deleteAll(@NotNull Iterable entities) { 39 | entities 40 | .forEach(this::delete); 41 | } 42 | 43 | T saveAndRefresh(T entity); 44 | 45 | T merge (T entity); 46 | 47 | } 48 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/abstracts/repository/CRJpaRepositoryImp.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.abstracts.repository; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.AbstractAuditingEntity; 4 | 5 | import jakarta.persistence.EntityManager; 6 | import org.springframework.data.jpa.repository.support.JpaEntityInformation; 7 | import org.springframework.data.jpa.repository.support.SimpleJpaRepository; 8 | import org.springframework.transaction.annotation.Transactional; 9 | 10 | import java.io.Serializable; 11 | 12 | public class CRJpaRepositoryImp extends SimpleJpaRepository 13 | implements CRJpaRepository { 14 | 15 | private final EntityManager entityManager; 16 | 17 | public CRJpaRepositoryImp(JpaEntityInformation entityInformation, EntityManager entityManager) { 18 | super(entityInformation, entityManager); 19 | this.entityManager = entityManager; 20 | } 21 | 22 | 23 | @Transactional 24 | @Override 25 | public T saveAndRefresh(T entity) { 26 | entity = save(entity); 27 | entityManager.refresh(entity); 28 | return entity; 29 | } 30 | 31 | @Transactional 32 | public T merge (T updatedEntity ) { 33 | return entityManager.merge(updatedEntity); 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/annotation/TransactionalService.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.annotation; 2 | 3 | 4 | 5 | import org.springframework.stereotype.Service; 6 | import org.springframework.transaction.annotation.Transactional; 7 | 8 | 9 | import java.lang.annotation.ElementType; 10 | import java.lang.annotation.Retention; 11 | import java.lang.annotation.RetentionPolicy; 12 | import java.lang.annotation.Target; 13 | 14 | @Target({ElementType.TYPE, ElementType.METHOD}) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Transactional 17 | @Service 18 | public @interface TransactionalService { 19 | } 20 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/auth/AuthController.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.auth; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.http.ResponseEntity; 5 | import org.springframework.web.bind.annotation.PostMapping; 6 | import org.springframework.web.bind.annotation.RequestBody; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | @RestController 11 | @RequestMapping("api/v1/auth") 12 | @RequiredArgsConstructor 13 | public class AuthController { 14 | 15 | 16 | private final AuthService authService; 17 | 18 | 19 | @PostMapping("/login") 20 | public ResponseEntity login(@RequestBody LoginVM loginVM) { 21 | 22 | return ResponseEntity.ok(authService.login(loginVM.getUsername(), loginVM.getPassword())); 23 | 24 | } 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/auth/AuthService.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.auth; 2 | 3 | 4 | import com.amigoscode.chohort2.carRental.annotation.TransactionalService; 5 | import com.amigoscode.chohort2.carRental.constants.ErrorConstants; 6 | import com.amigoscode.chohort2.carRental.exception.ApiRequestException; 7 | import com.amigoscode.chohort2.carRental.security.jwt.JWTUtil; 8 | import lombok.RequiredArgsConstructor; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.security.authentication.AuthenticationManager; 12 | import org.springframework.security.authentication.BadCredentialsException; 13 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 14 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 15 | import org.springframework.security.core.userdetails.UserDetails; 16 | import org.springframework.security.core.userdetails.UserDetailsService; 17 | 18 | 19 | import java.util.List; 20 | 21 | @TransactionalService 22 | @RequiredArgsConstructor 23 | public class AuthService { 24 | private static final Logger log = LoggerFactory.getLogger(AuthService.class); 25 | private final AuthenticationManager authenticationManager; 26 | 27 | private final JWTUtil jwtUtil; 28 | 29 | private final UserDetailsService userDetailsService; 30 | 31 | 32 | 33 | public String login(String username, String password) { 34 | //log.info("user try to login username:{}", username); 35 | 36 | authenticate(username, password); 37 | 38 | final UserDetails userDetails = userDetailsService.loadUserByUsername(username); 39 | 40 | List userAuthorities = userDetails 41 | .getAuthorities() 42 | .stream() 43 | .map(auth-> new SimpleGrantedAuthority(auth.getAuthority())) 44 | .toList(); 45 | 46 | 47 | return jwtUtil.issueToken(username,userAuthorities); 48 | } 49 | 50 | 51 | 52 | 53 | 54 | private void authenticate(String username, String password) { 55 | 56 | 57 | try { 58 | authenticationManager 59 | .authenticate(new UsernamePasswordAuthenticationToken(username, password)); 60 | 61 | 62 | } catch (BadCredentialsException exception) { 63 | log.warn("user with username: {} is not authenticated", username); 64 | throw new ApiRequestException(exception.getMessage(), ErrorConstants.LOGIN); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/auth/LoginVM.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.auth; 2 | 3 | import com.amigoscode.chohort2.carRental.security.SecurityUtils; 4 | import lombok.*; 5 | 6 | import java.io.Serializable; 7 | 8 | @Setter 9 | @Getter 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | @ToString 13 | public class LoginVM implements Serializable { 14 | private String username; 15 | private String password; 16 | @ToString.Include 17 | private String password(){ 18 | return SecurityUtils.obfuscateString(password); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/authority/Authority.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.authority; 2 | 3 | import jakarta.persistence.*; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import lombok.experimental.Accessors; 7 | 8 | 9 | @Entity 10 | @Table(name = "authority") 11 | @Setter 12 | @Getter 13 | @Accessors(chain = true) 14 | public class Authority { 15 | 16 | @Id 17 | private String name; 18 | 19 | @Column(name = "full_name") 20 | private String fullName; 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/authority/AuthorityConstants.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.authority; 2 | 3 | public abstract class AuthorityConstants { 4 | 5 | public static final String ADMIN = "ROLE_ADMIN"; 6 | 7 | public static final String CAR_PROVIDER = "ROLE_CAR_PROVIDER"; 8 | 9 | public static final String CLIENT = "ROLE_CLIENT"; 10 | 11 | 12 | private AuthorityConstants() { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/authority/AuthorityRepository.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.authority; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import org.springframework.stereotype.Repository; 5 | 6 | @Repository 7 | public interface AuthorityRepository extends JpaRepository { 8 | } 9 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/authority/AuthorityService.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.authority; 2 | 3 | import com.amigoscode.chohort2.carRental.annotation.TransactionalService; 4 | import com.amigoscode.chohort2.carRental.exception.ApiRequestException; 5 | import lombok.RequiredArgsConstructor; 6 | 7 | @TransactionalService 8 | @RequiredArgsConstructor 9 | public class AuthorityService { 10 | 11 | private final AuthorityRepository authorityRepository; 12 | 13 | public Authority findByName(String authName) { 14 | return authorityRepository.findById(authName) 15 | .orElseThrow(()-> new ApiRequestException("authority not found")); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/brand/Brand.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.brand; 2 | 3 | import com.amigoscode.chohort2.carRental.brandModel.BrandModel; 4 | import jakarta.persistence.*; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Getter; 7 | import lombok.NoArgsConstructor; 8 | import lombok.Setter; 9 | import lombok.experimental.Accessors; 10 | 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | 16 | @Entity 17 | @Table(name = "brand") 18 | @Setter 19 | @Getter 20 | @AllArgsConstructor 21 | @NoArgsConstructor 22 | @Accessors(chain = true) 23 | public class Brand { 24 | 25 | @Id 26 | @GeneratedValue(strategy = GenerationType.IDENTITY) 27 | private Long id; 28 | 29 | @Column(name = "code", nullable = false, unique = true) 30 | private Integer code; 31 | 32 | @Column(name = "name", nullable = false, unique = true) 33 | private String name; 34 | 35 | @OneToMany(mappedBy = "brand") 36 | private List brandModels = new ArrayList<>(); 37 | } 38 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/brand/BrandController.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.brand; 2 | 3 | 4 | import lombok.RequiredArgsConstructor; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @RestController 9 | @RequestMapping("api/v1/brands") 10 | @RequiredArgsConstructor 11 | public class BrandController { 12 | 13 | private final BrandService brandService; 14 | } 15 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/brand/BrandDTO.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.brand; 2 | 3 | 4 | import lombok.EqualsAndHashCode; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | import lombok.ToString; 8 | import lombok.experimental.Accessors; 9 | 10 | @Setter 11 | @Getter 12 | @Accessors(chain = true) 13 | @ToString 14 | @EqualsAndHashCode 15 | public class BrandDTO { 16 | 17 | private Long id; 18 | private Integer code; 19 | private String name; 20 | 21 | 22 | } 23 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/brand/BrandMapper.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.brand; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.EntityMapper; 4 | import org.mapstruct.Mapper; 5 | import org.mapstruct.factory.Mappers; 6 | 7 | 8 | @Mapper 9 | public interface BrandMapper extends EntityMapper { 10 | 11 | BrandMapper INSTANCE = Mappers.getMapper(BrandMapper.class); 12 | } 13 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/brand/BrandRepository.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.brand; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.repository.CRJpaRepository; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | @Repository 8 | public interface BrandRepository extends JpaRepository { 9 | } 10 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/brand/BrandService.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.brand; 2 | 3 | import com.amigoscode.chohort2.carRental.annotation.TransactionalService; 4 | import lombok.RequiredArgsConstructor; 5 | 6 | @TransactionalService 7 | @RequiredArgsConstructor 8 | public class BrandService { 9 | 10 | private final BrandRepository brandRepository; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/brandModel/BrandModel.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.brandModel; 2 | 3 | import com.amigoscode.chohort2.carRental.brand.Brand; 4 | import jakarta.persistence.*; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Getter; 7 | import lombok.NoArgsConstructor; 8 | import lombok.Setter; 9 | import lombok.experimental.Accessors; 10 | 11 | @Entity 12 | @Table(name = "brand_model") 13 | @Setter 14 | @Getter 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | @Accessors(chain = true) 18 | public class BrandModel { 19 | 20 | @Id 21 | @GeneratedValue(strategy = GenerationType.IDENTITY) 22 | private Long id; 23 | 24 | @Column (name = "brand_id", nullable = false) 25 | private Long brandId; 26 | 27 | @ManyToOne (fetch = FetchType.LAZY) 28 | @JoinColumn (name = "brand_id", updatable = false,insertable = false) 29 | private Brand brand; 30 | 31 | @Column (name = "code", nullable = false) 32 | private Integer code; 33 | 34 | @Column (name = "name", nullable = false) 35 | private String name; 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/brandModel/BrandModelController.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.brandModel; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | @RestController 8 | @RequestMapping("api/v1/brand-models") 9 | @RequiredArgsConstructor 10 | public class BrandModelController { 11 | } 12 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/brandModel/BrandModelDTO.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.brandModel; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | import lombok.experimental.Accessors; 8 | 9 | @Setter 10 | @Getter 11 | @Accessors(chain = true) 12 | @ToString 13 | @EqualsAndHashCode 14 | public class BrandModelDTO { 15 | 16 | private Long id; 17 | 18 | private Integer brandId; 19 | 20 | private Integer code; 21 | 22 | private String name; 23 | 24 | 25 | } 26 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/brandModel/BrandModelMapper.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.brandModel; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.EntityMapper; 4 | import com.amigoscode.chohort2.carRental.brand.Brand; 5 | import com.amigoscode.chohort2.carRental.brand.BrandDTO; 6 | import com.amigoscode.chohort2.carRental.brand.BrandMapper; 7 | import org.mapstruct.Mapper; 8 | import org.mapstruct.factory.Mappers; 9 | @Mapper 10 | public interface BrandModelMapper extends EntityMapper { 11 | BrandModelMapper INSTANCE = Mappers.getMapper(BrandModelMapper.class); 12 | } 13 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/brandModel/BrandModelRepository.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.brandModel; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | public interface BrandModelRepository extends JpaRepository { 6 | } 7 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/brandModel/BrandModelService.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.brandModel; 2 | 3 | import com.amigoscode.chohort2.carRental.annotation.TransactionalService; 4 | import lombok.AllArgsConstructor; 5 | import lombok.RequiredArgsConstructor; 6 | 7 | @TransactionalService 8 | @RequiredArgsConstructor 9 | public class BrandModelService { 10 | 11 | private final BrandModelRepository brandModelRepository; 12 | } 13 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/car/CarController.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.car; 2 | 3 | import com.amigoscode.chohort2.carRental.authority.AuthorityConstants; 4 | import com.amigoscode.chohort2.carRental.car.VM.CarSearchByProviderUserVM; 5 | import com.amigoscode.chohort2.carRental.car.VM.CarSearchVM; 6 | import com.amigoscode.chohort2.carRental.car.VM.CarVM; 7 | import com.amigoscode.chohort2.carRental.specification.CarSearchSpecification; 8 | import jakarta.validation.Valid; 9 | import lombok.RequiredArgsConstructor; 10 | import org.springframework.data.domain.Page; 11 | import org.springframework.data.domain.Pageable; 12 | import org.springframework.data.jpa.domain.Specification; 13 | import org.springframework.data.web.PageableDefault; 14 | import org.springframework.http.HttpStatus; 15 | import org.springframework.http.ResponseEntity; 16 | import org.springframework.security.access.annotation.Secured; 17 | import org.springframework.web.bind.annotation.*; 18 | 19 | @RestController 20 | @RequestMapping("api/v1/cars") 21 | @RequiredArgsConstructor 22 | public class CarController { 23 | 24 | private final CarService carService; 25 | 26 | @PostMapping 27 | @Secured({AuthorityConstants.CAR_PROVIDER}) 28 | public ResponseEntity addCar(@RequestBody @Valid CarVM carVM) { 29 | return ResponseEntity.ok(carService.addCar(carVM)); 30 | } 31 | 32 | @DeleteMapping("/{id}") 33 | @Secured({AuthorityConstants.CAR_PROVIDER}) 34 | public ResponseEntity deleteCarById(@PathVariable Long id) { 35 | carService.delete(id); 36 | return ResponseEntity.status(HttpStatus.OK).build(); 37 | } 38 | 39 | @GetMapping("/{id}") 40 | public ResponseEntity getCarById(@PathVariable Long id) { 41 | return ResponseEntity.ok(carService.getCarById(id)); 42 | } 43 | 44 | @PostMapping("/search") 45 | public ResponseEntity> searchCars(@RequestBody CarSearchVM carSearchVM, @PageableDefault Pageable pageable) { 46 | Specification carSpecification = carSearchVM instanceof CarSearchByProviderUserVM vm1 47 | ? CarSearchSpecification.carSearch(vm1): CarSearchSpecification.carSearch(carSearchVM) ; 48 | 49 | return ResponseEntity.ok(carService.getSearchCars(carSpecification, pageable)); 50 | } 51 | 52 | @PutMapping("/{carId}") 53 | @Secured({AuthorityConstants.CAR_PROVIDER}) 54 | public ResponseEntity updateCar(@PathVariable Long carId, @RequestBody @Valid CarVM carVM) { 55 | return ResponseEntity.ok(carService.update(carId, carVM)); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/car/CarDTO.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.car; 2 | 3 | 4 | import com.amigoscode.chohort2.carRental.brand.Brand; 5 | import com.amigoscode.chohort2.carRental.brand.BrandDTO; 6 | import com.amigoscode.chohort2.carRental.brandModel.BrandModel; 7 | import com.amigoscode.chohort2.carRental.brandModel.BrandModelDTO; 8 | import com.amigoscode.chohort2.carRental.lookupCode.LookupCodeDTO; 9 | import lombok.EqualsAndHashCode; 10 | import lombok.Getter; 11 | import lombok.Setter; 12 | import lombok.ToString; 13 | import lombok.experimental.Accessors; 14 | 15 | import java.time.LocalDate; 16 | import java.util.UUID; 17 | 18 | @Setter 19 | @Getter 20 | @Accessors(chain = true) 21 | @EqualsAndHashCode 22 | @ToString 23 | public class CarDTO { 24 | 25 | private Long id; 26 | 27 | private Long carProviderId; 28 | 29 | 30 | private UUID registrationNumber; 31 | 32 | private Integer brandCode; 33 | 34 | private BrandDTO brand; 35 | 36 | private Integer brandModelCode; 37 | private BrandModelDTO brandModel; 38 | 39 | 40 | private LocalDate productionYear; 41 | 42 | private Integer maxSpeed; 43 | 44 | private Integer horsePower; 45 | 46 | private String rgbCode; 47 | 48 | private String description; 49 | 50 | private Integer categoryCode; 51 | 52 | private LookupCodeDTO category; 53 | 54 | private Integer bookingStatusCode; 55 | 56 | private LookupCodeDTO bookingStatus; 57 | 58 | private Float price; 59 | 60 | private String imgUrl; 61 | 62 | private Boolean isVisible; 63 | 64 | 65 | } 66 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/car/CarMapper.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.car; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.EntityMapper; 4 | import com.amigoscode.chohort2.carRental.brand.BrandMapper; 5 | import com.amigoscode.chohort2.carRental.brandModel.BrandModelMapper; 6 | import com.amigoscode.chohort2.carRental.lookupCode.LookupCodeMapper; 7 | import org.mapstruct.Mapper; 8 | import org.mapstruct.factory.Mappers; 9 | 10 | @Mapper(uses = {LookupCodeMapper.class, BrandMapper.class, BrandModelMapper.class}) 11 | public interface CarMapper extends EntityMapper { 12 | CarMapper INSTANCE = Mappers.getMapper(CarMapper.class); 13 | } 14 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/car/CarRepository.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.car; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.repository.CRJpaRepository; 4 | import org.springframework.data.domain.Page; 5 | import org.springframework.data.domain.Pageable; 6 | import org.springframework.data.jpa.domain.Specification; 7 | import org.springframework.data.jpa.repository.JpaSpecificationExecutor; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import java.util.List; 11 | 12 | @Repository 13 | public interface CarRepository extends CRJpaRepository , JpaSpecificationExecutor { 14 | 15 | 16 | Page findAll(Specification carSearch, Pageable pageable); 17 | } 18 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/car/VM/CarSearchByProviderUserVM.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.car.VM; 2 | 3 | 4 | import lombok.EqualsAndHashCode; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | import lombok.ToString; 8 | import lombok.experimental.Accessors; 9 | 10 | @Setter 11 | @Getter 12 | @Accessors(chain = true) 13 | @ToString(callSuper = true) 14 | @EqualsAndHashCode(callSuper = true) 15 | public class CarSearchByProviderUserVM extends CarSearchVM { 16 | 17 | private Long providerUserId; 18 | } 19 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/car/VM/CarSearchVM.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.car.VM; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | import lombok.experimental.Accessors; 8 | 9 | import java.io.Serializable; 10 | import java.time.LocalDate; 11 | import java.util.List; 12 | import java.util.UUID; 13 | 14 | @Setter 15 | @Getter 16 | @Accessors(chain = true) 17 | @ToString 18 | @EqualsAndHashCode 19 | public class CarSearchVM implements Serializable { 20 | 21 | 22 | private List carProviderIds; 23 | 24 | private UUID registrationNumber; 25 | 26 | private Integer brandCode; 27 | private Integer brandModelCode; 28 | 29 | private LocalDate productionYearFrom; 30 | private LocalDate productionYearTo; 31 | 32 | private Integer maxSpeedFrom; 33 | private Integer maxSpeedTo; 34 | 35 | private Integer horsePowerFrom; 36 | private Integer horsePowerTo; 37 | 38 | private String rgbCode; 39 | 40 | private String description; 41 | 42 | private Integer categoryCode; 43 | private Integer bookingStatusCode; 44 | 45 | private Float priceFrom; 46 | private Float priceTo; 47 | 48 | 49 | 50 | } 51 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/car/VM/CarVM.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.car.VM; 2 | 3 | import com.amigoscode.chohort2.carRental.car.Car; 4 | import jakarta.validation.constraints.Min; 5 | import jakarta.validation.constraints.NotEmpty; 6 | import jakarta.validation.constraints.NotNull; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | import lombok.experimental.Accessors; 10 | 11 | import java.io.Serial; 12 | import java.io.Serializable; 13 | import java.time.LocalDate; 14 | 15 | @Setter 16 | @Getter 17 | @Accessors(chain = true) 18 | public class CarVM implements Serializable { 19 | 20 | @NotNull 21 | private Integer brandCode; 22 | 23 | @NotNull 24 | private Integer brandModelCode; 25 | 26 | @NotNull 27 | private LocalDate productionYear; 28 | 29 | @NotNull 30 | @Min(220) 31 | private Integer maxSpeed; 32 | 33 | @NotNull 34 | private Integer horsePower; 35 | 36 | @NotEmpty 37 | private String rgbCode; 38 | 39 | @NotEmpty 40 | private String description; 41 | 42 | @NotNull 43 | private Integer categoryCode; 44 | 45 | @NotNull 46 | private Float price; 47 | 48 | @NotEmpty 49 | private String imgUrl; 50 | 51 | 52 | public static Car vmToEntity(CarVM carVM){ 53 | return new Car() 54 | .setBrandCode(carVM.brandCode) 55 | .setBrandModelCode(carVM.brandModelCode) 56 | .setProductionYear(carVM.productionYear) 57 | .setMaxSpeed(carVM.maxSpeed) 58 | .setHorsePower(carVM.horsePower) 59 | .setRgbCode(carVM.rgbCode) 60 | .setDescription(carVM.description) 61 | .setCategoryCode(carVM.categoryCode) 62 | .setPrice(carVM.price) 63 | .setImgUrl(carVM.imgUrl); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carBooking/CarBooking.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carBooking; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.AbstractAuditingEntity; 4 | import com.amigoscode.chohort2.carRental.carUser.CarUser; 5 | import com.amigoscode.chohort2.carRental.lookupCode.LookupCode; 6 | import com.amigoscode.chohort2.carRental.lookupCode.LookupCodes; 7 | import com.amigoscode.chohort2.carRental.user.User; 8 | import jakarta.persistence.*; 9 | import lombok.AllArgsConstructor; 10 | import lombok.Getter; 11 | import lombok.NoArgsConstructor; 12 | import lombok.Setter; 13 | import lombok.experimental.Accessors; 14 | import org.hibernate.annotations.JoinColumnOrFormula; 15 | import org.hibernate.annotations.JoinColumnsOrFormulas; 16 | import org.hibernate.annotations.JoinFormula; 17 | import org.hibernate.annotations.Where; 18 | 19 | import java.time.LocalDate; 20 | 21 | @Entity 22 | @Table(name = "car_booking") 23 | @Setter 24 | @Getter 25 | @AllArgsConstructor 26 | @NoArgsConstructor 27 | @Accessors(chain = true) 28 | @Where(clause = "is_deleted = false") 29 | public class CarBooking extends AbstractAuditingEntity { 30 | 31 | @Id 32 | @GeneratedValue(strategy = GenerationType.IDENTITY) 33 | private Long id; 34 | 35 | @Column(name = "user_id",nullable = false) 36 | private Long userId; 37 | 38 | @ManyToOne(fetch = FetchType.LAZY) 39 | @JoinColumn(name = "user_id",updatable = false,insertable = false) 40 | private User user; 41 | 42 | @Column(name = "car_user_id",nullable = false) 43 | private Long carUserId; 44 | 45 | @ManyToOne(fetch = FetchType.LAZY) 46 | @JoinColumn(name = "car_user_id",updatable = false,insertable = false) 47 | private CarUser carUser; 48 | 49 | @Column(name = "check_in_date",nullable = false) 50 | private LocalDate checkInDate; 51 | 52 | @Column(name = "check_out_date",nullable = false) 53 | private LocalDate checkOutDate; 54 | 55 | @Column(name = "status_code",nullable = false) 56 | private Integer statusCode; 57 | 58 | 59 | @JoinColumnsOrFormulas({ 60 | @JoinColumnOrFormula(formula = @JoinFormula(value = "'"+ LookupCodes.UserBookingStatus.KEY +"'", referencedColumnName = "lookup_key")), 61 | @JoinColumnOrFormula(column = @JoinColumn(name = "status_code", referencedColumnName = "code", insertable = false, updatable = false)) 62 | }) 63 | @OneToOne 64 | private LookupCode status; 65 | 66 | private Float tax; 67 | 68 | private Float finalPrice; 69 | 70 | 71 | 72 | 73 | 74 | } 75 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carBooking/CarBookingController.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carBooking; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | @RestController 8 | @RequiredArgsConstructor 9 | @RequestMapping("api/v1/car-bookings") 10 | public class CarBookingController { 11 | private final CarBookingService carBookingService; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carBooking/CarBookingDTO.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carBooking; 2 | 3 | import com.amigoscode.chohort2.carRental.lookupCode.LookupCode; 4 | import com.amigoscode.chohort2.carRental.lookupCode.LookupCodes; 5 | import jakarta.persistence.*; 6 | import lombok.*; 7 | import lombok.experimental.Accessors; 8 | import org.hibernate.annotations.JoinColumnOrFormula; 9 | import org.hibernate.annotations.JoinColumnsOrFormulas; 10 | import org.hibernate.annotations.JoinFormula; 11 | 12 | import java.time.LocalDate; 13 | 14 | @Setter 15 | @Getter 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | @Accessors(chain = true) 19 | @ToString 20 | @EqualsAndHashCode 21 | public class CarBookingDTO { 22 | 23 | 24 | private Long id; 25 | 26 | 27 | private Long userId; 28 | 29 | 30 | private Long carUserId; 31 | 32 | 33 | private LocalDate checkInDate; 34 | 35 | 36 | private LocalDate checkOutDate; 37 | 38 | 39 | private Integer statusCode; 40 | 41 | 42 | private LookupCode status; 43 | 44 | private Float tax; 45 | 46 | private Float finalPrice; 47 | 48 | } 49 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carBooking/CarBookingMapper.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carBooking; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.EntityMapper; 4 | import org.mapstruct.Mapper; 5 | import org.mapstruct.factory.Mappers; 6 | 7 | @Mapper 8 | public interface CarBookingMapper extends EntityMapper { 9 | CarBookingMapper INSTANCE = Mappers.getMapper(CarBookingMapper.class); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carBooking/CarBookingRepository.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carBooking; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.repository.CRJpaRepository; 4 | import org.springframework.stereotype.Repository; 5 | 6 | @Repository 7 | public interface CarBookingRepository extends CRJpaRepository { 8 | } 9 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carBooking/CarBookingService.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carBooking; 2 | 3 | import com.amigoscode.chohort2.carRental.annotation.TransactionalService; 4 | import lombok.RequiredArgsConstructor; 5 | 6 | @TransactionalService 7 | @RequiredArgsConstructor 8 | public class CarBookingService { 9 | 10 | private final CarBookingRepository carBookingRepository; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carProvider/CarProvider.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carProvider; 2 | 3 | 4 | import com.amigoscode.chohort2.carRental.abstracts.AbstractAuditingEntity; 5 | import com.amigoscode.chohort2.carRental.car.Car; 6 | import com.amigoscode.chohort2.carRental.carProviderCoupon.CarProviderCoupon; 7 | import jakarta.persistence.*; 8 | import lombok.AllArgsConstructor; 9 | import lombok.Getter; 10 | import lombok.NoArgsConstructor; 11 | import lombok.Setter; 12 | import lombok.experimental.Accessors; 13 | import org.hibernate.annotations.Where; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | @Entity 19 | @Table(name = "car_provider") 20 | @Setter 21 | @Getter 22 | @AllArgsConstructor 23 | @NoArgsConstructor 24 | @Accessors(chain = true) 25 | @Where(clause = "is_deleted = false") 26 | public class CarProvider extends AbstractAuditingEntity { 27 | 28 | @Id 29 | @GeneratedValue(strategy = GenerationType.IDENTITY) 30 | private Long id; 31 | 32 | @Column(name = "name", nullable = false, unique = true) 33 | private String name; 34 | 35 | @Column (name = "cr_number", nullable = false, unique = true) 36 | private String crNumber; 37 | 38 | @OneToMany(mappedBy = "carProvider") 39 | private List cars = new ArrayList<>(); 40 | 41 | @OneToMany (mappedBy = "carProvider") 42 | private List carProviderCoupons = new ArrayList<>(); 43 | 44 | } 45 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carProvider/CarProviderController.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carProvider; 2 | 3 | 4 | import lombok.RequiredArgsConstructor; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import org.springframework.web.bind.annotation.*; 9 | 10 | @RestController 11 | @RequestMapping("api/v1/car-providers") 12 | @RequiredArgsConstructor 13 | public class CarProviderController { 14 | private final Logger log = LoggerFactory.getLogger(CarProviderController.class); 15 | 16 | private final CarProviderService carProviderService; 17 | 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carProvider/CarProviderDTO.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carProvider; 2 | 3 | 4 | import lombok.EqualsAndHashCode; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | import lombok.ToString; 8 | import lombok.experimental.Accessors; 9 | 10 | @Setter 11 | @Getter 12 | @Accessors(chain = true) 13 | @ToString 14 | @EqualsAndHashCode 15 | public class CarProviderDTO { 16 | 17 | private Long id; 18 | 19 | private String name; 20 | 21 | private String crNumber; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carProvider/CarProviderMapper.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carProvider; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.EntityMapper; 4 | import com.amigoscode.chohort2.carRental.car.CarMapper; 5 | import com.amigoscode.chohort2.carRental.lookupCode.LookupCodeMapper; 6 | import org.mapstruct.Mapper; 7 | import org.mapstruct.factory.Mappers; 8 | 9 | @Mapper(uses = {LookupCodeMapper.class}) 10 | public interface CarProviderMapper extends EntityMapper { 11 | CarProviderMapper INSTANCE = Mappers.getMapper(CarProviderMapper.class); 12 | } 13 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carProvider/CarProviderRepository.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carProvider; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.repository.CRJpaRepository; 4 | import org.springframework.stereotype.Repository; 5 | 6 | @Repository 7 | public interface CarProviderRepository extends CRJpaRepository { 8 | } 9 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carProvider/CarProviderService.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carProvider; 2 | 3 | import com.amigoscode.chohort2.carRental.annotation.TransactionalService; 4 | import com.amigoscode.chohort2.carRental.constants.ErrorConstants; 5 | import com.amigoscode.chohort2.carRental.exception.ApiRequestException; 6 | import com.amigoscode.chohort2.carRental.security.SecurityUtils; 7 | import com.amigoscode.chohort2.carRental.user.UserService; 8 | import lombok.RequiredArgsConstructor; 9 | 10 | 11 | import java.util.Optional; 12 | 13 | 14 | @TransactionalService 15 | @RequiredArgsConstructor 16 | public class CarProviderService { 17 | 18 | private final CarProviderRepository carProviderRepository; 19 | private final UserService userService; 20 | 21 | public CarProvider saveCarProvider(CarProvider carProvider) { 22 | return carProviderRepository.save(carProvider); 23 | } 24 | 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carProvider/VM/CarProviderVM.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carProvider.VM; 2 | 3 | import com.amigoscode.chohort2.carRental.carProvider.CarProvider; 4 | import jakarta.validation.constraints.NotEmpty; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | import lombok.experimental.Accessors; 8 | 9 | @Setter 10 | @Getter 11 | @Accessors(chain = true) 12 | public class CarProviderVM { 13 | 14 | 15 | @NotEmpty 16 | private String name; 17 | 18 | @NotEmpty 19 | private String crNumber; 20 | 21 | 22 | public static CarProvider vmToEntity(CarProviderVM carProviderVM) { 23 | return new CarProvider().setName(carProviderVM.name).setCrNumber(carProviderVM.crNumber); 24 | } 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carProviderAddress/CarProviderAddress.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carProviderAddress; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.AbstractAddress; 4 | import com.amigoscode.chohort2.carRental.carProvider.CarProvider; 5 | import com.amigoscode.chohort2.carRental.city.City; 6 | import jakarta.persistence.*; 7 | import lombok.AllArgsConstructor; 8 | import lombok.Getter; 9 | import lombok.NoArgsConstructor; 10 | import lombok.Setter; 11 | import lombok.experimental.Accessors; 12 | import org.hibernate.annotations.Where; 13 | 14 | @Entity 15 | @Table(name = "car_provider_address") 16 | @Setter 17 | @Getter 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Accessors(chain = true) 21 | @Where(clause = "is_deleted = false") 22 | public class CarProviderAddress extends AbstractAddress { 23 | @Id 24 | @GeneratedValue(strategy = GenerationType.IDENTITY) 25 | private Long id; 26 | 27 | @Column (name = "car_provider_id", nullable = false) 28 | private Long carProviderId; 29 | 30 | @ManyToOne (fetch = FetchType.LAZY,optional = false) 31 | @JoinColumn (name = "car_provider_id", updatable = false, insertable = false) 32 | private CarProvider carProvider; 33 | 34 | } 35 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carProviderAddress/CarProviderAddressController.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carProviderAddress; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | @RestController 8 | @RequestMapping("api/v1/car-provider-addresses") 9 | @RequiredArgsConstructor 10 | public class CarProviderAddressController { 11 | } 12 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carProviderAddress/CarProviderAddressDTO.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carProviderAddress; 2 | 3 | import com.amigoscode.chohort2.carRental.city.CityDTO; 4 | import lombok.*; 5 | 6 | import java.io.Serializable; 7 | 8 | @Data 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | @ToString 12 | @EqualsAndHashCode 13 | public class CarProviderAddressDTO implements Serializable { 14 | private Long id; 15 | private Long carProviderId; 16 | private Long cityId; 17 | private CityDTO city; 18 | private String location; 19 | private String postalCode; 20 | } 21 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carProviderAddress/CarProviderAddressMapper.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carProviderAddress; 2 | 3 | import org.mapstruct.Mapper; 4 | import org.mapstruct.factory.Mappers; 5 | @Mapper 6 | public interface CarProviderAddressMapper { 7 | CarProviderAddressMapper INSTANCE = Mappers.getMapper(CarProviderAddressMapper.class); 8 | } 9 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carProviderAddress/CarProviderAddressRepository.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carProviderAddress; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.repository.CRJpaRepository; 4 | import org.springframework.stereotype.Repository; 5 | 6 | @Repository 7 | public interface CarProviderAddressRepository extends CRJpaRepository { 8 | } 9 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carProviderAddress/CarProviderAddressService.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carProviderAddress; 2 | 3 | import com.amigoscode.chohort2.carRental.annotation.TransactionalService; 4 | import lombok.RequiredArgsConstructor; 5 | 6 | @TransactionalService 7 | @RequiredArgsConstructor 8 | public class CarProviderAddressService { 9 | } 10 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carProviderCoupon/CarProviderCoupon.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carProviderCoupon; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.AbstractAuditingEntity; 4 | import com.amigoscode.chohort2.carRental.carProvider.CarProvider; 5 | import jakarta.persistence.*; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Getter; 8 | import lombok.NoArgsConstructor; 9 | import lombok.Setter; 10 | import lombok.experimental.Accessors; 11 | import org.hibernate.annotations.Where; 12 | 13 | import java.time.LocalDate; 14 | 15 | @Entity 16 | @Table(name = "car_provider_coupon") 17 | @Setter 18 | @Getter 19 | @AllArgsConstructor 20 | @NoArgsConstructor 21 | @Accessors(chain = true) 22 | @Where(clause = "is_deleted = false") 23 | public class CarProviderCoupon extends AbstractAuditingEntity { 24 | 25 | @Id 26 | @GeneratedValue(strategy = GenerationType.IDENTITY) 27 | private Long id; 28 | 29 | @Column (name = "car_provider_id", nullable = false) 30 | private Long carProviderId; 31 | 32 | @ManyToOne (fetch = FetchType.LAZY) 33 | @JoinColumn (name = "car_provider_id", insertable = false, updatable = false) 34 | private CarProvider carProvider; 35 | 36 | @Column (name = "coupon_code", nullable = false, unique = true) 37 | private String couponCode; 38 | 39 | @Column (name = "start_date", nullable = false) 40 | private LocalDate startDate; 41 | 42 | @Column (name = "end_date", nullable = false) 43 | private LocalDate endDate; 44 | 45 | @Column (name = "num_of_user_per_user", nullable = false) 46 | private Integer numOfUsePerUser; 47 | 48 | @Column (name = "is_available", nullable = false) 49 | private Boolean isAvailable = true; 50 | 51 | 52 | } 53 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carProviderCoupon/CarProviderCouponController.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carProviderCoupon; 2 | 3 | import com.amigoscode.chohort2.carRental.authority.AuthorityConstants; 4 | import com.amigoscode.chohort2.carRental.carProviderCoupon.VM.CarProviderCouponAvailabilityVM; 5 | import com.amigoscode.chohort2.carRental.carProviderCoupon.VM.CarProviderCouponVM; 6 | import lombok.RequiredArgsConstructor; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.http.HttpStatus; 10 | import org.springframework.http.ResponseEntity; 11 | import org.springframework.security.access.annotation.Secured; 12 | import org.springframework.web.bind.annotation.*; 13 | 14 | @RestController 15 | @RequestMapping (value = "api/v1/car-provider-coupons") 16 | @RequiredArgsConstructor 17 | public class CarProviderCouponController { 18 | private final Logger log = LoggerFactory.getLogger(CarProviderCouponController.class); 19 | private final CarProviderCouponService carProviderCouponService; 20 | 21 | @PostMapping 22 | @Secured({AuthorityConstants.CAR_PROVIDER}) 23 | public ResponseEntity createCarProviderCoupon(@RequestBody CarProviderCouponVM carProviderCouponVM){ 24 | log.info("car provider coupon info {}", carProviderCouponVM); 25 | CarProviderCouponDTO couponDTO = carProviderCouponService.save(carProviderCouponVM); 26 | return ResponseEntity.status(HttpStatus.CREATED).body(couponDTO); 27 | } 28 | 29 | 30 | @PutMapping("{couponId}") 31 | @Secured({AuthorityConstants.CAR_PROVIDER}) 32 | public ResponseEntity updateCarProviderCouponAvailability(@PathVariable("couponId") Long couponId,@RequestBody CarProviderCouponAvailabilityVM carProviderCouponAvailabilityVM){ 33 | log.info("car provider coupon info {}", carProviderCouponAvailabilityVM); 34 | CarProviderCouponDTO availabilityCouponDTO = carProviderCouponService.updateCouponAvailability(couponId,carProviderCouponAvailabilityVM); 35 | return ResponseEntity.ok().body(availabilityCouponDTO); 36 | } 37 | 38 | 39 | } 40 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carProviderCoupon/CarProviderCouponDTO.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carProviderCoupon; 2 | 3 | import com.amigoscode.chohort2.carRental.carProvider.CarProviderDTO; 4 | import lombok.EqualsAndHashCode; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | import lombok.ToString; 8 | import lombok.experimental.Accessors; 9 | 10 | import java.io.Serializable; 11 | import java.time.LocalDate; 12 | 13 | /** 14 | * DTO for {@link CarProviderCoupon} 15 | */ 16 | @Getter 17 | @Setter 18 | @Accessors(chain = true) 19 | @ToString 20 | @EqualsAndHashCode 21 | public class CarProviderCouponDTO implements Serializable { 22 | private Long id; 23 | private Long carProviderId; 24 | private CarProviderDTO carProvider; 25 | private String couponCode; 26 | private LocalDate startDate; 27 | private LocalDate endDate; 28 | private Integer numOfUsePerUser; 29 | private Boolean isAvailable; 30 | } -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carProviderCoupon/CarProviderCouponMapper.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carProviderCoupon; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.EntityMapper; 4 | import org.mapstruct.Mapper; 5 | import org.mapstruct.factory.Mappers; 6 | @Mapper 7 | public interface CarProviderCouponMapper extends EntityMapper { 8 | 9 | CarProviderCouponMapper INSTANCE = Mappers.getMapper(CarProviderCouponMapper.class); 10 | } 11 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carProviderCoupon/CarProviderCouponRepository.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carProviderCoupon; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.repository.CRJpaRepository; 4 | import org.springframework.data.jpa.repository.Query; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.util.Optional; 8 | 9 | @Repository 10 | public interface CarProviderCouponRepository extends CRJpaRepository { 11 | @Query("select u from CarProviderCoupon u where u.couponCode=:couponCode") 12 | Optional findByCouponCode(String couponCode); 13 | } 14 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carProviderCoupon/CarProviderCouponService.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carProviderCoupon; 2 | 3 | import com.amigoscode.chohort2.carRental.annotation.TransactionalService; 4 | import com.amigoscode.chohort2.carRental.carProviderCoupon.VM.CarProviderCouponAvailabilityVM; 5 | import com.amigoscode.chohort2.carRental.carProviderCoupon.VM.CarProviderCouponVM; 6 | import com.amigoscode.chohort2.carRental.carProviderUser.CarProviderUser; 7 | import com.amigoscode.chohort2.carRental.carProviderUser.CarProviderUserService; 8 | import com.amigoscode.chohort2.carRental.exception.ApiRequestException; 9 | import com.amigoscode.chohort2.carRental.user.User; 10 | import com.amigoscode.chohort2.carRental.user.UserService; 11 | import com.amigoscode.chohort2.carRental.validation.Validator; 12 | import lombok.RequiredArgsConstructor; 13 | 14 | import java.util.Optional; 15 | 16 | 17 | @TransactionalService 18 | @RequiredArgsConstructor 19 | public class CarProviderCouponService { 20 | private final CarProviderCouponRepository carProviderCouponRepository; 21 | private final CarProviderUserService carProviderUserService; 22 | private final UserService userService; 23 | 24 | public CarProviderCouponDTO save(CarProviderCouponVM carProviderCouponVM) { 25 | CarProviderCoupon carProviderCoupon = new CarProviderCoupon() 26 | .setCarProviderId(getCarProvideId()) 27 | .setCouponCode(carProviderCouponVM.getCouponCode()) 28 | .setStartDate(carProviderCouponVM.getStartDate()) 29 | .setEndDate(carProviderCouponVM.getEndDate()) 30 | .setNumOfUsePerUser(carProviderCouponVM.getNumOfUsePerUser()) 31 | .setIsAvailable(carProviderCouponVM.getIsAvailable()); 32 | return CarProviderCouponMapper.INSTANCE.toDto(carProviderCouponRepository.save(carProviderCoupon)); 33 | } 34 | 35 | 36 | public CarProviderCouponDTO updateCouponAvailability(Long id, CarProviderCouponAvailabilityVM carProviderCouponAvailabilityVM) { 37 | CarProviderCoupon carProviderCoupon = getCarProviderCouponById(id); 38 | 39 | Validator.invalidateIfTrue(() -> !carProviderCoupon.getCarProviderId().equals(getCarProvideId()), 40 | "Coupon not belong to company"); 41 | 42 | 43 | carProviderCoupon.setIsAvailable(carProviderCouponAvailabilityVM.getIsAvailable()); 44 | 45 | return CarProviderCouponMapper.INSTANCE.toDto(carProviderCouponRepository.save(carProviderCoupon)); 46 | } 47 | 48 | public CarProviderCoupon getCarProviderCouponById(Long id) { 49 | return carProviderCouponRepository.findById(id) 50 | .orElseThrow(() -> new ApiRequestException("Coupon not found")); 51 | } 52 | 53 | private Long getCarProvideId() { 54 | User user = userService.getLoggedInUser(); 55 | CarProviderUser carProviderUser = carProviderUserService.findCarProviderUserByUserId(user.getId()); 56 | return carProviderUser.getCarProviderId(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carProviderCoupon/VM/CarProviderCouponAvailabilityVM.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carProviderCoupon.VM; 2 | 3 | import jakarta.validation.constraints.NotEmpty; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | import lombok.experimental.Accessors; 8 | 9 | import java.io.Serializable; 10 | @Setter 11 | @Getter 12 | @ToString 13 | @Accessors(chain = true) 14 | public class CarProviderCouponAvailabilityVM implements Serializable { 15 | 16 | @NotEmpty 17 | private Boolean isAvailable; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carProviderCoupon/VM/CarProviderCouponVM.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carProviderCoupon.VM; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import jakarta.validation.constraints.NotEmpty; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | import lombok.experimental.Accessors; 8 | 9 | import java.io.Serializable; 10 | import java.time.LocalDate; 11 | 12 | @Setter 13 | @Getter 14 | @Accessors(chain = true) 15 | public class CarProviderCouponVM implements Serializable { 16 | 17 | private static final long serialVersionUID = 9178661439383356177L; 18 | @NotEmpty 19 | private String couponCode; 20 | @NotEmpty 21 | @JsonFormat(pattern = "dd/MM/yyyy") 22 | private LocalDate startDate; 23 | @NotEmpty 24 | @JsonFormat(pattern = "dd/MM/yyyy") 25 | private LocalDate endDate; 26 | @NotEmpty 27 | private Integer numOfUsePerUser; 28 | @NotEmpty 29 | private Boolean isAvailable = true; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carProviderUser/CarProviderUser.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carProviderUser; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.AbstractAuditingEntity; 4 | import com.amigoscode.chohort2.carRental.carProvider.CarProvider; 5 | import com.amigoscode.chohort2.carRental.user.User; 6 | import jakarta.persistence.*; 7 | import lombok.AllArgsConstructor; 8 | import lombok.Getter; 9 | import lombok.NoArgsConstructor; 10 | import lombok.Setter; 11 | import lombok.experimental.Accessors; 12 | import org.hibernate.annotations.Where; 13 | 14 | @Entity 15 | @Table(name = "car_provider_user") 16 | @Setter 17 | @Getter 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Accessors(chain = true) 21 | @Where(clause = "is_deleted = false") 22 | public class CarProviderUser extends AbstractAuditingEntity { 23 | 24 | @Id 25 | @GeneratedValue(strategy = GenerationType.IDENTITY) 26 | private Long id; 27 | 28 | @Column (name = "user_id", nullable = false) 29 | private Long userId; 30 | 31 | @OneToOne (fetch = FetchType.LAZY, optional = false) 32 | @JoinColumn (name = "user_id", updatable = false, insertable = false) 33 | private User user; 34 | 35 | @Column (name = "car_provider_id", nullable = false) 36 | private Long carProviderId; 37 | 38 | @OneToOne (fetch = FetchType.LAZY,optional = false) 39 | @JoinColumn (name = "car_provider_id", updatable = false, insertable = false) 40 | private CarProvider carProvider; 41 | 42 | @Column (name = "company_admin", nullable = false) 43 | private Boolean companyAdmin; 44 | } 45 | 46 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carProviderUser/CarProviderUserController.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carProviderUser; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | @RestController 8 | @RequestMapping(value = "api/v1/car-providers") 9 | @RequiredArgsConstructor 10 | public class CarProviderUserController { 11 | private final CarProviderUserService carProviderUserService; 12 | } 13 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carProviderUser/CarProviderUserDTO.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carProviderUser; 2 | 3 | import com.amigoscode.chohort2.carRental.carProvider.CarProviderDTO; 4 | import com.amigoscode.chohort2.carRental.user.UserDTO; 5 | import jakarta.validation.constraints.NotNull; 6 | import lombok.*; 7 | 8 | import java.io.Serializable; 9 | 10 | /** 11 | * DTO for {@link CarProviderUser} 12 | */ 13 | @Data 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | @ToString 17 | @EqualsAndHashCode 18 | public class CarProviderUserDTO implements Serializable { 19 | private Long id; 20 | private Long userId; 21 | private UserDTO user; 22 | private Long carProviderId; 23 | private CarProviderDTO carProvider; 24 | private Boolean companyAdmin; 25 | } -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carProviderUser/CarProviderUserMapper.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carProviderUser; 2 | 3 | import com.amigoscode.chohort2.carRental.car.CarMapper; 4 | import org.mapstruct.Mapper; 5 | import org.mapstruct.factory.Mappers; 6 | 7 | @Mapper 8 | public interface CarProviderUserMapper { 9 | CarProviderUserMapper INSTANCE = Mappers.getMapper(CarProviderUserMapper.class); 10 | } 11 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carProviderUser/CarProviderUserRepository.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carProviderUser; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.repository.CRJpaRepository; 4 | import org.springframework.stereotype.Repository; 5 | 6 | import java.util.Optional; 7 | 8 | @Repository 9 | public interface CarProviderUserRepository extends CRJpaRepository { 10 | Optional findByUserId(Long userId); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carProviderUser/CarProviderUserService.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carProviderUser; 2 | 3 | import com.amigoscode.chohort2.carRental.annotation.TransactionalService; 4 | import com.amigoscode.chohort2.carRental.constants.ErrorConstants; 5 | import com.amigoscode.chohort2.carRental.exception.ApiRequestException; 6 | import lombok.RequiredArgsConstructor; 7 | 8 | @TransactionalService 9 | @RequiredArgsConstructor 10 | public class CarProviderUserService { 11 | private final CarProviderUserRepository carProviderUserRepository; 12 | 13 | public CarProviderUser saveCarProviderUser(CarProviderUser carProviderUser) { 14 | return carProviderUserRepository.save(carProviderUser); 15 | } 16 | public CarProviderUser findCarProviderUserByUserId(Long id) { 17 | return carProviderUserRepository.findByUserId(id) 18 | .orElseThrow(()-> new ApiRequestException(ErrorConstants.CAR_PROVIDER_USER)); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carUser/CarUserController.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carUser; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | @RestController 8 | @RequestMapping("api/v1/car-users") 9 | @RequiredArgsConstructor 10 | public class CarUserController { 11 | private CarUserService carUserService; 12 | } 13 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carUser/CarUserDTO.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carUser; 2 | 3 | import com.amigoscode.chohort2.carRental.brand.Brand; 4 | import com.amigoscode.chohort2.carRental.brandModel.BrandModel; 5 | import com.amigoscode.chohort2.carRental.car.Car; 6 | import com.amigoscode.chohort2.carRental.lookupCode.LookupCode; 7 | import lombok.*; 8 | import lombok.experimental.Accessors; 9 | 10 | 11 | import java.time.LocalDate; 12 | import java.util.UUID; 13 | 14 | @Setter 15 | @Getter 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | @Accessors(chain = true) 19 | @ToString 20 | @EqualsAndHashCode 21 | public class CarUserDTO { 22 | 23 | private Long id; 24 | 25 | private Long carId; 26 | 27 | private UUID registrationNumber; 28 | 29 | private Integer brandCode; 30 | 31 | private Brand brand; 32 | 33 | 34 | private Integer brandModelCode; 35 | 36 | 37 | private BrandModel brandModel; 38 | 39 | 40 | private LocalDate productionYear; 41 | 42 | 43 | private Integer maxSpeed; 44 | 45 | 46 | private Integer horsePower; 47 | 48 | 49 | private String rgbCode; 50 | 51 | 52 | private String description; 53 | 54 | 55 | private Integer categoryCode; 56 | 57 | private LookupCode category; 58 | 59 | 60 | private Integer bookingStatusCode; 61 | 62 | private LookupCode bookingStatus; 63 | 64 | 65 | private Float price; 66 | 67 | 68 | private String imgUrl; 69 | 70 | 71 | } 72 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carUser/CarUserMapper.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carUser; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.EntityMapper; 4 | import org.mapstruct.Mapper; 5 | import org.mapstruct.factory.Mappers; 6 | 7 | @Mapper 8 | public interface CarUserMapper extends EntityMapper { 9 | CarUserMapper INSTANCE = Mappers.getMapper(CarUserMapper.class); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carUser/CarUserRepository.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carUser; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import org.springframework.stereotype.Repository; 5 | 6 | @Repository 7 | public interface CarUserRepository extends JpaRepository { 8 | } 9 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/carUser/CarUserService.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.carUser; 2 | 3 | import com.amigoscode.chohort2.carRental.annotation.TransactionalService; 4 | import lombok.RequiredArgsConstructor; 5 | 6 | @TransactionalService 7 | @RequiredArgsConstructor 8 | public class CarUserService { 9 | 10 | private final CarUserRepository userRepository; 11 | 12 | 13 | } 14 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/city/City.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.city; 2 | 3 | import com.amigoscode.chohort2.carRental.country.Country; 4 | import jakarta.persistence.*; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Getter; 7 | import lombok.NoArgsConstructor; 8 | import lombok.Setter; 9 | import lombok.experimental.Accessors; 10 | 11 | @Entity 12 | @Setter 13 | @Getter 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | @Accessors(chain = true) 17 | public class City { 18 | 19 | @Id 20 | @GeneratedValue(strategy = GenerationType.IDENTITY) 21 | private Long id; 22 | 23 | @Column(name = "country_id") 24 | private Long countryId; 25 | 26 | @ManyToOne(fetch = FetchType.LAZY) 27 | @JoinColumn(name = "country_id", insertable = false, updatable = false) 28 | private Country country; 29 | 30 | @Column(name = "name", nullable = false) 31 | private String name; 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/city/CityController.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.city; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | @RestController 8 | @RequestMapping("api/v1/cities") 9 | @RequiredArgsConstructor 10 | public class CityController { 11 | private final CityService cityService; 12 | } 13 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/city/CityDTO.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.city; 2 | 3 | import lombok.*; 4 | import lombok.experimental.Accessors; 5 | 6 | @Setter 7 | @Getter 8 | @Accessors(chain = true) 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | @ToString 12 | @EqualsAndHashCode 13 | public class CityDTO { 14 | 15 | private Long id; 16 | 17 | private Long countryId; 18 | 19 | private String name; 20 | 21 | 22 | } 23 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/city/CityMapper.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.city; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.EntityMapper; 4 | import org.mapstruct.Mapper; 5 | import org.mapstruct.factory.Mappers; 6 | 7 | @Mapper 8 | public interface CityMapper extends EntityMapper { 9 | 10 | CityMapper INSTANCE = Mappers.getMapper(CityMapper.class); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/city/CityRepository.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.city; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import org.springframework.stereotype.Repository; 5 | 6 | @Repository 7 | public interface CityRepository extends JpaRepository { 8 | } 9 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/city/CityService.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.city; 2 | 3 | import com.amigoscode.chohort2.carRental.annotation.TransactionalService; 4 | import lombok.RequiredArgsConstructor; 5 | 6 | @TransactionalService 7 | @RequiredArgsConstructor 8 | public class CityService { 9 | private final CityRepository cityRepository; 10 | } 11 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/config/CustomStringDeserializer.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.config; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.databind.DeserializationContext; 5 | import com.fasterxml.jackson.databind.deser.std.StdDeserializer; 6 | 7 | import java.io.IOException; 8 | 9 | public class CustomStringDeserializer extends StdDeserializer { 10 | protected CustomStringDeserializer() { 11 | super(String.class); 12 | } 13 | 14 | @Override 15 | public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { 16 | return jsonParser.getText().trim(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/config/audit/AuditConfig.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.config.audit; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.data.domain.AuditorAware; 6 | import org.springframework.data.jpa.repository.config.EnableJpaAuditing; 7 | 8 | @Configuration 9 | @EnableJpaAuditing(auditorAwareRef = "springAuditorAware") 10 | public class AuditConfig { 11 | 12 | @Bean 13 | AuditorAware springAuditorAware(){ 14 | return new SystemAudit(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/config/audit/SystemAudit.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.config.audit; 2 | 3 | import com.amigoscode.chohort2.carRental.constants.Constants; 4 | import com.amigoscode.chohort2.carRental.security.SecurityUtils; 5 | import org.springframework.data.domain.AuditorAware; 6 | 7 | import java.util.Optional; 8 | 9 | 10 | public class SystemAudit implements AuditorAware { 11 | 12 | 13 | @Override 14 | public Optional getCurrentAuditor() { 15 | String auditBy = SecurityUtils 16 | .getCurrentUsernameOpt() 17 | .orElse(Constants.SYSTEM); 18 | 19 | return Optional. 20 | of(auditBy.equalsIgnoreCase(Constants.ANONYMOUS_USER) ? Constants.SYSTEM : auditBy); 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/constants/Constants.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.constants; 2 | 3 | 4 | public final class Constants { 5 | public static final String SYSTEM = "System"; 6 | 7 | public static final String ANONYMOUS_USER = "anonymousUser"; 8 | 9 | public static final String USERNAME_REGEX = "^(?=.{3,50}$)(?![_.])(?!.*[_.]{2})[a-zA-Z0-9._]+(? cities = new ArrayList<>(); 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/country/CountryController.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.country; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | @RestController 8 | @RequestMapping("api/v1/countries") 9 | @RequiredArgsConstructor 10 | public class CountryController { 11 | 12 | private final CountryService countryService; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/country/CountryDTO.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.country; 2 | 3 | import com.amigoscode.chohort2.carRental.city.CityDTO; 4 | import lombok.*; 5 | import lombok.experimental.Accessors; 6 | 7 | import java.util.List; 8 | 9 | @Setter 10 | @Getter 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | @Accessors(chain = true) 14 | @ToString 15 | @EqualsAndHashCode 16 | public class CountryDTO { 17 | 18 | 19 | private Long id; 20 | 21 | 22 | private String ccCode; 23 | 24 | 25 | private String callingCode; 26 | 27 | private List cities; 28 | 29 | 30 | } 31 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/country/CountryMapper.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.country; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.EntityMapper; 4 | import com.amigoscode.chohort2.carRental.city.CityMapper; 5 | import org.mapstruct.Mapper; 6 | import org.mapstruct.factory.Mappers; 7 | 8 | @Mapper(uses = {CityMapper.class}) 9 | public interface CountryMapper extends EntityMapper { 10 | 11 | CountryMapper INSTANCE = Mappers.getMapper(CountryMapper.class); 12 | } 13 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/country/CountryRepository.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.country; 2 | 3 | 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | @Repository 8 | public interface CountryRepository extends JpaRepository { 9 | 10 | 11 | 12 | } 13 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/country/CountryService.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.country; 2 | 3 | import com.amigoscode.chohort2.carRental.annotation.TransactionalService; 4 | import lombok.RequiredArgsConstructor; 5 | 6 | @TransactionalService 7 | @RequiredArgsConstructor 8 | public class CountryService { 9 | 10 | private final CountryRepository countryRepository; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/driverLicense/DriverLicense.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.driverLicense; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.AbstractAuditingEntity; 4 | import com.amigoscode.chohort2.carRental.user.User; 5 | import jakarta.persistence.*; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Getter; 8 | import lombok.NoArgsConstructor; 9 | import lombok.Setter; 10 | import lombok.experimental.Accessors; 11 | import org.hibernate.annotations.Where; 12 | 13 | import java.time.LocalDate; 14 | 15 | @Entity 16 | @Table(name = "driver_license") 17 | @Setter 18 | @Getter 19 | @AllArgsConstructor 20 | @NoArgsConstructor 21 | @Accessors(chain = true) 22 | @Where(clause = "is_deleted = false") 23 | public class DriverLicense extends AbstractAuditingEntity { 24 | @Id 25 | @GeneratedValue(strategy = GenerationType.IDENTITY) 26 | private Long id; 27 | 28 | @Column (name = "user_id", nullable = false) 29 | private Long userId; 30 | 31 | @OneToOne(fetch = FetchType.LAZY) 32 | @JoinColumn (name = "user_id", updatable = false,insertable = false) 33 | private User user; 34 | 35 | @Column (name = "number", nullable = false) 36 | private String driverLicenseNumber; 37 | 38 | @Column (name = "issued_in", nullable = false) 39 | private Long issuedIn; 40 | 41 | @Column (name = "issued_at", nullable = false) 42 | private LocalDate issuedAt; 43 | 44 | @Column (name = "expired_date", nullable = false) 45 | private LocalDate expiredDate; 46 | 47 | 48 | } 49 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/driverLicense/DriverLicenseController.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.driverLicense; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | @RestController 8 | @RequestMapping("api/v1/driver-licenses") 9 | @RequiredArgsConstructor 10 | public class DriverLicenseController { 11 | } 12 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/driverLicense/DriverLicenseDTO.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.driverLicense; 2 | 3 | import com.amigoscode.chohort2.carRental.user.UserDTO; 4 | import lombok.EqualsAndHashCode; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | import lombok.ToString; 8 | import lombok.experimental.Accessors; 9 | 10 | import java.time.LocalDate; 11 | 12 | @Setter 13 | @Getter 14 | @Accessors(chain = true) 15 | @ToString 16 | @EqualsAndHashCode 17 | public class DriverLicenseDTO { 18 | 19 | private Long id; 20 | 21 | private Long userId; 22 | 23 | private UserDTO user; 24 | 25 | private String driverLicenseNumber; 26 | 27 | private Integer issuedIn; 28 | 29 | private LocalDate issuedAt; 30 | 31 | private LocalDate expiredDate; 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/driverLicense/DriverLicenseMapper.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.driverLicense; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.EntityMapper; 4 | import com.amigoscode.chohort2.carRental.lookupCode.LookupCodeMapper; 5 | import com.amigoscode.chohort2.carRental.user.UserMapper; 6 | import org.mapstruct.Mapper; 7 | import org.mapstruct.factory.Mappers; 8 | 9 | @Mapper(uses ={UserMapper.class}) 10 | public interface DriverLicenseMapper extends EntityMapper { 11 | DriverLicenseMapper INSTANCE = Mappers.getMapper(DriverLicenseMapper.class); 12 | } 13 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/driverLicense/DriverLicenseRepository.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.driverLicense; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.repository.CRJpaRepository; 4 | import org.springframework.stereotype.Repository; 5 | 6 | import java.util.Optional; 7 | 8 | @Repository 9 | public interface DriverLicenseRepository extends CRJpaRepository { 10 | 11 | Optional findByDriverLicenseNumber(String number); 12 | } 13 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/driverLicense/DriverLicenseService.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.driverLicense; 2 | 3 | import com.amigoscode.chohort2.carRental.annotation.TransactionalService; 4 | import lombok.RequiredArgsConstructor; 5 | 6 | @TransactionalService 7 | @RequiredArgsConstructor 8 | public class DriverLicenseService { 9 | private final DriverLicenseRepository driverLicenseRepository; 10 | 11 | public void save(DriverLicense driverLicense) { 12 | driverLicenseRepository.save(driverLicense); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/driverLicense/VM/DriverLicenseVM.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.driverLicense.VM; 2 | 3 | 4 | 5 | import com.amigoscode.chohort2.carRental.driverLicense.DriverLicense; 6 | import jakarta.validation.constraints.NotEmpty; 7 | import jakarta.validation.constraints.NotNull; 8 | import lombok.EqualsAndHashCode; 9 | import lombok.Getter; 10 | import lombok.Setter; 11 | import lombok.ToString; 12 | import lombok.experimental.Accessors; 13 | 14 | import java.io.Serializable; 15 | import java.time.LocalDate; 16 | 17 | @Setter 18 | @Getter 19 | @ToString 20 | @Accessors(chain = true) 21 | public class DriverLicenseVM implements Serializable { 22 | 23 | @NotEmpty 24 | private String driverLicenseNumber; 25 | 26 | @NotEmpty 27 | private Long issuedIn; 28 | 29 | @NotNull 30 | private LocalDate issuedAt; 31 | 32 | @NotNull 33 | private LocalDate expiredDate; 34 | 35 | 36 | public static DriverLicense vmToEntity(DriverLicenseVM driverLicenseVM){ 37 | 38 | return new DriverLicense() 39 | .setDriverLicenseNumber(driverLicenseVM.driverLicenseNumber) 40 | .setIssuedIn(driverLicenseVM.issuedIn) 41 | .setIssuedAt(driverLicenseVM.issuedAt) 42 | .setExpiredDate(driverLicenseVM.expiredDate); 43 | } 44 | 45 | 46 | 47 | 48 | 49 | } 50 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/exception/ApiExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.exception; 2 | 3 | import com.amigoscode.chohort2.carRental.constants.ErrorConstants; 4 | 5 | import jakarta.servlet.http.HttpServletRequest; 6 | import lombok.RequiredArgsConstructor; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.context.MessageSource; 10 | import org.springframework.http.HttpStatus; 11 | import org.springframework.http.ResponseEntity; 12 | import org.springframework.web.bind.MethodArgumentNotValidException; 13 | import org.springframework.web.bind.annotation.ExceptionHandler; 14 | import org.springframework.web.bind.annotation.RestControllerAdvice; 15 | 16 | 17 | @RestControllerAdvice 18 | @RequiredArgsConstructor 19 | public class ApiExceptionHandler { 20 | 21 | private final MessageSource messageSource; 22 | private final Logger log = LoggerFactory.getLogger(ApiExceptionHandler.class); 23 | 24 | 25 | 26 | @ExceptionHandler(value = {ApiRequestException.class}) 27 | public ResponseEntity handelRequestException(ApiRequestException e, HttpServletRequest request) { 28 | 29 | 30 | return ResponseEntity 31 | .status(e.getStatusCode()) 32 | .body(ApiExceptionResponse 33 | .builder() 34 | .path(request.getRequestURI()) 35 | .message(e.getMessage()) 36 | .statusCode(e.getStatusCode()) 37 | .errorKey(e.getErrorKey()) 38 | .userMessage(e.getMessage()) 39 | .build()); 40 | 41 | } 42 | 43 | @ExceptionHandler(value = {MethodArgumentNotValidException.class}) 44 | public ResponseEntity handelArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request) { 45 | 46 | 47 | log.error("Error: ",e); 48 | return ResponseEntity 49 | .badRequest() 50 | .body(ApiExceptionResponse 51 | .builder() 52 | .path(request.getRequestURI()) 53 | .statusCode(HttpStatus.BAD_REQUEST.value()) 54 | .message("Invalid Inputs to API: " + request.getRequestURI()) 55 | .userMessage(e.getMessage()) 56 | .build()); 57 | 58 | } 59 | 60 | 61 | 62 | 63 | @ExceptionHandler(value = {Exception.class}) 64 | public ResponseEntity handelApplicationException(Exception e, HttpServletRequest request) { 65 | 66 | log.error("Error: ",e); 67 | return ResponseEntity 68 | .status(HttpStatus.INTERNAL_SERVER_ERROR) 69 | .body(ApiExceptionResponse 70 | .builder() 71 | .path(request.getRequestURI()) 72 | .message(e.getMessage()) 73 | .statusCode(HttpStatus.INTERNAL_SERVER_ERROR.value()) 74 | .userMessage(ErrorConstants.INTERNAL) 75 | .build()); 76 | 77 | } 78 | 79 | 80 | 81 | } 82 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/exception/ApiExceptionResponse.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.exception; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | 7 | import java.time.LocalDateTime; 8 | import java.util.Map; 9 | 10 | @Builder 11 | @Data 12 | @JsonInclude(JsonInclude.Include.NON_NULL) 13 | public class ApiExceptionResponse { 14 | 15 | private String path; 16 | private String message; 17 | private int statusCode; 18 | private String errorKey; 19 | private String userMessage; 20 | private final LocalDateTime timestamp = LocalDateTime.now(); 21 | } 22 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/exception/ApiRequestException.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.exception; 2 | 3 | 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import org.springframework.http.HttpStatus; 7 | 8 | 9 | @Setter 10 | @Getter 11 | public class ApiRequestException extends RuntimeException { 12 | 13 | private String message; 14 | 15 | private String errorKey; 16 | 17 | private Object[] messageArgs; 18 | 19 | private int statusCode = HttpStatus.BAD_REQUEST.value(); 20 | 21 | public ApiRequestException(String errorKey) { 22 | this(null, errorKey); 23 | } 24 | 25 | public ApiRequestException(String message, String errorKey) { 26 | super(errorKey); 27 | this.message = message; 28 | this.errorKey = errorKey; 29 | 30 | } 31 | 32 | public ApiRequestException message(String message) { 33 | this.setMessage(message); 34 | return this; 35 | } 36 | 37 | public ApiRequestException errorKey(String errorKey) { 38 | this.setErrorKey(errorKey); 39 | return this; 40 | } 41 | 42 | 43 | public ApiRequestException statusCode(int statusCode) { 44 | this.setStatusCode(statusCode); 45 | return this; 46 | } 47 | 48 | public ApiRequestException messageArgs(Object[] messageArgs) { 49 | this.setMessageArgs(messageArgs); 50 | return this; 51 | } 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/logging/AbstractAspect.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.logging; 2 | 3 | import org.aspectj.lang.annotation.Pointcut; 4 | 5 | public class AbstractAspect { 6 | 7 | @Pointcut("execution(public * *(..))") 8 | void anyPublicOperation() {} 9 | 10 | @Pointcut ("within(com.amigoscode.chohort2.carRental..*)") 11 | void inProjectPoint(){} 12 | 13 | } 14 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/logging/ControllerLoggingAspect.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.logging; 2 | 3 | import com.amigoscode.chohort2.carRental.car.CarMapper; 4 | import com.amigoscode.chohort2.carRental.constants.LoggingConstants; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.apache.coyote.Response; 7 | import org.aspectj.lang.JoinPoint; 8 | import org.aspectj.lang.annotation.AfterReturning; 9 | import org.aspectj.lang.annotation.Aspect; 10 | import org.aspectj.lang.annotation.Before; 11 | import org.aspectj.lang.annotation.Pointcut; 12 | import org.springframework.http.ResponseEntity; 13 | import org.springframework.stereotype.Component; 14 | 15 | import java.io.Serializable; 16 | import java.util.Arrays; 17 | 18 | @Component 19 | @Aspect 20 | @Slf4j 21 | public class ControllerLoggingAspect extends AbstractAspect { 22 | 23 | @Pointcut("bean(*Controller) && inProjectPoint()") 24 | void inAnyControllerPoint() { 25 | } 26 | 27 | @Pointcut ("inAnyControllerPoint() && anyPublicOperation()") 28 | void publicControllerOperation (){ 29 | } 30 | 31 | @Pointcut ("@annotation(org.springframework.web.bind.annotation.PostMapping)") 32 | void anyPostOperation (){ 33 | } 34 | 35 | @Pointcut ("@annotation(org.springframework.web.bind.annotation.GetMapping)") 36 | void anyGetOperation (){ 37 | } 38 | 39 | @Pointcut ("@annotation(org.springframework.web.bind.annotation.DeleteMapping)") 40 | void anyDeleteOperation (){ 41 | } 42 | 43 | @Pointcut ("@annotation(org.springframework.web.bind.annotation.PutMapping)") 44 | void anyPutOperation (){ 45 | } 46 | @Pointcut ("@annotation(org.springframework.web.bind.annotation.PatchMapping)") 47 | void anyPatchOperation (){ 48 | } 49 | 50 | 51 | /** 52 | * @deprecated beware that using this method in production might potentially lead to security risks because the passed 53 | * object is logged before being validated. 54 | * */ 55 | @Before("publicControllerOperation() && (anyPostOperation() || anyPutOperation() || anyPatchOperation() || anyDeleteOperation())") 56 | void logBeforePost(JoinPoint joinPoint){ 57 | String methodName = joinPoint.getSignature().getName(); 58 | String args = Arrays.toString(joinPoint.getArgs()); 59 | log.info(LoggingConstants.CALLED_WITH_ARGS, methodName, args); 60 | } 61 | 62 | @Before("publicControllerOperation() && anyGetOperation()") 63 | void logBeforeGet(JoinPoint joinPoint){ 64 | String methodName = joinPoint.getSignature().getName(); 65 | String args = Arrays.toString(joinPoint.getArgs()); 66 | log.trace(LoggingConstants.CALLED_WITH_ARGS, methodName, args); 67 | } 68 | @AfterReturning (value = "publicControllerOperation()", returning = "retVal") 69 | void logAfterReturning(JoinPoint joinPoint, ResponseEntity retVal){ 70 | String methodName = joinPoint.getSignature().getName(); 71 | log.trace(LoggingConstants.SUCCESS_AND_RETURN, methodName, retVal.getBody()); 72 | } 73 | 74 | 75 | } 76 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/logging/DataAccessLoggingAspect.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.logging; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.aspectj.lang.annotation.Aspect; 5 | import org.aspectj.lang.annotation.Pointcut; 6 | import org.springframework.stereotype.Component; 7 | 8 | @Component 9 | @Aspect 10 | @Slf4j 11 | public class DataAccessLoggingAspect extends AbstractAspect{ 12 | 13 | @Pointcut("bean(*Repository) && inProjectPoint()") 14 | void inAnyRepositoryPoint() { 15 | } 16 | @Pointcut ("inAnyRepositoryPoint() && anyPublicOperation()") 17 | void publicServiceOperation (){ 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/logging/ServiceLoggingAspect.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.logging; 2 | 3 | import com.amigoscode.chohort2.carRental.constants.LoggingConstants; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.aspectj.lang.JoinPoint; 6 | import org.aspectj.lang.annotation.Aspect; 7 | import org.aspectj.lang.annotation.Before; 8 | import org.aspectj.lang.annotation.Pointcut; 9 | import org.springframework.stereotype.Component; 10 | 11 | import java.io.Serializable; 12 | import java.util.Arrays; 13 | 14 | @Component 15 | @Aspect 16 | @Slf4j 17 | public class ServiceLoggingAspect extends AbstractAspect{ 18 | @Pointcut("bean(*Service) && inProjectPoint()") 19 | void inAnyServicePoint() { 20 | } 21 | 22 | @Pointcut ("inAnyServicePoint() && anyPublicOperation()") 23 | void publicServiceOperation (){ 24 | } 25 | 26 | @Before("publicServiceOperation()") 27 | void logBeforePublicOperations(JoinPoint joinPoint){ 28 | String methodName = joinPoint.getSignature().getName(); 29 | String args = Arrays.toString(joinPoint.getArgs()); 30 | log.trace(LoggingConstants.CALLED_WITH_ARGS, methodName, args); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/lookupCode/LookupCode.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.lookupCode; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | 5 | import jakarta.persistence.*; 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | 9 | import java.io.Serializable; 10 | 11 | @Entity 12 | @Table(name = "lookup_code") 13 | @Setter 14 | @Getter 15 | public class LookupCode implements Serializable { 16 | 17 | 18 | @JsonIgnore 19 | @Id 20 | @GeneratedValue(strategy = GenerationType.IDENTITY) 21 | private Long id; 22 | 23 | @Column(name = "lookup_key", nullable = false) 24 | private String key; 25 | 26 | @Column(name = "code", nullable = false) 27 | private Integer code; 28 | 29 | @Column(name = "name", nullable = false) 30 | private String name; 31 | 32 | 33 | public static LookupCode getDefault() { 34 | LookupCode lookupCode = new LookupCode(); 35 | lookupCode.setKey("default_key"); 36 | lookupCode.setCode(0); 37 | lookupCode.setName("not found"); 38 | 39 | 40 | return lookupCode; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/lookupCode/LookupCodeController.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.lookupCode; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.http.ResponseEntity; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.PathVariable; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | import java.util.List; 11 | 12 | @RestController 13 | @RequiredArgsConstructor 14 | @RequestMapping("/api/lookup-codes") 15 | public class LookupCodeController { 16 | 17 | private final LookupCodeService lookupCodeService; 18 | 19 | @GetMapping("/by-key/{key}") 20 | public ResponseEntity>getAllByKey(@PathVariable String key){ 21 | 22 | return ResponseEntity.ok(lookupCodeService.getAllLookupCodesByKey(key)); 23 | } 24 | 25 | @GetMapping("/by-key-and-code/{key}/{code}") 26 | public ResponseEntitygetByKeyAndCode(@PathVariable String key ,@PathVariable Integer code){ 27 | return ResponseEntity.ok(lookupCodeService.getLookupCodeByKeyAndCode(key,code)); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/lookupCode/LookupCodeDTO.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.lookupCode; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | import lombok.experimental.Accessors; 8 | 9 | @Setter 10 | @Getter 11 | @Accessors(chain = true) 12 | @EqualsAndHashCode 13 | @ToString 14 | public class LookupCodeDTO { 15 | 16 | private String key; 17 | 18 | private Integer code; 19 | 20 | private String name; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/lookupCode/LookupCodeMapper.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.lookupCode; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.EntityMapper; 4 | import org.mapstruct.Mapper; 5 | import org.mapstruct.factory.Mappers; 6 | 7 | @Mapper 8 | public interface LookupCodeMapper extends EntityMapper { 9 | LookupCodeMapper INSTANCE = Mappers.getMapper(LookupCodeMapper.class); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/lookupCode/LookupCodeRepository.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.lookupCode; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import org.springframework.stereotype.Repository; 5 | 6 | import java.util.List; 7 | import java.util.Optional; 8 | 9 | @Repository 10 | public interface LookupCodeRepository extends JpaRepository { 11 | List findAllByKey(String key); 12 | 13 | Optional findByKeyAndCode(String key, Integer code); 14 | } 15 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/lookupCode/LookupCodeService.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.lookupCode; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.stereotype.Service; 5 | 6 | import java.util.List; 7 | 8 | @Service 9 | @RequiredArgsConstructor 10 | public class LookupCodeService { 11 | 12 | private final LookupCodeRepository lookupCodeRepository; 13 | 14 | 15 | public List getAllLookupCodesByKey(String key) { 16 | return lookupCodeRepository.findAllByKey(key); 17 | } 18 | 19 | public List findAllLookupCodes() { 20 | return lookupCodeRepository.findAll(); 21 | } 22 | 23 | public LookupCode getLookupCodeByKeyAndCode(String key, Integer code) { 24 | return lookupCodeRepository 25 | .findByKeyAndCode(key, code) 26 | .orElse(LookupCode.getDefault()); 27 | } 28 | 29 | 30 | } 31 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/lookupCode/LookupCodes.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.lookupCode; 2 | 3 | public interface LookupCodes { 4 | 5 | 6 | interface UserType { 7 | String KEY = "user_type"; 8 | Integer admin = 1; 9 | Integer carProvider = 2; 10 | Integer client = 3; 11 | 12 | } 13 | 14 | interface UserStatus { 15 | String KEY = "user_status"; 16 | Integer active = 1; 17 | Integer inactive = 2; 18 | Integer blocked = 3; 19 | 20 | 21 | } 22 | 23 | interface CarCategory { 24 | String KEY = "car_category"; 25 | 26 | Integer luxury = 1; 27 | 28 | Integer economy = 2; 29 | } 30 | 31 | interface CarBookingStatus { 32 | 33 | String KEY = "car_booking_status"; 34 | 35 | Integer available = 1; 36 | Integer inUse = 2; 37 | } 38 | 39 | interface MediumCode { 40 | String KEY = "medium_code"; 41 | Integer portal = 1; 42 | Integer email = 2; 43 | Integer sms = 3; 44 | } 45 | interface UserBookingStatus { 46 | String KEY = "user_booking_status"; 47 | Integer inUse = 1; 48 | Integer returned = 2; 49 | 50 | } 51 | 52 | 53 | } 54 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/registration/RegistrationController.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.registration; 2 | 3 | import com.amigoscode.chohort2.carRental.registration.VM.CarProviderRegistrationVM; 4 | import com.amigoscode.chohort2.carRental.registration.VM.ClientRegistrationVM; 5 | import jakarta.validation.Valid; 6 | import lombok.RequiredArgsConstructor; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.http.HttpStatus; 10 | import org.springframework.http.ResponseEntity; 11 | import org.springframework.web.bind.annotation.*; 12 | 13 | @RequiredArgsConstructor 14 | @RestController 15 | @RequestMapping("api/v1/registrations") 16 | public class RegistrationController { 17 | 18 | private final Logger log = LoggerFactory.getLogger(RegistrationController.class); 19 | 20 | private final RegistrationService registrationService; 21 | 22 | @PostMapping("clients") 23 | public ResponseEntity clientRegistration(@RequestBody @Valid ClientRegistrationVM clientRegistrationVM) { 24 | 25 | log.info("user registration info {}", clientRegistrationVM); 26 | 27 | registrationService.registration(clientRegistrationVM); 28 | 29 | return ResponseEntity.status(HttpStatus.CREATED).build(); 30 | } 31 | 32 | @PostMapping("car-providers") 33 | public ResponseEntity carProviderRegistration(@RequestBody @Valid CarProviderRegistrationVM carProviderRegistrationVM) { 34 | 35 | log.info("car provider user registration info {}", carProviderRegistrationVM); 36 | 37 | registrationService.registration(carProviderRegistrationVM); 38 | 39 | return ResponseEntity.status(HttpStatus.CREATED).build(); 40 | } 41 | 42 | 43 | } 44 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/registration/VM/CarProviderRegistrationVM.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.registration.VM; 2 | 3 | 4 | import com.amigoscode.chohort2.carRental.carProvider.VM.CarProviderVM; 5 | import jakarta.validation.constraints.NotNull; 6 | import lombok.*; 7 | 8 | 9 | @Setter 10 | @Getter 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | @ToString (callSuper = true) 14 | public class CarProviderRegistrationVM extends UserRegistrationVM { 15 | 16 | 17 | 18 | @NotNull 19 | @ToString.Exclude 20 | private CarProviderVM carProviderVM; 21 | 22 | 23 | 24 | } 25 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/registration/VM/ClientRegistrationVM.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.registration.VM; 2 | 3 | 4 | import com.amigoscode.chohort2.carRental.driverLicense.VM.DriverLicenseVM; 5 | import jakarta.validation.constraints.NotNull; 6 | import lombok.*; 7 | import lombok.experimental.Accessors; 8 | 9 | 10 | 11 | @Setter 12 | @Getter 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | @ToString(callSuper = true) 16 | @Accessors(chain = true) 17 | public class ClientRegistrationVM extends UserRegistrationVM { 18 | 19 | 20 | 21 | @NotNull 22 | private DriverLicenseVM driverLicense; 23 | 24 | 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/registration/VM/UserRegistrationVM.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.registration.VM; 2 | 3 | 4 | import com.amigoscode.chohort2.carRental.security.SecurityUtils; 5 | import com.amigoscode.chohort2.carRental.user.User; 6 | import jakarta.validation.constraints.NotEmpty; 7 | import lombok.*; 8 | import lombok.experimental.Accessors; 9 | 10 | import java.io.Serializable; 11 | 12 | @Setter 13 | @Getter 14 | @Accessors(chain = true) 15 | @ToString 16 | public class UserRegistrationVM implements Serializable { 17 | 18 | @NotEmpty 19 | protected String username; 20 | 21 | @NotEmpty 22 | protected String firstName; 23 | 24 | @NotEmpty 25 | protected String lastName; 26 | 27 | @NotEmpty 28 | protected String email; 29 | 30 | @NotEmpty 31 | protected String nin; 32 | 33 | @NotEmpty 34 | protected String password; 35 | @ToString.Include 36 | private String password(){ 37 | return SecurityUtils.obfuscateString(password); 38 | } 39 | @ToString.Include 40 | private String email(){ 41 | return SecurityUtils.maskEmail(email); 42 | } 43 | 44 | 45 | public static User vmToEntity(UserRegistrationVM userRegistrationVM){ 46 | return new User() 47 | .setUsername(userRegistrationVM.username) 48 | .setFirstName(userRegistrationVM.firstName) 49 | .setLastName(userRegistrationVM.lastName) 50 | .setEmail(userRegistrationVM.email) 51 | .setNin(userRegistrationVM.nin); 52 | } 53 | 54 | 55 | } 56 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/security/CorsConfig.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.security; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.web.cors.CorsConfiguration; 7 | import org.springframework.web.cors.CorsConfigurationSource; 8 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource; 9 | 10 | import java.util.List; 11 | 12 | @Configuration 13 | public class CorsConfig { 14 | 15 | @Value("#{'${cors.allowed-origins}'.split(',')}") 16 | private List allowedOrigins; 17 | 18 | @Value("#{'${cors.allowed-methods}'.split(',')}") 19 | private List allowedMethods; 20 | 21 | @Value("#{'${cors.allowed-headers}'.split(',')}") 22 | private List allowedHeaders; 23 | 24 | @Value("#{'${cors.exposed-headers}'.split(',')}") 25 | private List expectedHeaders; 26 | 27 | @Bean 28 | public CorsConfigurationSource corsConfigurationSource() { 29 | CorsConfiguration configuration = new CorsConfiguration(); 30 | configuration.setAllowedOrigins(allowedOrigins); 31 | configuration.setAllowedMethods(allowedMethods); 32 | configuration.setAllowedHeaders(allowedHeaders); 33 | configuration.setExposedHeaders(expectedHeaders); 34 | UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 35 | source.registerCorsConfiguration("/api/**", configuration); 36 | return source; 37 | } 38 | } -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/security/PasswordEncoderConfig.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.security; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 6 | import org.springframework.security.crypto.password.PasswordEncoder; 7 | 8 | @Configuration 9 | public class PasswordEncoderConfig { 10 | 11 | @Bean 12 | public PasswordEncoder passwordEncoder(){ 13 | return new BCryptPasswordEncoder(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/security/SecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.security; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.authentication.AuthenticationManager; 6 | import org.springframework.security.authentication.AuthenticationProvider; 7 | import org.springframework.security.authentication.dao.DaoAuthenticationProvider; 8 | import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; 9 | import org.springframework.security.core.userdetails.UserDetailsService; 10 | import org.springframework.security.crypto.password.PasswordEncoder; 11 | 12 | 13 | @Configuration 14 | public class SecurityConfig { 15 | 16 | @Bean 17 | public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) 18 | throws Exception { 19 | return configuration.getAuthenticationManager(); 20 | } 21 | 22 | @Bean 23 | public AuthenticationProvider authenticationProvider(UserDetailsService userDetailsService, 24 | PasswordEncoder passwordEncoder){ 25 | 26 | DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(); 27 | daoAuthenticationProvider.setPasswordEncoder(passwordEncoder); 28 | daoAuthenticationProvider.setUserDetailsService(userDetailsService); 29 | return daoAuthenticationProvider; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/security/SecurityFilterChainConfig.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.security; 2 | 3 | 4 | import com.amigoscode.chohort2.carRental.security.jwt.JWTAuthFilter; 5 | import lombok.RequiredArgsConstructor; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.security.authentication.AuthenticationProvider; 9 | import org.springframework.security.config.Customizer; 10 | import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; 11 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 12 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 13 | import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; 14 | import org.springframework.security.config.http.SessionCreationPolicy; 15 | import org.springframework.security.web.SecurityFilterChain; 16 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 17 | 18 | 19 | @Configuration 20 | @EnableWebSecurity 21 | @EnableMethodSecurity( securedEnabled = true) 22 | @RequiredArgsConstructor 23 | public class SecurityFilterChainConfig { 24 | 25 | private final AuthenticationProvider authenticationProvider; 26 | private final JWTAuthFilter jwtAuthFilter; 27 | 28 | // private final AuthenticationEntryPoint authenticationEntryPoint; 29 | 30 | 31 | @Bean 32 | public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { 33 | return http 34 | .csrf(AbstractHttpConfigurer::disable) 35 | .cors(Customizer.withDefaults()) 36 | .authorizeHttpRequests(requestMatcherRegistry -> 37 | requestMatcherRegistry 38 | .requestMatchers("/api/v1/auth/**") 39 | .permitAll() 40 | .requestMatchers("/api/v1/registrations/**") 41 | .permitAll() 42 | .anyRequest() 43 | .authenticated() 44 | ) 45 | .sessionManagement(sessionConfigurer -> sessionConfigurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) 46 | .authenticationProvider(authenticationProvider) 47 | .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class) 48 | .build(); 49 | 50 | 51 | } 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/security/UserDetailsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.security; 2 | 3 | 4 | import com.amigoscode.chohort2.carRental.annotation.TransactionalService; 5 | import com.amigoscode.chohort2.carRental.user.User; 6 | import com.amigoscode.chohort2.carRental.user.UserRepository; 7 | import lombok.RequiredArgsConstructor; 8 | import org.springframework.security.core.GrantedAuthority; 9 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 10 | import org.springframework.security.core.userdetails.UserDetails; 11 | import org.springframework.security.core.userdetails.UserDetailsService; 12 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 13 | 14 | import java.util.Collection; 15 | 16 | 17 | @TransactionalService 18 | @RequiredArgsConstructor 19 | public class UserDetailsServiceImpl implements UserDetailsService { 20 | 21 | private final UserRepository userRepository; 22 | 23 | 24 | 25 | @Override 26 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 27 | User user = this.userRepository.findByUsernameWithAuthorities(username) 28 | .orElseThrow(() -> new UsernameNotFoundException("username is not found")); 29 | 30 | Collection authorities = user.getAuthorities() 31 | .stream() 32 | .map(auth ->new SimpleGrantedAuthority(auth.getName())) 33 | .toList(); 34 | 35 | return new org.springframework. 36 | security.core.userdetails.User(user.getUsername(), user.getPassword(), authorities); 37 | 38 | 39 | } 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/security/jwt/JWTAuthFilter.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.security.jwt; 2 | 3 | import jakarta.servlet.FilterChain; 4 | import jakarta.servlet.ServletException; 5 | import jakarta.servlet.http.HttpServletRequest; 6 | import jakarta.servlet.http.HttpServletResponse; 7 | import org.apache.commons.lang3.StringUtils; 8 | import org.springframework.http.HttpHeaders; 9 | import org.springframework.lang.NonNull; 10 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 11 | import org.springframework.security.core.context.SecurityContextHolder; 12 | import org.springframework.security.core.userdetails.UserDetails; 13 | import org.springframework.security.core.userdetails.UserDetailsService; 14 | import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; 15 | import org.springframework.stereotype.Component; 16 | import org.springframework.web.filter.OncePerRequestFilter; 17 | 18 | import java.io.IOException; 19 | 20 | @Component 21 | public class JWTAuthFilter extends OncePerRequestFilter { 22 | 23 | private final JWTUtil jwtUtil; 24 | 25 | private final UserDetailsService userDetailsService; 26 | 27 | public JWTAuthFilter(JWTUtil jwtUtil, UserDetailsService userDetailsService) { 28 | this.jwtUtil = jwtUtil; 29 | this.userDetailsService = userDetailsService; 30 | } 31 | 32 | @Override 33 | protected void doFilterInternal(@NonNull HttpServletRequest request, 34 | @NonNull HttpServletResponse response, 35 | @NonNull FilterChain filterChain) throws ServletException, IOException { 36 | 37 | String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION); 38 | String bearer = "Bearer "; 39 | if (StringUtils.isBlank(authHeader) || !authHeader.startsWith(bearer)) { 40 | filterChain.doFilter(request, response); 41 | return; 42 | } 43 | 44 | String jwt = authHeader.substring(bearer.length()); 45 | 46 | String subject = jwtUtil.getSubject(jwt); 47 | 48 | if (StringUtils.isBlank(subject)) { 49 | filterChain.doFilter(request, response); 50 | return; 51 | } 52 | 53 | if (SecurityContextHolder.getContext().getAuthentication() == null) { 54 | UserDetails userDetails = userDetailsService.loadUserByUsername(subject); 55 | if (!jwtUtil.isTokenValid(jwt, userDetails.getUsername())) { 56 | filterChain.doFilter(request, response); 57 | return; 58 | } 59 | UsernamePasswordAuthenticationToken authenticationToken = 60 | new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); 61 | 62 | authenticationToken.setDetails( 63 | new WebAuthenticationDetailsSource() 64 | .buildDetails(request) 65 | ); 66 | 67 | SecurityContextHolder.getContext().setAuthentication(authenticationToken); 68 | 69 | } 70 | 71 | 72 | filterChain.doFilter(request, response); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/security/jwt/JWTUtil.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.security.jwt; 2 | 3 | import io.jsonwebtoken.Claims; 4 | import io.jsonwebtoken.Jwts; 5 | import io.jsonwebtoken.SignatureAlgorithm; 6 | import io.jsonwebtoken.security.Keys; 7 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 8 | import org.springframework.stereotype.Service; 9 | 10 | import java.security.Key; 11 | import java.time.Instant; 12 | import java.time.temporal.ChronoUnit; 13 | import java.util.Date; 14 | import java.util.List; 15 | import java.util.Map; 16 | 17 | @Service 18 | public class JWTUtil { 19 | 20 | private static final String SECRET_KEY = 21 | "foobar_123456789_foobar_123456789_foobar_123456789_foobar_123456789_foobar_123456789_foobar_123456789"; 22 | 23 | 24 | public String issueToken(String subject, List authorities) { 25 | 26 | return issueToken(subject, Map.of("authorities", authorities)); 27 | } 28 | 29 | public String issueToken(String subject, 30 | Map claims) { 31 | 32 | 33 | return Jwts 34 | .builder() 35 | .setClaims(claims) 36 | .setSubject(subject) 37 | .setIssuer("https://car-rental.com") 38 | .setIssuedAt(Date.from(Instant.now())) 39 | .setExpiration(Date.from(Instant.now().plus(15, ChronoUnit.DAYS))) 40 | .signWith(getSigninKey(), SignatureAlgorithm.HS256) 41 | .compact(); 42 | } 43 | 44 | public String getSubject(String token) { 45 | 46 | return getClaims(token).getSubject(); 47 | } 48 | 49 | private Claims getClaims(String token) { 50 | return Jwts.parserBuilder() 51 | .setSigningKey(getSigninKey()) 52 | .build() 53 | .parseClaimsJws(token) 54 | .getBody(); 55 | 56 | } 57 | 58 | private Key getSigninKey() { 59 | return Keys.hmacShaKeyFor(SECRET_KEY.getBytes()); 60 | } 61 | 62 | public boolean isTokenValid(String jwt, String username) { 63 | return getSubject(jwt).equals(username) && !isTokenExpired(jwt); 64 | } 65 | 66 | private boolean isTokenExpired(String jwt) { 67 | 68 | return getClaims(jwt).getExpiration().before(Date.from(Instant.now())); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/user/User.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.user; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.AbstractAuditingEntity; 4 | import com.amigoscode.chohort2.carRental.authority.Authority; 5 | import com.amigoscode.chohort2.carRental.lookupCode.LookupCode; 6 | import com.amigoscode.chohort2.carRental.lookupCode.LookupCodes; 7 | import jakarta.persistence.*; 8 | import lombok.AllArgsConstructor; 9 | import lombok.Getter; 10 | import lombok.NoArgsConstructor; 11 | import lombok.Setter; 12 | import lombok.experimental.Accessors; 13 | import org.hibernate.annotations.JoinColumnOrFormula; 14 | import org.hibernate.annotations.JoinColumnsOrFormulas; 15 | import org.hibernate.annotations.JoinFormula; 16 | import org.hibernate.annotations.Where; 17 | 18 | import java.util.HashSet; 19 | import java.util.Set; 20 | 21 | @Entity 22 | @Table(name = "cr_user") 23 | @Setter 24 | @Getter 25 | @AllArgsConstructor 26 | @NoArgsConstructor 27 | @Accessors(chain = true) 28 | @Where(clause = "is_deleted = false") 29 | public class User extends AbstractAuditingEntity { 30 | 31 | @Id 32 | @GeneratedValue(strategy = GenerationType.IDENTITY) 33 | private Long id; 34 | 35 | @Column(name = "username", nullable = false, unique = true,length = 50) 36 | private String username; 37 | 38 | @Column(name = "first_name", nullable = false,length = 50) 39 | private String firstName; 40 | 41 | @Column(name = "last_name", nullable = false,length = 50) 42 | private String lastName; 43 | 44 | @Column(name = "email", nullable = false,unique = true) 45 | private String email; 46 | 47 | @Column(name = "nin", nullable = false,unique = true) 48 | private String nin; 49 | 50 | @Column(name = "password", nullable = false) 51 | private String password; 52 | 53 | @Column(name = "type_code",nullable = false) 54 | private Integer typeCode; 55 | 56 | @JoinColumnsOrFormulas({ 57 | @JoinColumnOrFormula(formula = @JoinFormula(value = "'"+ LookupCodes.UserType.KEY +"'", referencedColumnName = "lookup_key")), 58 | @JoinColumnOrFormula(column = @JoinColumn(name = "type_code", referencedColumnName = "code", insertable = false, updatable = false)) 59 | }) 60 | @OneToOne 61 | private LookupCode type; 62 | 63 | @Column(name = "status_code",nullable = false) 64 | private Integer statusCode; 65 | 66 | @JoinColumnsOrFormulas({ 67 | @JoinColumnOrFormula(formula = @JoinFormula(value = "'"+ LookupCodes.UserStatus.KEY +"'", referencedColumnName = "lookup_key")), 68 | @JoinColumnOrFormula(column = @JoinColumn(name = "type_code", referencedColumnName = "code", insertable = false, updatable = false)) 69 | }) 70 | @OneToOne 71 | private LookupCode status; 72 | 73 | 74 | @ManyToMany(fetch = FetchType.LAZY) 75 | @JoinTable(name = "user_authority", 76 | joinColumns = {@JoinColumn(name = "user_id")}, 77 | inverseJoinColumns = {@JoinColumn(name = "authority_name")} 78 | 79 | ) 80 | private Set authorities = new HashSet<>(); 81 | 82 | 83 | public User addAuthority(Authority authority){ 84 | if (this.authorities == null) { 85 | this.authorities = new HashSet<>(); 86 | } 87 | 88 | this.authorities.add(authority); 89 | 90 | return this; 91 | } 92 | 93 | 94 | } 95 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/user/UserController.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.user; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | @RestController 8 | @RequestMapping("api/v1/users") 9 | @RequiredArgsConstructor 10 | public class UserController { 11 | 12 | private final UserService userService; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/user/UserDTO.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.user; 2 | 3 | import com.amigoscode.chohort2.carRental.lookupCode.LookupCodeDTO; 4 | import com.amigoscode.chohort2.carRental.security.SecurityUtils; 5 | import lombok.EqualsAndHashCode; 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | import lombok.ToString; 9 | import lombok.experimental.Accessors; 10 | 11 | @Setter 12 | @Getter 13 | @Accessors(chain = true) 14 | @ToString 15 | @EqualsAndHashCode 16 | public class UserDTO { 17 | 18 | private Long id; 19 | 20 | private String username; 21 | 22 | private String firstName; 23 | 24 | private String lastName; 25 | 26 | private String email; 27 | 28 | private String nin; 29 | 30 | private Integer typeCode; 31 | 32 | private LookupCodeDTO type; 33 | 34 | private Integer statusCode; 35 | 36 | private LookupCodeDTO status; 37 | @ToString.Include 38 | private String email(){ 39 | return SecurityUtils.maskEmail(email); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/user/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.user; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.EntityMapper; 4 | import com.amigoscode.chohort2.carRental.lookupCode.LookupCodeMapper; 5 | import org.mapstruct.Mapper; 6 | import org.mapstruct.factory.Mappers; 7 | 8 | @Mapper(uses = {LookupCodeMapper.class}) 9 | public interface UserMapper extends EntityMapper { 10 | UserMapper INSTANCE = Mappers.getMapper(UserMapper.class); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/user/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.user; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.repository.CRJpaRepository; 4 | import org.springframework.data.jpa.repository.Query; 5 | import org.springframework.data.repository.query.Param; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import java.util.Optional; 9 | 10 | @Repository 11 | public interface UserRepository extends CRJpaRepository { 12 | @Query("select u from User u join FETCH u.authorities where u.username=:username") 13 | Optional findByUsernameWithAuthorities(@Param("username") String username); 14 | } 15 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/user/UserService.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.user; 2 | 3 | import com.amigoscode.chohort2.carRental.annotation.TransactionalService; 4 | import com.amigoscode.chohort2.carRental.constants.ErrorConstants; 5 | import com.amigoscode.chohort2.carRental.exception.ApiRequestException; 6 | import com.amigoscode.chohort2.carRental.security.SecurityUtils; 7 | import lombok.RequiredArgsConstructor; 8 | 9 | @TransactionalService 10 | @RequiredArgsConstructor 11 | public class UserService { 12 | 13 | private final UserRepository userRepository; 14 | 15 | public User save(User user) { 16 | return userRepository.save(user); 17 | } 18 | 19 | public User getLoggedInUser() { 20 | String username = SecurityUtils.getCurrentUsername(); 21 | return userRepository.findByUsernameWithAuthorities(username).orElseThrow(() -> new ApiRequestException(ErrorConstants.USER_NOT_FOUND)); 22 | } 23 | 24 | 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/userAddress/UserAddress.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.userAddress; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.AbstractAddress; 4 | import com.amigoscode.chohort2.carRental.city.City; 5 | import jakarta.persistence.*; 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | import lombok.experimental.Accessors; 9 | import org.hibernate.annotations.Where; 10 | 11 | @Entity 12 | @Setter 13 | @Getter 14 | @Accessors(chain = true) 15 | @Where(clause = "is_deleted = false") 16 | public class UserAddress extends AbstractAddress { 17 | 18 | @Id 19 | @GeneratedValue(strategy = GenerationType.IDENTITY) 20 | private Long id; 21 | 22 | @ManyToOne(fetch = FetchType.LAZY) 23 | @JoinColumn(name = "city_id",insertable = false,updatable = false) 24 | private City city; 25 | 26 | 27 | @Column(name = "user_id", nullable = false) 28 | private Long userId; 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/userAddress/UserAddressController.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.userAddress; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | @RestController 8 | @RequestMapping("api/v1/user-addresses") 9 | @RequiredArgsConstructor 10 | public class UserAddressController { 11 | } 12 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/userAddress/UserAddressDTO.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.userAddress; 2 | 3 | 4 | import lombok.EqualsAndHashCode; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | import lombok.ToString; 8 | import lombok.experimental.Accessors; 9 | 10 | @Setter 11 | @Getter 12 | @Accessors(chain = true) 13 | @ToString 14 | @EqualsAndHashCode 15 | public class UserAddressDTO { 16 | 17 | private Long id; 18 | 19 | private Long userId; 20 | 21 | private Long cityId; 22 | 23 | 24 | private String location; 25 | 26 | 27 | private String postalCode; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/userAddress/UserAddressMapper.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.userAddress; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.EntityMapper; 4 | import org.mapstruct.Mapper; 5 | import org.mapstruct.factory.Mappers; 6 | 7 | @Mapper 8 | public interface UserAddressMapper extends EntityMapper { 9 | 10 | UserAddressMapper INSTANCE = Mappers.getMapper(UserAddressMapper.class); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/userAddress/UserAddressRepository.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.userAddress; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.repository.CRJpaRepository; 4 | import org.springframework.stereotype.Repository; 5 | 6 | 7 | @Repository 8 | public interface UserAddressRepository extends CRJpaRepository { 9 | } 10 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/userAddress/UserAddressServices.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.userAddress; 2 | 3 | import com.amigoscode.chohort2.carRental.annotation.TransactionalService; 4 | import lombok.RequiredArgsConstructor; 5 | 6 | @TransactionalService 7 | @RequiredArgsConstructor 8 | public class UserAddressServices { 9 | 10 | private final UserAddressRepository userAddressRepository; 11 | } 12 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/userNotification/UserNotification.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.userNotification; 2 | 3 | import com.amigoscode.chohort2.carRental.lookupCode.LookupCode; 4 | import com.amigoscode.chohort2.carRental.lookupCode.LookupCodes; 5 | import com.amigoscode.chohort2.carRental.user.User; 6 | import jakarta.persistence.*; 7 | import lombok.AllArgsConstructor; 8 | import lombok.Getter; 9 | import lombok.NoArgsConstructor; 10 | import lombok.Setter; 11 | import lombok.experimental.Accessors; 12 | import org.hibernate.annotations.JoinColumnOrFormula; 13 | import org.hibernate.annotations.JoinColumnsOrFormulas; 14 | import org.hibernate.annotations.JoinFormula; 15 | import java.time.LocalDateTime; 16 | 17 | @Entity 18 | @Table(name = "user_notification") 19 | @Setter 20 | @Getter 21 | @AllArgsConstructor 22 | @NoArgsConstructor 23 | @Accessors(chain = true) 24 | public class UserNotification { 25 | 26 | @Id 27 | @GeneratedValue (strategy = GenerationType.IDENTITY) 28 | private Long id; 29 | 30 | @Column (name = "user_id", nullable = false) 31 | private Long userId; 32 | 33 | @ManyToOne (fetch = FetchType.LAZY) 34 | @JoinColumn (name = "user_id", updatable = false, insertable = false) 35 | private User user; 36 | 37 | @Column (name = "message", nullable = false) 38 | private String message; 39 | 40 | @Column (name = "medium_code", nullable = false) 41 | private Integer mediumCode; 42 | 43 | @JoinColumnsOrFormulas({ 44 | @JoinColumnOrFormula(formula = @JoinFormula(value = "'"+ LookupCodes.MediumCode.KEY +"'", referencedColumnName = "lookup_key")), 45 | @JoinColumnOrFormula(column = @JoinColumn(name = "medium_code", referencedColumnName = "code", insertable = false, updatable = false)) 46 | }) 47 | @OneToOne 48 | private LookupCode medium; 49 | 50 | @Column (name = "is_sent", nullable = false) 51 | private Boolean isSent; 52 | 53 | @Column (name = "sent_date") 54 | private LocalDateTime sentDate; 55 | 56 | } 57 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/userNotification/UserNotificationController.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.userNotification; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | @RestController 8 | @RequestMapping(value = "api/v1/user-notifications") 9 | @RequiredArgsConstructor 10 | public class UserNotificationController { 11 | 12 | private final UserNotificationService userNotificationService; 13 | } 14 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/userNotification/UserNotificationDTO.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.userNotification; 2 | 3 | import com.amigoscode.chohort2.carRental.lookupCode.LookupCodeDTO; 4 | import com.amigoscode.chohort2.carRental.user.UserDTO; 5 | import lombok.EqualsAndHashCode; 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | import lombok.ToString; 9 | import lombok.experimental.Accessors; 10 | 11 | import java.io.Serializable; 12 | import java.time.LocalDate; 13 | import java.time.LocalDateTime; 14 | 15 | /** 16 | * DTO for {@link UserNotification} 17 | */ 18 | @Getter 19 | @Setter 20 | @Accessors(chain = true) 21 | @ToString 22 | @EqualsAndHashCode 23 | public class UserNotificationDTO implements Serializable { 24 | private Long id; 25 | private Long userId; 26 | // private UserDTO user; 27 | private String message; 28 | private Integer mediumCode; 29 | private LookupCodeDTO medium; 30 | private Boolean isSent; 31 | private LocalDateTime sentDate; 32 | } -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/userNotification/UserNotificationMapper.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.userNotification; 2 | 3 | import com.amigoscode.chohort2.carRental.abstracts.EntityMapper; 4 | import com.amigoscode.chohort2.carRental.car.CarMapper; 5 | import com.amigoscode.chohort2.carRental.lookupCode.LookupCodeMapper; 6 | import org.mapstruct.Mapper; 7 | import org.mapstruct.factory.Mappers; 8 | 9 | @Mapper(uses = {LookupCodeMapper.class}) 10 | public interface UserNotificationMapper extends EntityMapper { 11 | UserNotificationMapper INSTANCE = Mappers.getMapper(UserNotificationMapper.class); 12 | } 13 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/userNotification/UserNotificationRepository.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.userNotification; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import org.springframework.stereotype.Repository; 5 | 6 | @Repository 7 | public interface UserNotificationRepository extends JpaRepository { 8 | } 9 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/userNotification/UserNotificationService.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.userNotification; 2 | 3 | import com.amigoscode.chohort2.carRental.annotation.TransactionalService; 4 | import lombok.RequiredArgsConstructor; 5 | 6 | @RequiredArgsConstructor 7 | @TransactionalService 8 | public class UserNotificationService { 9 | 10 | private final UserNotificationRepository userNotificationRepository; 11 | } 12 | -------------------------------------------------------------------------------- /carRental/src/main/java/com/amigoscode/chohort2/carRental/validation/Validator.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.validation; 2 | 3 | import com.amigoscode.chohort2.carRental.exception.ApiRequestException; 4 | 5 | import java.util.function.Supplier; 6 | 7 | public abstract class Validator { 8 | 9 | public static void invalidateIfTrue(Supplier supplier, String message) { 10 | invalidateIfTrue(supplier, null,message); 11 | } 12 | public static void invalidateIfFalse(Supplier supplier, String message) { 13 | invalidateIfFalse(supplier, null,message); 14 | } 15 | 16 | public static void invalidateIfTrue(Supplier supplier, String errorKey, String message, Object... args) { 17 | if (supplier.get()) { 18 | throw new ApiRequestException(message, errorKey) 19 | .messageArgs(args); 20 | } 21 | } 22 | 23 | public static void invalidateIfFalse(Supplier supplier, String errorKey, String message, Object... args) { 24 | if (!supplier.get()) { 25 | throw new ApiRequestException(message, errorKey) 26 | .messageArgs(args); 27 | } 28 | } 29 | 30 | public static void invalidateIfTrue(Supplier supplier, ApiRequestException e) { 31 | if (supplier.get()) { 32 | throw e; 33 | } 34 | } 35 | 36 | public static void invalidateIfFalse(Supplier supplier, ApiRequestException e) { 37 | if (!supplier.get()) { 38 | throw e; 39 | } 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /carRental/src/main/resources/application-dev.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: '@app.name@' 4 | datasource: 5 | url: jdbc:postgresql://localhost:5432/postgres 6 | username: postgres 7 | password: 123 8 | jpa: 9 | show-sql: true 10 | open-in-view: false 11 | hibernate: 12 | ddl-auto: none 13 | properties: 14 | hibernate: 15 | dialect: org.hibernate.dialect.PostgreSQLDialect 16 | format_sql: true 17 | liquibase: 18 | change-log: classpath:db/changelog/master.xml 19 | jackson: 20 | mapper: 21 | accept-case-insensitive-properties: true 22 | deserialization: 23 | fail-on-unknown-properties: false 24 | fail-on-ignored-properties: false 25 | date-format: yyyy-MM-dd HH:mm:ss 26 | 27 | 28 | logging: 29 | level: 30 | root: info 31 | org: 32 | springframework: info 33 | com: 34 | amigoscode: 35 | chohort2: 36 | carRental: debug 37 | 38 | 39 | cors: 40 | allowed-origins: "*" 41 | allowed-methods: "*" 42 | allowed-headers: "*" 43 | exposed-headers: "*" 44 | -------------------------------------------------------------------------------- /carRental/src/main/resources/application-prod.yml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /carRental/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: '@app.name@' 4 | datasource: 5 | url: jdbc:postgresql://localhost:5432/postgres 6 | username: postgres 7 | password: 123 8 | jpa: 9 | show-sql: true 10 | open-in-view: false 11 | hibernate: 12 | ddl-auto: none 13 | properties: 14 | hibernate: 15 | dialect: org.hibernate.dialect.PostgreSQLDialect 16 | format_sql: true 17 | liquibase: 18 | change-log: classpath:db/changelog/master.xml 19 | jackson: 20 | mapper: 21 | accept-case-insensitive-properties: true 22 | deserialization: 23 | fail-on-unknown-properties: false 24 | fail-on-ignored-properties: false 25 | date-format: yyyy-MM-dd HH:mm:ss 26 | 27 | 28 | logging: 29 | level: 30 | root: info 31 | org: 32 | springframework: info 33 | com: 34 | amigoscode: 35 | chohort2: 36 | carRental: debug 37 | 38 | 39 | cors: 40 | allowed-origins: "*" 41 | allowed-methods: "*" 42 | allowed-headers: "*" 43 | exposed-headers: "*" -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306211212._added_entity_LookupCode.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306212059_added_entity_brand.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306212060_added_entity_brand_model.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306212135_added_entity_Car_Provider.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 27 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306221751_added_entity_UserAddress.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306221800_added_constraints_UserAddress.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306222016_added_entity_Driver_License.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306231445_added_fk_car_car_provider.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306231451_added_sequence_brand.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 14 | 15 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306231500_add_fk_brand_model_brand.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306231530_added_fk_constraints_driver_license.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306240441_added_entity_Car_Provider_User.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306240449_added_fk_constraints_car_provider_user.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | 17 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306261435_added_entity_Car_Provider_Coupon.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306261441_added_fk_constraints_car_provider_coupon.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306271523_added_entity_Country.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306271544_added_entity_City.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306271718_added_fk_constraints_city__country_id.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306271755_added_fk_constraints_user_address__city_id.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306271811_added_fk_constraints_car_provider_address.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | 17 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306271820_added_entity_Car_Provider_Address.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306281333_added_entity_Car_User.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306281336_added_fk_constraints_car_user__car_id.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306281347_added_entity_User_Notification.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306281356_added_entity_Car_Booking.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306281358_added_fk_constraints_user_notification.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306281401_added_fk_constraints_car_booking.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202306291216_insert_Authorities.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202307041630_insert_Brands.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/0.0.0.1/202307041635_insert_BrandModels.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /carRental/src/main/resources/db/changelog/dateTimeStamp_Example_entity_EntityName.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /carRental/src/test/java/com/amigoscode/chohort2/carRental/AbstractTestContainer.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental; 2 | 3 | import org.springframework.boot.jdbc.DataSourceBuilder; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | import org.springframework.test.context.ActiveProfiles; 6 | import org.springframework.test.context.DynamicPropertyRegistry; 7 | import org.springframework.test.context.DynamicPropertySource; 8 | import org.springframework.test.context.TestPropertySource; 9 | import org.testcontainers.containers.PostgreSQLContainer; 10 | import org.testcontainers.junit.jupiter.Container; 11 | import org.testcontainers.junit.jupiter.Testcontainers; 12 | 13 | import javax.sql.DataSource; 14 | 15 | @Testcontainers 16 | @ActiveProfiles("test") 17 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 18 | @TestPropertySource(properties = "spring.datasource.url=jdbc:tc:postgresql:latest:///integration-tests-db") 19 | public abstract class AbstractTestContainer { 20 | 21 | // @Container 22 | // protected static final PostgreSQLContainer postgreSQLContainer = 23 | // new PostgreSQLContainer<>("postgres:latest") 24 | // .withDatabaseName("unit-test") 25 | // .withUsername("root") 26 | // .withPassword("123"); 27 | // 28 | // @DynamicPropertySource 29 | // private static void registerDataSourceProperties(DynamicPropertyRegistry registry){ 30 | // 31 | // registry.add("spring.datasource.url", postgreSQLContainer::getJdbcUrl); 32 | // registry.add("spring.datasource.username", postgreSQLContainer::getUsername); 33 | // registry.add("spring.datasource.password", postgreSQLContainer::getPassword); 34 | // } 35 | // 36 | // protected static DataSource getDataSource(){ 37 | // return DataSourceBuilder 38 | // .create() 39 | // .driverClassName(postgreSQLContainer.getDriverClassName()) 40 | // .url(postgreSQLContainer.getJdbcUrl()) 41 | // .username(postgreSQLContainer.getUsername()) 42 | // .password(postgreSQLContainer.getPassword()) 43 | // .build(); 44 | // } 45 | 46 | 47 | } 48 | -------------------------------------------------------------------------------- /carRental/src/test/java/com/amigoscode/chohort2/carRental/auth/AuthControllerIT.java: -------------------------------------------------------------------------------- 1 | package com.amigoscode.chohort2.carRental.auth; 2 | 3 | import com.amigoscode.chohort2.carRental.AbstractTestContainer; 4 | import com.amigoscode.chohort2.carRental.driverLicense.VM.DriverLicenseVM; 5 | import com.amigoscode.chohort2.carRental.registration.RegistrationService; 6 | import com.amigoscode.chohort2.carRental.registration.VM.ClientRegistrationVM; 7 | import org.junit.jupiter.api.BeforeAll; 8 | import org.junit.jupiter.api.Test; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.http.MediaType; 11 | import org.springframework.test.web.reactive.server.WebTestClient; 12 | import reactor.core.publisher.Mono; 13 | 14 | import java.time.LocalDate; 15 | 16 | import static org.assertj.core.api.Assertions.*; 17 | class AuthControllerIT extends AbstractTestContainer { 18 | 19 | @Autowired 20 | private WebTestClient webTestClient; 21 | 22 | @Autowired 23 | private RegistrationService registrationService; 24 | 25 | private static final String API_URL = "api/v1/auth/"; 26 | 27 | 28 | 29 | @Test 30 | void givenLoginInfo_whenPreformLogin_thenReturnJWT() { 31 | // given precondition or setup 32 | ClientRegistrationVM clientRegistrationVM = (ClientRegistrationVM) new ClientRegistrationVM() 33 | .setUsername("esmaeeilll") 34 | .setFirstName("esmaeeil") 35 | .setLastName("enaniii") 36 | .setEmail("enaniii@gmail.com") 37 | .setNin("123456781") 38 | .setPassword("123456789"); 39 | 40 | DriverLicenseVM driverLicenseVM = new DriverLicenseVM() 41 | .setDriverLicenseNumber("123456781") 42 | .setIssuedIn(1L) 43 | .setIssuedAt(LocalDate.now().minusYears(3)) 44 | .setExpiredDate(LocalDate.now().plusYears(3)); 45 | 46 | clientRegistrationVM.setDriverLicense(driverLicenseVM); 47 | registrationService.registration(clientRegistrationVM); 48 | 49 | // when - action or the behaviour that we are going test 50 | String jwt = webTestClient 51 | .post() 52 | .uri(API_URL + "login") 53 | .contentType(MediaType.APPLICATION_JSON) 54 | .accept(MediaType.APPLICATION_JSON) 55 | .body(Mono.just(new LoginVM(clientRegistrationVM.getUsername(),"123456789")), LoginVM.class) 56 | .exchange() 57 | .expectStatus().isOk() 58 | .expectBody(String.class) 59 | .returnResult() 60 | .getResponseBody(); 61 | 62 | 63 | 64 | // then verify the output 65 | assertThat(jwt).isNotBlank(); 66 | 67 | } 68 | 69 | 70 | } -------------------------------------------------------------------------------- /carRental/src/test/resources/application-test.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: '@app.name@' 4 | jpa: 5 | hibernate: 6 | ddl-auto: none 7 | properties: 8 | hibernate: 9 | dialect: org.hibernate.dialect.PostgreSQLDialect 10 | liquibase: 11 | change-log: classpath:db/changelog/master.xml 12 | jackson: 13 | mapper: 14 | accept-case-insensitive-properties: true 15 | deserialization: 16 | fail-on-unknown-properties: false 17 | fail-on-ignored-properties: false 18 | date-format: yyyy-MM-dd HH:mm:ss 19 | 20 | 21 | logging: 22 | level: 23 | root: info 24 | org: 25 | springframework: info 26 | com: 27 | amigoscode: 28 | chohort2: 29 | carRental: debug 30 | -------------------------------------------------------------------------------- /infrastructure/Makefile: -------------------------------------------------------------------------------- 1 | SHELL:=/bin/bash 2 | .ONESHELL: 3 | check-yes: 4 | @echo -n "${DANGER}Are you sure? [y/N] " && read ans && [ $${ans:-N} == y ] 5 | desc-org: 6 | aws organizations describe-organization 7 | list-acc: 8 | aws organizations list-accounts 9 | list-ou: 10 | aws organizations list-organizational-units-for-parent --parent-id $$(cut -c7- <<< $$(aws organizations list-roots | grep "Id: r-")) 11 | untrack-terralock: 12 | find ./ -name $(_EXTENSION) | xargs \; 13 | find ./ -name $(_EXTENSION) -exec git rm --cache --dry-run {} | xargs printf $(_DANGER) \; 14 | make check-yes && find ./ -name $(_EXTENSION) -exec git rm --cache {} \; 15 | 16 | _SUCCESS := "\033[32m[%s]\033[0m %s\n" 17 | SUCCESS := '\033[0;32m' 18 | _DANGER := "\033[31m[%s]\033[0m %s\n" 19 | DANGER := '\033[0;31m' 20 | _EXTENSION := "*.lock.hcl" -------------------------------------------------------------------------------- /infrastructure/modules/aws_budgeting/budget.tf: -------------------------------------------------------------------------------- 1 | resource "aws_budgets_budget" "budget" { 2 | name = var.budget_settings[0].name 3 | budget_type = var.budget_settings[0].budget_type 4 | limit_amount = var.budget_settings[0].limit_amount 5 | limit_unit = var.budget_settings[0].limit_unit 6 | time_unit = var.budget_settings[0].time_unit 7 | 8 | # cost_filter { 9 | # name = "Service" 10 | # values = [ 11 | # "Amazon Elastic Compute Cloud - Compute", 12 | # ] 13 | # } 14 | 15 | notification { 16 | comparison_operator = var.notification[0].comparison_operator 17 | threshold = var.notification[0].threshold 18 | threshold_type = var.notification[0].threshold_type 19 | notification_type = var.notification[0].notification_type 20 | subscriber_email_addresses = var.notification[0].subscriber_email_addresses 21 | } 22 | } -------------------------------------------------------------------------------- /infrastructure/modules/aws_budgeting/variables.tf: -------------------------------------------------------------------------------- 1 | variable "budget_settings" { 2 | type = list (object({ 3 | name = string 4 | budget_type = string 5 | limit_amount = string 6 | limit_unit = string 7 | time_unit = string 8 | })) 9 | default = [ 10 | { 11 | name = "monthly-budget" 12 | budget_type = "COST" 13 | limit_amount = "2" 14 | limit_unit = "USD" 15 | time_unit = "MONTHLY" 16 | } 17 | ] 18 | } 19 | variable "notification" { 20 | type = list (object({ 21 | comparison_operator = string 22 | threshold = number 23 | threshold_type = string 24 | notification_type = string 25 | subscriber_email_addresses = list(string) 26 | })) 27 | default =[ 28 | { 29 | comparison_operator = "GREATER_THAN" 30 | threshold = 100 31 | threshold_type = "PERCENTAGE" 32 | notification_type = "FORECASTED" 33 | subscriber_email_addresses = ["test@example.com"] 34 | } 35 | ] 36 | } -------------------------------------------------------------------------------- /infrastructure/modules/aws_org_ous/outputs.tf: -------------------------------------------------------------------------------- 1 | output "organizational_units" { 2 | value = local.all_ou_attributes 3 | } 4 | 5 | output "accounts" { 6 | value = local.all_account_attributes 7 | } -------------------------------------------------------------------------------- /infrastructure/modules/aws_org_ous/terraform.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13.1" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = ">= 5.5.0" 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /infrastructure/organization/aws-dev-s3-state/variables.tf: -------------------------------------------------------------------------------- 1 | variable "master_account_id" { 2 | type = number 3 | } 4 | variable "organization_name" { 5 | type = string 6 | default = "rental-cars" 7 | } 8 | variable "master_aws_profile" { 9 | type = string 10 | sensitive = true 11 | description = "AWS Access Credentials" 12 | } 13 | variable "master_account_default_region" { 14 | type = string 15 | default = "us-east-2" 16 | description = "default region of master account" 17 | } 18 | variable "default_tag_created_by" { 19 | type = string 20 | default = "Terraform" 21 | } 22 | variable "default_tag_environment" { 23 | type = string 24 | default = "Sandbox-account-additional-infrastructure" 25 | } 26 | variable "default_org_tag" { 27 | type = string 28 | default = "Car-Rental" 29 | } 30 | 31 | variable "target_account_id" { 32 | type = number 33 | nullable = false 34 | } 35 | 36 | variable "cross_account_role_name" { 37 | type = string 38 | nullable = false 39 | default = "OrganizationAccountAccessRole" 40 | } 41 | variable "account_name" { 42 | type = string 43 | nullable = false 44 | default = "SANDBOX" 45 | } -------------------------------------------------------------------------------- /infrastructure/organization/aws-organization/budget.tf: -------------------------------------------------------------------------------- 1 | module "aws_budgeting_total_budget" { 2 | source = "../../modules/aws_budgeting" 3 | budget_settings = [var.budget_settings["BUDGET_TOTAL"]] 4 | notification = [var.budget_notification_settings["TOTAL_NOTIFICATION_SETTINGS"]] 5 | } -------------------------------------------------------------------------------- /infrastructure/organization/aws-organization/iam.tf: -------------------------------------------------------------------------------- 1 | #{ 2 | #"Version": "2012-10-17", 3 | #"Statement": [ 4 | #{ 5 | #"Sid": "AWSCloudTrailCreateLogStream2014110", 6 | #"Effect": "Allow", 7 | #"Action": [ 8 | #"logs:CreateLogStream" 9 | #], 10 | #"Resource": [ 11 | #"arn:aws:logs:us-east-1:141488247317:log-group:aws-cloudtrail-logs-141488247317-94f877dc:log-stream:141488247317_CloudTrail_us-east-1*" 12 | #] 13 | #}, 14 | #{ 15 | #"Sid": "AWSCloudTrailPutLogEvents20141101", 16 | #"Effect": "Allow", 17 | #"Action": [ 18 | #"logs:PutLogEvents" 19 | #], 20 | #"Resource": [ 21 | #"arn:aws:logs:us-east-1:141488247317:log-group:aws-cloudtrail-logs-141488247317-94f877dc:log-stream:141488247317_CloudTrail_us-east-1*" 22 | #] 23 | #} 24 | #] 25 | #} -------------------------------------------------------------------------------- /infrastructure/organization/aws-organization/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | aws = { 4 | source = "hashicorp/aws" 5 | version = "5.5.0" 6 | } 7 | } 8 | #################################################################################################################### 9 | # Definition of organization and workspace inside of Terraform Cloud, which is completely optional. 10 | # As the matter of fact we are provisioning master account infrastructure, there's no way to store the current 11 | # infrastructure state (CIS) in a S3 bucket due to not having any. That's why we're making use of Terraform Cloud 12 | # that provides a functionality of storing and locking a state for our master account. BTW, it also provides a 13 | # functionality of executing changes both remotely and locally. 14 | #################################################################################################################### 15 | cloud { 16 | organization = "car-rental" 17 | 18 | workspaces { 19 | name = "rental-car-master-account" 20 | } 21 | } 22 | required_version = ">= 0.13.1" 23 | 24 | } 25 | -------------------------------------------------------------------------------- /infrastructure/organization/aws-organization/organization.tf: -------------------------------------------------------------------------------- 1 | resource "aws_organizations_organization" "organization" { 2 | feature_set = var.feature_set 3 | aws_service_access_principals = var.aws_service_access_principals 4 | enabled_policy_types = var.enabled_policy_types 5 | } 6 | 7 | output "organization_arn" { 8 | value = aws_organizations_organization.organization.arn 9 | } 10 | output "organization_id" { 11 | value = aws_organizations_organization.organization.id 12 | } 13 | 14 | output "organization_root_id" { 15 | value = aws_organizations_organization.organization.roots[0].id 16 | } 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /infrastructure/organization/aws-organization/provider.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | profile = var.master_aws_profile 3 | region = var.master_account_default_region 4 | ##################################################################################################################### 5 | # Default Tag(s) which are attached to each resource capable of having a tag. Default tag(s) can be overridden by a 6 | # in-place tag definition; 7 | ##################################################################################################################### 8 | default_tags { 9 | tags = { 10 | Environment = var.default_tag_environment 11 | CreatedVia = var.default_tag_created_by 12 | Organization = var.default_org_tag 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /infrastructure/organization/aws-organization/scp.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amigoscode/cohort-2-c/4dcf9da0007e042e45b73792da07a1bfbd879403/infrastructure/organization/aws-organization/scp.tf -------------------------------------------------------------------------------- /infrastructure/organization/aws-prod-s3-state/variables.tf: -------------------------------------------------------------------------------- 1 | variable "master_account_id" { 2 | type = number 3 | } 4 | variable "organization_name" { 5 | type = string 6 | default = "rental-cars" 7 | } 8 | variable "master_aws_profile" { 9 | type = string 10 | sensitive = true 11 | description = "AWS Access Credentials" 12 | } 13 | variable "master_account_default_region" { 14 | type = string 15 | default = "us-east-2" 16 | description = "default region of master account" 17 | } 18 | variable "default_tag_created_by" { 19 | type = string 20 | default = "Terraform" 21 | } 22 | variable "default_tag_environment" { 23 | type = string 24 | default = "Prod-foundational-infra" 25 | } 26 | variable "default_org_tag" { 27 | type = string 28 | default = "Car-Rental" 29 | } 30 | 31 | variable "target_account_id" { 32 | type = number 33 | nullable = false 34 | } 35 | 36 | variable "cross_account_role_name" { 37 | type = string 38 | nullable = false 39 | default = "OrganizationAccountAccessRole" 40 | } 41 | variable "account_name" { 42 | type = string 43 | nullable = false 44 | default = "PROD" 45 | } -------------------------------------------------------------------------------- /infrastructure/organization/aws-sandbox-s3-state/variables.tf: -------------------------------------------------------------------------------- 1 | variable "master_account_id" { 2 | type = number 3 | } 4 | variable "organization_name" { 5 | type = string 6 | default = "rental-cars" 7 | } 8 | variable "master_aws_profile" { 9 | type = string 10 | sensitive = true 11 | description = "AWS Access Credentials" 12 | } 13 | variable "master_account_default_region" { 14 | type = string 15 | default = "us-east-2" 16 | description = "default region of master account" 17 | } 18 | variable "default_tag_created_by" { 19 | type = string 20 | default = "Terraform" 21 | } 22 | variable "default_tag_environment" { 23 | type = string 24 | default = "sandbox-foundational-infra" 25 | } 26 | variable "default_org_tag" { 27 | type = string 28 | default = "Car-Rental" 29 | } 30 | 31 | variable "target_account_id" { 32 | type = number 33 | nullable = false 34 | } 35 | 36 | variable "cross_account_role_name" { 37 | type = string 38 | nullable = false 39 | default = "OrganizationAccountAccessRole" 40 | } 41 | variable "account_name" { 42 | type = string 43 | nullable = false 44 | default = "SANDBOX" 45 | } -------------------------------------------------------------------------------- /infrastructure/organization/aws-staging-s3-state/variables.tf: -------------------------------------------------------------------------------- 1 | variable "master_account_id" { 2 | type = number 3 | } 4 | variable "organization_name" { 5 | type = string 6 | default = "rental-cars" 7 | } 8 | variable "master_aws_profile" { 9 | type = string 10 | sensitive = true 11 | description = "AWS Access Credentials" 12 | } 13 | variable "master_account_default_region" { 14 | type = string 15 | default = "us-east-2" 16 | description = "default region of master account" 17 | } 18 | variable "default_tag_created_by" { 19 | type = string 20 | default = "Terraform" 21 | } 22 | variable "default_tag_environment" { 23 | type = string 24 | default = "Staging-foundational-infra" 25 | } 26 | variable "default_org_tag" { 27 | type = string 28 | default = "Car-Rental" 29 | } 30 | 31 | variable "target_account_id" { 32 | type = number 33 | nullable = false 34 | } 35 | 36 | variable "cross_account_role_name" { 37 | type = string 38 | nullable = false 39 | default = "OrganizationAccountAccessRole" 40 | } 41 | variable "account_name" { 42 | type = string 43 | nullable = false 44 | default = "STAGING" 45 | } --------------------------------------------------------------------------------