├── .idea
├── .gitignore
├── compiler.xml
├── encodings.xml
├── jarRepositories.xml
├── misc.xml
└── vcs.xml
├── README.MD
├── captures
└── keycloak
│ ├── 1.png
│ ├── 10.png
│ ├── 11.png
│ ├── 12.png
│ ├── 13.png
│ ├── 14.png
│ ├── 15.png
│ ├── 16.png
│ ├── 17.png
│ ├── 18.png
│ ├── 19.png
│ ├── 2.png
│ ├── 20.png
│ ├── 21.png
│ ├── 22.png
│ ├── 23.png
│ ├── 24.png
│ ├── 25.png
│ ├── 26.png
│ ├── 27.png
│ ├── 28.png
│ ├── 29.png
│ ├── 3.png
│ ├── 30.png
│ ├── 31.png
│ ├── 32.png
│ ├── 33.png
│ ├── 34.png
│ ├── 35.png
│ ├── 36.png
│ ├── 37.png
│ ├── 38.png
│ ├── 39.png
│ ├── 4.png
│ ├── 40.png
│ ├── 41.png
│ ├── 42.png
│ ├── 5.png
│ ├── 6.png
│ ├── 7.png
│ ├── 8.png
│ └── 9.png
├── front-end-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.ts
│ │ ├── services
│ │ │ └── security-service.service.ts
│ │ └── ui
│ │ │ ├── customers
│ │ │ ├── customers.component.css
│ │ │ ├── customers.component.html
│ │ │ ├── customers.component.spec.ts
│ │ │ └── customers.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
├── front-end-thymeleaf
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── net
│ │ │ └── youssfi
│ │ │ └── frontendthymeleaf
│ │ │ ├── FrontEndThymeleafApplication.java
│ │ │ ├── entities
│ │ │ ├── AppUser.java
│ │ │ └── Customer.java
│ │ │ ├── model
│ │ │ └── Product.java
│ │ │ ├── repository
│ │ │ ├── AppUserRepository.java
│ │ │ └── CustomerRepository.java
│ │ │ ├── sec
│ │ │ ├── SecurityConfig.java
│ │ │ └── UserSynchronizationService.java
│ │ │ └── web
│ │ │ ├── CustomerController.java
│ │ │ ├── ProductController.java
│ │ │ └── UserRestController.java
│ └── resources
│ │ ├── application.properties
│ │ └── templates
│ │ ├── customers.html
│ │ ├── index.html
│ │ ├── oauth2LoginPage.html
│ │ ├── products.html
│ │ └── template.html
│ └── test
│ └── java
│ └── net
│ └── youssfi
│ └── frontendthymeleaf
│ └── FrontEndThymeleafApplicationTests.java
├── inventoory-service
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── net
│ │ │ └── youssfi
│ │ │ └── inventooryservice
│ │ │ ├── InventooryServiceApplication.java
│ │ │ ├── entities
│ │ │ └── Product.java
│ │ │ ├── repository
│ │ │ └── ProductRepository.java
│ │ │ ├── sec
│ │ │ ├── JwtAuthConverter.java
│ │ │ └── SecurityConfig.java
│ │ │ └── web
│ │ │ ├── ProductController.java
│ │ │ └── ProductNotFoundException.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── net
│ └── youssfi
│ └── inventooryservice
│ └── InventooryServiceApplicationTests.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 |
--------------------------------------------------------------------------------
/README.MD:
--------------------------------------------------------------------------------
1 |
Keycloak
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/captures/keycloak/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/1.png
--------------------------------------------------------------------------------
/captures/keycloak/10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/10.png
--------------------------------------------------------------------------------
/captures/keycloak/11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/11.png
--------------------------------------------------------------------------------
/captures/keycloak/12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/12.png
--------------------------------------------------------------------------------
/captures/keycloak/13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/13.png
--------------------------------------------------------------------------------
/captures/keycloak/14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/14.png
--------------------------------------------------------------------------------
/captures/keycloak/15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/15.png
--------------------------------------------------------------------------------
/captures/keycloak/16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/16.png
--------------------------------------------------------------------------------
/captures/keycloak/17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/17.png
--------------------------------------------------------------------------------
/captures/keycloak/18.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/18.png
--------------------------------------------------------------------------------
/captures/keycloak/19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/19.png
--------------------------------------------------------------------------------
/captures/keycloak/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/2.png
--------------------------------------------------------------------------------
/captures/keycloak/20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/20.png
--------------------------------------------------------------------------------
/captures/keycloak/21.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/21.png
--------------------------------------------------------------------------------
/captures/keycloak/22.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/22.png
--------------------------------------------------------------------------------
/captures/keycloak/23.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/23.png
--------------------------------------------------------------------------------
/captures/keycloak/24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/24.png
--------------------------------------------------------------------------------
/captures/keycloak/25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/25.png
--------------------------------------------------------------------------------
/captures/keycloak/26.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/26.png
--------------------------------------------------------------------------------
/captures/keycloak/27.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/27.png
--------------------------------------------------------------------------------
/captures/keycloak/28.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/28.png
--------------------------------------------------------------------------------
/captures/keycloak/29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/29.png
--------------------------------------------------------------------------------
/captures/keycloak/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/3.png
--------------------------------------------------------------------------------
/captures/keycloak/30.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/30.png
--------------------------------------------------------------------------------
/captures/keycloak/31.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/31.png
--------------------------------------------------------------------------------
/captures/keycloak/32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/32.png
--------------------------------------------------------------------------------
/captures/keycloak/33.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/33.png
--------------------------------------------------------------------------------
/captures/keycloak/34.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/34.png
--------------------------------------------------------------------------------
/captures/keycloak/35.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/35.png
--------------------------------------------------------------------------------
/captures/keycloak/36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/36.png
--------------------------------------------------------------------------------
/captures/keycloak/37.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/37.png
--------------------------------------------------------------------------------
/captures/keycloak/38.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/38.png
--------------------------------------------------------------------------------
/captures/keycloak/39.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/39.png
--------------------------------------------------------------------------------
/captures/keycloak/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/4.png
--------------------------------------------------------------------------------
/captures/keycloak/40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/40.png
--------------------------------------------------------------------------------
/captures/keycloak/41.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/41.png
--------------------------------------------------------------------------------
/captures/keycloak/42.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/42.png
--------------------------------------------------------------------------------
/captures/keycloak/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/5.png
--------------------------------------------------------------------------------
/captures/keycloak/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/6.png
--------------------------------------------------------------------------------
/captures/keycloak/7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/7.png
--------------------------------------------------------------------------------
/captures/keycloak/8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/8.png
--------------------------------------------------------------------------------
/captures/keycloak/9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/captures/keycloak/9.png
--------------------------------------------------------------------------------
/front-end-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 |
--------------------------------------------------------------------------------
/front-end-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 |
--------------------------------------------------------------------------------
/front-end-angular/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846
3 | "recommendations": ["angular.ng-template"]
4 | }
5 |
--------------------------------------------------------------------------------
/front-end-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 |
--------------------------------------------------------------------------------
/front-end-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 |
--------------------------------------------------------------------------------
/front-end-angular/README.md:
--------------------------------------------------------------------------------
1 | # FrontEndAngular
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 |
--------------------------------------------------------------------------------
/front-end-angular/angular.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3 | "version": 1,
4 | "newProjectRoot": "projects",
5 | "projects": {
6 | "front-end-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/front-end-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": "front-end-angular:build:production"
74 | },
75 | "development": {
76 | "buildTarget": "front-end-angular:build:development"
77 | }
78 | },
79 | "defaultConfiguration": "development"
80 | },
81 | "extract-i18n": {
82 | "builder": "@angular-devkit/build-angular:extract-i18n",
83 | "options": {
84 | "buildTarget": "front-end-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": "1a25e031-b1c1-4c21-85ba-38397f714c00"
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/front-end-angular/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "front-end-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.2",
23 | "keycloak-angular": "^15.0.0",
24 | "keycloak-js": "^22.0.5",
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 |
--------------------------------------------------------------------------------
/front-end-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 |
7 | const routes: Routes = [
8 | {path : "products", component : ProductsComponent, canActivate : [AuthGuard], data : { roles : ['ADMIN']}},
9 | {path: "customers", component : CustomersComponent}
10 | ];
11 |
12 | @NgModule({
13 | imports: [RouterModule.forRoot(routes)],
14 | exports: [RouterModule]
15 | })
16 | export class AppRoutingModule { }
17 |
--------------------------------------------------------------------------------
/front-end-angular/src/app/app.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/front-end-angular/src/app/app.component.css
--------------------------------------------------------------------------------
/front-end-angular/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/front-end-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 'front-end-angular'`, () => {
24 | const fixture = TestBed.createComponent(AppComponent);
25 | const app = fixture.componentInstance;
26 | expect(app.title).toEqual('front-end-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, front-end-angular');
34 | });
35 | });
36 |
--------------------------------------------------------------------------------
/front-end-angular/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 | import {SecurityService} from "./services/security-service.service";
3 |
4 | @Component({
5 | selector: 'app-root',
6 | templateUrl: './app.component.html',
7 | styleUrl: './app.component.css'
8 | })
9 | export class AppComponent {
10 | title = 'front-end-angular';
11 | constructor(public securityService: SecurityService ) {
12 | }
13 | async login(){
14 | await this.securityService.kcService.login({
15 | redirectUri : window.location.origin
16 | })
17 | }
18 | onLogout() {
19 | this.securityService.kcService.logout(window.location.origin);
20 | }
21 |
22 | account() {
23 | window.location.href="http://localhost:8080/realms/ebank-realm/account/#/personal-info";
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/front-end-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 {KeycloakAngularModule, KeycloakService} from "keycloak-angular";
9 | import {HttpClientModule} from "@angular/common/http";
10 | export function kcFactory(kcService : KeycloakService){
11 | return ()=>{
12 | kcService.init({
13 | config : {
14 | realm :"ebank-realm",
15 | clientId : "angular-client",
16 | url : "http://localhost:8080"
17 | },
18 | initOptions : {
19 | onLoad : "check-sso",
20 | checkLoginIframe : true,
21 | silentCheckSsoRedirectUri:
22 | window.location.origin + '/assets/silent-check-sso.html'
23 | }
24 | })
25 | }
26 | }
27 |
28 | @NgModule({
29 | declarations: [
30 | AppComponent,
31 | ProductsComponent,
32 | CustomersComponent
33 | ],
34 | imports: [
35 | BrowserModule,
36 | AppRoutingModule,
37 | KeycloakAngularModule,
38 | HttpClientModule
39 | ],
40 | providers: [
41 | {provide : APP_INITIALIZER, deps : [KeycloakService],useFactory : kcFactory, multi : true}
42 | ],
43 | bootstrap: [AppComponent]
44 | })
45 | export class AppModule { }
46 |
--------------------------------------------------------------------------------
/front-end-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
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 (!(requiredRoles instanceof Array) || 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 |
--------------------------------------------------------------------------------
/front-end-angular/src/app/services/security-service.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from "@angular/core";
2 | import {KeycloakProfile} from "keycloak-js";
3 | import {KeycloakEventType, KeycloakService} from "keycloak-angular";
4 |
5 | @Injectable({providedIn : "root"})
6 | export class SecurityService {
7 | public profile? : KeycloakProfile;
8 | constructor (public kcService: KeycloakService) {
9 | this.init();
10 | }
11 | init(){
12 | this.kcService.keycloakEvents$.subscribe({
13 | next: (e) => {
14 | if (e.type == KeycloakEventType.OnAuthSuccess) {
15 | this.kcService.loadUserProfile().then(profile=>{
16 | this.profile=profile;
17 | });
18 | }
19 | }
20 | });
21 | }
22 | public hasRoleIn(roles:string[]):boolean{
23 | let userRoles = this.kcService.getUserRoles();
24 | for(let role of roles){
25 | if (userRoles.includes(role)) return true;
26 | } return false;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/front-end-angular/src/app/ui/customers/customers.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/front-end-angular/src/app/ui/customers/customers.component.css
--------------------------------------------------------------------------------
/front-end-angular/src/app/ui/customers/customers.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Customers Content
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/front-end-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 |
--------------------------------------------------------------------------------
/front-end-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 |
--------------------------------------------------------------------------------
/front-end-angular/src/app/ui/products/products.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/front-end-angular/src/app/ui/products/products.component.css
--------------------------------------------------------------------------------
/front-end-angular/src/app/ui/products/products.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | ID | Name | Price | Quantity |
8 |
9 |
10 |
11 |
12 | {{p.id}} |
13 | {{p.name}} |
14 | {{p.price}} |
15 | {{p.quantity}} |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/front-end-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 |
--------------------------------------------------------------------------------
/front-end-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 | products : any;
11 | constructor(private httpClient : HttpClient) {
12 | }
13 | ngOnInit() {
14 | this.httpClient.get("http://localhost:8081/api/products")
15 | .subscribe({
16 | next : products => {
17 | this.products = products;
18 | },
19 | error : err => {
20 | console.log(err);
21 | }
22 | })
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/front-end-angular/src/assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/front-end-angular/src/assets/.gitkeep
--------------------------------------------------------------------------------
/front-end-angular/src/assets/silent-check-sso.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
--------------------------------------------------------------------------------
/front-end-angular/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/front-end-angular/src/favicon.ico
--------------------------------------------------------------------------------
/front-end-angular/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | FrontEndAngular
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/front-end-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 |
--------------------------------------------------------------------------------
/front-end-angular/src/styles.css:
--------------------------------------------------------------------------------
1 | /* You can add global styles to this file, and also import other style files */
2 |
--------------------------------------------------------------------------------
/front-end-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 |
--------------------------------------------------------------------------------
/front-end-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 |
--------------------------------------------------------------------------------
/front-end-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 |
--------------------------------------------------------------------------------
/front-end-thymeleaf/.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 |
--------------------------------------------------------------------------------
/front-end-thymeleaf/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/front-end-thymeleaf/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/front-end-thymeleaf/.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 |
--------------------------------------------------------------------------------
/front-end-thymeleaf/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 |
--------------------------------------------------------------------------------
/front-end-thymeleaf/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 |
--------------------------------------------------------------------------------
/front-end-thymeleaf/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 3.2.0
9 |
10 |
11 | net.youssfi
12 | front-end-thymeleaf
13 | 0.0.1-SNAPSHOT
14 | front-end-thymeleaf
15 | front-end-thymeleaf
16 |
17 | 21
18 |
19 |
20 |
21 | org.springframework.boot
22 | spring-boot-starter-data-jpa
23 |
24 |
25 | org.springframework.boot
26 | spring-boot-starter-oauth2-client
27 |
28 |
29 | org.springframework.boot
30 | spring-boot-starter-thymeleaf
31 |
32 |
33 | org.springframework.boot
34 | spring-boot-starter-web
35 |
36 |
37 | org.webjars
38 | bootstrap
39 | 5.3.2
40 |
41 |
42 |
43 | nz.net.ultraq.thymeleaf
44 | thymeleaf-layout-dialect
45 | 3.2.1
46 |
47 |
48 |
49 |
50 | org.thymeleaf.extras
51 | thymeleaf-extras-springsecurity6
52 | 3.1.0.M1
53 |
54 |
55 |
56 | com.h2database
57 | h2
58 | runtime
59 |
60 |
61 | org.projectlombok
62 | lombok
63 | true
64 |
65 |
66 | org.springframework.boot
67 | spring-boot-starter-test
68 | test
69 |
70 |
71 |
72 |
73 |
74 |
75 | org.springframework.boot
76 | spring-boot-maven-plugin
77 |
78 |
79 |
80 | org.projectlombok
81 | lombok
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/front-end-thymeleaf/src/main/java/net/youssfi/frontendthymeleaf/FrontEndThymeleafApplication.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.frontendthymeleaf;
2 |
3 | import net.youssfi.frontendthymeleaf.entities.Customer;
4 | import net.youssfi.frontendthymeleaf.repository.CustomerRepository;
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 | import org.springframework.web.client.RestClient;
10 |
11 | @SpringBootApplication
12 | public class FrontEndThymeleafApplication {
13 |
14 | public static void main(String[] args) {
15 | SpringApplication.run(FrontEndThymeleafApplication.class, args);
16 | }
17 | @Bean
18 | CommandLineRunner commandLineRunner(CustomerRepository customerRepository){
19 | return args -> {
20 | customerRepository.save(Customer.builder().name("Mohamed").email("med@gmail.com").build());
21 | customerRepository.save(Customer.builder().name("Hanne").email("hanane@gmail.com").build());
22 | customerRepository.save(Customer.builder().name("Ines").email("ines@gmail.com").build());
23 | customerRepository.save(Customer.builder().name("Malak").email("malak@gmail.com").build());
24 | };
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/front-end-thymeleaf/src/main/java/net/youssfi/frontendthymeleaf/entities/AppUser.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.frontendthymeleaf.entities;
2 |
3 | import jakarta.persistence.Entity;
4 | import jakarta.persistence.Id;
5 | import lombok.*;
6 |
7 | @Entity
8 | @NoArgsConstructor @AllArgsConstructor @Getter @Setter @Builder
9 | public class AppUser {
10 | @Id
11 | private String userId;
12 | private String identityProvider;
13 | private String email;
14 | private String login;
15 | private String preferredUserName;
16 | }
17 |
--------------------------------------------------------------------------------
/front-end-thymeleaf/src/main/java/net/youssfi/frontendthymeleaf/entities/Customer.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.frontendthymeleaf.entities;
2 |
3 | import jakarta.persistence.Entity;
4 | import jakarta.persistence.GeneratedValue;
5 | import jakarta.persistence.GenerationType;
6 | import jakarta.persistence.Id;
7 | import lombok.*;
8 |
9 | @Entity
10 | @NoArgsConstructor @AllArgsConstructor @Getter @Setter @Builder
11 | public class Customer {
12 | @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
13 | private Long id;
14 | private String name;
15 | private String email;
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/front-end-thymeleaf/src/main/java/net/youssfi/frontendthymeleaf/model/Product.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.frontendthymeleaf.model;
2 |
3 | import lombok.*;
4 |
5 |
6 | @Getter @Setter @NoArgsConstructor @AllArgsConstructor @Builder
7 | public class Product {
8 | private String id;
9 | private String name;
10 | private double price;
11 | private int quantity;
12 | }
13 |
--------------------------------------------------------------------------------
/front-end-thymeleaf/src/main/java/net/youssfi/frontendthymeleaf/repository/AppUserRepository.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.frontendthymeleaf.repository;
2 |
3 | import net.youssfi.frontendthymeleaf.entities.AppUser;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 |
6 | public interface AppUserRepository extends JpaRepository {
7 | }
8 |
--------------------------------------------------------------------------------
/front-end-thymeleaf/src/main/java/net/youssfi/frontendthymeleaf/repository/CustomerRepository.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.frontendthymeleaf.repository;
2 | import net.youssfi.frontendthymeleaf.entities.Customer;
3 | import org.springframework.data.jpa.repository.JpaRepository;
4 |
5 | public interface CustomerRepository extends JpaRepository {
6 | }
7 |
--------------------------------------------------------------------------------
/front-end-thymeleaf/src/main/java/net/youssfi/frontendthymeleaf/sec/SecurityConfig.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.frontendthymeleaf.sec;
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.core.GrantedAuthority;
10 | import org.springframework.security.core.authority.SimpleGrantedAuthority;
11 | import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
12 | import org.springframework.security.oauth2.client.InMemoryOAuth2AuthorizedClientService;
13 | import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
14 | import org.springframework.security.oauth2.client.oidc.web.logout.OidcClientInitiatedLogoutSuccessHandler;
15 | import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
16 | import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority;
17 | import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
18 | import org.springframework.security.web.SecurityFilterChain;
19 |
20 | import java.util.*;
21 |
22 | @Configuration
23 | @EnableWebSecurity
24 | @EnableMethodSecurity(prePostEnabled = true)
25 | public class SecurityConfig {
26 |
27 | private ClientRegistrationRepository clientRegistrationRepository;
28 |
29 | public SecurityConfig(ClientRegistrationRepository clientRegistrationRepository) {
30 | this.clientRegistrationRepository = clientRegistrationRepository;
31 | }
32 |
33 | @Bean
34 | public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
35 |
36 | return http.cors(Customizer.withDefaults())
37 | .csrf(Customizer.withDefaults())
38 | .authorizeHttpRequests((authorize) -> authorize
39 | .requestMatchers("/","/customOauth2login/**", "/css/**", "/js/**", "/images/**", "/webjars/**","/h2-console/**").permitAll()
40 | .anyRequest().authenticated())
41 | .headers(h->h.frameOptions(fo->fo.disable()))
42 | .csrf(csrf->csrf.ignoringRequestMatchers("/h2-console/**"))
43 | .oauth2Login(o2->{
44 | o2.loginPage("/customOauth2login");
45 | })
46 | .logout((logout) -> logout
47 | .logoutSuccessHandler(oidcLogoutSuccessHandler())
48 | .logoutSuccessUrl("/").permitAll()
49 | .deleteCookies("JSESSIONID"))
50 | .build();
51 | }
52 |
53 | private OidcClientInitiatedLogoutSuccessHandler oidcLogoutSuccessHandler() {
54 | final OidcClientInitiatedLogoutSuccessHandler oidcLogoutSuccessHandler =
55 | new OidcClientInitiatedLogoutSuccessHandler(this.clientRegistrationRepository);
56 | oidcLogoutSuccessHandler.setPostLogoutRedirectUri("{baseUrl}?logoutsuccess=true");
57 | return oidcLogoutSuccessHandler;
58 | }
59 |
60 | @Bean
61 | public GrantedAuthoritiesMapper userAuthoritiesMapper() {
62 | return (authorities) -> {
63 | final Set mappedAuthorities = new HashSet<>();
64 | authorities.forEach((authority) -> {
65 | if (authority instanceof OidcUserAuthority oidcAuth) {
66 | mappedAuthorities.addAll(mapAuthorities(oidcAuth.getIdToken().getClaims()));
67 | System.out.println("----------");
68 | System.out.println(oidcAuth.getAttributes());
69 | } else if (authority instanceof OAuth2UserAuthority oauth2Auth) {
70 | mappedAuthorities.addAll(mapAuthorities(oauth2Auth.getAttributes()));
71 | System.out.println("************");
72 | System.out.println(oauth2Auth.getAttributes());
73 | }
74 | });
75 | return mappedAuthorities;
76 | };
77 | }
78 |
79 | /**
80 | * Read claims from attribute realm_access.roles as SimpleGrantedAuthority.
81 | */
82 | private List mapAuthorities(final Map attributes) {
83 | final Map realmAccess = ((Map)attributes.getOrDefault("realm_access", Collections.emptyMap()));
84 | final Collection roles = ((Collection)realmAccess.getOrDefault("roles", Collections.emptyList()));
85 | System.out.println("Roles");
86 | System.out.println(roles.size());
87 | return roles.stream()
88 | .map((role) -> new SimpleGrantedAuthority(role))
89 | .toList();
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/front-end-thymeleaf/src/main/java/net/youssfi/frontendthymeleaf/sec/UserSynchronizationService.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.frontendthymeleaf.sec;
2 |
3 | import com.fasterxml.jackson.core.JsonProcessingException;
4 | import lombok.extern.slf4j.Slf4j;
5 |
6 | import net.youssfi.frontendthymeleaf.entities.AppUser;
7 | import net.youssfi.frontendthymeleaf.repository.AppUserRepository;
8 | import org.springframework.context.event.EventListener;
9 | import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
10 | import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
11 | import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
12 | import org.springframework.security.oauth2.core.oidc.user.OidcUser;
13 | import org.springframework.security.oauth2.core.user.OAuth2User;
14 | import org.springframework.stereotype.Service;
15 |
16 | import java.util.Map;
17 |
18 | /**
19 | * @author mohamedyoussfi
20 | **/
21 | @Service
22 | @Slf4j
23 | public class UserSynchronizationService {
24 |
25 | private AppUserRepository appUserRepository;
26 | private ClientRegistrationRepository clientRegistrationRepository;
27 | private OAuth2AuthorizedClientService oAuth2AuthorizedClientService;
28 |
29 |
30 | public UserSynchronizationService(AppUserRepository appUserRepository, ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientService oAuth2AuthorizedClientService) {
31 | this.appUserRepository = appUserRepository;
32 | this.clientRegistrationRepository = clientRegistrationRepository;
33 | }
34 |
35 | private void syncWithDatabase(String userId, Map attributes) throws JsonProcessingException {
36 | AppUser user = appUserRepository.findById(userId).orElse(null);
37 | if (user == null) {
38 | log.info("adding new user after successful login: {}", userId);
39 | user = new AppUser();
40 | user.setUserId(userId);
41 | } else {
42 | log.info("updating existing user after successful login: {}", userId);
43 | }
44 | user.setLogin(attributes.getOrDefault("login","").toString());
45 | user.setEmail(String.valueOf(attributes.getOrDefault("email","")));
46 | user.setPreferredUserName(attributes.getOrDefault("preferred_username","").toString());
47 | appUserRepository.save(user);
48 | }
49 |
50 | @EventListener(AuthenticationSuccessEvent.class)
51 | public void onAuthenticationSuccessEvent(final AuthenticationSuccessEvent event) throws JsonProcessingException {
52 | if(event.getAuthentication().getAuthorities() instanceof OidcUser oidcUser){
53 | syncWithDatabase(oidcUser.getSubject(),oidcUser.getAttributes());
54 | } else if(event.getAuthentication().getPrincipal() instanceof OAuth2User oauth2user) {
55 | syncWithDatabase(oauth2user.getName(), oauth2user.getAttributes());
56 | }
57 | System.out.println(".............");
58 |
59 | }
60 |
61 | }
--------------------------------------------------------------------------------
/front-end-thymeleaf/src/main/java/net/youssfi/frontendthymeleaf/web/CustomerController.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.frontendthymeleaf.web;
2 |
3 | import net.youssfi.frontendthymeleaf.repository.CustomerRepository;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.core.ResolvableType;
6 | import org.springframework.security.access.prepost.PreAuthorize;
7 | import org.springframework.security.core.Authentication;
8 | import org.springframework.security.oauth2.client.registration.ClientRegistration;
9 | import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
10 | import org.springframework.stereotype.Controller;
11 | import org.springframework.ui.Model;
12 | import org.springframework.web.bind.annotation.GetMapping;
13 | import org.springframework.web.bind.annotation.ResponseBody;
14 |
15 | import java.util.HashMap;
16 | import java.util.Map;
17 | @Controller
18 | public class CustomerController {
19 | @Autowired
20 | private CustomerRepository customerRepository;
21 | @Autowired
22 | private ClientRegistrationRepository clientRegistrationRepository;
23 |
24 |
25 | @GetMapping("/securedMessage")
26 | @PreAuthorize("hasAuthority('ADMIN')")
27 | @ResponseBody
28 | public Map securedEndpoint(){
29 | return Map.of("securedMessage","Secured Customer");
30 | }
31 | @GetMapping("/auth")
32 | @ResponseBody
33 | public Authentication authentication(Authentication authentication){
34 | return authentication;
35 | }
36 | @GetMapping("/")
37 | public String index(){
38 | return "index";
39 | }
40 | @GetMapping("/customOauth2login")
41 | public String oauth2Login(Model model){
42 | String authorizationRequestBaseUri = "oauth2/authorization";
43 | Map oauth2AuthenticationUrls = new HashMap();
44 | Iterable clientRegistrations = null;
45 | ResolvableType type = ResolvableType.forInstance(clientRegistrationRepository)
46 | .as(Iterable.class);
47 | if (type != ResolvableType.NONE &&
48 | ClientRegistration.class.isAssignableFrom(type.resolveGenerics()[0])) {
49 | clientRegistrations = (Iterable) clientRegistrationRepository;
50 | System.out.println("..............******");
51 | }
52 |
53 | clientRegistrations.forEach(registration ->{
54 | oauth2AuthenticationUrls.put(registration.getClientName(),
55 | authorizationRequestBaseUri + "/" + registration.getRegistrationId());
56 | System.out.println(registration.getClientName());
57 | });
58 |
59 | model.addAttribute("urls", oauth2AuthenticationUrls);
60 | return "oauth2LoginPage";
61 | }
62 | @GetMapping("/customers")
63 | public String customers(Model model){
64 | model.addAttribute("customers", customerRepository.findAll());
65 | return "customers";
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/front-end-thymeleaf/src/main/java/net/youssfi/frontendthymeleaf/web/ProductController.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.frontendthymeleaf.web;
2 | import net.youssfi.frontendthymeleaf.model.Product;
3 | import org.springframework.core.ParameterizedTypeReference;
4 | import org.springframework.http.HttpHeaders;
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.client.authentication.OAuth2AuthenticationToken;
9 | import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
10 | import org.springframework.stereotype.Controller;
11 | import org.springframework.ui.Model;
12 | import org.springframework.web.bind.annotation.GetMapping;
13 | import org.springframework.web.client.RestClient;
14 |
15 | import java.util.List;
16 |
17 | @Controller
18 | public class ProductController {
19 |
20 | @GetMapping("/products")
21 | public String products(Model model){
22 | SecurityContext context = SecurityContextHolder.getContext();
23 | Authentication authentication = context.getAuthentication();
24 | OAuth2AuthenticationToken oAuth2AuthenticationToken= (OAuth2AuthenticationToken) authentication;
25 | DefaultOidcUser oidcUser = (DefaultOidcUser) oAuth2AuthenticationToken.getPrincipal();
26 | String jwtTokenValue=oidcUser.getIdToken().getTokenValue();
27 | RestClient restClient = RestClient.create("http://localhost:8081");
28 | List products = restClient.get()
29 | .uri("/api/products")
30 | .headers(httpHeaders -> httpHeaders.set(HttpHeaders.AUTHORIZATION, "Bearer "+jwtTokenValue))
31 | .retrieve()
32 | .body(new ParameterizedTypeReference<>(){});
33 | model.addAttribute("products",products);
34 | return "products";
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/front-end-thymeleaf/src/main/java/net/youssfi/frontendthymeleaf/web/UserRestController.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.frontendthymeleaf.web;
2 |
3 | import net.youssfi.frontendthymeleaf.entities.AppUser;
4 | import net.youssfi.frontendthymeleaf.repository.AppUserRepository;
5 | import org.springframework.web.bind.annotation.GetMapping;
6 | import org.springframework.web.bind.annotation.RestController;
7 |
8 | import java.util.List;
9 |
10 | @RestController
11 | public class UserRestController {
12 | private AppUserRepository appUserRepository;
13 |
14 | public UserRestController(AppUserRepository appUserRepository) {
15 | this.appUserRepository = appUserRepository;
16 | }
17 | @GetMapping("/appUsers")
18 | public List appUsers(){
19 | return appUserRepository.findAll();
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/front-end-thymeleaf/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
2 | server.port=8888
3 | spring.datasource.url=jdbc:h2:mem:users-db
4 | spring.h2.console.enabled=true
5 |
6 |
7 | spring.security.oauth2.client.registration.github.clientId=Iv1.29a7aad8e671d9b3
8 | spring.security.oauth2.client.registration.github.client-secret=3f92e348fb108b292c1d03350ac60014e417529b
9 | spring.security.oauth2.client.provider.github.user-name-attribute=login
10 |
11 | spring.security.oauth2.client.registration.google.clientId=424329089617-3vel32qbq0ld89ahd3lkg7em8f23akfi.apps.googleusercontent.com
12 | spring.security.oauth2.client.registration.google.client-secret=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
13 | spring.security.oauth2.client.provider.google.user-name-attribute=email
14 |
15 | spring.security.oauth2.client.registration.keycloak.client-name=keycloak
16 | spring.security.oauth2.client.registration.keycloak.client-id=customer-client
17 | spring.security.oauth2.client.registration.keycloak.client-secret=Lf3hRYLQq0V4dZyQPWSdBvrR3FtHgJAr
18 | #spring.security.oauth2.client.registration.keycloak.client-secret=--generated--
19 | spring.security.oauth2.client.registration.keycloak.scope=openid,profile,email,offline_access
20 | spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
21 | spring.security.oauth2.client.registration.keycloak.redirect-uri=http://localhost:8888/login/oauth2/code/customer-client
22 | spring.security.oauth2.client.provider.keycloak.issuer-uri=http://localhost:8080/realms/ebank-realm
23 |
24 | spring.security.oauth2.client.provider.keycloak.user-name-attribute=preferred_username
25 | spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8080/realms/ebank-realm
26 |
27 | #github.clientid=Iv1.29a7aad8e671d9b3
28 | #github.clientsecret=3f92e348fb108b292c1d03350ac60014e417529b
29 |
30 |
31 | #google.clientid=424329089617-3vel32qbq0ld89ahd3lkg7em8f23akfi.apps.googleusercontent.com
32 | #google.clientsecret=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
33 |
34 | #{"installed":{"client_id":"424329089617-3vel32qbq0ld89ahd3lkg7em8f23akfi.apps.googleusercontent.com","project_id":"customers-app-406510","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"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","redirect_uris":["http://localhost"]}}
35 |
36 |
--------------------------------------------------------------------------------
/front-end-thymeleaf/src/main/resources/templates/customers.html:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 | Customers
9 |
10 |
11 |
12 |
13 |
14 |
15 | ID | Name | Email |
16 |
17 |
18 |
19 |
20 | |
21 | |
22 | |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/front-end-thymeleaf/src/main/resources/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 | Index
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/front-end-thymeleaf/src/main/resources/templates/oauth2LoginPage.html:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 | Oauth 2 Login
9 |
10 |
11 |
12 |
13 |
Oauth2 Login with:
14 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/front-end-thymeleaf/src/main/resources/templates/products.html:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 | Customers
9 |
10 |
11 |
12 |
13 |
14 |
15 | ID | Name | Price | Quantity |
16 |
17 |
18 |
19 |
20 | |
21 | |
22 | |
23 | |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/front-end-thymeleaf/src/main/resources/templates/template.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 | Template
7 |
8 |
9 |
10 |
11 |
12 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/front-end-thymeleaf/src/test/java/net/youssfi/frontendthymeleaf/FrontEndThymeleafApplicationTests.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.frontendthymeleaf;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class FrontEndThymeleafApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/inventoory-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 |
--------------------------------------------------------------------------------
/inventoory-service/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mohamedYoussfi/spring-angular-oauth2-keycloak/ac513ce310e690141136e924f3b6c3212b6ff0bb/inventoory-service/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/inventoory-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 |
--------------------------------------------------------------------------------
/inventoory-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 |
--------------------------------------------------------------------------------
/inventoory-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 |
--------------------------------------------------------------------------------
/inventoory-service/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 3.2.0
9 |
10 |
11 | net.youssfi
12 | inventoory-service
13 | 0.0.1-SNAPSHOT
14 | inventoory-service
15 | inventoory-service
16 |
17 | 21
18 |
19 |
20 |
21 | org.springframework.boot
22 | spring-boot-starter-data-jpa
23 |
24 |
25 | org.springframework.boot
26 | spring-boot-starter-oauth2-resource-server
27 |
28 |
29 | org.springframework.boot
30 | spring-boot-starter-web
31 |
32 |
33 |
34 | com.h2database
35 | h2
36 | runtime
37 |
38 |
39 | org.projectlombok
40 | lombok
41 | true
42 |
43 |
44 | org.springframework.boot
45 | spring-boot-starter-test
46 | test
47 |
48 |
49 |
50 |
51 |
52 |
53 | org.springframework.boot
54 | spring-boot-maven-plugin
55 |
56 |
57 |
58 | org.projectlombok
59 | lombok
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/inventoory-service/src/main/java/net/youssfi/inventooryservice/InventooryServiceApplication.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.inventooryservice;
2 |
3 | import net.youssfi.inventooryservice.entities.Product;
4 | import net.youssfi.inventooryservice.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 InventooryServiceApplication {
14 |
15 | public static void main(String[] args) {
16 | SpringApplication.run(InventooryServiceApplication.class, args);
17 | }
18 |
19 | @Bean
20 | CommandLineRunner commandLineRunner(ProductRepository productRepository){
21 | return args -> {
22 | productRepository.save(Product.builder()
23 | .id(UUID.randomUUID().toString())
24 | .name("Computer")
25 | .price(5400)
26 | .quantity(12)
27 | .build());
28 | productRepository.save(Product.builder()
29 | .id(UUID.randomUUID().toString())
30 | .name("Printer")
31 | .price(3200)
32 | .quantity(33)
33 | .build());
34 | productRepository.save(Product.builder()
35 | .id(UUID.randomUUID().toString())
36 | .name("Smart Phone")
37 | .price(12000)
38 | .quantity(4)
39 | .build());
40 | };
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/inventoory-service/src/main/java/net/youssfi/inventooryservice/entities/Product.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.inventooryservice.entities;
2 |
3 | import jakarta.persistence.Entity;
4 | import jakarta.persistence.Id;
5 | import lombok.*;
6 |
7 | @Entity
8 | @Getter @Setter @NoArgsConstructor @AllArgsConstructor @Builder
9 | public class Product {
10 | @Id
11 | private String id;
12 | private String name;
13 | private double price;
14 | private int quantity;
15 | }
16 |
--------------------------------------------------------------------------------
/inventoory-service/src/main/java/net/youssfi/inventooryservice/repository/ProductRepository.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.inventooryservice.repository;
2 |
3 | import net.youssfi.inventooryservice.entities.Product;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 |
6 | /**
7 | * @author mohamedyoussfi
8 | **/
9 | public interface ProductRepository extends JpaRepository {
10 | }
11 |
--------------------------------------------------------------------------------
/inventoory-service/src/main/java/net/youssfi/inventooryservice/sec/JwtAuthConverter.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.inventooryservice.sec;
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 |
22 |
23 | @Override
24 | public AbstractAuthenticationToken convert(Jwt jwt) {
25 | Collection authorities = Stream.concat(
26 | jwtGrantedAuthoritiesConverter.convert(jwt).stream(),
27 | extractResourceRoles(jwt).stream()
28 | ).collect(Collectors.toSet());
29 | return new JwtAuthenticationToken(jwt, authorities,jwt.getClaim("preferred_username"));
30 | }
31 |
32 | private Collection extractResourceRoles(Jwt jwt) {
33 | Map realmAccess;
34 | Collection roles;
35 | if(jwt.getClaim("realm_access")==null){
36 | return Set.of();
37 | }
38 | realmAccess = jwt.getClaim("realm_access");
39 | roles = (Collection) realmAccess.get("roles");
40 | return roles.stream().map(role->new SimpleGrantedAuthority(role)).collect(Collectors.toSet());
41 | }
42 |
43 | }
44 | /*
45 | JWT :
46 | {
47 | "exp": 1701102420,
48 | "iat": 1701102120,
49 | "jti": "80af2544-ada8-4471-bea1-142a7f5fdf9f",
50 | "iss": "http://localhost:8080/realms/ebank-realm",
51 | "aud": "account",
52 | "sub": "9299e9e4-6cdd-4907-89b5-813d2c6a8c36",
53 | "typ": "Bearer",
54 | "azp": "customer-client",
55 | "session_state": "e085be18-fca8-46bd-b746-80f024ffa535",
56 | "acr": "1",
57 | "allowed-origins": [
58 | "/*"
59 | ],
60 | "realm_access": {
61 | "roles": [
62 | "offline_access",
63 | "default-roles-ebank-realm",
64 | "uma_authorization",
65 | "ADMIN",
66 | "USER"
67 | ]
68 | },
69 | "resource_access": {
70 | "account": {
71 | "roles": [
72 | "manage-account",
73 | "manage-account-links",
74 | "view-profile"
75 | ]
76 | }
77 | },
78 | "scope": "email profile",
79 | "sid": "e085be18-fca8-46bd-b746-80f024ffa535",
80 | "email_verified": false,
81 | "name": "Mohamed YOUSSFI",
82 | "preferred_username": "user1",
83 | "given_name": "Mohamed",
84 | "family_name": "YOUSSFI",
85 | "email": "user1@gmail.com"
86 | }
87 | */
88 |
--------------------------------------------------------------------------------
/inventoory-service/src/main/java/net/youssfi/inventooryservice/sec/SecurityConfig.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.inventooryservice.sec;
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 http) throws Exception {
29 |
30 | return http.cors(Customizer.withDefaults())
31 | .csrf(Customizer.withDefaults())
32 | .authorizeHttpRequests((authorize) -> authorize
33 | .requestMatchers("/","/customOauth2login/**", "/css/**", "/js/**", "/images/**", "/webjars/**","/h2-console/**").permitAll()
34 | .anyRequest().authenticated())
35 | .headers(h->h.frameOptions(fo->fo.disable()))
36 | .csrf(csrf->csrf.ignoringRequestMatchers("/h2-console/**"))
37 | .oauth2ResourceServer(ors->ors.jwt(jwt->jwt.jwtAuthenticationConverter(jwtAuthConverter)))
38 | .sessionManagement(sm->sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
39 | .build();
40 | }
41 |
42 | @Bean
43 | CorsConfigurationSource corsConfigurationSource() {
44 | CorsConfiguration configuration = new CorsConfiguration();
45 | configuration.setAllowedOrigins(Arrays.asList("*"));
46 | configuration.setAllowedMethods(Arrays.asList("*"));
47 | configuration.setAllowedHeaders(Arrays.asList("*"));
48 | UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
49 | source.registerCorsConfiguration("/**", configuration);
50 | return source;
51 | }
52 |
53 |
54 |
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/inventoory-service/src/main/java/net/youssfi/inventooryservice/web/ProductController.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.inventooryservice.web;
2 |
3 | import net.youssfi.inventooryservice.entities.Product;
4 | import net.youssfi.inventooryservice.repository.ProductRepository;
5 | import org.springframework.security.access.prepost.PreAuthorize;
6 | import org.springframework.security.core.Authentication;
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 | /**
15 | * @author mohamedyoussfi
16 | **/
17 | @RestController
18 | @RequestMapping("/api")
19 | public class ProductController {
20 | private ProductRepository productRepository;
21 |
22 | public ProductController(ProductRepository productRepository) {
23 | this.productRepository = productRepository;
24 | }
25 |
26 |
27 | @GetMapping("/products")
28 | //@PreAuthorize("hasAuthority('ADMIN')")
29 | public List findAllProducts(){
30 | return productRepository.findAll();
31 | }
32 | @GetMapping("/products/{id}")
33 | public Product findProductById(@PathVariable String id){
34 | return productRepository.findById(id).orElseThrow(ProductNotFoundException::new);
35 | }
36 | @GetMapping("/auth")
37 | public Authentication authentication(Authentication authentication){
38 | return authentication;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/inventoory-service/src/main/java/net/youssfi/inventooryservice/web/ProductNotFoundException.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.inventooryservice.web;
2 |
3 | import org.springframework.http.HttpStatus;
4 | import org.springframework.web.bind.annotation.ResponseStatus;
5 |
6 | @ResponseStatus(HttpStatus.NOT_FOUND)
7 | public class ProductNotFoundException extends RuntimeException {
8 | }
9 |
--------------------------------------------------------------------------------
/inventoory-service/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.application.name=inventory-service
2 | server.port=8081
3 |
4 | spring.datasource.url=jdbc:h2:mem:products-db
5 | spring.h2.console.enabled=true
6 |
7 | spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8080/realms/ebank-realm
8 | spring.security.oauth2.resourceserver.jwt.jwk-set-uri=http://localhost:8080/realms/ebank-realm/protocol/openid-connect/certs
9 |
10 |
11 |
--------------------------------------------------------------------------------
/inventoory-service/src/test/java/net/youssfi/inventooryservice/InventooryServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package net.youssfi.inventooryservice;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class InventooryServiceApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | net.youssfi
8 | oauth2-oidc-apps
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 | }
--------------------------------------------------------------------------------