28 | )
29 | }
--------------------------------------------------------------------------------
/openapi-demo/src/main/java/com/tmsvr/openapidemo/service/UuidService.java:
--------------------------------------------------------------------------------
1 | package com.tmsvr.openapidemo.service;
2 |
3 | import com.tmsvr.openapidemo.uuid.api.UuidApi;
4 | import lombok.RequiredArgsConstructor;
5 | import lombok.extern.slf4j.Slf4j;
6 | import org.springframework.stereotype.Service;
7 | import org.springframework.web.client.RestClientException;
8 |
9 | import java.util.List;
10 |
11 | @Slf4j
12 | @Service
13 | @RequiredArgsConstructor
14 | public class UuidService {
15 |
16 | private final UuidApi uuidApi;
17 |
18 | public List getUuids() {
19 | try {
20 | return uuidApi.generateUuid(4);
21 | } catch (RestClientException restClientException) {
22 | // TODO handle exceptions here
23 | log.warn(restClientException.getMessage(), restClientException);
24 | return List.of("not-so-unique");
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/multi-modules/service/src/main/java/com/tmsvr/Service.java:
--------------------------------------------------------------------------------
1 | package com.tmsvr;
2 |
3 | import com.tmsvr.common.ResultProvider;
4 | import com.tmsvr.partnera.PartnerAResultProvider;
5 | import com.tmsvr.partnerb.PartnerBResultProvider;
6 | import lombok.extern.slf4j.Slf4j;
7 | import org.springframework.boot.CommandLineRunner;
8 | import org.springframework.boot.SpringApplication;
9 | import org.springframework.boot.autoconfigure.SpringBootApplication;
10 |
11 | @Slf4j
12 | @SpringBootApplication
13 | public class Service implements CommandLineRunner {
14 |
15 | public static void main(String[] args) {
16 | SpringApplication.run(Service.class, args);
17 | }
18 |
19 | @Override
20 | public void run(String... args) {
21 | ResultProvider partnerA = new PartnerAResultProvider();
22 | ResultProvider partnerB = new PartnerBResultProvider();
23 |
24 | log.info(partnerA.getResult().code());
25 | log.info(partnerB.getResult().code());
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/openapi-demo/uuid.yml:
--------------------------------------------------------------------------------
1 | openapi: 3.0.0
2 | servers:
3 | - description: UUID Generator API
4 | url: https://www.uuidtools.com/api/generate
5 | info:
6 | title: UUID Generator API
7 | version: "2.13.4"
8 | description: "These endpoints are specific to Xero Files API"
9 | tags:
10 | - name: Uuid
11 | paths:
12 | /v4/count/{count}:
13 | get:
14 | operationId: generateUuid
15 | summary: Generate type 4 UUID
16 | tags:
17 | - Uuid
18 | parameters:
19 | - name: count
20 | in: path
21 | required: true
22 | schema:
23 | type: integer
24 | format: int32
25 | responses:
26 | '200':
27 | description: search results matching criteria
28 | content:
29 | application/json:
30 | schema:
31 | $ref: '#/components/schemas/UuidResponse'
32 | components:
33 | schemas:
34 | UuidResponse:
35 | type: array
36 | items:
37 | type: string
38 |
--------------------------------------------------------------------------------
/react-choropleth-map/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-choropleth-map",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.16.1",
7 | "@testing-library/react": "^12.1.2",
8 | "@testing-library/user-event": "^13.5.0",
9 | "leaflet": "^1.7.1",
10 | "react": "^17.0.2",
11 | "react-dom": "^17.0.2",
12 | "react-leaflet": "^3.2.5",
13 | "react-scripts": "5.0.0",
14 | "web-vitals": "^2.1.4"
15 | },
16 | "scripts": {
17 | "start": "react-scripts start",
18 | "build": "react-scripts build",
19 | "test": "react-scripts test",
20 | "eject": "react-scripts eject"
21 | },
22 | "eslintConfig": {
23 | "extends": [
24 | "react-app",
25 | "react-app/jest"
26 | ]
27 | },
28 | "browserslist": {
29 | "production": [
30 | ">0.2%",
31 | "not dead",
32 | "not op_mini all"
33 | ],
34 | "development": [
35 | "last 1 chrome version",
36 | "last 1 firefox version",
37 | "last 1 safari version"
38 | ]
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/oauth-demo/src/main/java/com/tmsvr/oauthdemo/rest/AuthorizationController.java:
--------------------------------------------------------------------------------
1 | package com.tmsvr.oauthdemo.rest;
2 |
3 | import com.tmsvr.oauthdemo.service.AuthorizationService;
4 | import lombok.AllArgsConstructor;
5 | import org.springframework.http.HttpStatus;
6 | import org.springframework.http.ResponseEntity;
7 | import org.springframework.web.bind.annotation.*;
8 |
9 | @AllArgsConstructor
10 | @RestController
11 | @RequestMapping("/api/authorization")
12 | public class AuthorizationController {
13 |
14 | private final AuthorizationService authorizationService;
15 |
16 | @GetMapping("/start-auth")
17 | public ResponseEntity getRedirectUrl() {
18 | return ResponseEntity.ok(authorizationService.getAuthorizationUrl());
19 | }
20 |
21 | @PostMapping("/finish-auth")
22 | public ResponseEntity finishAuth(@RequestBody FinishAuthRequest finishAuthRequest) {
23 | authorizationService.finishAuth(finishAuthRequest.code(), finishAuthRequest.state());
24 | return ResponseEntity.status(HttpStatus.OK).build();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/openapi-demo/src/main/java/com/tmsvr/openapidemo/controllers/PetStoreController.java:
--------------------------------------------------------------------------------
1 | package com.tmsvr.openapidemo.controllers;
2 |
3 | import com.tmsvr.openapidemo.petstore.model.Pet;
4 | import com.tmsvr.openapidemo.petstore.api.PetApi;
5 | import com.tmsvr.openapidemo.service.UuidService;
6 | import lombok.RequiredArgsConstructor;
7 | import lombok.extern.slf4j.Slf4j;
8 | import org.springframework.http.HttpStatus;
9 | import org.springframework.http.ResponseEntity;
10 | import org.springframework.web.bind.annotation.RestController;
11 |
12 | import java.util.List;
13 |
14 | @Slf4j
15 | @RestController
16 | @RequiredArgsConstructor
17 | public class PetStoreController implements PetApi {
18 |
19 | private final UuidService uuidService;
20 |
21 | @Override
22 | public ResponseEntity getPetById(Long petId) {
23 | log.info("FOUND");
24 |
25 | List uuids = uuidService.getUuids();
26 | for (String uuid : uuids) {
27 | log.info("UUID: {}", uuid);
28 | }
29 |
30 | var foundPet = new Pet();
31 | foundPet.setId(1L);
32 | foundPet.setName("Beethoven - " + uuids.get(0));
33 |
34 | return ResponseEntity.ok(foundPet);
35 | }
36 |
37 | @Override
38 | public ResponseEntity addPet(Pet pet) {
39 | log.info("CREATED");
40 | return new ResponseEntity<>(HttpStatus.CREATED);
41 | }
42 |
43 | @Override
44 | public ResponseEntity deletePet(Long petId, String apiKey) {
45 | log.info("DELETED");
46 | return ResponseEntity.ok().build();
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | # TMSVR Blog code examples
2 |
3 | This page is about the code examples created for my blog [TMSVR.com](https://tmsvr.com).
4 |
5 | ## React leaflet interactive map examples
6 |
7 | One topic is the Interactive leaflet map that I have created in React to learn these new technologies. This experimenting later turned into a side-project called [AtlasNinja](https://atlasninja.com). There are 2 articles on my blog about the technical aspects of creating an interactive amp in React using Leaflet:
8 |
9 | - [Making an interactive map with React and Leaflet](https://tmsvr.com/making-an-interactive-map-with-react-and-leaflet/)
10 | - [React interactive choropleth map - Part 2](https://tmsvr.com/react-leaflet-map-performance-issues/)
11 |
12 | There are code examples for these articles in my git repo here: https://github.com/Timester/tmsvr-blog/tree/master/react-choropleth-map
13 |
14 | And a third one is about the AtlasNinja project, whic is a website providing factual information about countries ina modern clean design.
15 |
16 | - [Introducing a new app, AtlasNinja](https://tmsvr.com/introducing-a-new-app-atlasninja/)
17 | - [AtlasNinja](https://atlasninja.com)
18 |
19 | ## Spring Boot OAuth handling
20 |
21 | The first topic I have covered was the OAuth protocol and implementing OAuth based functions in Spring Boot with Java.
22 |
23 | - [OAuth 2.0 - A practical intro](https://tmsvr.com/oauth-2-practical-intro/)
24 | - [OAuth 2.0 - Implementing a client](https://tmsvr.com/oauth-2-client-implementation/)
25 | - [OAuth 2.0 - Token management](https://tmsvr.com/oauth-2-0-token-management/)
26 |
27 | The code examples for these articles can be found here: https://github.com/Timester/tmsvr-blog/tree/master/oauth-demo
28 |
--------------------------------------------------------------------------------
/react-choropleth-map/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | React App
28 |
29 |
32 |
35 |
36 |
37 |
38 |
39 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/openapi-demo/README.md:
--------------------------------------------------------------------------------
1 | # OpenAPI demo
2 |
3 | This PoC application demonstrates the usage of OpenAPI descriptors and the [openapi generator](https://github.com/OpenAPITools/openapi-generator) project to generate client and server code from OpenAPI descriptors with Gradle for Spring Boot projects.
4 |
5 | ## Setup
6 |
7 | For the code generation to work there must be OpenAPI descriptors available. These should represent a contract between services, fontend-backend etc. on how the API looks like.
8 |
9 | The ```build.gradle``` file is commented to highlight the necessary modifications to enable code generation. Generation can be used to create client and server code as well. This example application implements the API described in ```petstore.yml``` and consumes an API described by ```uuid.yml```. The business logic is nonsense, the goal of the PoC is to demonstrate the code generation, and the basic usage of the generated code.
10 |
11 | ## Code generation on the backend
12 |
13 | The ```build.gradle``` file contains the configuration for the code generation in the ```buildUuidClient``` and ```buildPetStoreServer``` tasks. Details on the configuration options can be found [here](https://openapi-generator.tech/docs/generators/) for the various generator options (the PoC uses java for client and spring for server generation), generic config options are [here](https://github.com/OpenAPITools/openapi-generator/tree/master/modules/openapi-generator-gradle-plugin)
14 |
15 | The generated code is an independent gradle/maven project created in the folder specified in ```build.gradle```. Since it is a project in itself it is possible to publish artifacts built from it to Maven repositories. A scenario can be to generate both client and server code for the API of a service. The client code can be published to a Maven repository and used by other services connecting to this one as a dependency.
16 |
17 | In the PoC project instead of depending on the separate artifact created from the generated code, we include the generated source folders in the source sets of the project, and adding the necessary dependencies for it to compile.
18 |
19 | ## Frontend use
20 |
21 | The openapi generator used in the PoC is capable of creating clients for many languages and frameworks, however frontend developers often choose [NSwag](https://github.com/RicoSuter/NSwag) (an other genertor) instead. It is better in generating code for Angular projects.
22 |
23 | ## How to try out this PoC
24 |
25 | Just clone the repo and run the ```bootRun``` gradle task. The code will be generated in the ```build/generated``` folder, according to the settings in ```build.gradle```.
26 |
27 | There is an endpoint (generated) which is implemented in the PetStoreController. The delete pet method calls the UUID API using the also generated client code. So by calling the following, you can try out both the server and client generated parts.
28 |
29 | ```shell
30 | curl --location -H 'Content-Type: application/json' -H 'Accept: application/json' --request GET 'http://localhost:8080/pet/12'
31 | ```
32 |
--------------------------------------------------------------------------------
/oauth-demo/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/multi-modules/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/openapi-demo/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/oauth-demo/src/main/java/com/tmsvr/oauthdemo/service/AuthorizationService.java:
--------------------------------------------------------------------------------
1 | package com.tmsvr.oauthdemo.service;
2 |
3 | import com.tmsvr.oauthdemo.config.OAuthConfig;
4 | import com.tmsvr.oauthdemo.persistence.Token;
5 | import com.tmsvr.oauthdemo.persistence.TokenRepository;
6 | import lombok.AllArgsConstructor;
7 | import lombok.extern.slf4j.Slf4j;
8 | import org.springframework.http.HttpEntity;
9 | import org.springframework.http.HttpHeaders;
10 | import org.springframework.http.MediaType;
11 | import org.springframework.stereotype.Service;
12 | import org.springframework.util.LinkedMultiValueMap;
13 | import org.springframework.util.MultiValueMap;
14 | import org.springframework.web.client.RestTemplate;
15 |
16 | import java.time.Instant;
17 | import java.time.temporal.ChronoUnit;
18 |
19 | @Slf4j
20 | @Service
21 | @AllArgsConstructor
22 | public class AuthorizationService {
23 | private final OAuthConfig oAuthConfig;
24 | private final TokenRepository tokenRepository;
25 |
26 | public String getAuthorizationUrl() {
27 | return oAuthConfig.authUrl() +
28 | "?response_type=code" +
29 | "&redirect_uri=" + oAuthConfig.redirectUrl() +
30 | "&client_id=" + oAuthConfig.clientId() +
31 | "&scope=" + oAuthConfig.scopes() +
32 | "&state=" + generateState() +
33 | "&access_type=offline";
34 | }
35 |
36 | public void finishAuth(String code, String state) {
37 | checkState(state);
38 |
39 | Token token = exchangeCodeForTokens(code);
40 |
41 | tokenRepository.save(token);
42 |
43 | log.info("Auth successful. Token saved to database {}", token.refreshToken().substring(token.refreshToken().length() - 4));
44 | }
45 |
46 | private Token exchangeCodeForTokens(String code) {
47 | String tokenUrl = oAuthConfig.tokenUrl();
48 |
49 | HttpHeaders headers = new HttpHeaders();
50 | headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
51 |
52 | MultiValueMap map = new LinkedMultiValueMap<>();
53 | map.add("grant_type", "authorization_code");
54 | map.add("client_id", oAuthConfig.clientId());
55 | map.add("client_secret", oAuthConfig.clientSecret());
56 | map.add("redirect_uri", oAuthConfig.redirectUrl());
57 | map.add("code", code);
58 |
59 | HttpEntity> request = new HttpEntity<>(map, headers);
60 |
61 | RestTemplate restTemplate = new RestTemplate();
62 | TokenResponse response = restTemplate.postForEntity(tokenUrl, request, TokenResponse.class).getBody();
63 |
64 | return new Token(response.getAccessToken(),
65 | Instant.now().plusSeconds(response.getExpiresIn()),
66 | response.getRefreshToken(),
67 | Instant.now().plus(30, ChronoUnit.DAYS),
68 | Instant.now(),
69 | 1L
70 | );
71 | }
72 |
73 | private String generateState() {
74 | // generate a state string that you have to store until the auth flow is completed,
75 | // or it could be computed from some user property for example
76 | return "dont-do-this";
77 | }
78 |
79 | private void checkState(String state) {
80 | // validate that the state is the same that we have sent
81 | // throw exception if not
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/openapi-demo/build.gradle:
--------------------------------------------------------------------------------
1 | import org.openapitools.generator.gradle.plugin.tasks.GenerateTask
2 |
3 | plugins {
4 | id 'org.springframework.boot' version '2.7.6'
5 | id 'io.spring.dependency-management' version '1.1.0'
6 | id 'java'
7 |
8 | // applying the openapi generator plugin
9 | id "org.openapi.generator" version "6.2.1"
10 | }
11 |
12 | group = 'com.tmsvr'
13 | version = '0.0.1-SNAPSHOT'
14 | sourceCompatibility = '17'
15 |
16 | // adding the generated sources to the source sets
17 | sourceSets.main.java.srcDirs += 'build/generated/petstore/src/main/java'
18 | sourceSets.main.java.srcDirs += 'build/generated/uuid/src/main/java'
19 |
20 | configurations {
21 | compileOnly {
22 | extendsFrom annotationProcessor
23 | }
24 | }
25 |
26 | repositories {
27 | mavenCentral()
28 | }
29 |
30 | dependencies {
31 | implementation 'org.springframework.boot:spring-boot-starter-web'
32 | compileOnly 'org.projectlombok:lombok'
33 | annotationProcessor 'org.projectlombok:lombok'
34 | testImplementation 'org.springframework.boot:spring-boot-starter-test'
35 |
36 | // required for generated openapi stuff
37 | implementation "javax.validation:validation-api:2.0.1.Final"
38 | implementation "io.springfox:springfox-swagger2:3.0.0"
39 | implementation 'org.openapitools:jackson-databind-nullable:0.2.4'
40 | implementation 'com.google.code.findbugs:jsr305:3.0.2'
41 | annotationProcessor 'io.swagger:swagger-annotations:1.6.8'
42 | }
43 |
44 | // 2 new tasks to generate the client and server code
45 | task buildUuidClient(type: GenerateTask) {
46 | generatorName = "java"
47 | groupId = "com.tmsvr.api"
48 | id = "uuidapi"
49 | inputSpec = "$rootDir/uuid.yml".toString()
50 | outputDir = "$buildDir/generated/uuid".toString()
51 | apiPackage = "com.tmsvr.openapidemo.uuid.api"
52 | invokerPackage = "com.tmsvr.openapidemo.uuid.invoker"
53 | modelPackage = "com.tmsvr.openapidemo.uuid.model"
54 | configOptions = [
55 | dateLibrary: "java8",
56 | library: "resttemplate",
57 | serializableModel : "true",
58 | hideGenerationTimestamp : "true"
59 | ]
60 | }
61 |
62 | task buildPetStoreServer(type: GenerateTask) {
63 | generatorName = "spring"
64 | groupId = "$project.group"
65 | id = "$project.name-java-client"
66 | version = "$project.version"
67 | inputSpec = "$rootDir/petstore.yml".toString()
68 | outputDir = "$buildDir/generated/petstore".toString()
69 | apiPackage = "com.tmsvr.openapidemo.petstore.api"
70 | invokerPackage = "com.tmsvr.openapidemo.petstore.invoker"
71 | modelPackage = "com.tmsvr.openapidemo.petstore.model"
72 | generateApiDocumentation = false
73 | generateModelDocumentation = false
74 | generateModelTests = false
75 | generateApiTests = false
76 | configOptions = [
77 | java8 : "true",
78 | dateLibrary : "java8",
79 | serializationLibrary: "jackson",
80 | library : "spring-boot",
81 | useBeanValidation : "true",
82 | interfaceOnly : "true",
83 | serializableModel : "true",
84 | useTags : "true"
85 | ]
86 | }
87 |
88 | // make compileJava run the code generation
89 | compileJava.dependsOn tasks.buildPetStoreServer, tasks.buildUuidClient
90 |
91 | test {
92 | useJUnitPlatform()
93 | }
94 |
--------------------------------------------------------------------------------
/react-choropleth-map/README.md:
--------------------------------------------------------------------------------
1 | # Getting Started with Create React App
2 |
3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
4 |
5 | ## Available Scripts
6 |
7 | In the project directory, you can run:
8 |
9 | ### `npm start`
10 |
11 | Runs the app in the development mode.\
12 | Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
13 |
14 | The page will reload when you make changes.\
15 | You may also see any lint errors in the console.
16 |
17 | ### `npm test`
18 |
19 | Launches the test runner in the interactive watch mode.\
20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
21 |
22 | ### `npm run build`
23 |
24 | Builds the app for production to the `build` folder.\
25 | It correctly bundles React in production mode and optimizes the build for the best performance.
26 |
27 | The build is minified and the filenames include the hashes.\
28 | Your app is ready to be deployed!
29 |
30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
31 |
32 | ### `npm run eject`
33 |
34 | **Note: this is a one-way operation. Once you `eject`, you can't go back!**
35 |
36 | If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
37 |
38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
39 |
40 | You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
41 |
42 | ## Learn More
43 |
44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
45 |
46 | To learn React, check out the [React documentation](https://reactjs.org/).
47 |
48 | ### Code Splitting
49 |
50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
51 |
52 | ### Analyzing the Bundle Size
53 |
54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
55 |
56 | ### Making a Progressive Web App
57 |
58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
59 |
60 | ### Advanced Configuration
61 |
62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
63 |
64 | ### Deployment
65 |
66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
67 |
68 | ### `npm run build` fails to minify
69 |
70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
71 |
--------------------------------------------------------------------------------
/react-choropleth-map/src/ChoroplethMap.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import { MapContainer, TileLayer, GeoJSON } from 'react-leaflet'
3 | import { InfoBox } from './InfoBox';
4 | import { DataScopeSelector } from './DataScopeSelector';
5 |
6 | import './index.css';
7 |
8 | import countries from './custom.geo.50.json';
9 |
10 | const dataScopes = [
11 | {
12 | name: "Population",
13 | key: "pop_est",
14 | description: "The population of the country",
15 | unit: "",
16 | scale: [0, 5000000, 10000000, 25000000, 50000000, 75000000, 100000000, 200000000, 1000000000, 8000000000]
17 | },
18 | {
19 | name: "GDP",
20 | key: "gdp_md_est",
21 | description: "The GDP of the country",
22 | unit: "USD",
23 | scale: [0, 10000, 50000, 100000, 500000, 1000000, 5000000, 1000000000]
24 | }
25 | ];
26 |
27 | // from small to big, 15 colors https://colordesigner.io/gradient-generator
28 | const colors = [
29 | '#fffddd',
30 | '#faf3c8',
31 | '#f6e8b3',
32 | '#f4dd9f',
33 | '#f3d18b',
34 | '#f2c578',
35 | '#f2b866',
36 | '#f2ab55',
37 | '#f39d46',
38 | '#f38e38',
39 | '#f47d2c',
40 | '#f56b23',
41 | '#f6571d',
42 | '#f63c1a',
43 | '#f6081b'
44 | ]
45 |
46 | export default function ChoroplethMap() {
47 |
48 | const [dataScope, setDataScope] = useState(dataScopes[0]);
49 | const [selectedCountry, setSelectedCountry] = useState(null);
50 | const [hoveredCountry, setHoveredCountry] = useState(null);
51 |
52 | const handleDataScopeChange = (event) => {
53 | setDataScope(dataScopes.find(element => element.key === event.target.value));
54 | }
55 |
56 | const highlightFeature = (e) => {
57 | let layer = e.target;
58 | setHoveredCountry(layer.feature.properties);
59 | }
60 |
61 | const resetHighlight = (e) => {
62 | setHoveredCountry(null);
63 | }
64 |
65 | const onEachFeature = (feature, layer) => {
66 | layer.on({
67 | mouseover: highlightFeature,
68 | mouseout: resetHighlight,
69 | click: () => setSelectedCountry(feature.properties)
70 | });
71 | }
72 |
73 | const getColor = (val) => {
74 | for (let i = 1; i < dataScope.scale.length; i++) {
75 | if (val < dataScope.scale[i]) {
76 | return colors[i - 1];
77 | }
78 | }
79 |
80 | return colors[colors.length - 1];
81 | }
82 |
83 | const style = (feature) => {
84 | let mapStyle = {
85 | fillColor: getColor(feature.properties[dataScope.key]),
86 | weight: 1,
87 | opacity: 1,
88 | color: '#888',
89 | dashArray: '3',
90 | fillOpacity: 0.7
91 | };
92 |
93 | if (hoveredCountry && feature.properties.iso_a3 === hoveredCountry.iso_a3) {
94 | mapStyle.color = '#444';
95 | mapStyle.weight = 2;
96 | }
97 |
98 | return mapStyle;
99 | }
100 |
101 | return (
102 |