├── .idea
├── .gitignore
├── compiler.xml
├── encodings.xml
├── jarRepositories.xml
├── misc.xml
└── vcs.xml
├── ecom-app-angular
├── .editorconfig
├── .gitignore
├── .vscode
│ ├── extensions.json
│ ├── launch.json
│ └── tasks.json
├── README.md
├── angular.json
├── package-lock.json
├── package.json
├── src
│ ├── app
│ │ ├── app-routing.module.ts
│ │ ├── app.component.css
│ │ ├── app.component.html
│ │ ├── app.component.spec.ts
│ │ ├── app.component.ts
│ │ ├── app.module.ts
│ │ ├── guards
│ │ │ ├── auth.guard.spec.ts
│ │ │ └── auth.guard.ts
│ │ └── ui
│ │ │ ├── customers
│ │ │ ├── customers.component.css
│ │ │ ├── customers.component.html
│ │ │ ├── customers.component.spec.ts
│ │ │ └── customers.component.ts
│ │ │ ├── order-details
│ │ │ ├── order-details.component.css
│ │ │ ├── order-details.component.html
│ │ │ ├── order-details.component.spec.ts
│ │ │ └── order-details.component.ts
│ │ │ ├── orders
│ │ │ ├── orders.component.css
│ │ │ ├── orders.component.html
│ │ │ ├── orders.component.spec.ts
│ │ │ └── orders.component.ts
│ │ │ └── products
│ │ │ ├── products.component.css
│ │ │ ├── products.component.html
│ │ │ ├── products.component.spec.ts
│ │ │ └── products.component.ts
│ ├── assets
│ │ ├── .gitkeep
│ │ └── silent-check-sso.html
│ ├── favicon.ico
│ ├── index.html
│ ├── main.ts
│ └── styles.css
├── tsconfig.app.json
├── tsconfig.json
└── tsconfig.spec.json
├── inventory-service
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── net
│ │ │ └── youssfi
│ │ │ └── inventoryservice
│ │ │ ├── InventoryServiceApplication.java
│ │ │ ├── entities
│ │ │ └── Product.java
│ │ │ ├── repository
│ │ │ └── ProductRepository.java
│ │ │ ├── security
│ │ │ ├── JwtAuthConverter.java
│ │ │ └── SecurityConfig.java
│ │ │ └── web
│ │ │ └── ProductRestController.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── net
│ └── youssfi
│ └── inventoryservice
│ └── InventoryServiceApplicationTests.java
├── order-service
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── net
│ │ │ └── youssfi
│ │ │ └── orderservice
│ │ │ ├── OrderServiceApplication.java
│ │ │ ├── entities
│ │ │ ├── Order.java
│ │ │ ├── OrderState.java
│ │ │ └── ProductItem.java
│ │ │ ├── interceptors
│ │ │ └── FeignInterceptor.java
│ │ │ ├── model
│ │ │ └── Product.java
│ │ │ ├── repsoitories
│ │ │ ├── OrderRepository.java
│ │ │ └── ProductItemRepository.java
│ │ │ ├── restclients
│ │ │ └── InventoryRestClient.java
│ │ │ ├── security
│ │ │ ├── JwtAuthConverter.java
│ │ │ └── SecurityConfig.java
│ │ │ └── web
│ │ │ └── OrdersRestControllers.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── net
│ └── youssfi
│ └── orderservice
│ └── OrderServiceApplicationTests.java
├── pom.xml
└── src
└── main
└── java
└── net
└── youssfi
└── Main.java
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/ecom-app-angular/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see https://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.ts]
12 | quote_type = single
13 |
14 | [*.md]
15 | max_line_length = off
16 | trim_trailing_whitespace = false
17 |
--------------------------------------------------------------------------------
/ecom-app-angular/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # Compiled output
4 | /dist
5 | /tmp
6 | /out-tsc
7 | /bazel-out
8 |
9 | # Node
10 | /node_modules
11 | npm-debug.log
12 | yarn-error.log
13 |
14 | # IDEs and editors
15 | .idea/
16 | .project
17 | .classpath
18 | .c9/
19 | *.launch
20 | .settings/
21 | *.sublime-workspace
22 |
23 | # Visual Studio Code
24 | .vscode/*
25 | !.vscode/settings.json
26 | !.vscode/tasks.json
27 | !.vscode/launch.json
28 | !.vscode/extensions.json
29 | .history/*
30 |
31 | # Miscellaneous
32 | /.angular/cache
33 | .sass-cache/
34 | /connect.lock
35 | /coverage
36 | /libpeerconnection.log
37 | testem.log
38 | /typings
39 |
40 | # System files
41 | .DS_Store
42 | Thumbs.db
43 |
--------------------------------------------------------------------------------
/ecom-app-angular/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846
3 | "recommendations": ["angular.ng-template"]
4 | }
5 |
--------------------------------------------------------------------------------
/ecom-app-angular/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
3 | "version": "0.2.0",
4 | "configurations": [
5 | {
6 | "name": "ng serve",
7 | "type": "chrome",
8 | "request": "launch",
9 | "preLaunchTask": "npm: start",
10 | "url": "http://localhost:4200/"
11 | },
12 | {
13 | "name": "ng test",
14 | "type": "chrome",
15 | "request": "launch",
16 | "preLaunchTask": "npm: test",
17 | "url": "http://localhost:9876/debug.html"
18 | }
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------
/ecom-app-angular/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558
3 | "version": "2.0.0",
4 | "tasks": [
5 | {
6 | "type": "npm",
7 | "script": "start",
8 | "isBackground": true,
9 | "problemMatcher": {
10 | "owner": "typescript",
11 | "pattern": "$tsc",
12 | "background": {
13 | "activeOnStart": true,
14 | "beginsPattern": {
15 | "regexp": "(.*?)"
16 | },
17 | "endsPattern": {
18 | "regexp": "bundle generation complete"
19 | }
20 | }
21 | }
22 | },
23 | {
24 | "type": "npm",
25 | "script": "test",
26 | "isBackground": true,
27 | "problemMatcher": {
28 | "owner": "typescript",
29 | "pattern": "$tsc",
30 | "background": {
31 | "activeOnStart": true,
32 | "beginsPattern": {
33 | "regexp": "(.*?)"
34 | },
35 | "endsPattern": {
36 | "regexp": "bundle generation complete"
37 | }
38 | }
39 | }
40 | }
41 | ]
42 | }
43 |
--------------------------------------------------------------------------------
/ecom-app-angular/README.md:
--------------------------------------------------------------------------------
1 | # EcomAppAngular
2 |
3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 17.0.1.
4 |
5 | ## Development server
6 |
7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files.
8 |
9 | ## Code scaffolding
10 |
11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
12 |
13 | ## Build
14 |
15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory.
16 |
17 | ## Running unit tests
18 |
19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
20 |
21 | ## Running end-to-end tests
22 |
23 | Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities.
24 |
25 | ## Further help
26 |
27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
28 |
--------------------------------------------------------------------------------
/ecom-app-angular/angular.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3 | "version": 1,
4 | "newProjectRoot": "projects",
5 | "projects": {
6 | "ecom-app-angular": {
7 | "projectType": "application",
8 | "schematics": {
9 | "@schematics/angular:component": {
10 | "standalone": false
11 | },
12 | "@schematics/angular:directive": {
13 | "standalone": false
14 | },
15 | "@schematics/angular:pipe": {
16 | "standalone": false
17 | }
18 | },
19 | "root": "",
20 | "sourceRoot": "src",
21 | "prefix": "app",
22 | "architect": {
23 | "build": {
24 | "builder": "@angular-devkit/build-angular:application",
25 | "options": {
26 | "outputPath": "dist/ecom-app-angular",
27 | "index": "src/index.html",
28 | "browser": "src/main.ts",
29 | "polyfills": [
30 | "zone.js"
31 | ],
32 | "tsConfig": "tsconfig.app.json",
33 | "assets": [
34 | "src/favicon.ico",
35 | "src/assets"
36 | ],
37 | "styles": [
38 | "src/styles.css",
39 | "node_modules/bootstrap/dist/css/bootstrap.min.css"
40 | ],
41 | "scripts": [
42 | "node_modules/bootstrap/dist/js/bootstrap.bundle.js"
43 | ]
44 | },
45 | "configurations": {
46 | "production": {
47 | "budgets": [
48 | {
49 | "type": "initial",
50 | "maximumWarning": "500kb",
51 | "maximumError": "1mb"
52 | },
53 | {
54 | "type": "anyComponentStyle",
55 | "maximumWarning": "2kb",
56 | "maximumError": "4kb"
57 | }
58 | ],
59 | "outputHashing": "all"
60 | },
61 | "development": {
62 | "optimization": false,
63 | "extractLicenses": false,
64 | "sourceMap": true
65 | }
66 | },
67 | "defaultConfiguration": "production"
68 | },
69 | "serve": {
70 | "builder": "@angular-devkit/build-angular:dev-server",
71 | "configurations": {
72 | "production": {
73 | "buildTarget": "ecom-app-angular:build:production"
74 | },
75 | "development": {
76 | "buildTarget": "ecom-app-angular:build:development"
77 | }
78 | },
79 | "defaultConfiguration": "development"
80 | },
81 | "extract-i18n": {
82 | "builder": "@angular-devkit/build-angular:extract-i18n",
83 | "options": {
84 | "buildTarget": "ecom-app-angular:build"
85 | }
86 | },
87 | "test": {
88 | "builder": "@angular-devkit/build-angular:karma",
89 | "options": {
90 | "polyfills": [
91 | "zone.js",
92 | "zone.js/testing"
93 | ],
94 | "tsConfig": "tsconfig.spec.json",
95 | "assets": [
96 | "src/favicon.ico",
97 | "src/assets"
98 | ],
99 | "styles": [
100 | "src/styles.css"
101 | ],
102 | "scripts": []
103 | }
104 | }
105 | }
106 | }
107 | },
108 | "cli": {
109 | "analytics": "fca32e76-93fd-46c6-b34a-7b80ebe4a76b"
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/ecom-app-angular/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ecom-app-angular",
3 | "version": "0.0.0",
4 | "scripts": {
5 | "ng": "ng",
6 | "start": "ng serve",
7 | "build": "ng build",
8 | "watch": "ng build --watch --configuration development",
9 | "test": "ng test"
10 | },
11 | "private": true,
12 | "dependencies": {
13 | "@angular/animations": "^17.0.0",
14 | "@angular/common": "^17.0.0",
15 | "@angular/compiler": "^17.0.0",
16 | "@angular/core": "^17.0.0",
17 | "@angular/forms": "^17.0.0",
18 | "@angular/platform-browser": "^17.0.0",
19 | "@angular/platform-browser-dynamic": "^17.0.0",
20 | "@angular/router": "^17.0.0",
21 | "bootstrap": "^5.3.2",
22 | "bootstrap-icons": "^1.11.3",
23 | "keycloak-angular": "^15.1.0",
24 | "keycloak-js": "^23.0.6",
25 | "rxjs": "~7.8.0",
26 | "tslib": "^2.3.0",
27 | "zone.js": "~0.14.2"
28 | },
29 | "devDependencies": {
30 | "@angular-devkit/build-angular": "^17.0.1",
31 | "@angular/cli": "^17.0.1",
32 | "@angular/compiler-cli": "^17.0.0",
33 | "@types/jasmine": "~5.1.0",
34 | "jasmine-core": "~5.1.0",
35 | "karma": "~6.4.0",
36 | "karma-chrome-launcher": "~3.2.0",
37 | "karma-coverage": "~2.2.0",
38 | "karma-jasmine": "~5.1.0",
39 | "karma-jasmine-html-reporter": "~2.1.0",
40 | "typescript": "~5.2.2"
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/ecom-app-angular/src/app/app-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { RouterModule, Routes } from '@angular/router';
3 | import {ProductsComponent} from "./ui/products/products.component";
4 | import {CustomersComponent} from "./ui/customers/customers.component";
5 | import {AuthGuard} from "./guards/auth.guard";
6 | import {OrdersComponent} from "./ui/orders/orders.component";
7 | import {OrderDetailsComponent} from "./ui/order-details/order-details.component";
8 |
9 | const routes: Routes = [
10 | {path : "products", component : ProductsComponent, canActivate : [AuthGuard], data : {roles :['ADMIN']}},
11 | {path : "customers", component : CustomersComponent, canActivate : [AuthGuard], data : {roles : ['USER']}},
12 | {path : "orders", component : OrdersComponent, canActivate : [AuthGuard], data : {roles : ['USER']}},
13 | {path : "order-details/:id", component : OrderDetailsComponent, canActivate : [AuthGuard], data : {roles : ['USER']}},
14 | ];
15 |
16 | @NgModule({
17 | imports: [RouterModule.forRoot(routes)],
18 | exports: [RouterModule]
19 | })
20 | export class AppRoutingModule { }
21 |
--------------------------------------------------------------------------------
/ecom-app-angular/src/app/app.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-keycloak-master-IIBDCC/3afc78baa4354130ed75d65dbe90107b68be481b/ecom-app-angular/src/app/app.component.css
--------------------------------------------------------------------------------
/ecom-app-angular/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/ecom-app-angular/src/app/app.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed } from '@angular/core/testing';
2 | import { RouterTestingModule } from '@angular/router/testing';
3 | import { AppComponent } from './app.component';
4 |
5 | describe('AppComponent', () => {
6 | beforeEach(async () => {
7 | await TestBed.configureTestingModule({
8 | imports: [
9 | RouterTestingModule
10 | ],
11 | declarations: [
12 | AppComponent
13 | ],
14 | }).compileComponents();
15 | });
16 |
17 | it('should create the app', () => {
18 | const fixture = TestBed.createComponent(AppComponent);
19 | const app = fixture.componentInstance;
20 | expect(app).toBeTruthy();
21 | });
22 |
23 | it(`should have as title 'ecom-app-angular'`, () => {
24 | const fixture = TestBed.createComponent(AppComponent);
25 | const app = fixture.componentInstance;
26 | expect(app.title).toEqual('ecom-app-angular');
27 | });
28 |
29 | it('should render title', () => {
30 | const fixture = TestBed.createComponent(AppComponent);
31 | fixture.detectChanges();
32 | const compiled = fixture.nativeElement as HTMLElement;
33 | expect(compiled.querySelector('h1')?.textContent).toContain('Hello, ecom-app-angular');
34 | });
35 | });
36 |
--------------------------------------------------------------------------------
/ecom-app-angular/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core';
2 | import {KeycloakService} from "keycloak-angular";
3 | import {KeycloakProfile} from "keycloak-js";
4 |
5 | @Component({
6 | selector: 'app-root',
7 | templateUrl: './app.component.html',
8 | styleUrl: './app.component.css'
9 | })
10 | export class AppComponent implements OnInit{
11 | title = 'ecom-app-angular';
12 | public profile! : KeycloakProfile;
13 | constructor(public keycloakService : KeycloakService) {
14 | }
15 |
16 | ngOnInit() {
17 | if(this.keycloakService.isLoggedIn()){
18 | this.keycloakService.loadUserProfile().then(profile=>{
19 | this.profile=profile;
20 | });
21 | }
22 | }
23 |
24 | async handleLogin() {
25 | await this.keycloakService.login({
26 | redirectUri: window.location.origin
27 | });
28 | }
29 |
30 | handleLogout(){
31 | this.keycloakService.logout(window.location.origin);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/ecom-app-angular/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import {APP_INITIALIZER, NgModule} from '@angular/core';
2 | import { BrowserModule } from '@angular/platform-browser';
3 |
4 | import { AppRoutingModule } from './app-routing.module';
5 | import { AppComponent } from './app.component';
6 | import { ProductsComponent } from './ui/products/products.component';
7 | import { CustomersComponent } from './ui/customers/customers.component';
8 | import {HttpClientModule} from "@angular/common/http";
9 | import {KeycloakAngularModule, KeycloakService} from "keycloak-angular";
10 | import { OrdersComponent } from './ui/orders/orders.component';
11 | import { OrderDetailsComponent } from './ui/order-details/order-details.component';
12 |
13 | function initializeKeycloak(keycloak: KeycloakService) {
14 | return () =>
15 | keycloak.init({
16 | config: {
17 | url: 'http://localhost:8080',
18 | realm: 'bdcc-realm',
19 | clientId: 'ecom-client-ang'
20 | },
21 | initOptions: {
22 | onLoad: 'check-sso',
23 | silentCheckSsoRedirectUri:
24 | window.location.origin + '/assets/silent-check-sso.html'
25 | }
26 | });
27 | }
28 | @NgModule({
29 | declarations: [
30 | AppComponent,
31 | ProductsComponent,
32 | CustomersComponent,
33 | OrdersComponent,
34 | OrderDetailsComponent
35 | ],
36 | imports: [
37 | BrowserModule,
38 | AppRoutingModule, HttpClientModule, KeycloakAngularModule
39 | ],
40 | providers: [
41 | {provide : APP_INITIALIZER, useFactory : initializeKeycloak, multi :true, deps : [KeycloakService]}
42 | ],
43 | bootstrap: [AppComponent]
44 | })
45 | export class AppModule { }
46 |
--------------------------------------------------------------------------------
/ecom-app-angular/src/app/guards/auth.guard.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed } from '@angular/core/testing';
2 | import { CanActivateFn } from '@angular/router';
3 |
4 | import { authGuard } from './auth.guard';
5 |
6 | describe('authGuard', () => {
7 | const executeGuard: CanActivateFn = (...guardParameters) =>
8 | TestBed.runInInjectionContext(() => authGuard(...guardParameters));
9 |
10 | beforeEach(() => {
11 | TestBed.configureTestingModule({});
12 | });
13 |
14 | it('should be created', () => {
15 | expect(executeGuard).toBeTruthy();
16 | });
17 | });
18 |
--------------------------------------------------------------------------------
/ecom-app-angular/src/app/guards/auth.guard.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import {
3 | ActivatedRouteSnapshot,
4 | Router,
5 | RouterStateSnapshot
6 | } from '@angular/router';
7 | import { KeycloakAuthGuard, KeycloakService } from 'keycloak-angular';
8 |
9 | @Injectable({
10 | providedIn: 'root'
11 | })
12 | export class AuthGuard extends KeycloakAuthGuard {
13 | constructor(
14 | protected override readonly router: Router,
15 | protected readonly keycloak: KeycloakService
16 | ) {
17 | super(router, keycloak);
18 | }
19 |
20 | public async isAccessAllowed(
21 | route: ActivatedRouteSnapshot,
22 | state: RouterStateSnapshot
23 | ) {
24 | // Force the user to log in if currently unauthenticated.
25 | if (!this.authenticated) {
26 | await this.keycloak.login({
27 | redirectUri: window.location.origin + state.url
28 | });
29 | }
30 |
31 | // Get the roles required from the route.
32 | const requiredRoles = route.data['roles'];
33 |
34 | // Allow the user to proceed if no additional roles are required to access the route.
35 | if (!Array.isArray(requiredRoles) || requiredRoles.length === 0) {
36 | return true;
37 | }
38 |
39 | // Allow the user to proceed if all the required roles are present.
40 | return requiredRoles.every((role) => this.roles.includes(role));
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/ecom-app-angular/src/app/ui/customers/customers.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-keycloak-master-IIBDCC/3afc78baa4354130ed75d65dbe90107b68be481b/ecom-app-angular/src/app/ui/customers/customers.component.css
--------------------------------------------------------------------------------
/ecom-app-angular/src/app/ui/customers/customers.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
Customers
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ecom-app-angular/src/app/ui/customers/customers.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { CustomersComponent } from './customers.component';
4 |
5 | describe('CustomersComponent', () => {
6 | let component: CustomersComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async () => {
10 | await TestBed.configureTestingModule({
11 | declarations: [CustomersComponent]
12 | })
13 | .compileComponents();
14 |
15 | fixture = TestBed.createComponent(CustomersComponent);
16 | component = fixture.componentInstance;
17 | fixture.detectChanges();
18 | });
19 |
20 | it('should create', () => {
21 | expect(component).toBeTruthy();
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/ecom-app-angular/src/app/ui/customers/customers.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-customers',
5 | templateUrl: './customers.component.html',
6 | styleUrl: './customers.component.css'
7 | })
8 | export class CustomersComponent {
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/ecom-app-angular/src/app/ui/order-details/order-details.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-keycloak-master-IIBDCC/3afc78baa4354130ed75d65dbe90107b68be481b/ecom-app-angular/src/app/ui/order-details/order-details.component.css
--------------------------------------------------------------------------------
/ecom-app-angular/src/app/ui/order-details/order-details.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | - Date : {{orderDetails.date | date : 'dd/MM/yyyy'}}
7 | - State : {{orderDetails.state}}
8 |
9 |
10 |
11 |
12 | | ID |
13 | Product Name |
14 | Price |
15 | Quantity |
16 | Amount |
17 |
18 |
19 |
20 |
21 | | {{pi.id}} |
22 | {{pi.product.name}} |
23 | {{pi.price | number :'0.2-2'}} |
24 | {{pi.quantity}} |
25 | {{pi.quantity * pi.price | number :'0.2-2'}} |
26 |
27 |
28 | | Total |
29 | {{getTotal(orderDetails)| number :'0.2-2'}} |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/ecom-app-angular/src/app/ui/order-details/order-details.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { OrderDetailsComponent } from './order-details.component';
4 |
5 | describe('OrderDetailsComponent', () => {
6 | let component: OrderDetailsComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async () => {
10 | await TestBed.configureTestingModule({
11 | declarations: [OrderDetailsComponent]
12 | })
13 | .compileComponents();
14 |
15 | fixture = TestBed.createComponent(OrderDetailsComponent);
16 | component = fixture.componentInstance;
17 | fixture.detectChanges();
18 | });
19 |
20 | it('should create', () => {
21 | expect(component).toBeTruthy();
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/ecom-app-angular/src/app/ui/order-details/order-details.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core';
2 | import {ActivatedRoute} from "@angular/router";
3 | import {HttpClient} from "@angular/common/http";
4 |
5 | @Component({
6 | selector: 'app-order-details',
7 | templateUrl: './order-details.component.html',
8 | styleUrl: './order-details.component.css'
9 | })
10 | export class OrderDetailsComponent implements OnInit{
11 | orderId : string;
12 | orderDetails : any;
13 | constructor(private route : ActivatedRoute, private http : HttpClient) {
14 | this.orderId = this.route.snapshot.params['id'];
15 | }
16 | ngOnInit() {
17 | this.http.get("http://localhost:8088/api/orders/"+this.orderId).subscribe({
18 | next : order => {
19 | this.orderDetails = order
20 | },
21 | error : err => {
22 | console.log(err);
23 | }
24 | })
25 | }
26 |
27 | getTotal(orderDetails: any) {
28 | let total : number = 0;
29 | for (let pi of orderDetails.productItems){
30 | total = total + (pi.price * pi.quantity);
31 | }
32 | return total;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/ecom-app-angular/src/app/ui/orders/orders.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-keycloak-master-IIBDCC/3afc78baa4354130ed75d65dbe90107b68be481b/ecom-app-angular/src/app/ui/orders/orders.component.css
--------------------------------------------------------------------------------
/ecom-app-angular/src/app/ui/orders/orders.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
Orders
6 |
7 |
8 |
9 | | ID | Date | State | Products Count |
10 |
11 |
12 |
13 |
14 | | {{o.id}} |
15 | {{o.date}} |
16 | {{o.state}} |
17 | {{o.productItems.length}} |
18 |
19 |
20 | |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ecom-app-angular/src/app/ui/orders/orders.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { OrdersComponent } from './orders.component';
4 |
5 | describe('OrdersComponent', () => {
6 | let component: OrdersComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async () => {
10 | await TestBed.configureTestingModule({
11 | declarations: [OrdersComponent]
12 | })
13 | .compileComponents();
14 |
15 | fixture = TestBed.createComponent(OrdersComponent);
16 | component = fixture.componentInstance;
17 | fixture.detectChanges();
18 | });
19 |
20 | it('should create', () => {
21 | expect(component).toBeTruthy();
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/ecom-app-angular/src/app/ui/orders/orders.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core';
2 | import {HttpClient} from "@angular/common/http";
3 | import {Router} from "@angular/router";
4 |
5 | @Component({
6 | selector: 'app-orders',
7 | templateUrl: './orders.component.html',
8 | styleUrl: './orders.component.css'
9 | })
10 | export class OrdersComponent implements OnInit{
11 | public orders : any;
12 |
13 | constructor(private http : HttpClient, private router : Router) {
14 | }
15 | ngOnInit() {
16 | this.http.get("http://localhost:8088/api/orders").subscribe({
17 | next : orders => {
18 | this.orders = orders;
19 | },
20 | error : err => {
21 | console.log(err);
22 | }
23 | })
24 | }
25 |
26 | getOrderDetails(o:any) {
27 | this.router.navigateByUrl("/order-details/"+o.id);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/ecom-app-angular/src/app/ui/products/products.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-keycloak-master-IIBDCC/3afc78baa4354130ed75d65dbe90107b68be481b/ecom-app-angular/src/app/ui/products/products.component.css
--------------------------------------------------------------------------------
/ecom-app-angular/src/app/ui/products/products.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
Products
6 |
7 |
8 |
9 | | ID | Name | Price | Quantity |
10 |
11 |
12 |
13 |
14 | | {{p.id}} |
15 | {{p.name}} |
16 | {{p.price}} |
17 | {{p.quantity}} |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/ecom-app-angular/src/app/ui/products/products.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { ProductsComponent } from './products.component';
4 |
5 | describe('ProductsComponent', () => {
6 | let component: ProductsComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async () => {
10 | await TestBed.configureTestingModule({
11 | declarations: [ProductsComponent]
12 | })
13 | .compileComponents();
14 |
15 | fixture = TestBed.createComponent(ProductsComponent);
16 | component = fixture.componentInstance;
17 | fixture.detectChanges();
18 | });
19 |
20 | it('should create', () => {
21 | expect(component).toBeTruthy();
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/ecom-app-angular/src/app/ui/products/products.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core';
2 | import {HttpClient} from "@angular/common/http";
3 |
4 | @Component({
5 | selector: 'app-products',
6 | templateUrl: './products.component.html',
7 | styleUrl: './products.component.css'
8 | })
9 | export class ProductsComponent implements OnInit{
10 | public products : any;
11 | constructor(private http : HttpClient) {
12 | }
13 | ngOnInit() {
14 | this.http.get("http://localhost:8087/api/products").subscribe({
15 | next : data => {
16 | this.products = data;
17 | },
18 | error : err => {
19 | console.log(err);
20 | }
21 | })
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ecom-app-angular/src/assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-keycloak-master-IIBDCC/3afc78baa4354130ed75d65dbe90107b68be481b/ecom-app-angular/src/assets/.gitkeep
--------------------------------------------------------------------------------
/ecom-app-angular/src/assets/silent-check-sso.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ecom-app-angular/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-keycloak-master-IIBDCC/3afc78baa4354130ed75d65dbe90107b68be481b/ecom-app-angular/src/favicon.ico
--------------------------------------------------------------------------------
/ecom-app-angular/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | EcomAppAngular
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/ecom-app-angular/src/main.ts:
--------------------------------------------------------------------------------
1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
2 |
3 | import { AppModule } from './app/app.module';
4 |
5 |
6 | platformBrowserDynamic().bootstrapModule(AppModule)
7 | .catch(err => console.error(err));
8 |
--------------------------------------------------------------------------------
/ecom-app-angular/src/styles.css:
--------------------------------------------------------------------------------
1 | /* You can add global styles to this file, and also import other style files */
2 |
--------------------------------------------------------------------------------
/ecom-app-angular/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "extends": "./tsconfig.json",
4 | "compilerOptions": {
5 | "outDir": "./out-tsc/app",
6 | "types": []
7 | },
8 | "files": [
9 | "src/main.ts"
10 | ],
11 | "include": [
12 | "src/**/*.d.ts"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/ecom-app-angular/tsconfig.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "compileOnSave": false,
4 | "compilerOptions": {
5 | "outDir": "./dist/out-tsc",
6 | "forceConsistentCasingInFileNames": true,
7 | "strict": true,
8 | "noImplicitOverride": true,
9 | "noPropertyAccessFromIndexSignature": true,
10 | "noImplicitReturns": true,
11 | "noFallthroughCasesInSwitch": true,
12 | "esModuleInterop": true,
13 | "sourceMap": true,
14 | "declaration": false,
15 | "experimentalDecorators": true,
16 | "moduleResolution": "node",
17 | "importHelpers": true,
18 | "target": "ES2022",
19 | "module": "ES2022",
20 | "useDefineForClassFields": false,
21 | "lib": [
22 | "ES2022",
23 | "dom"
24 | ]
25 | },
26 | "angularCompilerOptions": {
27 | "enableI18nLegacyMessageIdFormat": false,
28 | "strictInjectionParameters": true,
29 | "strictInputAccessModifiers": true,
30 | "strictTemplates": true
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/ecom-app-angular/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "extends": "./tsconfig.json",
4 | "compilerOptions": {
5 | "outDir": "./out-tsc/spec",
6 | "types": [
7 | "jasmine"
8 | ]
9 | },
10 | "include": [
11 | "src/**/*.spec.ts",
12 | "src/**/*.d.ts"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/inventory-service/.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 |
--------------------------------------------------------------------------------
/inventory-service/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-keycloak-master-IIBDCC/3afc78baa4354130ed75d65dbe90107b68be481b/inventory-service/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/inventory-service/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
3 |
--------------------------------------------------------------------------------
/inventory-service/mvnw:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # ----------------------------------------------------------------------------
3 | # Licensed to the Apache Software Foundation (ASF) under one
4 | # or more contributor license agreements. See the NOTICE file
5 | # distributed with this work for additional information
6 | # regarding copyright ownership. The ASF licenses this file
7 | # to you under the Apache License, Version 2.0 (the
8 | # "License"); you may not use this file except in compliance
9 | # with the License. You may obtain a copy of the License at
10 | #
11 | # https://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing,
14 | # software distributed under the License is distributed on an
15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | # KIND, either express or implied. See the License for the
17 | # specific language governing permissions and limitations
18 | # under the License.
19 | # ----------------------------------------------------------------------------
20 |
21 | # ----------------------------------------------------------------------------
22 | # Apache Maven Wrapper startup batch script, version 3.2.0
23 | #
24 | # Required ENV vars:
25 | # ------------------
26 | # JAVA_HOME - location of a JDK home dir
27 | #
28 | # Optional ENV vars
29 | # -----------------
30 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | # e.g. to debug Maven itself, use
32 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | # ----------------------------------------------------------------------------
35 |
36 | if [ -z "$MAVEN_SKIP_RC" ] ; then
37 |
38 | if [ -f /usr/local/etc/mavenrc ] ; then
39 | . /usr/local/etc/mavenrc
40 | fi
41 |
42 | if [ -f /etc/mavenrc ] ; then
43 | . /etc/mavenrc
44 | fi
45 |
46 | if [ -f "$HOME/.mavenrc" ] ; then
47 | . "$HOME/.mavenrc"
48 | fi
49 |
50 | fi
51 |
52 | # OS specific support. $var _must_ be set to either true or false.
53 | cygwin=false;
54 | darwin=false;
55 | mingw=false
56 | case "$(uname)" in
57 | CYGWIN*) cygwin=true ;;
58 | MINGW*) mingw=true;;
59 | Darwin*) darwin=true
60 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
61 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
62 | if [ -z "$JAVA_HOME" ]; then
63 | if [ -x "/usr/libexec/java_home" ]; then
64 | JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
65 | else
66 | JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
67 | fi
68 | fi
69 | ;;
70 | esac
71 |
72 | if [ -z "$JAVA_HOME" ] ; then
73 | if [ -r /etc/gentoo-release ] ; then
74 | JAVA_HOME=$(java-config --jre-home)
75 | fi
76 | fi
77 |
78 | # For Cygwin, ensure paths are in UNIX format before anything is touched
79 | if $cygwin ; then
80 | [ -n "$JAVA_HOME" ] &&
81 | JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
82 | [ -n "$CLASSPATH" ] &&
83 | CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
84 | fi
85 |
86 | # For Mingw, ensure paths are in UNIX format before anything is touched
87 | if $mingw ; then
88 | [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
89 | JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
90 | fi
91 |
92 | if [ -z "$JAVA_HOME" ]; then
93 | javaExecutable="$(which javac)"
94 | if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
95 | # readlink(1) is not available as standard on Solaris 10.
96 | readLink=$(which readlink)
97 | if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
98 | if $darwin ; then
99 | javaHome="$(dirname "\"$javaExecutable\"")"
100 | javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
101 | else
102 | javaExecutable="$(readlink -f "\"$javaExecutable\"")"
103 | fi
104 | javaHome="$(dirname "\"$javaExecutable\"")"
105 | javaHome=$(expr "$javaHome" : '\(.*\)/bin')
106 | JAVA_HOME="$javaHome"
107 | export JAVA_HOME
108 | fi
109 | fi
110 | fi
111 |
112 | if [ -z "$JAVACMD" ] ; then
113 | if [ -n "$JAVA_HOME" ] ; then
114 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
115 | # IBM's JDK on AIX uses strange locations for the executables
116 | JAVACMD="$JAVA_HOME/jre/sh/java"
117 | else
118 | JAVACMD="$JAVA_HOME/bin/java"
119 | fi
120 | else
121 | JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
122 | fi
123 | fi
124 |
125 | if [ ! -x "$JAVACMD" ] ; then
126 | echo "Error: JAVA_HOME is not defined correctly." >&2
127 | echo " We cannot execute $JAVACMD" >&2
128 | exit 1
129 | fi
130 |
131 | if [ -z "$JAVA_HOME" ] ; then
132 | echo "Warning: JAVA_HOME environment variable is not set."
133 | fi
134 |
135 | # traverses directory structure from process work directory to filesystem root
136 | # first directory with .mvn subdirectory is considered project base directory
137 | find_maven_basedir() {
138 | if [ -z "$1" ]
139 | then
140 | echo "Path not specified to find_maven_basedir"
141 | return 1
142 | fi
143 |
144 | basedir="$1"
145 | wdir="$1"
146 | while [ "$wdir" != '/' ] ; do
147 | if [ -d "$wdir"/.mvn ] ; then
148 | basedir=$wdir
149 | break
150 | fi
151 | # workaround for JBEAP-8937 (on Solaris 10/Sparc)
152 | if [ -d "${wdir}" ]; then
153 | wdir=$(cd "$wdir/.." || exit 1; pwd)
154 | fi
155 | # end of workaround
156 | done
157 | printf '%s' "$(cd "$basedir" || exit 1; pwd)"
158 | }
159 |
160 | # concatenates all lines of a file
161 | concat_lines() {
162 | if [ -f "$1" ]; then
163 | # Remove \r in case we run on Windows within Git Bash
164 | # and check out the repository with auto CRLF management
165 | # enabled. Otherwise, we may read lines that are delimited with
166 | # \r\n and produce $'-Xarg\r' rather than -Xarg due to word
167 | # splitting rules.
168 | tr -s '\r\n' ' ' < "$1"
169 | fi
170 | }
171 |
172 | log() {
173 | if [ "$MVNW_VERBOSE" = true ]; then
174 | printf '%s\n' "$1"
175 | fi
176 | }
177 |
178 | BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
179 | if [ -z "$BASE_DIR" ]; then
180 | exit 1;
181 | fi
182 |
183 | MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
184 | log "$MAVEN_PROJECTBASEDIR"
185 |
186 | ##########################################################################################
187 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
188 | # This allows using the maven wrapper in projects that prohibit checking in binary data.
189 | ##########################################################################################
190 | wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
191 | if [ -r "$wrapperJarPath" ]; then
192 | log "Found $wrapperJarPath"
193 | else
194 | log "Couldn't find $wrapperJarPath, downloading it ..."
195 |
196 | if [ -n "$MVNW_REPOURL" ]; then
197 | wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
198 | else
199 | wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
200 | fi
201 | while IFS="=" read -r key value; do
202 | # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
203 | safeValue=$(echo "$value" | tr -d '\r')
204 | case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
205 | esac
206 | done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
207 | log "Downloading from: $wrapperUrl"
208 |
209 | if $cygwin; then
210 | wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
211 | fi
212 |
213 | if command -v wget > /dev/null; then
214 | log "Found wget ... using wget"
215 | [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
216 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
217 | wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
218 | else
219 | wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
220 | fi
221 | elif command -v curl > /dev/null; then
222 | log "Found curl ... using curl"
223 | [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
224 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
225 | curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
226 | else
227 | curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
228 | fi
229 | else
230 | log "Falling back to using Java to download"
231 | javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
232 | javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
233 | # For Cygwin, switch paths to Windows format before running javac
234 | if $cygwin; then
235 | javaSource=$(cygpath --path --windows "$javaSource")
236 | javaClass=$(cygpath --path --windows "$javaClass")
237 | fi
238 | if [ -e "$javaSource" ]; then
239 | if [ ! -e "$javaClass" ]; then
240 | log " - Compiling MavenWrapperDownloader.java ..."
241 | ("$JAVA_HOME/bin/javac" "$javaSource")
242 | fi
243 | if [ -e "$javaClass" ]; then
244 | log " - Running MavenWrapperDownloader.java ..."
245 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
246 | fi
247 | fi
248 | fi
249 | fi
250 | ##########################################################################################
251 | # End of extension
252 | ##########################################################################################
253 |
254 | # If specified, validate the SHA-256 sum of the Maven wrapper jar file
255 | wrapperSha256Sum=""
256 | while IFS="=" read -r key value; do
257 | case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
258 | esac
259 | done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
260 | if [ -n "$wrapperSha256Sum" ]; then
261 | wrapperSha256Result=false
262 | if command -v sha256sum > /dev/null; then
263 | if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
264 | wrapperSha256Result=true
265 | fi
266 | elif command -v shasum > /dev/null; then
267 | if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
268 | wrapperSha256Result=true
269 | fi
270 | else
271 | echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
272 | echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
273 | exit 1
274 | fi
275 | if [ $wrapperSha256Result = false ]; then
276 | echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
277 | echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
278 | echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
279 | exit 1
280 | fi
281 | fi
282 |
283 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
284 |
285 | # For Cygwin, switch paths to Windows format before running java
286 | if $cygwin; then
287 | [ -n "$JAVA_HOME" ] &&
288 | JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
289 | [ -n "$CLASSPATH" ] &&
290 | CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
291 | [ -n "$MAVEN_PROJECTBASEDIR" ] &&
292 | MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
293 | fi
294 |
295 | # Provide a "standardized" way to retrieve the CLI args that will
296 | # work with both Windows and non-Windows executions.
297 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
298 | export MAVEN_CMD_LINE_ARGS
299 |
300 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
301 |
302 | # shellcheck disable=SC2086 # safe args
303 | exec "$JAVACMD" \
304 | $MAVEN_OPTS \
305 | $MAVEN_DEBUG_OPTS \
306 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
307 | "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
308 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
309 |
--------------------------------------------------------------------------------
/inventory-service/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM https://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Apache Maven Wrapper startup batch script, version 3.2.0
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
28 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
29 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
30 | @REM e.g. to debug Maven itself, use
31 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
32 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
33 | @REM ----------------------------------------------------------------------------
34 |
35 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
36 | @echo off
37 | @REM set title of command window
38 | title %0
39 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
40 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
41 |
42 | @REM set %HOME% to equivalent of $HOME
43 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
44 |
45 | @REM Execute a user defined script before this one
46 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
47 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
48 | if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
49 | if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
50 | :skipRcPre
51 |
52 | @setlocal
53 |
54 | set ERROR_CODE=0
55 |
56 | @REM To isolate internal variables from possible post scripts, we use another setlocal
57 | @setlocal
58 |
59 | @REM ==== START VALIDATION ====
60 | if not "%JAVA_HOME%" == "" goto OkJHome
61 |
62 | echo.
63 | echo Error: JAVA_HOME not found in your environment. >&2
64 | echo Please set the JAVA_HOME variable in your environment to match the >&2
65 | echo location of your Java installation. >&2
66 | echo.
67 | goto error
68 |
69 | :OkJHome
70 | if exist "%JAVA_HOME%\bin\java.exe" goto init
71 |
72 | echo.
73 | echo Error: JAVA_HOME is set to an invalid directory. >&2
74 | echo JAVA_HOME = "%JAVA_HOME%" >&2
75 | echo Please set the JAVA_HOME variable in your environment to match the >&2
76 | echo location of your Java installation. >&2
77 | echo.
78 | goto error
79 |
80 | @REM ==== END VALIDATION ====
81 |
82 | :init
83 |
84 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
85 | @REM Fallback to current working directory if not found.
86 |
87 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
88 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
89 |
90 | set EXEC_DIR=%CD%
91 | set WDIR=%EXEC_DIR%
92 | :findBaseDir
93 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
94 | cd ..
95 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
96 | set WDIR=%CD%
97 | goto findBaseDir
98 |
99 | :baseDirFound
100 | set MAVEN_PROJECTBASEDIR=%WDIR%
101 | cd "%EXEC_DIR%"
102 | goto endDetectBaseDir
103 |
104 | :baseDirNotFound
105 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
106 | cd "%EXEC_DIR%"
107 |
108 | :endDetectBaseDir
109 |
110 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
111 |
112 | @setlocal EnableExtensions EnableDelayedExpansion
113 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
114 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
115 |
116 | :endReadAdditionalConfig
117 |
118 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
121 |
122 | set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
123 |
124 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
125 | IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
126 | )
127 |
128 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
129 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data.
130 | if exist %WRAPPER_JAR% (
131 | if "%MVNW_VERBOSE%" == "true" (
132 | echo Found %WRAPPER_JAR%
133 | )
134 | ) else (
135 | if not "%MVNW_REPOURL%" == "" (
136 | SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
137 | )
138 | if "%MVNW_VERBOSE%" == "true" (
139 | echo Couldn't find %WRAPPER_JAR%, downloading it ...
140 | echo Downloading from: %WRAPPER_URL%
141 | )
142 |
143 | powershell -Command "&{"^
144 | "$webclient = new-object System.Net.WebClient;"^
145 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
146 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
147 | "}"^
148 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
149 | "}"
150 | if "%MVNW_VERBOSE%" == "true" (
151 | echo Finished downloading %WRAPPER_JAR%
152 | )
153 | )
154 | @REM End of extension
155 |
156 | @REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
157 | SET WRAPPER_SHA_256_SUM=""
158 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
159 | IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
160 | )
161 | IF NOT %WRAPPER_SHA_256_SUM%=="" (
162 | powershell -Command "&{"^
163 | "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
164 | "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
165 | " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
166 | " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
167 | " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
168 | " exit 1;"^
169 | "}"^
170 | "}"
171 | if ERRORLEVEL 1 goto error
172 | )
173 |
174 | @REM Provide a "standardized" way to retrieve the CLI args that will
175 | @REM work with both Windows and non-Windows executions.
176 | set MAVEN_CMD_LINE_ARGS=%*
177 |
178 | %MAVEN_JAVA_EXE% ^
179 | %JVM_CONFIG_MAVEN_PROPS% ^
180 | %MAVEN_OPTS% ^
181 | %MAVEN_DEBUG_OPTS% ^
182 | -classpath %WRAPPER_JAR% ^
183 | "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
184 | %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
185 | if ERRORLEVEL 1 goto error
186 | goto end
187 |
188 | :error
189 | set ERROR_CODE=1
190 |
191 | :end
192 | @endlocal & set ERROR_CODE=%ERROR_CODE%
193 |
194 | if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
195 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
196 | if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
197 | if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
198 | :skipRcPost
199 |
200 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
201 | if "%MAVEN_BATCH_PAUSE%"=="on" pause
202 |
203 | if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
204 |
205 | cmd /C exit /B %ERROR_CODE%
206 |
--------------------------------------------------------------------------------
/inventory-service/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 3.2.2
9 |
10 |
11 | net.youssfi
12 | inventory-service
13 | 0.0.1-SNAPSHOT
14 | inventory-service
15 | inventory-service
16 |
17 | 21
18 | 2023.0.0
19 |
20 |
21 |
22 | org.springframework.boot
23 | spring-boot-starter-data-jpa
24 |
25 |
26 | org.springframework.boot
27 | spring-boot-starter-oauth2-resource-server
28 |
29 |
30 | org.springframework.boot
31 | spring-boot-starter-web
32 |
33 |
34 | org.springframework.cloud
35 | spring-cloud-starter-config
36 |
37 |
38 | org.springframework.cloud
39 | spring-cloud-starter-netflix-eureka-client
40 |
41 |
42 |
43 | com.h2database
44 | h2
45 | runtime
46 |
47 |
48 | org.projectlombok
49 | lombok
50 | true
51 |
52 |
53 | org.springframework.boot
54 | spring-boot-starter-test
55 | test
56 |
57 |
58 |
59 |
60 |
61 | org.springframework.cloud
62 | spring-cloud-dependencies
63 | ${spring-cloud.version}
64 | pom
65 | import
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | org.springframework.boot
74 | spring-boot-maven-plugin
75 |
76 |
77 |
78 | org.projectlombok
79 | lombok
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/inventory-service/src/main/java/net/youssfi/inventoryservice/InventoryServiceApplication.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.inventoryservice;
2 |
3 | import net.youssfi.inventoryservice.entities.Product;
4 | import net.youssfi.inventoryservice.repository.ProductRepository;
5 | import org.springframework.boot.CommandLineRunner;
6 | import org.springframework.boot.SpringApplication;
7 | import org.springframework.boot.autoconfigure.SpringBootApplication;
8 | import org.springframework.context.annotation.Bean;
9 |
10 | import java.util.UUID;
11 |
12 | @SpringBootApplication
13 | public class InventoryServiceApplication {
14 |
15 | public static void main(String[] args) {
16 | SpringApplication.run(InventoryServiceApplication.class, args);
17 | }
18 | @Bean
19 | CommandLineRunner commandLineRunner(ProductRepository productRepository){
20 | return args -> {
21 | productRepository.save(Product.builder().id("P01").name("Computer").price(2300).quantity(5)
22 | .build());
23 | productRepository.save(Product.builder().id("P02").name("Printer").price(1200).quantity(10)
24 | .build());
25 | productRepository.save(Product.builder().id("P03").name("Smart Phone").price(4200).quantity(34)
26 | .build());
27 | };
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/inventory-service/src/main/java/net/youssfi/inventoryservice/entities/Product.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.inventoryservice.entities;
2 |
3 | import jakarta.persistence.Entity;
4 | import jakarta.persistence.Id;
5 | import lombok.*;
6 |
7 | @Entity
8 | @NoArgsConstructor @AllArgsConstructor @Getter @Setter @Builder @ToString
9 | public class Product {
10 | @Id
11 | private String id;
12 | private String name;
13 | private double price;
14 | private int quantity;
15 | }
16 |
--------------------------------------------------------------------------------
/inventory-service/src/main/java/net/youssfi/inventoryservice/repository/ProductRepository.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.inventoryservice.repository;
2 |
3 | import net.youssfi.inventoryservice.entities.Product;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 |
6 | public interface ProductRepository extends JpaRepository {
7 | }
8 |
--------------------------------------------------------------------------------
/inventory-service/src/main/java/net/youssfi/inventoryservice/security/JwtAuthConverter.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.inventoryservice.security;
2 |
3 | import org.springframework.core.convert.converter.Converter;
4 | import org.springframework.security.authentication.AbstractAuthenticationToken;
5 | import org.springframework.security.core.GrantedAuthority;
6 | import org.springframework.security.core.authority.SimpleGrantedAuthority;
7 | import org.springframework.security.oauth2.jwt.Jwt;
8 | import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
9 | import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
10 | import org.springframework.stereotype.Component;
11 |
12 | import java.util.Collection;
13 | import java.util.Map;
14 | import java.util.Set;
15 | import java.util.stream.Collectors;
16 | import java.util.stream.Stream;
17 |
18 | @Component
19 | public class JwtAuthConverter implements Converter {
20 | private final JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter=new JwtGrantedAuthoritiesConverter();
21 | @Override
22 | public AbstractAuthenticationToken convert(Jwt jwt) {
23 | Collection authorities = Stream.concat(
24 | jwtGrantedAuthoritiesConverter.convert(jwt).stream(),
25 | extractResourceRoles(jwt).stream()
26 | ).collect(Collectors.toSet());
27 | return new JwtAuthenticationToken(jwt, authorities,jwt.getClaim("preferred_username"));
28 | }
29 | private Collection extractResourceRoles(Jwt jwt) {
30 | Map realmAccess;
31 | Collection roles;
32 | if(jwt.getClaim("realm_access")==null){
33 | return Set.of();
34 | }
35 | realmAccess = jwt.getClaim("realm_access");
36 | roles = (Collection) realmAccess.get("roles");
37 | return roles.stream().map(role->new SimpleGrantedAuthority(role)).collect(Collectors.toSet());
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/inventory-service/src/main/java/net/youssfi/inventoryservice/security/SecurityConfig.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.inventoryservice.security;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.security.config.Customizer;
6 | import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
7 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
8 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
9 | import org.springframework.security.config.http.SessionCreationPolicy;
10 | import org.springframework.security.web.SecurityFilterChain;
11 | import org.springframework.web.cors.CorsConfiguration;
12 | import org.springframework.web.cors.CorsConfigurationSource;
13 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
14 |
15 | import java.util.Arrays;
16 |
17 | @Configuration
18 | @EnableWebSecurity
19 | @EnableMethodSecurity(prePostEnabled = true)
20 | public class SecurityConfig {
21 | private JwtAuthConverter jwtAuthConverter;
22 |
23 | public SecurityConfig(JwtAuthConverter jwtAuthConverter) {
24 | this.jwtAuthConverter = jwtAuthConverter;
25 | }
26 |
27 | @Bean
28 | public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
29 | return httpSecurity
30 | .cors(Customizer.withDefaults())
31 | .sessionManagement(sm->sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
32 | .csrf(csrf->csrf.disable())
33 | .headers(h->h.frameOptions(fo->fo.disable()))
34 | .authorizeHttpRequests(ar->ar.requestMatchers("/h2-console/**").permitAll())
35 | //.authorizeHttpRequests(ar->ar.requestMatchers("/api/products/**").hasAuthority("ADMIN"))
36 | .authorizeHttpRequests(ar->ar.anyRequest().authenticated())
37 | .oauth2ResourceServer(o2->o2.jwt(jwt->jwt.jwtAuthenticationConverter(jwtAuthConverter)))
38 | .build();
39 | }
40 | @Bean
41 | CorsConfigurationSource corsConfigurationSource() {
42 | CorsConfiguration configuration = new CorsConfiguration();
43 | configuration.setAllowedOrigins(Arrays.asList("*"));
44 | configuration.setAllowedMethods(Arrays.asList("*"));
45 | configuration.setAllowedHeaders(Arrays.asList("*"));
46 | configuration.setExposedHeaders(Arrays.asList("*"));
47 | UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
48 | source.registerCorsConfiguration("/**", configuration);
49 | return source;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/inventory-service/src/main/java/net/youssfi/inventoryservice/web/ProductRestController.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.inventoryservice.web;
2 |
3 | import net.youssfi.inventoryservice.entities.Product;
4 | import net.youssfi.inventoryservice.repository.ProductRepository;
5 | import org.springframework.security.access.prepost.PreAuthorize;
6 | import org.springframework.security.core.Authentication;
7 | import org.springframework.web.bind.annotation.*;
8 |
9 | import java.util.List;
10 |
11 | @RestController
12 | @RequestMapping("/api")
13 | public class ProductRestController {
14 | private ProductRepository productRepository;
15 |
16 | public ProductRestController(ProductRepository productRepository) {
17 | this.productRepository = productRepository;
18 | }
19 | @GetMapping("/products")
20 | //@PreAuthorize("hasAuthority('ADMIN')")
21 | public List productList(){
22 | return productRepository.findAll();
23 | }
24 | @GetMapping("/products/{id}")
25 | //@PreAuthorize("hasAuthority('USER')")
26 | public Product productById(@PathVariable String id){
27 | return productRepository.findById(id).get();
28 | }
29 | @GetMapping("/auth")
30 | public Authentication authentication(Authentication authentication){
31 | return authentication;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/inventory-service/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.application.name=inv-service
2 | server.port=8087
3 | spring.datasource.url=jdbc:h2:mem:products-db
4 | spring.h2.console.enabled=true
5 |
6 | spring.cloud.config.enabled=false
7 | spring.cloud.discovery.enabled=false
8 |
9 | spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8080/realms/bdcc-realm
10 | spring.security.oauth2.resourceserver.jwt.jwk-set-uri=http://localhost:8080/realms/bdcc-realm/protocol/openid-connect/certs
11 |
12 |
13 |
--------------------------------------------------------------------------------
/inventory-service/src/test/java/net/youssfi/inventoryservice/InventoryServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.inventoryservice;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class InventoryServiceApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/order-service/.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 |
--------------------------------------------------------------------------------
/order-service/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-keycloak-master-IIBDCC/3afc78baa4354130ed75d65dbe90107b68be481b/order-service/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/order-service/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
3 |
--------------------------------------------------------------------------------
/order-service/mvnw:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # ----------------------------------------------------------------------------
3 | # Licensed to the Apache Software Foundation (ASF) under one
4 | # or more contributor license agreements. See the NOTICE file
5 | # distributed with this work for additional information
6 | # regarding copyright ownership. The ASF licenses this file
7 | # to you under the Apache License, Version 2.0 (the
8 | # "License"); you may not use this file except in compliance
9 | # with the License. You may obtain a copy of the License at
10 | #
11 | # https://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing,
14 | # software distributed under the License is distributed on an
15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | # KIND, either express or implied. See the License for the
17 | # specific language governing permissions and limitations
18 | # under the License.
19 | # ----------------------------------------------------------------------------
20 |
21 | # ----------------------------------------------------------------------------
22 | # Apache Maven Wrapper startup batch script, version 3.2.0
23 | #
24 | # Required ENV vars:
25 | # ------------------
26 | # JAVA_HOME - location of a JDK home dir
27 | #
28 | # Optional ENV vars
29 | # -----------------
30 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | # e.g. to debug Maven itself, use
32 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | # ----------------------------------------------------------------------------
35 |
36 | if [ -z "$MAVEN_SKIP_RC" ] ; then
37 |
38 | if [ -f /usr/local/etc/mavenrc ] ; then
39 | . /usr/local/etc/mavenrc
40 | fi
41 |
42 | if [ -f /etc/mavenrc ] ; then
43 | . /etc/mavenrc
44 | fi
45 |
46 | if [ -f "$HOME/.mavenrc" ] ; then
47 | . "$HOME/.mavenrc"
48 | fi
49 |
50 | fi
51 |
52 | # OS specific support. $var _must_ be set to either true or false.
53 | cygwin=false;
54 | darwin=false;
55 | mingw=false
56 | case "$(uname)" in
57 | CYGWIN*) cygwin=true ;;
58 | MINGW*) mingw=true;;
59 | Darwin*) darwin=true
60 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
61 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
62 | if [ -z "$JAVA_HOME" ]; then
63 | if [ -x "/usr/libexec/java_home" ]; then
64 | JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
65 | else
66 | JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
67 | fi
68 | fi
69 | ;;
70 | esac
71 |
72 | if [ -z "$JAVA_HOME" ] ; then
73 | if [ -r /etc/gentoo-release ] ; then
74 | JAVA_HOME=$(java-config --jre-home)
75 | fi
76 | fi
77 |
78 | # For Cygwin, ensure paths are in UNIX format before anything is touched
79 | if $cygwin ; then
80 | [ -n "$JAVA_HOME" ] &&
81 | JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
82 | [ -n "$CLASSPATH" ] &&
83 | CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
84 | fi
85 |
86 | # For Mingw, ensure paths are in UNIX format before anything is touched
87 | if $mingw ; then
88 | [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
89 | JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
90 | fi
91 |
92 | if [ -z "$JAVA_HOME" ]; then
93 | javaExecutable="$(which javac)"
94 | if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
95 | # readlink(1) is not available as standard on Solaris 10.
96 | readLink=$(which readlink)
97 | if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
98 | if $darwin ; then
99 | javaHome="$(dirname "\"$javaExecutable\"")"
100 | javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
101 | else
102 | javaExecutable="$(readlink -f "\"$javaExecutable\"")"
103 | fi
104 | javaHome="$(dirname "\"$javaExecutable\"")"
105 | javaHome=$(expr "$javaHome" : '\(.*\)/bin')
106 | JAVA_HOME="$javaHome"
107 | export JAVA_HOME
108 | fi
109 | fi
110 | fi
111 |
112 | if [ -z "$JAVACMD" ] ; then
113 | if [ -n "$JAVA_HOME" ] ; then
114 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
115 | # IBM's JDK on AIX uses strange locations for the executables
116 | JAVACMD="$JAVA_HOME/jre/sh/java"
117 | else
118 | JAVACMD="$JAVA_HOME/bin/java"
119 | fi
120 | else
121 | JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
122 | fi
123 | fi
124 |
125 | if [ ! -x "$JAVACMD" ] ; then
126 | echo "Error: JAVA_HOME is not defined correctly." >&2
127 | echo " We cannot execute $JAVACMD" >&2
128 | exit 1
129 | fi
130 |
131 | if [ -z "$JAVA_HOME" ] ; then
132 | echo "Warning: JAVA_HOME environment variable is not set."
133 | fi
134 |
135 | # traverses directory structure from process work directory to filesystem root
136 | # first directory with .mvn subdirectory is considered project base directory
137 | find_maven_basedir() {
138 | if [ -z "$1" ]
139 | then
140 | echo "Path not specified to find_maven_basedir"
141 | return 1
142 | fi
143 |
144 | basedir="$1"
145 | wdir="$1"
146 | while [ "$wdir" != '/' ] ; do
147 | if [ -d "$wdir"/.mvn ] ; then
148 | basedir=$wdir
149 | break
150 | fi
151 | # workaround for JBEAP-8937 (on Solaris 10/Sparc)
152 | if [ -d "${wdir}" ]; then
153 | wdir=$(cd "$wdir/.." || exit 1; pwd)
154 | fi
155 | # end of workaround
156 | done
157 | printf '%s' "$(cd "$basedir" || exit 1; pwd)"
158 | }
159 |
160 | # concatenates all lines of a file
161 | concat_lines() {
162 | if [ -f "$1" ]; then
163 | # Remove \r in case we run on Windows within Git Bash
164 | # and check out the repository with auto CRLF management
165 | # enabled. Otherwise, we may read lines that are delimited with
166 | # \r\n and produce $'-Xarg\r' rather than -Xarg due to word
167 | # splitting rules.
168 | tr -s '\r\n' ' ' < "$1"
169 | fi
170 | }
171 |
172 | log() {
173 | if [ "$MVNW_VERBOSE" = true ]; then
174 | printf '%s\n' "$1"
175 | fi
176 | }
177 |
178 | BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
179 | if [ -z "$BASE_DIR" ]; then
180 | exit 1;
181 | fi
182 |
183 | MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
184 | log "$MAVEN_PROJECTBASEDIR"
185 |
186 | ##########################################################################################
187 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
188 | # This allows using the maven wrapper in projects that prohibit checking in binary data.
189 | ##########################################################################################
190 | wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
191 | if [ -r "$wrapperJarPath" ]; then
192 | log "Found $wrapperJarPath"
193 | else
194 | log "Couldn't find $wrapperJarPath, downloading it ..."
195 |
196 | if [ -n "$MVNW_REPOURL" ]; then
197 | wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
198 | else
199 | wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
200 | fi
201 | while IFS="=" read -r key value; do
202 | # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
203 | safeValue=$(echo "$value" | tr -d '\r')
204 | case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
205 | esac
206 | done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
207 | log "Downloading from: $wrapperUrl"
208 |
209 | if $cygwin; then
210 | wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
211 | fi
212 |
213 | if command -v wget > /dev/null; then
214 | log "Found wget ... using wget"
215 | [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
216 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
217 | wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
218 | else
219 | wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
220 | fi
221 | elif command -v curl > /dev/null; then
222 | log "Found curl ... using curl"
223 | [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
224 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
225 | curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
226 | else
227 | curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
228 | fi
229 | else
230 | log "Falling back to using Java to download"
231 | javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
232 | javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
233 | # For Cygwin, switch paths to Windows format before running javac
234 | if $cygwin; then
235 | javaSource=$(cygpath --path --windows "$javaSource")
236 | javaClass=$(cygpath --path --windows "$javaClass")
237 | fi
238 | if [ -e "$javaSource" ]; then
239 | if [ ! -e "$javaClass" ]; then
240 | log " - Compiling MavenWrapperDownloader.java ..."
241 | ("$JAVA_HOME/bin/javac" "$javaSource")
242 | fi
243 | if [ -e "$javaClass" ]; then
244 | log " - Running MavenWrapperDownloader.java ..."
245 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
246 | fi
247 | fi
248 | fi
249 | fi
250 | ##########################################################################################
251 | # End of extension
252 | ##########################################################################################
253 |
254 | # If specified, validate the SHA-256 sum of the Maven wrapper jar file
255 | wrapperSha256Sum=""
256 | while IFS="=" read -r key value; do
257 | case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
258 | esac
259 | done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
260 | if [ -n "$wrapperSha256Sum" ]; then
261 | wrapperSha256Result=false
262 | if command -v sha256sum > /dev/null; then
263 | if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
264 | wrapperSha256Result=true
265 | fi
266 | elif command -v shasum > /dev/null; then
267 | if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
268 | wrapperSha256Result=true
269 | fi
270 | else
271 | echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
272 | echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
273 | exit 1
274 | fi
275 | if [ $wrapperSha256Result = false ]; then
276 | echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
277 | echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
278 | echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
279 | exit 1
280 | fi
281 | fi
282 |
283 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
284 |
285 | # For Cygwin, switch paths to Windows format before running java
286 | if $cygwin; then
287 | [ -n "$JAVA_HOME" ] &&
288 | JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
289 | [ -n "$CLASSPATH" ] &&
290 | CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
291 | [ -n "$MAVEN_PROJECTBASEDIR" ] &&
292 | MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
293 | fi
294 |
295 | # Provide a "standardized" way to retrieve the CLI args that will
296 | # work with both Windows and non-Windows executions.
297 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
298 | export MAVEN_CMD_LINE_ARGS
299 |
300 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
301 |
302 | # shellcheck disable=SC2086 # safe args
303 | exec "$JAVACMD" \
304 | $MAVEN_OPTS \
305 | $MAVEN_DEBUG_OPTS \
306 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
307 | "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
308 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
309 |
--------------------------------------------------------------------------------
/order-service/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM https://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Apache Maven Wrapper startup batch script, version 3.2.0
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
28 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
29 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
30 | @REM e.g. to debug Maven itself, use
31 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
32 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
33 | @REM ----------------------------------------------------------------------------
34 |
35 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
36 | @echo off
37 | @REM set title of command window
38 | title %0
39 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
40 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
41 |
42 | @REM set %HOME% to equivalent of $HOME
43 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
44 |
45 | @REM Execute a user defined script before this one
46 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
47 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
48 | if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
49 | if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
50 | :skipRcPre
51 |
52 | @setlocal
53 |
54 | set ERROR_CODE=0
55 |
56 | @REM To isolate internal variables from possible post scripts, we use another setlocal
57 | @setlocal
58 |
59 | @REM ==== START VALIDATION ====
60 | if not "%JAVA_HOME%" == "" goto OkJHome
61 |
62 | echo.
63 | echo Error: JAVA_HOME not found in your environment. >&2
64 | echo Please set the JAVA_HOME variable in your environment to match the >&2
65 | echo location of your Java installation. >&2
66 | echo.
67 | goto error
68 |
69 | :OkJHome
70 | if exist "%JAVA_HOME%\bin\java.exe" goto init
71 |
72 | echo.
73 | echo Error: JAVA_HOME is set to an invalid directory. >&2
74 | echo JAVA_HOME = "%JAVA_HOME%" >&2
75 | echo Please set the JAVA_HOME variable in your environment to match the >&2
76 | echo location of your Java installation. >&2
77 | echo.
78 | goto error
79 |
80 | @REM ==== END VALIDATION ====
81 |
82 | :init
83 |
84 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
85 | @REM Fallback to current working directory if not found.
86 |
87 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
88 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
89 |
90 | set EXEC_DIR=%CD%
91 | set WDIR=%EXEC_DIR%
92 | :findBaseDir
93 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
94 | cd ..
95 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
96 | set WDIR=%CD%
97 | goto findBaseDir
98 |
99 | :baseDirFound
100 | set MAVEN_PROJECTBASEDIR=%WDIR%
101 | cd "%EXEC_DIR%"
102 | goto endDetectBaseDir
103 |
104 | :baseDirNotFound
105 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
106 | cd "%EXEC_DIR%"
107 |
108 | :endDetectBaseDir
109 |
110 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
111 |
112 | @setlocal EnableExtensions EnableDelayedExpansion
113 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
114 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
115 |
116 | :endReadAdditionalConfig
117 |
118 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
121 |
122 | set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
123 |
124 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
125 | IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
126 | )
127 |
128 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
129 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data.
130 | if exist %WRAPPER_JAR% (
131 | if "%MVNW_VERBOSE%" == "true" (
132 | echo Found %WRAPPER_JAR%
133 | )
134 | ) else (
135 | if not "%MVNW_REPOURL%" == "" (
136 | SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
137 | )
138 | if "%MVNW_VERBOSE%" == "true" (
139 | echo Couldn't find %WRAPPER_JAR%, downloading it ...
140 | echo Downloading from: %WRAPPER_URL%
141 | )
142 |
143 | powershell -Command "&{"^
144 | "$webclient = new-object System.Net.WebClient;"^
145 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
146 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
147 | "}"^
148 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
149 | "}"
150 | if "%MVNW_VERBOSE%" == "true" (
151 | echo Finished downloading %WRAPPER_JAR%
152 | )
153 | )
154 | @REM End of extension
155 |
156 | @REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
157 | SET WRAPPER_SHA_256_SUM=""
158 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
159 | IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
160 | )
161 | IF NOT %WRAPPER_SHA_256_SUM%=="" (
162 | powershell -Command "&{"^
163 | "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
164 | "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
165 | " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
166 | " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
167 | " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
168 | " exit 1;"^
169 | "}"^
170 | "}"
171 | if ERRORLEVEL 1 goto error
172 | )
173 |
174 | @REM Provide a "standardized" way to retrieve the CLI args that will
175 | @REM work with both Windows and non-Windows executions.
176 | set MAVEN_CMD_LINE_ARGS=%*
177 |
178 | %MAVEN_JAVA_EXE% ^
179 | %JVM_CONFIG_MAVEN_PROPS% ^
180 | %MAVEN_OPTS% ^
181 | %MAVEN_DEBUG_OPTS% ^
182 | -classpath %WRAPPER_JAR% ^
183 | "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
184 | %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
185 | if ERRORLEVEL 1 goto error
186 | goto end
187 |
188 | :error
189 | set ERROR_CODE=1
190 |
191 | :end
192 | @endlocal & set ERROR_CODE=%ERROR_CODE%
193 |
194 | if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
195 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
196 | if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
197 | if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
198 | :skipRcPost
199 |
200 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
201 | if "%MAVEN_BATCH_PAUSE%"=="on" pause
202 |
203 | if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
204 |
205 | cmd /C exit /B %ERROR_CODE%
206 |
--------------------------------------------------------------------------------
/order-service/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 3.2.2
9 |
10 |
11 | net.youssfi
12 | order-service
13 | 0.0.1-SNAPSHOT
14 | order-service
15 | order-service
16 |
17 | 21
18 | 2023.0.0
19 |
20 |
21 |
22 | org.springframework.boot
23 | spring-boot-starter-data-jpa
24 |
25 |
26 | org.springframework.boot
27 | spring-boot-starter-oauth2-resource-server
28 |
29 |
30 | org.springframework.boot
31 | spring-boot-starter-web
32 |
33 |
34 |
35 | org.springdoc
36 | springdoc-openapi-starter-webmvc-ui
37 | 2.3.0
38 |
39 |
40 | org.springframework.cloud
41 | spring-cloud-starter-config
42 |
43 |
44 | org.springframework.cloud
45 | spring-cloud-starter-netflix-eureka-client
46 |
47 |
48 | org.springframework.cloud
49 | spring-cloud-starter-openfeign
50 |
51 |
52 |
53 | com.h2database
54 | h2
55 | runtime
56 |
57 |
58 | org.projectlombok
59 | lombok
60 | true
61 |
62 |
63 | org.springframework.boot
64 | spring-boot-starter-test
65 | test
66 |
67 |
68 |
69 |
70 |
71 | org.springframework.cloud
72 | spring-cloud-dependencies
73 | ${spring-cloud.version}
74 | pom
75 | import
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | org.springframework.boot
84 | spring-boot-maven-plugin
85 |
86 |
87 |
88 | org.projectlombok
89 | lombok
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/order-service/src/main/java/net/youssfi/orderservice/OrderServiceApplication.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.orderservice;
2 |
3 | import net.youssfi.orderservice.entities.Order;
4 | import net.youssfi.orderservice.entities.OrderState;
5 | import net.youssfi.orderservice.entities.ProductItem;
6 | import net.youssfi.orderservice.model.Product;
7 | import net.youssfi.orderservice.repsoitories.OrderRepository;
8 | import net.youssfi.orderservice.repsoitories.ProductItemRepository;
9 | import net.youssfi.orderservice.restclients.InventoryRestClient;
10 | import org.springframework.boot.CommandLineRunner;
11 | import org.springframework.boot.SpringApplication;
12 | import org.springframework.boot.autoconfigure.SpringBootApplication;
13 | import org.springframework.cloud.openfeign.EnableFeignClients;
14 | import org.springframework.context.annotation.Bean;
15 |
16 | import java.time.LocalDate;
17 | import java.util.List;
18 | import java.util.Random;
19 | import java.util.UUID;
20 |
21 | @SpringBootApplication
22 | @EnableFeignClients
23 | public class OrderServiceApplication {
24 |
25 | public static void main(String[] args) {
26 | SpringApplication.run(OrderServiceApplication.class, args);
27 | }
28 | @Bean
29 | CommandLineRunner commandLineRunner(
30 | OrderRepository orderRepository,
31 | ProductItemRepository productItemRepository,
32 | InventoryRestClient inventoryRestClient
33 | ){
34 | return args -> {
35 | //List allProducts = inventoryRestClient.getAllProducts();
36 | List productsIds = List.of("P01","P02","P03");
37 | for (int i = 0; i < 5; i++) {
38 | Order order = Order.builder()
39 | .id(UUID.randomUUID().toString())
40 | .date(LocalDate.now())
41 | .state(OrderState.PENDING)
42 | .build();
43 | Order savedOrder = orderRepository.save(order);
44 | productsIds.forEach(pId->{
45 | ProductItem productItem = ProductItem.builder()
46 | .productId(pId)
47 | .quantity(new Random().nextInt(20))
48 | .price(Math.random()*6000+100)
49 | .order(savedOrder)
50 | .build();
51 | productItemRepository.save(productItem);
52 | });
53 |
54 | }
55 | };
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/order-service/src/main/java/net/youssfi/orderservice/entities/Order.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.orderservice.entities;
2 |
3 | import jakarta.persistence.*;
4 | import lombok.*;
5 |
6 | import java.time.LocalDate;
7 | import java.util.List;
8 | @Entity
9 | @NoArgsConstructor @AllArgsConstructor @Getter @Setter @Builder @ToString
10 | @Table(name = "ORDERS")
11 | public class Order {
12 | @Id
13 | private String id;
14 | private LocalDate date;
15 | @Enumerated(EnumType.STRING)
16 | private OrderState state;
17 | @OneToMany(mappedBy = "order")
18 | private List productItems;
19 | }
20 |
--------------------------------------------------------------------------------
/order-service/src/main/java/net/youssfi/orderservice/entities/OrderState.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.orderservice.entities;
2 |
3 | public enum OrderState {
4 | PENDING, CONFIRMED, CANCELED, EXECUTED
5 | }
6 |
--------------------------------------------------------------------------------
/order-service/src/main/java/net/youssfi/orderservice/entities/ProductItem.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.orderservice.entities;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 | import jakarta.persistence.*;
5 | import lombok.*;
6 | import net.youssfi.orderservice.model.Product;
7 |
8 | @Entity
9 | @NoArgsConstructor @AllArgsConstructor @Getter @Setter @Builder @ToString
10 | public class ProductItem {
11 | @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
12 | private Long id;
13 | private String productId;
14 | private double price;
15 | private int quantity;
16 | @ManyToOne
17 | @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
18 | private Order order;
19 | @Transient
20 | private Product product;
21 | }
22 |
--------------------------------------------------------------------------------
/order-service/src/main/java/net/youssfi/orderservice/interceptors/FeignInterceptor.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.orderservice.interceptors;
2 |
3 | import feign.RequestInterceptor;
4 | import feign.RequestTemplate;
5 | import org.springframework.security.core.Authentication;
6 | import org.springframework.security.core.context.SecurityContext;
7 | import org.springframework.security.core.context.SecurityContextHolder;
8 | import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
9 | import org.springframework.stereotype.Component;
10 |
11 | @Component
12 | public class FeignInterceptor implements RequestInterceptor {
13 | @Override
14 | public void apply(RequestTemplate requestTemplate) {
15 | SecurityContext context = SecurityContextHolder.getContext();
16 | Authentication authentication = context.getAuthentication();
17 | JwtAuthenticationToken jwtAuthenticationToken= (JwtAuthenticationToken) authentication;
18 | String jwtAccessToken = jwtAuthenticationToken.getToken().getTokenValue();
19 | requestTemplate.header("Authorization","Bearer "+jwtAccessToken);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/order-service/src/main/java/net/youssfi/orderservice/model/Product.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.orderservice.model;
2 | import lombok.*;
3 | @NoArgsConstructor @AllArgsConstructor @Getter @Setter @Builder @ToString
4 | public class Product {
5 | private String id;
6 | private String name;
7 | private double price;
8 | private int quantity;
9 | }
10 |
--------------------------------------------------------------------------------
/order-service/src/main/java/net/youssfi/orderservice/repsoitories/OrderRepository.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.orderservice.repsoitories;
2 |
3 |
4 | import net.youssfi.orderservice.entities.Order;
5 | import org.springframework.data.jpa.repository.JpaRepository;
6 |
7 | public interface OrderRepository extends JpaRepository {
8 | }
9 |
--------------------------------------------------------------------------------
/order-service/src/main/java/net/youssfi/orderservice/repsoitories/ProductItemRepository.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.orderservice.repsoitories;
2 |
3 | import net.youssfi.orderservice.entities.ProductItem;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 |
6 | public interface ProductItemRepository extends JpaRepository {
7 | }
8 |
--------------------------------------------------------------------------------
/order-service/src/main/java/net/youssfi/orderservice/restclients/InventoryRestClient.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.orderservice.restclients;
2 |
3 | import net.youssfi.orderservice.model.Product;
4 | import org.springframework.cloud.openfeign.FeignClient;
5 | import org.springframework.web.bind.annotation.GetMapping;
6 | import org.springframework.web.bind.annotation.PathVariable;
7 |
8 | import java.util.List;
9 | @FeignClient(url = "http://localhost:8087", name = "inventory-service")
10 | public interface InventoryRestClient {
11 | @GetMapping("/api/products")
12 | List getAllProducts();
13 | @GetMapping("/api/products/{id}")
14 | Product findProductById(@PathVariable String id);
15 | }
16 |
--------------------------------------------------------------------------------
/order-service/src/main/java/net/youssfi/orderservice/security/JwtAuthConverter.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.orderservice.security;
2 |
3 | import org.springframework.core.convert.converter.Converter;
4 | import org.springframework.security.authentication.AbstractAuthenticationToken;
5 | import org.springframework.security.core.GrantedAuthority;
6 | import org.springframework.security.core.authority.SimpleGrantedAuthority;
7 | import org.springframework.security.oauth2.jwt.Jwt;
8 | import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
9 | import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
10 | import org.springframework.stereotype.Component;
11 |
12 | import java.util.Collection;
13 | import java.util.Map;
14 | import java.util.Set;
15 | import java.util.stream.Collectors;
16 | import java.util.stream.Stream;
17 |
18 | @Component
19 | public class JwtAuthConverter implements Converter {
20 | private final JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter=new JwtGrantedAuthoritiesConverter();
21 | @Override
22 | public AbstractAuthenticationToken convert(Jwt jwt) {
23 | Collection authorities = Stream.concat(
24 | jwtGrantedAuthoritiesConverter.convert(jwt).stream(),
25 | extractResourceRoles(jwt).stream()
26 | ).collect(Collectors.toSet());
27 | return new JwtAuthenticationToken(jwt, authorities,jwt.getClaim("preferred_username"));
28 | }
29 | private Collection extractResourceRoles(Jwt jwt) {
30 | Map realmAccess;
31 | Collection roles;
32 | if(jwt.getClaim("realm_access")==null){
33 | return Set.of();
34 | }
35 | realmAccess = jwt.getClaim("realm_access");
36 | roles = (Collection) realmAccess.get("roles");
37 | return roles.stream().map(role->new SimpleGrantedAuthority(role)).collect(Collectors.toSet());
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/order-service/src/main/java/net/youssfi/orderservice/security/SecurityConfig.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.orderservice.security;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.security.config.Customizer;
6 | import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
7 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
8 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
9 | import org.springframework.security.config.http.SessionCreationPolicy;
10 | import org.springframework.security.web.SecurityFilterChain;
11 | import org.springframework.web.cors.CorsConfiguration;
12 | import org.springframework.web.cors.CorsConfigurationSource;
13 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
14 |
15 | import java.util.Arrays;
16 |
17 | @Configuration
18 | @EnableWebSecurity
19 | @EnableMethodSecurity(prePostEnabled = true)
20 | public class SecurityConfig {
21 | private JwtAuthConverter jwtAuthConverter;
22 |
23 | public SecurityConfig(JwtAuthConverter jwtAuthConverter) {
24 | this.jwtAuthConverter = jwtAuthConverter;
25 | }
26 |
27 | @Bean
28 | public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
29 | return httpSecurity
30 | .cors(Customizer.withDefaults())
31 | .sessionManagement(sm->sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
32 | .csrf(csrf->csrf.disable())
33 | .headers(h->h.frameOptions(fo->fo.disable()))
34 | .authorizeHttpRequests(ar->ar.requestMatchers("/h2-console/**","/swagger-ui.html","/v3/**","/swagger-ui/**").permitAll())
35 | //.authorizeHttpRequests(ar->ar.requestMatchers("/api/products/**").hasAuthority("ADMIN"))
36 | .authorizeHttpRequests(ar->ar.anyRequest().authenticated())
37 | .oauth2ResourceServer(o2->o2.jwt(jwt->jwt.jwtAuthenticationConverter(jwtAuthConverter)))
38 | .build();
39 | }
40 | @Bean
41 | CorsConfigurationSource corsConfigurationSource() {
42 | CorsConfiguration configuration = new CorsConfiguration();
43 | configuration.setAllowedOrigins(Arrays.asList("*"));
44 | configuration.setAllowedMethods(Arrays.asList("*"));
45 | configuration.setAllowedHeaders(Arrays.asList("*"));
46 | configuration.setExposedHeaders(Arrays.asList("*"));
47 | UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
48 | source.registerCorsConfiguration("/**", configuration);
49 | return source;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/order-service/src/main/java/net/youssfi/orderservice/web/OrdersRestControllers.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.orderservice.web;
2 |
3 | import net.youssfi.orderservice.entities.Order;
4 | import net.youssfi.orderservice.repsoitories.OrderRepository;
5 | import net.youssfi.orderservice.restclients.InventoryRestClient;
6 | import org.springframework.http.ResponseEntity;
7 | import org.springframework.web.bind.annotation.GetMapping;
8 | import org.springframework.web.bind.annotation.PathVariable;
9 | import org.springframework.web.bind.annotation.RequestMapping;
10 | import org.springframework.web.bind.annotation.RestController;
11 |
12 | import java.util.List;
13 |
14 | @RestController
15 | @RequestMapping("/api")
16 | public class OrdersRestControllers {
17 | private OrderRepository orderRepository;
18 | private InventoryRestClient inventoryRestClient;
19 |
20 | public OrdersRestControllers(OrderRepository orderRepository, InventoryRestClient inventoryRestClient) {
21 | this.orderRepository = orderRepository;
22 | this.inventoryRestClient = inventoryRestClient;
23 | }
24 |
25 | @GetMapping("/orders")
26 | public List findAllOrders(){
27 | List allOrders = orderRepository.findAll();
28 | allOrders.forEach(o->{
29 | o.getProductItems().forEach(pi->{
30 | pi.setProduct(inventoryRestClient.findProductById(pi.getProductId()));
31 | });
32 | });
33 | return allOrders;
34 | }
35 | @GetMapping("/orders/{id}")
36 | public Order findOrderById(@PathVariable String id){
37 | Order order = orderRepository.findById(id).get();
38 | order.getProductItems().forEach(pi->{
39 | pi.setProduct(inventoryRestClient.findProductById(pi.getProductId()));
40 | });
41 | return order;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/order-service/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.application.name=order-service
2 | server.port=8088
3 | spring.cloud.discovery.enabled=false
4 | spring.cloud.config.enabled=false
5 |
6 | spring.h2.console.enabled=true
7 | spring.datasource.url=jdbc:h2:mem:orders-db
8 |
9 | #spring.jpa.hibernate.ddl-auto=create-drop
10 |
11 | spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8080/realms/bdcc-realm
12 | spring.security.oauth2.resourceserver.jwt.jwk-set-uri=http://localhost:8080/realms/bdcc-realm/protocol/openid-connect/certs
13 |
--------------------------------------------------------------------------------
/order-service/src/test/java/net/youssfi/orderservice/OrderServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.orderservice;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class OrderServiceApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | net.youssfi
8 | ecom-bdcc-app
9 | 1.0-SNAPSHOT
10 |
11 |
12 | 17
13 | 17
14 | UTF-8
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/main/java/net/youssfi/Main.java:
--------------------------------------------------------------------------------
1 | package net.youssfi;
2 |
3 | /**
4 | * @author ${USER}
5 | **/
6 | public class Main {
7 | public static void main(String[] args) {
8 | System.out.println("Hello world!");
9 | }
10 | }
--------------------------------------------------------------------------------