├── .dockerignore ├── .env ├── .github └── workflows │ └── build-checks.yml ├── .gitignore ├── 3cn_realm.json ├── Dockerfile.3cn-parent-init ├── Dockerfile.update-3cn-parent ├── LICENSE ├── api-gateway ├── .dockerignore ├── .gitignore ├── Dockerfile.multistage ├── pom.xml ├── readme.md └── src │ └── main │ ├── java │ └── com │ │ └── ubaid │ │ └── ms │ │ └── apigateway │ │ ├── ApiGateway.java │ │ ├── config │ │ ├── Beans.java │ │ ├── CorsConfig.java │ │ ├── SecurityConfig.java │ │ ├── SwaggerConfig.java │ │ └── readme.md │ │ ├── controller │ │ ├── IndexController.java │ │ └── InformationController.java │ │ └── services │ │ ├── InfoService.java │ │ └── InfoServiceImpl.java │ └── resources │ ├── application-dev.properties │ ├── application-local.properties │ ├── application-prod.properties │ ├── application.properties │ └── config.properties ├── audit ├── .dockerignore ├── .gitignore ├── Dockerfile.multistage ├── pom.xml ├── readme.md └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── ubaid │ │ │ └── ms │ │ │ ├── AuditApplication.java │ │ │ └── audit │ │ │ ├── config │ │ │ ├── Beans.java │ │ │ ├── MessageBrokerConfig.java │ │ │ ├── SecurityConfig.java │ │ │ └── SwaggerConfig.java │ │ │ ├── controller │ │ │ ├── AuditController.java │ │ │ └── InfoController.java │ │ │ ├── dao │ │ │ └── AuditDAO.java │ │ │ ├── entity │ │ │ └── Audit.java │ │ │ ├── listener │ │ │ └── ListenAuditLogs.java │ │ │ └── service │ │ │ ├── AuditService.java │ │ │ ├── AuditServiceImpl.java │ │ │ ├── InfoService.java │ │ │ └── InfoServiceImpl.java │ └── resources │ │ ├── application-dev.properties │ │ ├── application-local.properties │ │ ├── application-prod.properties │ │ ├── application.properties │ │ ├── config.properties │ │ └── db │ │ └── migration │ │ ├── V1__gh_301_create_audit_table.sql │ │ └── V2__gh_360_replace_float_with_double.sql │ └── test │ └── java │ └── com │ └── ubaid │ └── ms │ └── auditservice │ └── AuditApplicationTests.java ├── build-3cn-parent-image.sh ├── build-all-microservice-images.sh ├── clients ├── 3cn-react-client │ ├── .dockerignore │ ├── .env.dev │ ├── .env.prod │ ├── .eslintrc.json │ ├── .gitignore │ ├── Dockerfile │ ├── README.md │ ├── build-push-prod-ui-image.sh │ ├── jsconfig.json │ ├── nginx │ │ └── nginx.conf │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── keycloak-dev.json │ │ ├── keycloak-local.json │ │ ├── keycloak-prod.json │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ ├── src │ │ ├── App.css │ │ ├── App.js │ │ ├── component │ │ │ ├── auth │ │ │ │ └── Authenticate.js │ │ │ ├── convertionPaper │ │ │ │ └── ConversionPaper.js │ │ │ ├── down │ │ │ │ └── ServiceDown.js │ │ │ ├── footer │ │ │ │ └── Footer.js │ │ │ ├── header │ │ │ │ └── Header.js │ │ │ ├── selectCountry │ │ │ │ └── CountrySelect.js │ │ │ └── userinfo │ │ │ │ └── UserInfo.js │ │ ├── container │ │ │ └── CurrencyConverter │ │ │ │ └── CurrencyConverter.js │ │ ├── hoc │ │ │ └── Layout │ │ │ │ └── Layout.js │ │ ├── http │ │ │ └── RequestHandler.js │ │ ├── index.css │ │ ├── index.js │ │ ├── keycloak.js │ │ ├── reportWebVitals.js │ │ ├── setupTests.js │ │ ├── store │ │ │ ├── ActionTypes.js │ │ │ ├── actions │ │ │ │ ├── AuthAction.js │ │ │ │ ├── ConvertCurrencyAction.js │ │ │ │ ├── PopulateCountryAction.js │ │ │ │ └── SelectCountryAction.js │ │ │ └── reducers │ │ │ │ ├── AuthReducer.js │ │ │ │ ├── ConvertCurrencyReducer.js │ │ │ │ ├── PopulateCountryReducer.js │ │ │ │ └── SelectCountryReducer.js │ │ └── util │ │ │ └── ProtectedRoute.js │ └── wireframes.drawio └── CurrencyConversionReactNativeClient │ ├── .buckconfig │ ├── .eslintrc.js │ ├── .flowconfig │ ├── .gitattributes │ ├── .gitignore │ ├── .prettierrc.js │ ├── .watchmanconfig │ ├── App.js │ ├── app.json │ ├── babel.config.js │ ├── index.js │ ├── metro.config.js │ └── package.json ├── common ├── .gitignore ├── dto │ ├── .gitignore │ ├── pom.xml │ ├── readme.md │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── ubaid │ │ └── ms │ │ └── common │ │ └── dto │ │ ├── AuditDTO.java │ │ ├── CountryCodeDTO.java │ │ ├── CurrencyInfoDTO.java │ │ ├── ExceptionDTO.java │ │ ├── ExchangeRateDTO.java │ │ ├── ExchangeValueDTO.java │ │ ├── Rate.java │ │ ├── ValueDTO.java │ │ ├── auth │ │ └── LoginCred.java │ │ └── serviceinfo │ │ ├── Commit.java │ │ ├── Git.java │ │ └── ServiceInformation.java ├── exception │ ├── .gitignore │ ├── pom.xml │ ├── readme.md │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── ubaid │ │ └── ms │ │ └── common │ │ └── util │ │ └── exception │ │ ├── CCException.java │ │ └── ExchangeValueNotFound.java ├── pom.xml ├── readme.md └── util │ ├── .gitignore │ ├── pom.xml │ └── src │ └── main │ └── java │ └── com │ └── ubaid │ └── ms │ └── common │ └── util │ └── Constants.java ├── config ├── .dockerignore ├── .gitignore ├── Dockerfile.multistage ├── pom.xml ├── readme.md └── src │ └── main │ ├── java │ └── com │ │ └── ubaid │ │ └── ms │ │ └── config │ │ └── ConfigServer.java │ └── resources │ ├── application-dev.yml │ ├── application-local.yml │ ├── application-prod.yml │ └── application.yml ├── country ├── .dockerignore ├── .gitignore ├── Dockerfile.multistage ├── pom.xml ├── readme.md └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── ubaid │ │ │ └── ms │ │ │ ├── CountryApplication.java │ │ │ └── country │ │ │ ├── advice │ │ │ └── ExceptionController.java │ │ │ ├── aop │ │ │ ├── Logging.java │ │ │ └── TargetMethods.java │ │ │ ├── config │ │ │ ├── Beans.java │ │ │ ├── SecurityConfig.java │ │ │ ├── SwaggerConfig.java │ │ │ └── validator │ │ │ │ └── AudienceValidator.java │ │ │ ├── controller │ │ │ ├── CountryController.java │ │ │ └── InfoController.java │ │ │ ├── dao │ │ │ └── CountryCodeDAO.java │ │ │ ├── entity │ │ │ └── CountryCode.java │ │ │ └── service │ │ │ ├── CountryCodeService.java │ │ │ ├── CountryCodeServiceImp.java │ │ │ ├── InfoService.java │ │ │ └── InfoServiceImpl.java │ └── resources │ │ ├── application-dev.properties │ │ ├── application-local.properties │ │ ├── application-prod.properties │ │ ├── application.properties │ │ ├── config.properties │ │ └── db │ │ └── changelog │ │ ├── changes │ │ ├── v0001.sql │ │ ├── v0002.sql │ │ ├── v0003.sql │ │ ├── v0004-add_column_in_country_code_table.sql │ │ ├── v0005-updating_iso_column_to_integer.sql │ │ ├── v0005a-correcting_iso_column_to10_varchar.sql │ │ └── v0006-populate_iso_code_column_in_country_code_table.sql │ │ └── db.changelog-master.yaml │ └── test │ ├── java │ └── com │ │ └── ubaid │ │ └── ms │ │ └── counteryservice │ │ └── CountryApplicationTests.java │ └── resources │ └── application.properties ├── currency-conversion ├── .dockerignore ├── .gitignore ├── Dockerfile.multistage ├── pom.xml ├── readme.md ├── runAllTests.sh └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── ubaid │ │ │ └── ms │ │ │ ├── CurrencyConversionApp.java │ │ │ └── currencyconversion │ │ │ ├── aop │ │ │ ├── Logging.java │ │ │ └── TargetMethods.java │ │ │ ├── config │ │ │ ├── Beans.java │ │ │ ├── Config.java │ │ │ ├── MessageBrokerConfig.java │ │ │ ├── SecurityConfig.java │ │ │ └── SwaggerConfig.java │ │ │ ├── controller │ │ │ ├── CurrencyConversionController.java │ │ │ └── InfoController.java │ │ │ ├── entity │ │ │ └── Limit.java │ │ │ ├── exceptionController │ │ │ └── ExceptionController.java │ │ │ ├── feignProxy │ │ │ ├── CurrencyConversionServiceProxy.java │ │ │ └── CurrencyExchangeServiceProxy.java │ │ │ ├── service │ │ │ ├── AuditService.java │ │ │ ├── AuditServiceImpl.java │ │ │ ├── AuthService.java │ │ │ ├── AuthServiceImpl.java │ │ │ ├── CurrencyConversionService.java │ │ │ ├── CurrencyConversionServiceImp.java │ │ │ ├── InfoService.java │ │ │ ├── InfoServiceImpl.java │ │ │ ├── RequestService.java │ │ │ └── RequestServiceImpl.java │ │ │ └── util │ │ │ └── BearerToken.java │ └── resources │ │ ├── application-dev.properties │ │ ├── application-local.properties │ │ ├── application-prod.properties │ │ ├── application.properties │ │ └── config.properties │ └── test │ └── resources │ ├── application.properties │ └── config.properties ├── currency-exchange ├── .dockerignore ├── .gitignore ├── Dockerfile.multistage ├── pom.xml ├── readme.md └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── ubaid │ │ │ └── ms │ │ │ ├── CurrencyExchangeServiceApplication.java │ │ │ └── currencyexchangeservice │ │ │ ├── aop │ │ │ ├── Logging.java │ │ │ └── TargetMethods.java │ │ │ ├── config │ │ │ ├── Beans.java │ │ │ ├── Config.java │ │ │ ├── SecurityConfig.java │ │ │ ├── SwaggerConfig.java │ │ │ └── validator │ │ │ │ └── AudienceValidator.java │ │ │ ├── controller │ │ │ ├── CurrencyExchangeController.java │ │ │ ├── ExceptionController.java │ │ │ └── InfoController.java │ │ │ ├── dao │ │ │ └── ExchangeRateDAO.java │ │ │ ├── entity │ │ │ └── ExchangeRate.java │ │ │ ├── service │ │ │ ├── ExchangeRateService.java │ │ │ ├── ExchangeRateServiceImp.java │ │ │ ├── InfoService.java │ │ │ ├── InfoServiceImpl.java │ │ │ ├── ServerInfoService.java │ │ │ └── ServerInfoServiceImpl.java │ │ │ ├── task │ │ │ └── PopulateDBWithExchangeRates.java │ │ │ └── utility │ │ │ └── ExchangeRateDTOConverter.java │ └── resources │ │ ├── application-dev.properties │ │ ├── application-local.properties │ │ ├── application-prod.properties │ │ ├── application.properties │ │ ├── config.properties │ │ ├── db │ │ └── changelog │ │ │ ├── changes │ │ │ └── v00001.sql │ │ │ └── db.changelog-master.yaml │ │ └── exchangeRates.json │ └── test │ ├── java │ └── com │ │ └── ubaid │ │ └── ms │ │ ├── currency_conversion_service │ │ └── ContextTest.java │ │ └── currencyexchangeservice │ │ ├── service │ │ └── ExchangeRateServiceImpTest.java │ │ ├── task │ │ └── PopulateDBWithExchangeRatesTest.java │ │ └── utility │ │ └── ExchangeRateDTOConverterTest.java │ └── resources │ ├── application.properties │ └── exchangeRates.json ├── discovery ├── .dockerignore ├── .gitignore ├── Dockerfile.multistage ├── pom.xml ├── readme.md └── src │ └── main │ ├── java │ └── com │ │ └── ubaid │ │ └── ms │ │ └── discovery │ │ └── DiscoveryApp.java │ └── resources │ └── application.properties ├── docker-compose-multi-stage-build.yml ├── envcn ├── .env ├── auth-db │ ├── Dockerfile │ ├── buid-push-prod-image.sh │ └── sql │ │ └── dump.sql ├── db │ ├── Dockerfile │ └── init.sql ├── docker-compose-multi-stage-build.yml ├── elasticsearch │ ├── Dockerfile │ └── config │ │ └── elasticsearch.yml ├── kc │ └── Dockerfile ├── kibana │ ├── Dockerfile │ └── config │ │ └── kibana.yml ├── logstash │ ├── Dockerfile │ ├── config │ │ └── logstash.yml │ └── pipeline │ │ └── logstash.conf ├── rabbitmq │ └── Dockerfile ├── run-multi-stage.sh └── zipkin │ └── Dockerfile ├── install-maven-jdk17.sh ├── k8s ├── configs.yml ├── deployments.yml ├── docx │ ├── moreinfo.md │ └── readme.md ├── housekeeping │ ├── delete-all-configMaps.sh │ ├── delete-all-deployments.sh │ ├── delete-all-ingress.sh │ ├── delete-all-pv-and-pvc.sh │ └── delete-all-services.sh ├── ingress.yml ├── k8s-down.sh ├── k8s-up.sh ├── minikube │ └── install_minikube_kubectl.sh ├── pvcs.yml ├── pvs.yml └── services.yml ├── math ├── .dockerignore ├── .gitignore ├── Dockerfile.multistage ├── pom.xml ├── readme.md └── src │ └── main │ ├── java │ └── com │ │ └── ubaid │ │ └── ms │ │ └── math │ │ ├── MathApplication.java │ │ ├── aop │ │ ├── Logging.java │ │ └── TargetMethods.java │ │ ├── config │ │ ├── Beans.java │ │ ├── SecurityConfig.java │ │ ├── SwaggerConfig.java │ │ └── validator │ │ │ └── AudienceValidator.java │ │ ├── controller │ │ ├── ExceptionController.java │ │ ├── InfoController.java │ │ └── MathController.java │ │ └── service │ │ ├── InfoService.java │ │ ├── InfoServiceImpl.java │ │ ├── MathService.java │ │ ├── MathServiceImp.java │ │ ├── ServerInfoService.java │ │ └── ServerInfoServiceImpl.java │ └── resources │ ├── application-dev.properties │ ├── application-local.properties │ ├── application-prod.properties │ ├── application.properties │ └── config.properties ├── misc └── docker-compose-postgres.yml ├── moreinfo.md ├── pom.xml ├── pull-all-microservice-images.sh ├── push-all-microservice-images.sh ├── readme.md ├── resource ├── 3cn-parent-image │ └── readme.md ├── Auth Flow 1.drawio ├── api-composer-swagger-ui-2.png ├── api-composer-swagger-ui.png ├── auth │ ├── 3cn-react-client-access-type.png │ ├── 3cn-react-client.png │ ├── auth-flow-v1.png │ ├── auth-flow.md │ ├── img.png │ └── img_1.png ├── checkstyle │ ├── google_checks.xml │ └── readme.md ├── copy-access-token.png ├── country-service-swagger-ui-2.png ├── country-service-swagger-ui.png ├── create-index-for-logging.md ├── create-index.PNG ├── definition-drop-down.png ├── effective-java │ └── readme.md ├── execute-exchnage-request.png ├── execute-login-reqeust.png ├── how-to-use-swagger.md ├── how-to-user-swagger.png ├── install-require-softwares.md ├── java-home.png ├── kibana-dashboard.png ├── lucid-diagrams │ └── 3cnArchitecture.png ├── mvn-version.png ├── pase-acces-token.png ├── see-the-response.png └── swagger-authorize-request.png ├── run-multi-stage.sh ├── update-3cn-parent-image.sh └── user ├── .dockerignore ├── .gitignore ├── Dockerfile.multistage ├── pom.xml ├── readme.md └── src ├── main ├── java │ └── com │ │ └── ubaid │ │ └── ms │ │ ├── UserApp.java │ │ └── user │ │ ├── advice │ │ └── ExceptionHandlerController.java │ │ ├── aop │ │ ├── Logging.java │ │ └── TargetMethods.java │ │ ├── config │ │ ├── Beans.java │ │ ├── SecurityConfig.java │ │ └── SwaggerConfig.java │ │ ├── controller │ │ ├── InfoController.java │ │ └── UserServiceController.java │ │ ├── feignproxy │ │ └── AuthTokenServiceProxy.java │ │ └── service │ │ ├── AccessTokenService.java │ │ ├── AccessTokenServiceImpl.java │ │ ├── InfoService.java │ │ └── InfoServiceImpl.java └── resources │ ├── application-dev.properties │ ├── application-local.properties │ ├── application-prod.properties │ ├── application.properties │ └── config.properties └── test └── java └── com └── ubaid └── ms └── userservice └── UserAppTests.java /.env: -------------------------------------------------------------------------------- 1 | APP_VERSION=0.0.3-SNAPSHOT -------------------------------------------------------------------------------- /.github/workflows/build-checks.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven 3 | 4 | name: Java CI with Maven develop & master Branch 5 | 6 | on: 7 | pull_request: 8 | branches: 9 | - develop 10 | - master 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Set up JDK 17 20 | uses: actions/setup-java@v1 21 | with: 22 | java-version: 17 23 | - name: Build 3CN Modules 24 | run: mvn clean install -DskipTests --file common/pom.xml 25 | - name: Build 3CN Parent 26 | run: mvn clean install -N -DskipTests --file pom.xml 27 | - name: Build 3CN Whole Project 28 | run: mvn -B package -DskipTests --file pom.xml 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.metadata/ 2 | .idea 3 | .vscode 4 | /currency-conversion-client 5 | /currency-conversion-api 6 | /CC-DTO 7 | /CC-Exception 8 | *.iml 9 | /localtunnel -------------------------------------------------------------------------------- /Dockerfile.3cn-parent-init: -------------------------------------------------------------------------------- 1 | FROM maven:3.8-openjdk-17-slim 2 | WORKDIR /3cn 3 | COPY . . 4 | RUN mvn install -DskipTests --file common/pom.xml \ 5 | && mvn install -N -DskipTests --file pom.xml \ 6 | && mvn install -DskipTests --file pom.xml \ 7 | && mv /3cn/.git / \ 8 | && rm -rf /3cn \ 9 | && rm -rf /root/.m2/repository/com/ubaid/ms/currency-conversion \ 10 | && rm -rf /root/.m2/repository/com/ubaid/ms/audit \ 11 | && rm -rf /root/.m2/repository/com/ubaid/ms/country \ 12 | && rm -rf /root/.m2/repository/com/ubaid/ms/math \ 13 | && rm -rf /root/.m2/repository/com/ubaid/ms/currency-exchange \ 14 | && rm -rf /root/.m2/repository/com/ubaid/ms/discovery \ 15 | && rm -rf /root/.m2/repository/com/ubaid/ms/api-gateway \ 16 | && rm -rf /root/.m2/repository/com/ubaid/ms/config \ 17 | && rm -rf /root/.m2/repository/com/ubaid/ms/user -------------------------------------------------------------------------------- /Dockerfile.update-3cn-parent: -------------------------------------------------------------------------------- 1 | FROM 3cn-parent:0.0.3-SNAPSHOT 2 | WORKDIR /3cn 3 | COPY . . 4 | RUN mvn install -DskipTests --file common/pom.xml \ 5 | && mvn install -N -DskipTests --file pom.xml \ 6 | && mvn install -DskipTests --file pom.xml \ 7 | && mv /3cn/.git / \ 8 | && rm -rf /3cn \ 9 | && rm -rf /root/.m2/repository/com/ubaid/ms/currency-conversion \ 10 | && rm -rf /root/.m2/repository/com/ubaid/ms/audit \ 11 | && rm -rf /root/.m2/repository/com/ubaid/ms/country \ 12 | && rm -rf /root/.m2/repository/com/ubaid/ms/math \ 13 | && rm -rf /root/.m2/repository/com/ubaid/ms/currency-exchange \ 14 | && rm -rf /root/.m2/repository/com/ubaid/ms/discovery \ 15 | && rm -rf /root/.m2/repository/com/ubaid/ms/api-gateway \ 16 | && rm -rf /root/.m2/repository/com/ubaid/ms/config \ 17 | && rm -rf /root/.m2/repository/com/ubaid/ms/user -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Ubaid ur Rehman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /api-gateway/.dockerignore: -------------------------------------------------------------------------------- 1 | /target 2 | .gitignore 3 | *.iml 4 | Dockerfile 5 | Dockerfile.debug 6 | Dockerfile.multistage 7 | readme.md -------------------------------------------------------------------------------- /api-gateway/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | 30 | ### VS Code ### 31 | .vscode/ 32 | -------------------------------------------------------------------------------- /api-gateway/Dockerfile.multistage: -------------------------------------------------------------------------------- 1 | ARG APP_VERSION 2 | FROM ubaidurehman/3cn-parent:${APP_VERSION} as build 3 | LABEL maintainer="urehman.bese16seecs@seecs.edu.pk" 4 | VOLUME /tmp 5 | WORKDIR / 6 | ADD . . 7 | RUN mvn clean install -DskipTests 8 | 9 | FROM openjdk:17-slim 10 | VOLUME /tmp 11 | WORKDIR / 12 | EXPOSE 8755 13 | ARG APP_VERSION 14 | COPY --from=build /target/api-gateway-${APP_VERSION}.jar service.jar 15 | ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-Dspring.profiles.active=dev","-jar","/service.jar"] 16 | -------------------------------------------------------------------------------- /api-gateway/readme.md: -------------------------------------------------------------------------------- 1 | ### About 2 | - A server which is responsible to reroute request to the resource server 3 | 4 | Dependencies 5 | ------------ 6 | - #### Cloud 7 | - ##### Config Client 8 | - spring-cloud-starter-config 9 | - ##### Naming Server Client 10 | - spring-cloud-starter-netflix-eureka-client 11 | - ##### API Gateway 12 | - spring-cloud-starter-gateway 13 | - ##### Distributed Tracing 14 | - spring-cloud-sleuth-zipkin 15 | - spring-cloud-starter-sleuth 16 | - #### Security 17 | - ##### Spring Security 18 | - spring-cloud-starter-security 19 | - ##### [OAuth2 Resource Server](./../moreinfo.md#Resource-server) 20 | - spring-boot-starter-oauth2-resource-server 21 | - ##### [OAuth2 Client](./../moreinfo.md#OAuth2-client) 22 | - spring-boot-starter-oauth2-client 23 | - #### Logstash (Sending logs to Logstash) 24 | - reactive-logstash-logging-spring-boot-starter 25 | - #### [Dependencies From Parent](./../moreinfo.md#Dependencies-from-parent) 26 | 27 | [Distributed Tracing](./../moreinfo.md#distributed-tracing) 28 | ----------------------------------------------------------- 29 | [ELK Stack](./../moreinfo.md#elk-stack) 30 | --------------------------------------- -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/ubaid/ms/apigateway/ApiGateway.java: -------------------------------------------------------------------------------- 1 | package com.ubaid.ms.apigateway; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | 7 | /** 8 | * Re-routes the incoming request to down-stream services according to the URL match pattern. 9 | * 10 | * @author ubaid 11 | */ 12 | @EnableDiscoveryClient 13 | @SpringBootApplication 14 | public class ApiGateway { 15 | public static void main(String[] args) { 16 | SpringApplication.run(ApiGateway.class, args); 17 | } 18 | } -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/ubaid/ms/apigateway/config/Beans.java: -------------------------------------------------------------------------------- 1 | package com.ubaid.ms.apigateway.config; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import org.springframework.beans.factory.config.ConfigurableBeanFactory; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Scope; 7 | 8 | public class Beans { 9 | 10 | @Bean 11 | @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) 12 | public ObjectMapper objectMapper() { 13 | return new ObjectMapper(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/ubaid/ms/apigateway/config/SwaggerConfig.java: -------------------------------------------------------------------------------- 1 | package com.ubaid.ms.apigateway.config; 2 | 3 | import static com.ubaid.ms.common.util.Constants.*; 4 | import lombok.RequiredArgsConstructor; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 7 | import org.springframework.cloud.client.discovery.DiscoveryClient; 8 | import org.springframework.context.annotation.Primary; 9 | import org.springframework.stereotype.Component; 10 | import springfox.documentation.swagger.web.SwaggerResource; 11 | import springfox.documentation.swagger.web.SwaggerResourcesProvider; 12 | import java.util.List; 13 | 14 | @Component 15 | @Primary 16 | @EnableAutoConfiguration 17 | @RequiredArgsConstructor 18 | @Slf4j 19 | public class SwaggerConfig implements SwaggerResourcesProvider { 20 | 21 | private final DiscoveryClient discoveryClient; 22 | 23 | @Override 24 | public List get() { 25 | List allServices = discoveryClient.getServices(); 26 | log.debug("All Services: {}", allServices); 27 | return allServices 28 | .stream() 29 | .filter(serviceName -> !serviceName.equalsIgnoreCase(API_GATEWAY)) 30 | .map(this::swaggerResource) 31 | .toList(); 32 | } 33 | 34 | private SwaggerResource swaggerResource(String name) { 35 | SwaggerResource swaggerResource = new SwaggerResource(); 36 | swaggerResource.setName(name); 37 | swaggerResource.setLocation("/" + name + API_DOCS_PATH); 38 | swaggerResource.setSwaggerVersion(APP_VERSION); 39 | return swaggerResource; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/ubaid/ms/apigateway/config/readme.md: -------------------------------------------------------------------------------- 1 | - Security Configuration of Spring Cloud Gateway 2 | ```java 3 | @Configuration 4 | @EnableWebFluxSecurity 5 | @EnableGlobalMethodSecurity(jsr250Enabled = true) 6 | public class SecurityConfig { 7 | 8 | @Bean 9 | public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) { 10 | http 11 | .authorizeExchange() 12 | .anyExchange() 13 | .authenticated() 14 | .and().oauth2ResourceServer().jwt(); 15 | 16 | http.csrf().disable(); 17 | 18 | return http.build(); 19 | } 20 | } 21 | ``` 22 | 23 | - Explanation 24 | 1. `@Configuration` Indicates that a class declares one or more `@Bean` methods and may be processed by the Spring container to generate bean definitions and service requests for those beans at runtime. 25 | 2. `@EnableWebFluxSecurity` As Spring Cloud API Gateway is based upon Reactor Project, so enabling `WebFluxSecurity` 26 | 3. `@EnableGlobalMethodSecurity(jsr250Enabled = true)` property allows us to use the `@RoleAllowed` annotation on methods 27 | 4. `SecurityWebFilterChain` bean which configuring security to authenticate all requests and adding support of `OAuth2` Server, (It is behaving both Client and Resource Server) 28 | 5. `spring.security.oauth2.resourceserver.jwt.issuer-uri` `ReactiveJwtDecoder` OIDC issuer Location 29 | 6. Along with this, we have to add a provider (Auth Server) and Clients (Resource Servers) (check the props files) 30 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/ubaid/ms/apigateway/controller/IndexController.java: -------------------------------------------------------------------------------- 1 | package com.ubaid.ms.apigateway.controller; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.http.server.reactive.ServerHttpResponse; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | import reactor.core.publisher.Mono; 8 | 9 | import java.net.URI; 10 | 11 | @RestController(value = "/") 12 | public class IndexController { 13 | 14 | @GetMapping(value = "/") 15 | public Mono index(ServerHttpResponse response) { 16 | response.setStatusCode(HttpStatus.PERMANENT_REDIRECT); 17 | response.getHeaders().setLocation(URI.create("/swagger-ui/index.html")); 18 | return response.setComplete(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/ubaid/ms/apigateway/controller/InformationController.java: -------------------------------------------------------------------------------- 1 | package com.ubaid.ms.apigateway.controller; 2 | 3 | import com.ubaid.ms.apigateway.services.InfoService; 4 | import com.ubaid.ms.common.dto.serviceinfo.ServiceInformation; 5 | import java.util.List; 6 | import java.util.Map; 7 | import java.util.stream.Collectors; 8 | import lombok.RequiredArgsConstructor; 9 | import org.springframework.cloud.client.discovery.DiscoveryClient; 10 | import org.springframework.http.ResponseEntity; 11 | import org.springframework.web.bind.annotation.GetMapping; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.bind.annotation.RestController; 14 | import reactor.core.publisher.Mono; 15 | 16 | @RestController 17 | @RequestMapping(value = "api/api-gateway/v1/info") 18 | @RequiredArgsConstructor 19 | public class InformationController { 20 | 21 | private final DiscoveryClient discoveryClient; 22 | private final InfoService infoService; 23 | 24 | @GetMapping("services") 25 | public Mono>> getAllServices() { 26 | List allServices = discoveryClient.getServices(); 27 | Map servicesWithInfoURI = allServices 28 | .stream() 29 | .collect(Collectors.toMap(key -> key, value -> "api/" + value + "/v1/info")); 30 | return Mono.just(ResponseEntity.ok(servicesWithInfoURI)); 31 | } 32 | 33 | @GetMapping 34 | Mono> get() { 35 | return Mono.just(ResponseEntity.ok(infoService.get())); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/ubaid/ms/apigateway/services/InfoService.java: -------------------------------------------------------------------------------- 1 | package com.ubaid.ms.apigateway.services; 2 | 3 | import com.ubaid.ms.common.dto.serviceinfo.ServiceInformation; 4 | 5 | public interface InfoService { 6 | ServiceInformation get(); 7 | } 8 | -------------------------------------------------------------------------------- /api-gateway/src/main/java/com/ubaid/ms/apigateway/services/InfoServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ubaid.ms.apigateway.services; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import com.netflix.appinfo.ApplicationInfoManager; 5 | import com.ubaid.ms.common.dto.serviceinfo.ServiceInformation; 6 | import com.ubaid.ms.common.dto.serviceinfo.ServiceInformationBuilder; 7 | import lombok.RequiredArgsConstructor; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.boot.actuate.info.InfoEndpoint; 10 | import org.springframework.stereotype.Service; 11 | 12 | @Service 13 | @Slf4j 14 | @RequiredArgsConstructor 15 | public class InfoServiceImpl implements InfoService { 16 | 17 | private final InfoEndpoint infoEndpoint; 18 | private final ObjectMapper objectMapper; 19 | private final ApplicationInfoManager applicationInfoManager; 20 | 21 | @Override 22 | public ServiceInformation get() { 23 | ServiceInformationBuilder builder = ServiceInformationBuilder 24 | .builder(objectMapper.convertValue(infoEndpoint.info(), ServiceInformation.class)); 25 | builder.name(applicationInfoManager.getInfo().getAppName()); 26 | ServiceInformation serviceInformation = builder.build(); 27 | log.debug("Service Information: {}", serviceInformation); 28 | return serviceInformation; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /api-gateway/src/main/resources/application-dev.properties: -------------------------------------------------------------------------------- 1 | #------------------------Config Client--------------------------# 2 | spring.config.import=optional:configserver:http://config:8888 3 | spring.cloud.config.profile=dev 4 | spring.cloud.config.fail-fast=true 5 | spring.cloud.config.request-connect-timeout=30000 6 | spring.cloud.config.request-read-timeout=360000 -------------------------------------------------------------------------------- /api-gateway/src/main/resources/application-local.properties: -------------------------------------------------------------------------------- 1 | #------------------------Config Client--------------------------# 2 | spring.config.import=optional:configserver:http://localhost:8888 3 | spring.cloud.config.profile=local 4 | 5 | #------------------------Live Reload --------------------------# 6 | spring.devtools.livereload.port=35730 7 | 8 | #------------------------Logging --------------------------# 9 | logging.level.org.springframework.cloud.gateway=DEBUG 10 | logging.level.org.springframework.security=DEBUG 11 | logging.level.org.springframework.web.reactive.function.client=DEBUG 12 | 13 | #------------------------Actuator --------------------------# 14 | management.endpoints.web.exposure.include=health,info 15 | management.endpoint.health.enabled=true 16 | management.endpoint.health.probes.enabled=true -------------------------------------------------------------------------------- /api-gateway/src/main/resources/application-prod.properties: -------------------------------------------------------------------------------- 1 | #------------------------Config Client--------------------------# 2 | spring.config.import=optional:configserver:http://config:8888 3 | spring.cloud.config.profile=prod 4 | spring.cloud.config.fail-fast=true 5 | spring.cloud.config.request-connect-timeout=30000 6 | spring.cloud.config.request-read-timeout=360000 -------------------------------------------------------------------------------- /api-gateway/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #----------------------------App Props---------------------------------------------# 2 | spring.application.name=api-gateway 3 | server.port=8755 4 | 5 | #----------------------------Active Profile----------------------------------------# 6 | spring.profiles.active=@activatedProperties@ 7 | 8 | #----------------------------show IP address---------------------------------------# 9 | eureka.instance.prefer-ip-address=true 10 | eureka.instance.instance-id=${spring.cloud.client.ip-address}:${server.port} 11 | eureka.instance.hostname=${spring.cloud.client.ip-address} 12 | 13 | spring.main.allow-bean-definition-overriding=true 14 | 15 | spring.cloud.gateway.discovery.locator.enabled=true 16 | spring.cloud.gateway.discovery.locator.lower-case-service-id=true -------------------------------------------------------------------------------- /api-gateway/src/main/resources/config.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubaid4j/Cloud-Native-App-Spring-Boot/d023b0a732b43f4196176cd9fa3a67490a79eaab/api-gateway/src/main/resources/config.properties -------------------------------------------------------------------------------- /audit/.dockerignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | audit.iml 3 | Dockerfile 4 | Dockerfile.multistage 5 | /target -------------------------------------------------------------------------------- /audit/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /audit/Dockerfile.multistage: -------------------------------------------------------------------------------- 1 | ARG APP_VERSION 2 | FROM ubaidurehman/3cn-parent:${APP_VERSION} as build 3 | LABEL maintainer="urehman.bese16seecs@seecs.edu.pk" 4 | VOLUME /tmp 5 | WORKDIR / 6 | ADD . . 7 | RUN mvn clean install -DskipTests 8 | 9 | FROM openjdk:17-slim 10 | VOLUME /tmp 11 | WORKDIR / 12 | EXPOSE 8950 13 | ARG APP_VERSION 14 | COPY --from=build /target/audit-${APP_VERSION}.jar service.jar 15 | ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-Dspring.profiles.active=dev","-jar","/service.jar"] 16 | -------------------------------------------------------------------------------- /audit/readme.md: -------------------------------------------------------------------------------- 1 | About 2 | ===== 3 | - [Audit Service](http://localhost:8755/swagger-ui/index.html?urls.primaryName=audit) 4 | 5 | Dependencies 6 | ============ 7 | - #### Web (Reactor Netty as the embedded reactive HTTP server + web flux) 8 | - spring-boot-starter-webflux 9 | - #### Data 10 | - spring-boot-starter-data-r2dbc 11 | - r2dbc-mysql 12 | - mysql-connector-java 13 | - #### Cloud 14 | - ##### Config Client 15 | - spring-cloud-starter-config 16 | - ##### Naming Server Client 17 | - spring-cloud-starter-netflix-eureka-client 18 | - ##### Distributed Tracing 19 | - spring-cloud-sleuth-zipkin 20 | - spring-cloud-starter-sleuth 21 | - #### Messaging 22 | - #### AMQP (Spring AMQP and Rabbit MQ) 23 | - #### Security 24 | - ##### Spring Security 25 | - spring-cloud-starter-security 26 | - ##### [OAuth2 Resource Server](./../moreinfo.md#Resource-server) 27 | - spring-boot-starter-oauth2-resource-server 28 | - #### AOP 29 | - spring-boot-starter-aop 30 | - #### Logstash (Sending logs to Logstash) 31 | - reactive-logstash-logging-spring-boot-starter 32 | - ### Database Migration (Custom Implementation) 33 | - r2dbc-migrate-spring-boot-starter 34 | - #### [Dependencies From Parent](./../moreinfo.md#Dependencies-from-parent) 35 | 36 | [Distributed Tracing](./../moreinfo.md#distributed-tracing) 37 | ----------------------------------------------------------- 38 | [ELK Stack](./../moreinfo.md#elk-stack) 39 | --------------------------------------- 40 | [Audience Validation](./../moreinfo.md#audience-validation) 41 | ------------------------ -------------------------------------------------------------------------------- /audit/src/main/java/com/ubaid/ms/AuditApplication.java: -------------------------------------------------------------------------------- 1 | package com.ubaid.ms; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | import org.springframework.web.reactive.config.EnableWebFlux; 7 | 8 | @SpringBootApplication 9 | @EnableDiscoveryClient 10 | @EnableWebFlux 11 | public class AuditApplication { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(AuditApplication.class, args); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /audit/src/main/java/com/ubaid/ms/audit/config/Beans.java: -------------------------------------------------------------------------------- 1 | package com.ubaid.ms.audit.config; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import org.springframework.beans.factory.config.ConfigurableBeanFactory; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Scope; 7 | 8 | public class Beans { 9 | 10 | @Bean 11 | @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) 12 | public ObjectMapper objectMapper() { 13 | return new ObjectMapper(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /audit/src/main/java/com/ubaid/ms/audit/config/MessageBrokerConfig.java: -------------------------------------------------------------------------------- 1 | package com.ubaid.ms.audit.config; 2 | 3 | import org.springframework.amqp.core.Queue; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | import static com.ubaid.ms.common.util.Constants.AUDIT_QUEUE; 8 | 9 | @Configuration 10 | public class MessageBrokerConfig { 11 | 12 | @Bean 13 | public Queue auditQueue() { 14 | return new Queue(AUDIT_QUEUE, false); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /audit/src/main/java/com/ubaid/ms/audit/controller/InfoController.java: -------------------------------------------------------------------------------- 1 | package com.ubaid.ms.audit.controller; 2 | 3 | import com.ubaid.ms.audit.service.InfoService; 4 | import com.ubaid.ms.common.dto.serviceinfo.ServiceInformation; 5 | import lombok.RequiredArgsConstructor; 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | @RestController 12 | @RequestMapping("v1") 13 | @RequiredArgsConstructor 14 | public class InfoController { 15 | private final InfoService infoService; 16 | 17 | @GetMapping("info") 18 | public ResponseEntity getInfo() { 19 | return ResponseEntity.ok(infoService.get()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /audit/src/main/java/com/ubaid/ms/audit/dao/AuditDAO.java: -------------------------------------------------------------------------------- 1 | package com.ubaid.ms.audit.dao; 2 | 3 | import com.ubaid.ms.audit.entity.Audit; 4 | import org.springframework.data.r2dbc.repository.Query; 5 | import org.springframework.data.r2dbc.repository.R2dbcRepository; 6 | import reactor.core.publisher.Flux; 7 | import reactor.core.publisher.Mono; 8 | 9 | public interface AuditDAO extends R2dbcRepository { 10 | Flux findAllByUserUuid(String userUUID); 11 | 12 | @Query(value = "UPDATE audit SET is_deleted=true WHERE id = :id") 13 | Mono delete(Long id); 14 | } 15 | -------------------------------------------------------------------------------- /audit/src/main/java/com/ubaid/ms/audit/entity/Audit.java: -------------------------------------------------------------------------------- 1 | package com.ubaid.ms.audit.entity; 2 | 3 | import lombok.Data; 4 | import org.springframework.data.annotation.Id; 5 | import org.springframework.data.relational.core.mapping.Table; 6 | 7 | import java.time.Instant; 8 | 9 | @Data 10 | @Table 11 | public class Audit { 12 | 13 | @Id 14 | private Long id; 15 | private String userUuid; 16 | private Instant createdAt; 17 | private String fromCurrency; 18 | private String toCurrency; 19 | private double exchangeRate; 20 | private double fromCurrencyValue; 21 | private double toCurrencyValue; 22 | private String userIPAddress; 23 | private String currencyExchangeURL; 24 | private String currencyConversionURL; 25 | private int currencyExchangePort; 26 | private int currencyConversionPort; 27 | private boolean isDeleted; 28 | private Instant lastUpdated; 29 | } 30 | -------------------------------------------------------------------------------- /audit/src/main/java/com/ubaid/ms/audit/service/AuditService.java: -------------------------------------------------------------------------------- 1 | package com.ubaid.ms.audit.service; 2 | 3 | import com.ubaid.ms.audit.entity.Audit; 4 | import reactor.core.publisher.Flux; 5 | import reactor.core.publisher.Mono; 6 | 7 | import java.security.Principal; 8 | 9 | public interface AuditService { 10 | Mono findById(Long id); 11 | Flux findAllByUserUUID(Principal principal); 12 | Flux findAll(); 13 | Mono save(Principal principal, Audit audit); 14 | Mono update(Principal principal, Audit audit); 15 | void save(Audit audit); 16 | Mono delete(Long id); 17 | } 18 | -------------------------------------------------------------------------------- /audit/src/main/java/com/ubaid/ms/audit/service/InfoService.java: -------------------------------------------------------------------------------- 1 | package com.ubaid.ms.audit.service; 2 | 3 | import com.ubaid.ms.common.dto.serviceinfo.ServiceInformation; 4 | 5 | public interface InfoService { 6 | ServiceInformation get(); 7 | } 8 | -------------------------------------------------------------------------------- /audit/src/main/java/com/ubaid/ms/audit/service/InfoServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ubaid.ms.audit.service; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import com.netflix.appinfo.ApplicationInfoManager; 5 | import com.ubaid.ms.common.dto.serviceinfo.ServiceInformation; 6 | import com.ubaid.ms.common.dto.serviceinfo.ServiceInformationBuilder; 7 | import lombok.RequiredArgsConstructor; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.boot.actuate.info.InfoEndpoint; 10 | import org.springframework.stereotype.Service; 11 | 12 | @Service 13 | @Slf4j 14 | @RequiredArgsConstructor 15 | public class InfoServiceImpl implements InfoService { 16 | 17 | private final InfoEndpoint infoEndpoint; 18 | private final ObjectMapper objectMapper; 19 | private final ApplicationInfoManager applicationInfoManager; 20 | 21 | @Override 22 | public ServiceInformation get() { 23 | ServiceInformationBuilder builder = ServiceInformationBuilder 24 | .builder(objectMapper.convertValue(infoEndpoint.info(), ServiceInformation.class)); 25 | builder.name(applicationInfoManager.getInfo().getAppName()); 26 | ServiceInformation serviceInformation = builder.build(); 27 | log.debug("Service Information: {}", serviceInformation); 28 | return serviceInformation; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /audit/src/main/resources/application-dev.properties: -------------------------------------------------------------------------------- 1 | #------------------------Config Client--------------------------# 2 | spring.config.import=optional:configserver:http://config:8888 3 | spring.cloud.config.profile=dev 4 | spring.cloud.config.fail-fast=true 5 | spring.cloud.config.request-connect-timeout=30000 6 | spring.cloud.config.request-read-timeout=360000 -------------------------------------------------------------------------------- /audit/src/main/resources/application-local.properties: -------------------------------------------------------------------------------- 1 | #------------------------Config Client--------------------------# 2 | spring.config.import=optional:configserver:http://localhost:8888 3 | spring.cloud.config.profile=local 4 | 5 | #------------------------Live Reload --------------------------# 6 | spring.devtools.livereload.port=35731 7 | 8 | 9 | #------------------------Logs --------------------------# 10 | logging.level.org.springframework.security=DEBUG 11 | logging.level.org.springframework.web.reactive.function.client=DEBUG 12 | logging.level.com.ubaid.ms.auditservice=DEBUG 13 | logging.level.name.nkonev.r2dbc=DEBUG 14 | logging.level.com.ubaid.ms=TRACE 15 | 16 | #------------------------Actuator --------------------------# 17 | management.endpoints.web.exposure.include=health,info 18 | management.endpoint.health.enabled=true 19 | management.endpoint.health.probes.enabled=true 20 | -------------------------------------------------------------------------------- /audit/src/main/resources/application-prod.properties: -------------------------------------------------------------------------------- 1 | #------------------------Config Client--------------------------# 2 | spring.config.import=optional:configserver:http://config:8888 3 | spring.cloud.config.profile=prod 4 | spring.cloud.config.fail-fast=true 5 | spring.cloud.config.request-connect-timeout=30000 6 | spring.cloud.config.request-read-timeout=360000 -------------------------------------------------------------------------------- /audit/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #----------------------------SApplication config-----------------------------------# 2 | spring.application.name=audit 3 | server.port=8950 4 | 5 | #----------------------------Active Profile----------------------------------------# 6 | spring.profiles.active=@activatedProperties@ 7 | 8 | #----------------------------Static IP---------------------------------------------# 9 | eureka.instance.prefer-ip-address=true 10 | eureka.instance.instance-id=${spring.cloud.client.ip-address}:${server.port} 11 | eureka.instance.hostname=${spring.cloud.client.ip-address} 12 | -------------------------------------------------------------------------------- /audit/src/main/resources/config.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubaid4j/Cloud-Native-App-Spring-Boot/d023b0a732b43f4196176cd9fa3a67490a79eaab/audit/src/main/resources/config.properties -------------------------------------------------------------------------------- /audit/src/main/resources/db/migration/V1__gh_301_create_audit_table.sql: -------------------------------------------------------------------------------- 1 | create table audit ( 2 | id bigint primary key auto_increment, 3 | created_at timestamp, 4 | currency_conversion_port int, 5 | currency_conversion_url varchar(255), 6 | currency_exchange_port int, 7 | currency_exchange_url varchar(255), 8 | exchange_rate float, 9 | from_currency varchar(255), 10 | from_currency_value float, 11 | to_currency varchar(255), 12 | to_currency_value float, 13 | is_deleted boolean, 14 | last_updated timestamp, 15 | user_ip_address varchar(255), 16 | user_uuid varchar(255) 17 | ) -------------------------------------------------------------------------------- /audit/src/main/resources/db/migration/V2__gh_360_replace_float_with_double.sql: -------------------------------------------------------------------------------- 1 | alter table audit 2 | modify column exchange_rate double; 3 | 4 | alter table audit 5 | modify column from_currency_value double; 6 | 7 | alter table audit 8 | modify column to_currency_value double; 9 | -------------------------------------------------------------------------------- /audit/src/test/java/com/ubaid/ms/auditservice/AuditApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.ubaid.ms.auditservice; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class AuditApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /build-3cn-parent-image.sh: -------------------------------------------------------------------------------- 1 | docker build -t ubaidurehman/3cn-parent:0.0.3-SNAPSHOT -f Dockerfile.3cn-parent-init . -------------------------------------------------------------------------------- /build-all-microservice-images.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | declare -a microservices=("api-gateway" "audit" "config" "country" "currency-conversion" "currency-exchange" "discovery" "math" "user") 3 | APP_VERSION=0.0.3-SNAPSHOT 4 | for microservice in "${microservices[@]}" 5 | do 6 | echo buidling image of "$microservice" 7 | mvn spring-boot:build-image -DskipTests -f "$microservice" 8 | echo tagging "$microservice":$APP_VERSION to ubaidurehman/"$microservice":$APP_VERSION 9 | docker tag "$microservice":$APP_VERSION ubaidurehman/"$microservice":$APP_VERSION 10 | done -------------------------------------------------------------------------------- /clients/3cn-react-client/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea 3 | *.drawio 4 | .gitignore -------------------------------------------------------------------------------- /clients/3cn-react-client/.env.dev: -------------------------------------------------------------------------------- 1 | REACT_APP_ENV=dev -------------------------------------------------------------------------------- /clients/3cn-react-client/.env.prod: -------------------------------------------------------------------------------- 1 | REACT_APP_ENV=prod -------------------------------------------------------------------------------- /clients/3cn-react-client/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "node": true 6 | }, 7 | "extends": [ 8 | "eslint:recommended", 9 | "plugin:react/recommended" 10 | ], 11 | "parserOptions": { 12 | "ecmaFeatures": { 13 | "jsx": true 14 | }, 15 | "ecmaVersion": 12, 16 | "sourceType": "module" 17 | }, 18 | "plugins": [ 19 | "react" 20 | ], 21 | "rules": { 22 | "indent": [ 23 | "error", 24 | 4 25 | ], 26 | "linebreak-style": [ 27 | "error", 28 | "unix" 29 | ], 30 | "quotes": [ 31 | "error", 32 | "single" 33 | ], 34 | "semi": [ 35 | "error", 36 | "always" 37 | ] 38 | }, 39 | "settings": { 40 | "react" : { 41 | "version": "latest" 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /clients/3cn-react-client/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | package-lock.json 26 | -------------------------------------------------------------------------------- /clients/3cn-react-client/Dockerfile: -------------------------------------------------------------------------------- 1 | #To build image: docker run -t 3cn-fe:{version} --build-arg ENV={env} . 2 | FROM node:14.17.3-alpine as build 3 | WORKDIR /app 4 | ENV PATH /app/node_modules/.bin:$PATH 5 | COPY package.json ./ 6 | RUN npm install 7 | COPY . ./ 8 | ARG ENV 9 | RUN npm run build:${ENV} 10 | 11 | # production environment 12 | FROM nginx:stable-alpine 13 | COPY --from=build /app/build /usr/share/nginx/html 14 | # new 15 | COPY nginx/nginx.conf /etc/nginx/conf.d/default.conf 16 | EXPOSE 80 17 | CMD ["nginx", "-g", "daemon off;"] -------------------------------------------------------------------------------- /clients/3cn-react-client/README.md: -------------------------------------------------------------------------------- 1 | Stay Tuned 2 | ========== 3 | 4 | 5 | # Notes: 6 | - ### ES LINT 7 | - To add Linting: ```eslint --init``` 8 | - To lint through all .js files: ```eslint . --ext .js``` 9 | -------------------------------------------------------------------------------- /clients/3cn-react-client/build-push-prod-ui-image.sh: -------------------------------------------------------------------------------- 1 | docker build -t ubaidurehman/3cn-fe:0.0.3-SNAPSHOT --build-arg ENV=prod . 2 | docker push ubaidurehman/3cn-fe:0.0.3-SNAPSHOT -------------------------------------------------------------------------------- /clients/3cn-react-client/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "src" 4 | }, 5 | "include": [ 6 | "src" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /clients/3cn-react-client/nginx/nginx.conf: -------------------------------------------------------------------------------- 1 | server { 2 | 3 | listen 80; 4 | 5 | location / { 6 | root /usr/share/nginx/html; 7 | index index.html index.htm; 8 | try_files $uri $uri/ /index.html; 9 | } 10 | 11 | error_page 500 502 503 504 /50x.html; 12 | 13 | location = /50x.html { 14 | root /usr/share/nginx/html; 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /clients/3cn-react-client/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubaid4j/Cloud-Native-App-Spring-Boot/d023b0a732b43f4196176cd9fa3a67490a79eaab/clients/3cn-react-client/public/favicon.ico -------------------------------------------------------------------------------- /clients/3cn-react-client/public/keycloak-dev.json: -------------------------------------------------------------------------------- 1 | { 2 | "realm": "3cn", 3 | "auth-server-url": "http://auth-server:9999/auth/", 4 | "ssl-required": "external", 5 | "resource": "3cn-react-client", 6 | "public-client": true, 7 | "confidential-port": 0 8 | } 9 | -------------------------------------------------------------------------------- /clients/3cn-react-client/public/keycloak-local.json: -------------------------------------------------------------------------------- 1 | { 2 | "realm": "3cn", 3 | "auth-server-url": "http://localhost:9999/auth/", 4 | "ssl-required": "external", 5 | "resource": "3cn-react-client", 6 | "public-client": true, 7 | "confidential-port": 0 8 | } 9 | -------------------------------------------------------------------------------- /clients/3cn-react-client/public/keycloak-prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "realm": "3cn", 3 | "auth-server-url": "http://auth-server-io/auth", 4 | "ssl-required": "external", 5 | "resource": "3cn-react-client", 6 | "public-client": true, 7 | "confidential-port": 0 8 | } 9 | -------------------------------------------------------------------------------- /clients/3cn-react-client/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubaid4j/Cloud-Native-App-Spring-Boot/d023b0a732b43f4196176cd9fa3a67490a79eaab/clients/3cn-react-client/public/logo192.png -------------------------------------------------------------------------------- /clients/3cn-react-client/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubaid4j/Cloud-Native-App-Spring-Boot/d023b0a732b43f4196176cd9fa3a67490a79eaab/clients/3cn-react-client/public/logo512.png -------------------------------------------------------------------------------- /clients/3cn-react-client/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /clients/3cn-react-client/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /clients/3cn-react-client/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | -------------------------------------------------------------------------------- /clients/3cn-react-client/src/App.js: -------------------------------------------------------------------------------- 1 | import 'App.css'; 2 | import React, {Suspense} from 'react'; 3 | import {Route, Switch} from 'react-router'; 4 | import Layout from 'hoc/Layout/Layout'; 5 | import CurrencyConverter from 'container/CurrencyConverter/CurrencyConverter'; 6 | import UserInfo from 'component/userinfo/UserInfo'; 7 | import ServiceDown from 'component/down/ServiceDown'; 8 | import ProtectedRoute from 'util/ProtectedRoute'; 9 | import Authenticate from 'component/auth/Authenticate'; 10 | import {ReactKeycloakProvider} from '@react-keycloak/web'; 11 | import keycloak from 'keycloak'; 12 | 13 | const App = () => { 14 | 15 | let routes = ( 16 | 17 | Loading.....

}> 18 | 19 | 20 | 21 | 22 |
23 |
24 | ); 25 | 26 | return ( 27 | 28 |
29 | 30 | {routes} 31 | 32 |
33 |
34 | ); 35 | }; 36 | export default App; 37 | -------------------------------------------------------------------------------- /clients/3cn-react-client/src/component/auth/Authenticate.js: -------------------------------------------------------------------------------- 1 | import React, {useCallback} from 'react'; 2 | import {useKeycloak} from '@react-keycloak/web'; 3 | import {Redirect} from 'react-router-dom'; 4 | import {useDispatch} from 'react-redux'; 5 | import {AddAccessToken} from 'store/actions/AuthAction'; 6 | 7 | const Authenticate = () => { 8 | 9 | const {initialized, keycloak} = useKeycloak(); 10 | const dispatch = useDispatch(); 11 | const addAccessToken = useCallback((accessToken) => dispatch(AddAccessToken(accessToken)), []); 12 | 13 | if (initialized && keycloak && !keycloak.authenticated) { 14 | console.log('In Authenticate: Login called'); 15 | keycloak.login(); 16 | } 17 | 18 | if (!initialized || !keycloak || !keycloak.authenticated) { 19 | return ( 20 |
21 | Authenticating, please wait.... 22 |
23 | ); 24 | } 25 | 26 | if (initialized && keycloak && keycloak.authenticated) { 27 | console.log('-----------------------In Authenticate--------------- Adding access token in state'); 28 | addAccessToken(keycloak.token); 29 | 30 | return ( 31 | 32 | ); 33 | } 34 | }; 35 | 36 | export default Authenticate; 37 | -------------------------------------------------------------------------------- /clients/3cn-react-client/src/component/convertionPaper/ConversionPaper.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React from 'react'; 3 | import {Container, Typography} from '@material-ui/core'; 4 | 5 | const ConversionPaper = ({fromCountry, toCountry, convertedAmount}) => { 6 | return ( 7 | 8 | {fromCountry ? fromCountry.currencyName + ' ' + fromCountry.country + '(' + fromCountry.currencyCode + ')' : ''} to {toCountry ? toCountry.currencyName + ' ' + toCountry.country + '(' + toCountry.currencyCode + ')' : ''} 9 |
10 | The Converted Amount is: {convertedAmount ? convertedAmount.exchangedCurrencyQuantity : ''} 11 |
12 | ); 13 | }; 14 | 15 | export default ConversionPaper; 16 | 17 | ConversionPaper.propTypes = { 18 | fromCountry : PropTypes.object, 19 | toCountry : PropTypes.object, 20 | convertedAmount: PropTypes.object 21 | }; 22 | 23 | -------------------------------------------------------------------------------- /clients/3cn-react-client/src/component/down/ServiceDown.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | const ServiceDown = () => { 3 | return ( 4 | <> 5 |

Service is Down. Sorry for inconvenience

6 | 7 | ); 8 | }; 9 | export default ServiceDown; 10 | -------------------------------------------------------------------------------- /clients/3cn-react-client/src/component/footer/Footer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { makeStyles } from '@material-ui/core/styles'; 3 | import BottomNavigation from '@material-ui/core/BottomNavigation'; 4 | import BottomNavigationAction from '@material-ui/core/BottomNavigationAction'; 5 | import InfoIcon from '@material-ui/icons/Info'; 6 | import RestoreIcon from '@material-ui/icons/Restore'; 7 | 8 | const useStyles = makeStyles({ 9 | root: { 10 | flexGrow: 1, 11 | width: '100%', 12 | position: 'fixed', 13 | bottom: 0 14 | }, 15 | }); 16 | 17 | 18 | const Footer = () => { 19 | 20 | const classes = useStyles(); 21 | const [value, setValue] = React.useState('Recents'); 22 | 23 | const handleChange = (event, newValue) => { 24 | setValue(newValue); 25 | }; 26 | return ( 27 | 28 | } /> 29 | } /> 30 | 31 | ); 32 | }; 33 | export default Footer; 34 | -------------------------------------------------------------------------------- /clients/3cn-react-client/src/component/userinfo/UserInfo.js: -------------------------------------------------------------------------------- 1 | import {useKeycloak} from '@react-keycloak/web'; 2 | import React from 'react'; 3 | 4 | const UserInfo = () => { 5 | const { keycloak, initialized } = useKeycloak(); 6 | 7 | if (keycloak && initialized && keycloak.authenticated) { 8 | return ( 9 |
10 | Hello {keycloak.tokenParsed.preferred_username} 11 | 14 |
15 | ); 16 | } 17 | }; 18 | export default UserInfo; 19 | -------------------------------------------------------------------------------- /clients/3cn-react-client/src/hoc/Layout/Layout.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import CssBaseline from '@material-ui/core/CssBaseline'; 3 | import Container from '@material-ui/core/Container'; 4 | import PropTypes from 'prop-types'; 5 | import Header from 'component/header/Header'; 6 | import Footer from 'component/footer/Footer'; 7 | 8 | const Layout = props => { 9 | return ( 10 | <> 11 | 12 |
13 | 14 | {props.children} 15 | 16 |