├── .gitignore ├── .openapi-generator-ignore ├── .openapi-generator └── VERSION ├── .travis.yml ├── Dockerfile ├── LICENSE ├── README.md ├── pom.xml └── src └── main ├── java └── org │ └── openapitools │ ├── OpenAPI2SpringBoot.java │ ├── RFC3339DateFormat.java │ ├── api │ ├── ApiUtil.java │ ├── ExceptionTranslator.java │ ├── PetApiDelegateImpl.java │ ├── StoreApiDelegateImpl.java │ └── UserApiDelegateImpl.java │ ├── configuration │ ├── AuthorizationServerConfiguration.java │ ├── HomeController.java │ ├── OpenAPIConfiguration.java │ ├── ResourceServerConfiguration.java │ └── SecurityConfiguration.java │ └── repository │ ├── HashMapRepository.java │ ├── OrderRepository.java │ ├── PetRepository.java │ └── UserRepository.java └── resources ├── application.properties ├── openapi.yaml └── public └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | ###################### 2 | # Eclipse 3 | ###################### 4 | *.pydevproject 5 | .project 6 | .metadata 7 | tmp/ 8 | tmp/**/* 9 | *.tmp 10 | *.bak 11 | *.swp 12 | *~.nib 13 | local.properties 14 | .classpath 15 | .settings/ 16 | .loadpath 17 | .factorypath 18 | /<%= SERVER_MAIN_RES_DIR %>rebel.xml 19 | 20 | # External tool builders 21 | .externalToolBuilders/** 22 | 23 | # Locally stored "Eclipse launch configurations" 24 | *.launch 25 | 26 | # CDT-specific 27 | .cproject 28 | 29 | # PDT-specific 30 | .buildpath 31 | 32 | ###################### 33 | # Intellij 34 | ###################### 35 | .idea/ 36 | *.iml 37 | *.iws 38 | *.ipr 39 | *.ids 40 | *.orig 41 | classes/ 42 | out/ 43 | 44 | ###################### 45 | # Visual Studio Code 46 | ###################### 47 | .vscode/ 48 | 49 | ###################### 50 | # Maven 51 | ###################### 52 | /log/ 53 | /target/ 54 | 55 | ###################### 56 | # Package Files 57 | ###################### 58 | *.jar 59 | *.war 60 | *.ear 61 | *.db 62 | 63 | ###################### 64 | # Windows 65 | ###################### 66 | # Windows image file caches 67 | Thumbs.db 68 | 69 | # Folder config file 70 | Desktop.ini 71 | 72 | ###################### 73 | # Mac OSX 74 | ###################### 75 | .DS_Store 76 | .svn 77 | 78 | # Thumbnails 79 | ._* 80 | 81 | # Files that might appear on external disk 82 | .Spotlight-V100 83 | .Trashes 84 | 85 | ###################### 86 | # Directories 87 | ###################### 88 | /bin/ 89 | /deploy/ 90 | 91 | ###################### 92 | # Logs 93 | ###################### 94 | *.log* 95 | 96 | ###################### 97 | # Others 98 | ###################### 99 | *.class 100 | *.*~ 101 | *~ 102 | .merge_file* 103 | 104 | -------------------------------------------------------------------------------- /.openapi-generator-ignore: -------------------------------------------------------------------------------- 1 | # OpenAPI Generator Ignore 2 | # Generated by openapi-generator https://github.com/openapitools/openapi-generator 3 | 4 | # Use this file to prevent files from being overwritten by the generator. 5 | # The patterns follow closely to .gitignore or .dockerignore. 6 | 7 | # As an example, the C# client generator defines ApiClient.cs. 8 | # You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: 9 | #ApiClient.cs 10 | 11 | # You can match any string of characters against a directory, file or extension with a single asterisk (*): 12 | #foo/*/qux 13 | # The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux 14 | 15 | # You can recursively match patterns against a directory, file or extension with a double asterisk (**): 16 | #foo/**/qux 17 | # This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux 18 | 19 | # You can also negate patterns with an exclamation (!). 20 | # For example, you can ignore all files in a docs folder with the file extension .md: 21 | #docs/*.md 22 | # Then explicitly reverse the ignore rule for a single file: 23 | #!docs/README.md 24 | -------------------------------------------------------------------------------- /.openapi-generator/VERSION: -------------------------------------------------------------------------------- 1 | 3.0.0-SNAPSHOT -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | language: java 3 | jdk: 4 | - openjdk8 5 | services: 6 | - docker 7 | cache: 8 | directories: 9 | - $HOME/.m2 10 | 11 | script: 12 | - mvn clean package 13 | 14 | before_deploy: 15 | - docker login -u $DOCKER_HUB_USERNAME -p $DOCKER_HUB_PASSWORD 16 | - docker build -t openapitools/openapi-petstore . 17 | 18 | deploy: 19 | provider: script 20 | script: docker push openapitools/openapi-petstore 21 | on: 22 | branch: master -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jre-alpine 2 | 3 | WORKDIR /petstore 4 | 5 | ENV OPENAPI_BASE_PATH=/v3 6 | 7 | COPY target/openapi-petstore-3.0.0.jar /petstore/openapi-petstore.jar 8 | 9 | EXPOSE 8080 10 | 11 | CMD ["java", "-Dopenapi.openAPIPetstore.base-path=${OPENAPI_BASE_PATH}", "-jar", "/petstore/openapi-petstore.jar"] 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenAPI petstore 2 | 3 | This is an implementation of the OpenAPI pet store based on Spring-Boot. 4 | 5 | ## Overview 6 | 7 | Start your server as a simple Spring-Boot application 8 | ``` 9 | mvn spring-boot:run 10 | ``` 11 | Or package it then run it as a Java application 12 | ``` 13 | mvn package 14 | java -jar target/openapi-petstore-{VERSION}.jar 15 | ``` 16 | 17 | You can view the api documentation in swagger-ui by pointing to 18 | http://localhost:8080/ 19 | 20 | ## Docker 21 | 22 | To start the server via docker, please run the following commands: 23 | ```sh 24 | docker pull openapitools/openapi-petstore 25 | docker run -d -e OPENAPI_BASE_PATH=/v3 -p 80:8080 openapitools/openapi-petstore 26 | ``` 27 | 28 | Ref: https://hub.docker.com/r/openapitools/openapi-petstore/ 29 | 30 | ## Security 31 | 32 | ### API key 33 | Use `special-key` for endpoints protected by the API key 34 | 35 | ### OAuth2 36 | By default the server supports the implicit and the password flow (even though only the implicit flow is described in the OAI spec) 37 | The default credentials are: 38 | * client-id: sample-client-id 39 | * client-secret: secret 40 | * username: user 41 | * password: user 42 | 43 | ## Configuration 44 | 45 | Spring parameters in application.properties: 46 | * Server port : `server.port` (default=8080) 47 | * API base path : `openapi.openAPIPetstore.base-path` (default=/v3). In the docker image the base path can also be set with the `OPENAPI_BASE_PATH` environment variable. 48 | 49 | Environment variables: 50 | * `DISABLE_API_KEY` : if set to "1", the server will not check the api key for the relevant endpoints. 51 | * `DISABLE_OAUTH` : if set to "1", the server will not check for an OAuth2 access token. 52 | 53 | ## License 54 | 55 | [Apache 2.0 License](http://www.apache.org/licenses/LICENSE-2.0) -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | org.openapitools 4 | openapi-petstore 5 | jar 6 | openapi-petstore 7 | 3.0.0 8 | 9 | 1.8 10 | ${java.version} 11 | ${java.version} 12 | 13 | 14 | org.springframework.boot 15 | spring-boot-starter-parent 16 | 2.0.2.RELEASE 17 | 18 | 19 | 20 | Apache License 2.0 21 | http://www.apache.org/licenses/LICENSE-2.0.html 22 | repo 23 | 24 | 25 | 26 | src/main/java 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-maven-plugin 31 | 32 | 33 | 34 | repackage 35 | 36 | 37 | 38 | 39 | 40 | org.openapitools 41 | openapi-generator-maven-plugin 42 | 3.0.0 43 | 44 | 45 | 46 | generate 47 | 48 | 49 | src/main/resources/openapi.yaml 50 | spring 51 | org.openapitools.api 52 | org.openapitools.model 53 | false 54 | 55 | true 56 | true 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | org.springframework.boot 67 | spring-boot-starter-web 68 | 69 | 70 | org.springframework.boot 71 | spring-boot-starter-security 72 | 73 | 74 | org.springframework.security.oauth.boot 75 | spring-security-oauth2-autoconfigure 76 | 2.0.1.RELEASE 77 | 78 | 79 | org.springframework.data 80 | spring-data-commons 81 | 82 | 83 | io.swagger.parser.v3 84 | swagger-parser 85 | 2.0.1 86 | 87 | 88 | org.webjars 89 | swagger-ui 90 | 3.14.2 91 | 92 | 93 | io.swagger 94 | swagger-annotations 95 | 1.5.14 96 | 97 | 98 | com.fasterxml.jackson.dataformat 99 | jackson-dataformat-yaml 100 | 101 | 102 | com.fasterxml.jackson.dataformat 103 | jackson-dataformat-xml 104 | 105 | 106 | com.fasterxml.woodstox 107 | woodstox-core 108 | 5.1.0 109 | 110 | 111 | com.fasterxml.jackson.datatype 112 | jackson-datatype-jsr310 113 | 114 | 115 | 116 | javax.validation 117 | validation-api 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /src/main/java/org/openapitools/OpenAPI2SpringBoot.java: -------------------------------------------------------------------------------- 1 | package org.openapitools; 2 | 3 | import org.springframework.boot.CommandLineRunner; 4 | import org.springframework.boot.ExitCodeGenerator; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.ComponentScan; 9 | import org.springframework.web.servlet.config.annotation.CorsRegistry; 10 | import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; 11 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 12 | 13 | @SpringBootApplication 14 | @ComponentScan(basePackages = {"org.openapitools", "org.openapitools.api" , "org.openapitools.configuration"}) 15 | public class OpenAPI2SpringBoot implements CommandLineRunner { 16 | 17 | @Override 18 | public void run(String... arg0) { 19 | if (arg0.length > 0 && arg0[0].equals("exitcode")) { 20 | throw new ExitException(); 21 | } 22 | } 23 | 24 | public static void main(String[] args) { 25 | new SpringApplication(OpenAPI2SpringBoot.class).run(args); 26 | } 27 | 28 | class ExitException extends RuntimeException implements ExitCodeGenerator { 29 | private static final long serialVersionUID = 1L; 30 | 31 | @Override 32 | public int getExitCode() { 33 | return 10; 34 | } 35 | 36 | } 37 | 38 | @Bean 39 | public WebMvcConfigurer webConfigurer() { 40 | return new WebMvcConfigurer() { 41 | @Override 42 | public void addCorsMappings(CorsRegistry registry) { 43 | registry.addMapping("/**") 44 | .allowedOrigins("*") 45 | .allowedMethods("*") 46 | .allowedHeaders("Content-Type"); 47 | } 48 | 49 | @Override 50 | public void addResourceHandlers(ResourceHandlerRegistry registry) { 51 | registry.addResourceHandler("/swagger-ui/**") 52 | .addResourceLocations("classpath:/META-INF/resources/webjars/swagger-ui/3.14.2/"); 53 | } 54 | }; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/org/openapitools/RFC3339DateFormat.java: -------------------------------------------------------------------------------- 1 | package org.openapitools; 2 | 3 | import com.fasterxml.jackson.databind.util.ISO8601DateFormat; 4 | import com.fasterxml.jackson.databind.util.ISO8601Utils; 5 | 6 | import java.text.FieldPosition; 7 | import java.util.Date; 8 | 9 | 10 | public class RFC3339DateFormat extends ISO8601DateFormat { 11 | 12 | private static final long serialVersionUID = 1L; 13 | 14 | // Same as ISO8601DateFormat but serializing milliseconds. 15 | @Override 16 | public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { 17 | String value = ISO8601Utils.format(date, true); 18 | toAppendTo.append(value); 19 | return toAppendTo; 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /src/main/java/org/openapitools/api/ApiUtil.java: -------------------------------------------------------------------------------- 1 | package org.openapitools.api; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.context.request.NativeWebRequest; 5 | import org.springframework.web.server.ResponseStatusException; 6 | 7 | import javax.servlet.http.HttpServletResponse; 8 | import java.io.IOException; 9 | 10 | public class ApiUtil { 11 | 12 | public static void setExampleResponse(NativeWebRequest req, String contentType, String example) { 13 | try { 14 | req.getNativeResponse(HttpServletResponse.class).addHeader("Content-Type", contentType); 15 | req.getNativeResponse(HttpServletResponse.class).getOutputStream().print(example); 16 | } catch (IOException e) { 17 | throw new RuntimeException(e); 18 | } 19 | } 20 | 21 | public static void checkApiKey(NativeWebRequest req) { 22 | if (!"1".equals(System.getenv("DISABLE_API_KEY")) && !"special-key".equals(req.getHeader("api_key"))) { 23 | throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "Missing API key!"); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/main/java/org/openapitools/api/ExceptionTranslator.java: -------------------------------------------------------------------------------- 1 | package org.openapitools.api; 2 | 3 | import org.springframework.boot.web.servlet.error.ErrorAttributes; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.bind.annotation.ExceptionHandler; 6 | import org.springframework.web.bind.annotation.ResponseStatus; 7 | import org.springframework.web.bind.annotation.RestControllerAdvice; 8 | import org.springframework.web.context.request.RequestAttributes; 9 | import org.springframework.web.context.request.WebRequest; 10 | 11 | import javax.validation.ConstraintViolationException; 12 | import java.util.Map; 13 | 14 | @RestControllerAdvice 15 | public class ExceptionTranslator { 16 | 17 | private final ErrorAttributes errorAttributes; 18 | 19 | public ExceptionTranslator(ErrorAttributes errorAttributes) { 20 | this.errorAttributes = errorAttributes; 21 | } 22 | 23 | @ExceptionHandler(ConstraintViolationException.class) 24 | @ResponseStatus(HttpStatus.BAD_REQUEST) 25 | public Map processConstraintViolationException(WebRequest request) { 26 | request.setAttribute("javax.servlet.error.status_code", HttpStatus.BAD_REQUEST.value(), RequestAttributes.SCOPE_REQUEST); 27 | return errorAttributes.getErrorAttributes(request, false); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/openapitools/api/PetApiDelegateImpl.java: -------------------------------------------------------------------------------- 1 | package org.openapitools.api; 2 | 3 | import org.apache.tomcat.util.http.fileupload.IOUtils; 4 | import org.openapitools.model.Category; 5 | import org.openapitools.model.ModelApiResponse; 6 | import org.openapitools.model.Pet; 7 | import org.openapitools.model.Tag; 8 | import org.openapitools.repository.PetRepository; 9 | import org.springframework.http.HttpStatus; 10 | import org.springframework.http.ResponseEntity; 11 | import org.springframework.stereotype.Service; 12 | import org.springframework.util.StringUtils; 13 | import org.springframework.web.context.request.NativeWebRequest; 14 | import org.springframework.web.multipart.MultipartFile; 15 | import org.springframework.web.server.ResponseStatusException; 16 | 17 | import javax.annotation.PostConstruct; 18 | import java.io.File; 19 | import java.io.FileOutputStream; 20 | import java.util.Arrays; 21 | import java.util.List; 22 | import java.util.Optional; 23 | import java.util.concurrent.atomic.AtomicLong; 24 | import java.util.stream.Collectors; 25 | 26 | @Service 27 | public class PetApiDelegateImpl implements PetApiDelegate { 28 | 29 | private final PetRepository petRepository; 30 | 31 | private final NativeWebRequest request; 32 | 33 | public PetApiDelegateImpl(PetRepository petRepository, NativeWebRequest request) { 34 | this.petRepository = petRepository; 35 | this.request = request; 36 | } 37 | 38 | @PostConstruct 39 | private void initPets() { 40 | Category dogs = new Category().id(1L).name("Dogs"); 41 | Category cats = new Category().id(2L).name("Cats"); 42 | Category rabbits = new Category().id(3L).name("Rabbits"); 43 | Category lions = new Category().id(4L).name("Lions"); 44 | 45 | petRepository.save(createPet(1, cats, "Cat 1", new String[] { 46 | "url1", "url2" }, new String[] { "tag1", "tag2" }, Pet.StatusEnum.AVAILABLE)); 47 | petRepository.save(createPet(2, cats, "Cat 2", new String[] { 48 | "url1", "url2" }, new String[] { "tag2", "tag3" }, Pet.StatusEnum.AVAILABLE)); 49 | petRepository.save(createPet(3, cats, "Cat 3", new String[] { 50 | "url1", "url2" }, new String[] { "tag3", "tag4" }, Pet.StatusEnum.PENDING)); 51 | 52 | petRepository.save(createPet(4, dogs, "Dog 1", new String[] { 53 | "url1", "url2" }, new String[] { "tag1", "tag2" }, Pet.StatusEnum.AVAILABLE)); 54 | petRepository.save(createPet(5, dogs, "Dog 2", new String[] { 55 | "url1", "url2" }, new String[] { "tag2", "tag3" }, Pet.StatusEnum.SOLD)); 56 | petRepository.save(createPet(6, dogs, "Dog 3", new String[] { 57 | "url1", "url2" }, new String[] { "tag3", "tag4" }, Pet.StatusEnum.PENDING)); 58 | 59 | petRepository.save(createPet(7, lions, "Lion 1", new String[] { 60 | "url1", "url2" }, new String[] { "tag1", "tag2" }, Pet.StatusEnum.AVAILABLE)); 61 | petRepository.save(createPet(8, lions, "Lion 2", new String[] { 62 | "url1", "url2" }, new String[] { "tag2", "tag3" }, Pet.StatusEnum.AVAILABLE)); 63 | petRepository.save(createPet(9, lions, "Lion 3", new String[] { 64 | "url1", "url2" }, new String[] { "tag3", "tag4" }, Pet.StatusEnum.AVAILABLE)); 65 | 66 | petRepository.save(createPet(10, rabbits, "Rabbit 1", new String[] { 67 | "url1", "url2" }, new String[] { "tag3", "tag4" }, Pet.StatusEnum.AVAILABLE)); 68 | } 69 | 70 | 71 | @Override 72 | public ResponseEntity addPet(Pet pet) { 73 | petRepository.save(pet); 74 | return ResponseEntity.ok().build(); 75 | } 76 | 77 | @Override 78 | public ResponseEntity deletePet(Long petId, String apiKey) { 79 | petRepository.deleteById(petId); 80 | return ResponseEntity.ok().build(); 81 | } 82 | 83 | @Override 84 | public ResponseEntity> findPetsByStatus(List statusList) { 85 | List statusEnums = statusList.stream() 86 | .map(s -> Optional.ofNullable(Pet.StatusEnum.fromValue(s)) 87 | .orElseThrow(() -> new ResponseStatusException(HttpStatus.BAD_REQUEST, "Invalid status: " + s)) 88 | ) 89 | .collect(Collectors.toList()); 90 | return ResponseEntity.ok(petRepository.findPetsByStatus(statusEnums)); 91 | } 92 | 93 | @Override 94 | public ResponseEntity> findPetsByTags(List tags) { 95 | return ResponseEntity.ok(petRepository.findPetsByTags(tags)); 96 | } 97 | 98 | @Override 99 | public ResponseEntity getPetById(Long petId) { 100 | ApiUtil.checkApiKey(request); 101 | return petRepository.findById(petId) 102 | .map(ResponseEntity::ok) 103 | .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)); 104 | } 105 | 106 | @Override 107 | public ResponseEntity updatePet(Pet pet) { 108 | return addPet(pet); 109 | } 110 | 111 | @Override 112 | public ResponseEntity updatePetWithForm(Long petId, String name, String status) { 113 | Pet pet = petRepository.findById(petId) 114 | .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)); 115 | if(!StringUtils.isEmpty(name)) 116 | pet.name(name); 117 | if(!StringUtils.isEmpty(name)) 118 | pet.setStatus(Pet.StatusEnum.fromValue(status)); 119 | return addPet(pet); 120 | } 121 | 122 | @Override 123 | public ResponseEntity uploadFile(Long petId, String additionalMetadata, MultipartFile file) { 124 | try { 125 | String uploadedFileLocation = "./" + file.getName(); 126 | System.out.println("uploading to " + uploadedFileLocation); 127 | IOUtils.copy(file.getInputStream(), new FileOutputStream(uploadedFileLocation)); 128 | String msg = String.format("additionalMetadata: %s\nFile uploaded to %s, %d bytes", additionalMetadata, uploadedFileLocation, (new File(uploadedFileLocation)).length()); 129 | ModelApiResponse output = new ModelApiResponse().code(200).message(msg); 130 | return ResponseEntity.ok(output); 131 | } 132 | catch (Exception e) { 133 | throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Couldn't upload file", e); 134 | } 135 | } 136 | 137 | private static Pet createPet(long id, Category category, String name, String[] urls, 138 | String[] tags, Pet.StatusEnum status) { 139 | Pet pet = new Pet() 140 | .id(id) 141 | .category(category) 142 | .name(name) 143 | .status(status); 144 | 145 | if (null != urls) { 146 | pet.setPhotoUrls(Arrays.asList(urls)); 147 | } 148 | 149 | final AtomicLong i = new AtomicLong(0); 150 | if (null != tags) { 151 | Arrays.stream(tags) 152 | .map(tag -> new Tag().name(tag).id(i.incrementAndGet())) 153 | .forEach(pet::addTagsItem); 154 | } 155 | return pet; 156 | } 157 | 158 | } 159 | -------------------------------------------------------------------------------- /src/main/java/org/openapitools/api/StoreApiDelegateImpl.java: -------------------------------------------------------------------------------- 1 | package org.openapitools.api; 2 | 3 | import org.openapitools.model.Order; 4 | import org.openapitools.model.Pet; 5 | import org.openapitools.repository.OrderRepository; 6 | import org.openapitools.repository.PetRepository; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.stereotype.Service; 10 | import org.springframework.web.context.request.NativeWebRequest; 11 | import org.springframework.web.server.ResponseStatusException; 12 | 13 | import javax.annotation.PostConstruct; 14 | import java.time.OffsetDateTime; 15 | import java.util.Map; 16 | import java.util.stream.Collectors; 17 | 18 | @Service 19 | public class StoreApiDelegateImpl implements StoreApiDelegate { 20 | 21 | private final OrderRepository orderRepository; 22 | 23 | private final PetRepository petRepository; 24 | 25 | private final NativeWebRequest request; 26 | 27 | public StoreApiDelegateImpl(OrderRepository orderRepository, PetRepository petRepository, NativeWebRequest request) { 28 | this.orderRepository = orderRepository; 29 | this.petRepository = petRepository; 30 | this.request = request; 31 | } 32 | 33 | @PostConstruct 34 | void initOrders() { 35 | orderRepository.save(createOrder(1, 1, Order.StatusEnum.PLACED)); 36 | orderRepository.save(createOrder(2, 1, Order.StatusEnum.DELIVERED)); 37 | orderRepository.save(createOrder(3, 2, Order.StatusEnum.PLACED)); 38 | orderRepository.save(createOrder(4, 2, Order.StatusEnum.DELIVERED)); 39 | orderRepository.save(createOrder(5, 3, Order.StatusEnum.PLACED)); 40 | orderRepository.save(createOrder(6, 3, Order.StatusEnum.PLACED)); 41 | orderRepository.save(createOrder(7, 3, Order.StatusEnum.PLACED)); 42 | orderRepository.save(createOrder(8, 3, Order.StatusEnum.PLACED)); 43 | orderRepository.save(createOrder(9, 3, Order.StatusEnum.PLACED)); 44 | orderRepository.save(createOrder(10, 3, Order.StatusEnum.PLACED)); 45 | } 46 | 47 | 48 | @Override 49 | public ResponseEntity deleteOrder(String orderId) { 50 | Order order = orderRepository.findById(Long.valueOf(orderId)) 51 | .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)); 52 | orderRepository.delete(order); 53 | return ResponseEntity.ok().build(); 54 | } 55 | 56 | @Override 57 | public ResponseEntity> getInventory() { 58 | ApiUtil.checkApiKey(request); 59 | return ResponseEntity.ok(petRepository.findAll().stream() 60 | .map(Pet::getStatus) 61 | .collect(Collectors.groupingBy(Pet.StatusEnum::toString, Collectors.reducing(0, e -> 1, Integer::sum)))); 62 | } 63 | 64 | @Override 65 | public ResponseEntity getOrderById(Long orderId) { 66 | return orderRepository.findById(orderId) 67 | .map(ResponseEntity::ok) 68 | .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Order not found")); 69 | } 70 | 71 | @Override 72 | public ResponseEntity placeOrder(Order order) { 73 | return ResponseEntity.ok(orderRepository.save(order)); 74 | } 75 | 76 | private static Order createOrder(long id, long petId, Order.StatusEnum status) { 77 | return new Order() 78 | .id(id) 79 | .petId(petId) 80 | .quantity(2) 81 | .shipDate(OffsetDateTime.now()) 82 | .status(status); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/org/openapitools/api/UserApiDelegateImpl.java: -------------------------------------------------------------------------------- 1 | package org.openapitools.api; 2 | 3 | import org.openapitools.model.User; 4 | import org.openapitools.repository.UserRepository; 5 | import org.springframework.http.HttpStatus; 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.stereotype.Service; 8 | import org.springframework.web.server.ResponseStatusException; 9 | 10 | import javax.annotation.PostConstruct; 11 | import java.time.Instant; 12 | import java.time.temporal.ChronoUnit; 13 | import java.util.Date; 14 | import java.util.List; 15 | 16 | @Service 17 | public class UserApiDelegateImpl implements UserApiDelegate { 18 | 19 | private final UserRepository userRepository; 20 | 21 | public UserApiDelegateImpl(UserRepository userRepository) { 22 | this.userRepository = userRepository; 23 | } 24 | 25 | @PostConstruct 26 | private void initUsers() { 27 | userRepository.save(createUser(1, "user1", "first name 1", "last name 1", 28 | "email1@test.com", 1)); 29 | userRepository.save(createUser(2, "user2", "first name 2", "last name 2", 30 | "email2@test.com", 2)); 31 | userRepository.save(createUser(3, "user3", "first name 3", "last name 3", 32 | "email3@test.com", 3)); 33 | userRepository.save(createUser(4, "user4", "first name 4", "last name 4", 34 | "email4@test.com", 1)); 35 | userRepository.save(createUser(5, "user5", "first name 5", "last name 5", 36 | "email5@test.com", 2)); 37 | userRepository.save(createUser(6, "user6", "first name 6", "last name 6", 38 | "email6@test.com", 3)); 39 | userRepository.save(createUser(7, "user7", "first name 7", "last name 7", 40 | "email7@test.com", 1)); 41 | userRepository.save(createUser(8, "user8", "first name 8", "last name 8", 42 | "email8@test.com", 2)); 43 | userRepository.save(createUser(9, "user9", "first name 9", "last name 9", 44 | "email9@test.com", 3)); 45 | userRepository.save(createUser(10, "user10", "first name 10", "last name 10", 46 | "email10@test.com", 1)); 47 | userRepository.save(createUser(11, "user?10", "first name ?10", "last name ?10", 48 | "email101@test.com", 1)); 49 | } 50 | 51 | @Override 52 | public ResponseEntity createUser(User user) { 53 | userRepository.save(user); 54 | return ResponseEntity.ok().build(); 55 | } 56 | 57 | @Override 58 | public ResponseEntity createUsersWithArrayInput(List users) { 59 | userRepository.saveAll(users); 60 | return ResponseEntity.ok().build(); 61 | } 62 | 63 | @Override 64 | public ResponseEntity createUsersWithListInput(List users) { 65 | return createUsersWithArrayInput(users); 66 | } 67 | 68 | @Override 69 | public ResponseEntity deleteUser(String username) { 70 | User user = userRepository.findById(username) 71 | .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)); 72 | userRepository.delete(user); 73 | return ResponseEntity.ok().build(); 74 | } 75 | 76 | @Override 77 | public ResponseEntity getUserByName(String username) { 78 | return userRepository.findById(username) 79 | .map(ResponseEntity::ok) 80 | .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)); 81 | } 82 | 83 | @Override 84 | public ResponseEntity loginUser(String username, String password) { 85 | Instant now = Instant.now().plus(1, ChronoUnit.HOURS); 86 | return ResponseEntity.ok() 87 | .header("X-Expires-After", new Date(now.toEpochMilli()).toString()) 88 | .header("X-Rate-Limit", "5000") 89 | .body("logged in user session:" + now.toEpochMilli()); 90 | } 91 | 92 | @Override 93 | public ResponseEntity logoutUser() { 94 | return ResponseEntity.ok().build(); 95 | } 96 | 97 | @Override 98 | public ResponseEntity updateUser(String username, User user) { 99 | user.setUsername(username); 100 | return createUser(user); 101 | } 102 | 103 | private static User createUser(long id, String username, String firstName, String lastName, String email, int userStatus) { 104 | return new User() 105 | .id(id) 106 | .username(username) 107 | .firstName(firstName) 108 | .lastName(lastName) 109 | .email(email) 110 | .password("XXXXXXXXXXX") 111 | .phone("123-456-7890") 112 | .userStatus(userStatus); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/org/openapitools/configuration/AuthorizationServerConfiguration.java: -------------------------------------------------------------------------------- 1 | package org.openapitools.configuration; 2 | 3 | import org.springframework.beans.factory.ObjectProvider; 4 | import org.springframework.boot.autoconfigure.security.oauth2.authserver.AuthorizationServerProperties; 5 | import org.springframework.boot.autoconfigure.security.oauth2.authserver.OAuth2AuthorizationServerConfiguration; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; 8 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; 9 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; 10 | import org.springframework.security.oauth2.provider.client.BaseClientDetails; 11 | import org.springframework.security.oauth2.provider.token.AccessTokenConverter; 12 | import org.springframework.security.oauth2.provider.token.TokenStore; 13 | 14 | @Configuration 15 | @EnableAuthorizationServer 16 | public class AuthorizationServerConfiguration extends OAuth2AuthorizationServerConfiguration { 17 | 18 | public AuthorizationServerConfiguration(BaseClientDetails details, 19 | AuthenticationConfiguration authenticationConfiguration, 20 | ObjectProvider tokenStore, 21 | ObjectProvider tokenConverter, 22 | AuthorizationServerProperties properties) throws Exception { 23 | super(details, authenticationConfiguration, tokenStore, tokenConverter, properties); 24 | } 25 | 26 | @Override 27 | public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { 28 | super.configure(endpoints); 29 | endpoints.pathMapping("/oauth/authorize", "/api/oauth/dialog"); 30 | } 31 | } -------------------------------------------------------------------------------- /src/main/java/org/openapitools/configuration/HomeController.java: -------------------------------------------------------------------------------- 1 | package org.openapitools.configuration; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import io.swagger.v3.core.util.Json; 5 | import io.swagger.v3.core.util.Yaml; 6 | import io.swagger.v3.oas.models.OpenAPI; 7 | import org.springframework.stereotype.Controller; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.ResponseBody; 11 | 12 | /** 13 | * Home redirection to OpenAPI api documentation 14 | */ 15 | @Controller 16 | public class HomeController { 17 | 18 | private final OpenAPI openAPI; 19 | 20 | public HomeController(OpenAPI openAPI) { 21 | this.openAPI = openAPI; 22 | } 23 | 24 | @GetMapping(value = "/openapi.yaml", produces = "application/vnd.oai.openapi") 25 | @ResponseBody 26 | public String openapiYaml() throws JsonProcessingException { 27 | return Yaml.mapper().writeValueAsString(openAPI); 28 | } 29 | 30 | @GetMapping(value = "/openapi.json", produces = "application/json") 31 | @ResponseBody 32 | public String openapiJson() throws JsonProcessingException { 33 | return Json.mapper().writeValueAsString(openAPI); 34 | } 35 | 36 | @RequestMapping("/oauth/authorize") 37 | public String authorize() { 38 | return "forward:/api/oauth/dialog"; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/openapitools/configuration/OpenAPIConfiguration.java: -------------------------------------------------------------------------------- 1 | package org.openapitools.configuration; 2 | 3 | import com.fasterxml.jackson.databind.node.ObjectNode; 4 | import io.swagger.parser.OpenAPIParser; 5 | import io.swagger.util.Yaml; 6 | import io.swagger.v3.oas.models.OpenAPI; 7 | import io.swagger.v3.oas.models.servers.Server; 8 | import io.swagger.v3.parser.core.models.ParseOptions; 9 | import org.springframework.beans.factory.annotation.Value; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | import org.springframework.core.io.Resource; 13 | import org.springframework.util.StreamUtils; 14 | 15 | import java.io.IOException; 16 | import java.io.InputStream; 17 | import java.nio.charset.Charset; 18 | import java.util.Collections; 19 | 20 | @Configuration 21 | public class OpenAPIConfiguration { 22 | 23 | @Bean 24 | public OpenAPI openapi( 25 | @Value("classpath:/openapi.yaml") Resource openapiResource, 26 | @Value("${openapi.openAPIPetstore.base-path:/v3}") String apiBasePath) throws IOException { 27 | try(InputStream is = openapiResource.getInputStream()) { 28 | OpenAPI openAPI = new OpenAPIParser() 29 | .readContents(StreamUtils.copyToString(is, Charset.defaultCharset()), null, new ParseOptions()) 30 | .getOpenAPI(); 31 | ObjectNode node = Yaml.mapper().readValue(openapiResource.getInputStream(), ObjectNode.class); 32 | if (node.get("servers") == null) { 33 | openAPI.setServers(Collections.singletonList(new Server().url(apiBasePath))); 34 | } 35 | return openAPI; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/openapitools/configuration/ResourceServerConfiguration.java: -------------------------------------------------------------------------------- 1 | package org.openapitools.configuration; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.http.HttpMethod; 6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 7 | import org.springframework.security.config.http.SessionCreationPolicy; 8 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; 9 | import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; 10 | 11 | @Configuration 12 | @EnableResourceServer 13 | public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { 14 | 15 | @Value("${openapi.openAPIPetstore.base-path:/v3}") 16 | private String apiBasePath; 17 | 18 | @Override 19 | public void configure(HttpSecurity http) throws Exception { 20 | http.requestMatchers() 21 | .antMatchers(apiBasePath + "/pet") 22 | .antMatchers(apiBasePath + "/pet/findByStatus") 23 | .antMatchers(HttpMethod.POST, apiBasePath + "/pet/**") 24 | .and() 25 | .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) 26 | .and() 27 | .authorizeRequests() 28 | .anyRequest().access("#oauth2.hasScope('write:pets') and #oauth2.hasScope('read:pets')"); 29 | } 30 | } -------------------------------------------------------------------------------- /src/main/java/org/openapitools/configuration/SecurityConfiguration.java: -------------------------------------------------------------------------------- 1 | package org.openapitools.configuration; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.http.HttpMethod; 5 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 6 | import org.springframework.security.config.annotation.web.builders.WebSecurity; 7 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 8 | 9 | @Configuration 10 | public class SecurityConfiguration extends WebSecurityConfigurerAdapter { 11 | 12 | @Override 13 | public void configure(WebSecurity web) { 14 | WebSecurity.IgnoredRequestConfigurer config = web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**"); 15 | if("1".equals(System.getenv("DISABLE_OAUTH"))) { 16 | config.antMatchers("/**"); 17 | } 18 | } 19 | 20 | @Override 21 | protected void configure(HttpSecurity http) throws Exception { 22 | http.requestMatchers() 23 | .antMatchers("/login", "/oauth/authorize", "/api/oauth/dialog") 24 | .and() 25 | .authorizeRequests() 26 | .anyRequest().authenticated() 27 | .and() 28 | .formLogin().permitAll(); 29 | } 30 | } -------------------------------------------------------------------------------- /src/main/java/org/openapitools/repository/HashMapRepository.java: -------------------------------------------------------------------------------- 1 | package org.openapitools.repository; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | import org.springframework.data.repository.NoRepositoryBean; 5 | import org.springframework.util.Assert; 6 | 7 | import java.util.*; 8 | 9 | @NoRepositoryBean 10 | public abstract class HashMapRepository implements CrudRepository { 11 | 12 | Map entities = new HashMap<>(); 13 | 14 | abstract ID getEntityId(S entity); 15 | 16 | @Override 17 | public S save(S entity) { 18 | Assert.notNull(entity, "entity cannot be null"); 19 | Assert.notNull(getEntityId(entity), "entity ID cannot be null"); 20 | entities.put(getEntityId(entity), entity); 21 | return entity; 22 | } 23 | 24 | @Override 25 | public List saveAll(Iterable entities) { 26 | Assert.notNull(entities, "entities cannot be null"); 27 | List result = new ArrayList<>(); 28 | entities.forEach(entity -> result.add(save(entity))); 29 | return result; 30 | } 31 | 32 | @Override 33 | public Collection findAll() { 34 | return entities.values(); 35 | } 36 | 37 | @Override 38 | public long count() { 39 | return entities.keySet().size(); 40 | } 41 | 42 | @Override 43 | public void delete(T entity) { 44 | Assert.notNull(entity, "entity cannot be null"); 45 | deleteById(getEntityId(entity)); 46 | } 47 | 48 | @Override 49 | public void deleteAll(Iterable entitiesToDelete) { 50 | Assert.notNull(entitiesToDelete, "entities cannot be null"); 51 | entitiesToDelete.forEach(entity -> entities.remove(getEntityId(entity))); 52 | } 53 | 54 | @Override 55 | public void deleteAll() { 56 | entities.clear(); 57 | } 58 | 59 | @Override 60 | public void deleteById(ID id) { 61 | Assert.notNull(id, "Id cannot be null"); 62 | entities.remove(id); 63 | } 64 | 65 | @Override 66 | public List findAllById(Iterable ids) { 67 | Assert.notNull(ids, "Ids cannot be null"); 68 | List result = new ArrayList<>(); 69 | ids.forEach(id -> findById(id).ifPresent(result::add)); 70 | return result; 71 | } 72 | 73 | @Override 74 | public boolean existsById(ID id) { 75 | Assert.notNull(id, "Id cannot be null"); 76 | return entities.keySet().contains(id); 77 | } 78 | 79 | public T findOne(ID id) { 80 | Assert.notNull(id, "Id cannot be null"); 81 | return entities.get(id); 82 | } 83 | 84 | @Override 85 | public Optional findById(ID id) { 86 | return Optional.ofNullable(findOne(id)); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/org/openapitools/repository/OrderRepository.java: -------------------------------------------------------------------------------- 1 | package org.openapitools.repository; 2 | 3 | import org.openapitools.model.Order; 4 | import org.springframework.stereotype.Repository; 5 | 6 | @Repository 7 | public class OrderRepository extends HashMapRepository { 8 | 9 | @Override 10 | Long getEntityId(S order) { 11 | return order.getId(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/openapitools/repository/PetRepository.java: -------------------------------------------------------------------------------- 1 | package org.openapitools.repository; 2 | 3 | import org.openapitools.model.Pet; 4 | import org.openapitools.model.Tag; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.util.List; 8 | import java.util.stream.Collectors; 9 | 10 | @Repository 11 | public class PetRepository extends HashMapRepository { 12 | 13 | private Long sequenceId = 1L; 14 | 15 | @Override 16 | Long getEntityId(S pet) { 17 | return pet.getId(); 18 | } 19 | 20 | @Override 21 | public S save(S pet) { 22 | if (pet.getId() != null && pet.getId() > sequenceId) { 23 | sequenceId = pet.getId() + 1; 24 | } 25 | if (pet.getId() == null) { 26 | pet.setId(sequenceId); 27 | sequenceId += 1; 28 | } 29 | return super.save(pet); 30 | } 31 | 32 | public List findPetsByStatus(List statusList) { 33 | return entities.values().stream() 34 | .filter(entity -> entity.getStatus() != null) 35 | .filter(entity -> statusList.contains(entity.getStatus())) 36 | .collect(Collectors.toList()); 37 | } 38 | 39 | public List findPetsByTags(List tags) { 40 | return entities.values().stream() 41 | .filter(entity -> entity.getTags() != null) 42 | .filter(entity -> entity.getTags().stream() 43 | .map(Tag::getName) 44 | .anyMatch(tags::contains) 45 | ) 46 | .collect(Collectors.toList()); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/openapitools/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package org.openapitools.repository; 2 | 3 | import org.openapitools.model.User; 4 | import org.springframework.stereotype.Repository; 5 | 6 | @Repository 7 | public class UserRepository extends HashMapRepository { 8 | 9 | @Override 10 | String getEntityId(S user) { 11 | return user.getUsername(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=8080 2 | spring.jackson.date-format=org.openapitools.RFC3339DateFormat 3 | spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false 4 | openapi.openAPIPetstore.base-path=/v3 5 | spring.security.user.password=user 6 | security.oauth2.authorization.check-token-access=isAuthenticated() 7 | security.oauth2.authorization.token-key-access=permitAll() 8 | security.oauth2.client.client-id=sample-client-id 9 | security.oauth2.client.client-secret=secret 10 | security.oauth2.client.authorized-grant-types=implicit, password 11 | security.oauth2.client.scope=write:pets, read:pets 12 | -------------------------------------------------------------------------------- /src/main/resources/openapi.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.0 2 | info: 3 | title: OpenAPI Petstore 4 | description: This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. For OAuth2 flow, you may use `user` as both username and password when asked to login. 5 | license: 6 | name: Apache-2.0 7 | url: http://www.apache.org/licenses/LICENSE-2.0.html 8 | version: 1.0.0 9 | externalDocs: 10 | description: Find out more about OpenAPI generator 11 | url: https://openapi-generator.tech 12 | tags: 13 | - name: pet 14 | description: Everything about your Pets 15 | - name: store 16 | description: Access to Petstore orders 17 | - name: user 18 | description: Operations about user 19 | paths: 20 | /pet: 21 | put: 22 | tags: 23 | - pet 24 | summary: Update an existing pet 25 | operationId: updatePet 26 | requestBody: 27 | $ref: '#/components/requestBodies/Pet' 28 | responses: 29 | 400: 30 | description: Invalid ID supplied 31 | 404: 32 | description: Pet not found 33 | 405: 34 | description: Validation exception 35 | security: 36 | - petstore_auth: 37 | - write:pets 38 | - read:pets 39 | x-accepts: application/json 40 | x-tags: 41 | - tag: pet 42 | x-contentType: application/json 43 | post: 44 | tags: 45 | - pet 46 | summary: Add a new pet to the store 47 | operationId: addPet 48 | requestBody: 49 | $ref: '#/components/requestBodies/Pet' 50 | responses: 51 | 405: 52 | description: Invalid input 53 | security: 54 | - petstore_auth: 55 | - write:pets 56 | - read:pets 57 | x-accepts: application/json 58 | x-tags: 59 | - tag: pet 60 | x-contentType: application/json 61 | /pet/findByStatus: 62 | get: 63 | tags: 64 | - pet 65 | summary: Finds Pets by status 66 | description: Multiple status values can be provided with comma separated strings 67 | operationId: findPetsByStatus 68 | parameters: 69 | - name: status 70 | in: query 71 | description: Status values that need to be considered for filter 72 | required: true 73 | style: form 74 | explode: false 75 | schema: 76 | type: array 77 | items: 78 | type: string 79 | default: available 80 | enum: 81 | - available 82 | - pending 83 | - sold 84 | responses: 85 | 200: 86 | description: successful operation 87 | content: 88 | application/xml: 89 | schema: 90 | type: array 91 | items: 92 | $ref: '#/components/schemas/Pet' 93 | application/json: 94 | schema: 95 | type: array 96 | items: 97 | $ref: '#/components/schemas/Pet' 98 | 400: 99 | description: Invalid status value 100 | security: 101 | - petstore_auth: 102 | - write:pets 103 | - read:pets 104 | x-accepts: application/json 105 | x-tags: 106 | - tag: pet 107 | /pet/findByTags: 108 | get: 109 | tags: 110 | - pet 111 | summary: Finds Pets by tags 112 | description: Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. 113 | operationId: findPetsByTags 114 | parameters: 115 | - name: tags 116 | in: query 117 | description: Tags to filter by 118 | required: true 119 | style: form 120 | explode: false 121 | schema: 122 | type: array 123 | items: 124 | type: string 125 | responses: 126 | 200: 127 | description: successful operation 128 | content: 129 | application/xml: 130 | schema: 131 | type: array 132 | items: 133 | $ref: '#/components/schemas/Pet' 134 | application/json: 135 | schema: 136 | type: array 137 | items: 138 | $ref: '#/components/schemas/Pet' 139 | 400: 140 | description: Invalid tag value 141 | deprecated: true 142 | security: 143 | - petstore_auth: 144 | - write:pets 145 | - read:pets 146 | x-accepts: application/json 147 | x-tags: 148 | - tag: pet 149 | /pet/{petId}: 150 | get: 151 | tags: 152 | - pet 153 | summary: Find pet by ID 154 | description: Returns a single pet 155 | operationId: getPetById 156 | parameters: 157 | - name: petId 158 | in: path 159 | description: ID of pet to return 160 | required: true 161 | style: simple 162 | explode: false 163 | schema: 164 | type: integer 165 | format: int64 166 | responses: 167 | 200: 168 | description: successful operation 169 | content: 170 | application/xml: 171 | schema: 172 | $ref: '#/components/schemas/Pet' 173 | application/json: 174 | schema: 175 | $ref: '#/components/schemas/Pet' 176 | 400: 177 | description: Invalid ID supplied 178 | 404: 179 | description: Pet not found 180 | security: 181 | - api_key: [] 182 | x-accepts: application/json 183 | x-tags: 184 | - tag: pet 185 | post: 186 | tags: 187 | - pet 188 | summary: Updates a pet in the store with form data 189 | operationId: updatePetWithForm 190 | parameters: 191 | - name: petId 192 | in: path 193 | description: ID of pet that needs to be updated 194 | required: true 195 | style: simple 196 | explode: false 197 | schema: 198 | type: integer 199 | format: int64 200 | requestBody: 201 | content: 202 | application/x-www-form-urlencoded: 203 | schema: 204 | $ref: '#/components/schemas/body' 205 | responses: 206 | 405: 207 | description: Invalid input 208 | security: 209 | - petstore_auth: 210 | - write:pets 211 | - read:pets 212 | x-accepts: application/json 213 | x-tags: 214 | - tag: pet 215 | x-contentType: application/x-www-form-urlencoded 216 | delete: 217 | tags: 218 | - pet 219 | summary: Deletes a pet 220 | operationId: deletePet 221 | parameters: 222 | - name: api_key 223 | in: header 224 | required: false 225 | style: simple 226 | explode: false 227 | schema: 228 | type: string 229 | - name: petId 230 | in: path 231 | description: Pet id to delete 232 | required: true 233 | style: simple 234 | explode: false 235 | schema: 236 | type: integer 237 | format: int64 238 | responses: 239 | 400: 240 | description: Invalid pet value 241 | security: 242 | - petstore_auth: 243 | - write:pets 244 | - read:pets 245 | x-accepts: application/json 246 | x-tags: 247 | - tag: pet 248 | /pet/{petId}/uploadImage: 249 | post: 250 | tags: 251 | - pet 252 | summary: uploads an image 253 | operationId: uploadFile 254 | parameters: 255 | - name: petId 256 | in: path 257 | description: ID of pet to update 258 | required: true 259 | style: simple 260 | explode: false 261 | schema: 262 | type: integer 263 | format: int64 264 | requestBody: 265 | content: 266 | multipart/form-data: 267 | schema: 268 | $ref: '#/components/schemas/body_1' 269 | responses: 270 | 200: 271 | description: successful operation 272 | content: 273 | application/json: 274 | schema: 275 | $ref: '#/components/schemas/ApiResponse' 276 | security: 277 | - petstore_auth: 278 | - write:pets 279 | - read:pets 280 | x-accepts: application/json 281 | x-tags: 282 | - tag: pet 283 | x-contentType: multipart/form-data 284 | /store/inventory: 285 | get: 286 | tags: 287 | - store 288 | summary: Returns pet inventories by status 289 | description: Returns a map of status codes to quantities 290 | operationId: getInventory 291 | responses: 292 | 200: 293 | description: successful operation 294 | content: 295 | application/json: 296 | schema: 297 | type: object 298 | additionalProperties: 299 | type: integer 300 | format: int32 301 | security: 302 | - api_key: [] 303 | x-accepts: application/json 304 | x-tags: 305 | - tag: store 306 | /store/order: 307 | post: 308 | tags: 309 | - store 310 | summary: Place an order for a pet 311 | operationId: placeOrder 312 | requestBody: 313 | description: order placed for purchasing the pet 314 | content: 315 | application/json: 316 | schema: 317 | $ref: '#/components/schemas/Order' 318 | required: true 319 | responses: 320 | 200: 321 | description: successful operation 322 | content: 323 | application/xml: 324 | schema: 325 | $ref: '#/components/schemas/Order' 326 | application/json: 327 | schema: 328 | $ref: '#/components/schemas/Order' 329 | 400: 330 | description: Invalid Order 331 | x-accepts: application/json 332 | x-tags: 333 | - tag: store 334 | x-contentType: application/json 335 | /store/order/{orderId}: 336 | get: 337 | tags: 338 | - store 339 | summary: Find purchase order by ID 340 | description: For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions 341 | operationId: getOrderById 342 | parameters: 343 | - name: orderId 344 | in: path 345 | description: ID of pet that needs to be fetched 346 | required: true 347 | style: simple 348 | explode: false 349 | schema: 350 | maximum: 5 351 | minimum: 1 352 | type: integer 353 | format: int64 354 | responses: 355 | 200: 356 | description: successful operation 357 | content: 358 | application/xml: 359 | schema: 360 | $ref: '#/components/schemas/Order' 361 | application/json: 362 | schema: 363 | $ref: '#/components/schemas/Order' 364 | 400: 365 | description: Invalid ID supplied 366 | 404: 367 | description: Order not found 368 | x-accepts: application/json 369 | x-tags: 370 | - tag: store 371 | delete: 372 | tags: 373 | - store 374 | summary: Delete purchase order by ID 375 | description: For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors 376 | operationId: deleteOrder 377 | parameters: 378 | - name: orderId 379 | in: path 380 | description: ID of the order that needs to be deleted 381 | required: true 382 | style: simple 383 | explode: false 384 | schema: 385 | type: string 386 | responses: 387 | 400: 388 | description: Invalid ID supplied 389 | 404: 390 | description: Order not found 391 | x-accepts: application/json 392 | x-tags: 393 | - tag: store 394 | /user: 395 | post: 396 | tags: 397 | - user 398 | summary: Create user 399 | description: This can only be done by the logged in user. 400 | operationId: createUser 401 | requestBody: 402 | description: Created user object 403 | content: 404 | application/json: 405 | schema: 406 | $ref: '#/components/schemas/User' 407 | required: true 408 | responses: 409 | default: 410 | description: successful operation 411 | x-accepts: application/json 412 | x-tags: 413 | - tag: user 414 | x-contentType: application/json 415 | /user/createWithArray: 416 | post: 417 | tags: 418 | - user 419 | summary: Creates list of users with given input array 420 | operationId: createUsersWithArrayInput 421 | requestBody: 422 | $ref: '#/components/requestBodies/UserArray' 423 | responses: 424 | default: 425 | description: successful operation 426 | x-accepts: application/json 427 | x-tags: 428 | - tag: user 429 | x-contentType: application/json 430 | /user/createWithList: 431 | post: 432 | tags: 433 | - user 434 | summary: Creates list of users with given input array 435 | operationId: createUsersWithListInput 436 | requestBody: 437 | $ref: '#/components/requestBodies/UserArray' 438 | responses: 439 | default: 440 | description: successful operation 441 | x-accepts: application/json 442 | x-tags: 443 | - tag: user 444 | x-contentType: application/json 445 | /user/login: 446 | get: 447 | tags: 448 | - user 449 | summary: Logs user into the system 450 | operationId: loginUser 451 | parameters: 452 | - name: username 453 | in: query 454 | description: The user name for login 455 | required: true 456 | style: form 457 | explode: true 458 | schema: 459 | type: string 460 | - name: password 461 | in: query 462 | description: The password for login in clear text 463 | required: true 464 | style: form 465 | explode: true 466 | schema: 467 | type: string 468 | responses: 469 | 200: 470 | description: successful operation 471 | headers: 472 | X-Rate-Limit: 473 | description: calls per hour allowed by the user 474 | style: simple 475 | explode: false 476 | schema: 477 | type: integer 478 | format: int32 479 | X-Expires-After: 480 | description: date in UTC when toekn expires 481 | style: simple 482 | explode: false 483 | schema: 484 | type: string 485 | format: date-time 486 | content: 487 | application/xml: 488 | schema: 489 | type: string 490 | application/json: 491 | schema: 492 | type: string 493 | 400: 494 | description: Invalid username/password supplied 495 | x-accepts: application/json 496 | x-tags: 497 | - tag: user 498 | /user/logout: 499 | get: 500 | tags: 501 | - user 502 | summary: Logs out current logged in user session 503 | operationId: logoutUser 504 | responses: 505 | default: 506 | description: successful operation 507 | x-accepts: application/json 508 | x-tags: 509 | - tag: user 510 | /user/{username}: 511 | get: 512 | tags: 513 | - user 514 | summary: Get user by user name 515 | operationId: getUserByName 516 | parameters: 517 | - name: username 518 | in: path 519 | description: The name that needs to be fetched. Use user1 for testing. 520 | required: true 521 | style: simple 522 | explode: false 523 | schema: 524 | type: string 525 | responses: 526 | 200: 527 | description: successful operation 528 | content: 529 | application/xml: 530 | schema: 531 | $ref: '#/components/schemas/User' 532 | application/json: 533 | schema: 534 | $ref: '#/components/schemas/User' 535 | 400: 536 | description: Invalid username supplied 537 | 404: 538 | description: User not found 539 | x-accepts: application/json 540 | x-tags: 541 | - tag: user 542 | put: 543 | tags: 544 | - user 545 | summary: Updated user 546 | description: This can only be done by the logged in user. 547 | operationId: updateUser 548 | parameters: 549 | - name: username 550 | in: path 551 | description: name that need to be deleted 552 | required: true 553 | style: simple 554 | explode: false 555 | schema: 556 | type: string 557 | requestBody: 558 | description: Updated user object 559 | content: 560 | application/json: 561 | schema: 562 | $ref: '#/components/schemas/User' 563 | required: true 564 | responses: 565 | 400: 566 | description: Invalid user supplied 567 | 404: 568 | description: User not found 569 | x-accepts: application/json 570 | x-tags: 571 | - tag: user 572 | x-contentType: application/json 573 | delete: 574 | tags: 575 | - user 576 | summary: Delete user 577 | description: This can only be done by the logged in user. 578 | operationId: deleteUser 579 | parameters: 580 | - name: username 581 | in: path 582 | description: The name that needs to be deleted 583 | required: true 584 | style: simple 585 | explode: false 586 | schema: 587 | type: string 588 | responses: 589 | 400: 590 | description: Invalid username supplied 591 | 404: 592 | description: User not found 593 | x-accepts: application/json 594 | x-tags: 595 | - tag: user 596 | components: 597 | schemas: 598 | Order: 599 | title: Pet Order 600 | type: object 601 | properties: 602 | id: 603 | type: integer 604 | format: int64 605 | petId: 606 | type: integer 607 | format: int64 608 | quantity: 609 | type: integer 610 | format: int32 611 | shipDate: 612 | type: string 613 | format: date-time 614 | status: 615 | type: string 616 | description: Order Status 617 | enum: 618 | - placed 619 | - approved 620 | - delivered 621 | complete: 622 | type: boolean 623 | default: false 624 | description: An order for a pets from the pet store 625 | example: 626 | petId: 6 627 | quantity: 1 628 | id: 0 629 | shipDate: 2000-01-23T04:56:07.000+00:00 630 | complete: false 631 | status: placed 632 | xml: 633 | name: Order 634 | Category: 635 | title: Pet category 636 | type: object 637 | properties: 638 | id: 639 | type: integer 640 | format: int64 641 | name: 642 | type: string 643 | description: A category for a pet 644 | example: 645 | name: name 646 | id: 6 647 | xml: 648 | name: Category 649 | User: 650 | title: a User 651 | type: object 652 | properties: 653 | id: 654 | type: integer 655 | format: int64 656 | username: 657 | type: string 658 | firstName: 659 | type: string 660 | lastName: 661 | type: string 662 | email: 663 | type: string 664 | password: 665 | type: string 666 | phone: 667 | type: string 668 | userStatus: 669 | type: integer 670 | description: User Status 671 | format: int32 672 | description: A User who is purchasing from the pet store 673 | example: 674 | firstName: firstName 675 | lastName: lastName 676 | password: password 677 | userStatus: 6 678 | phone: phone 679 | id: 0 680 | email: email 681 | username: username 682 | xml: 683 | name: User 684 | Tag: 685 | title: Pet Tag 686 | type: object 687 | properties: 688 | id: 689 | type: integer 690 | format: int64 691 | name: 692 | type: string 693 | description: A tag for a pet 694 | example: 695 | name: name 696 | id: 1 697 | xml: 698 | name: Tag 699 | Pet: 700 | title: a Pet 701 | required: 702 | - name 703 | - photoUrls 704 | type: object 705 | properties: 706 | id: 707 | type: integer 708 | format: int64 709 | category: 710 | $ref: '#/components/schemas/Category' 711 | name: 712 | type: string 713 | example: doggie 714 | photoUrls: 715 | type: array 716 | xml: 717 | name: photoUrl 718 | wrapped: true 719 | items: 720 | type: string 721 | tags: 722 | type: array 723 | xml: 724 | name: tag 725 | wrapped: true 726 | items: 727 | $ref: '#/components/schemas/Tag' 728 | status: 729 | type: string 730 | description: pet status in the store 731 | enum: 732 | - available 733 | - pending 734 | - sold 735 | description: A pet for sale in the pet store 736 | example: 737 | photoUrls: 738 | - photoUrls 739 | - photoUrls 740 | name: doggie 741 | id: 0 742 | category: 743 | name: name 744 | id: 6 745 | tags: 746 | - name: name 747 | id: 1 748 | - name: name 749 | id: 1 750 | status: available 751 | xml: 752 | name: Pet 753 | ApiResponse: 754 | title: An uploaded response 755 | type: object 756 | properties: 757 | code: 758 | type: integer 759 | format: int32 760 | type: 761 | type: string 762 | message: 763 | type: string 764 | description: Describes the result of uploading an image resource 765 | example: 766 | code: 0 767 | type: type 768 | message: message 769 | body: 770 | type: object 771 | properties: 772 | name: 773 | type: string 774 | description: Updated name of the pet 775 | status: 776 | type: string 777 | description: Updated status of the pet 778 | body_1: 779 | type: object 780 | properties: 781 | additionalMetadata: 782 | type: string 783 | description: Additional data to pass to server 784 | file: 785 | type: string 786 | description: file to upload 787 | format: binary 788 | requestBodies: 789 | UserArray: 790 | description: List of user object 791 | content: 792 | application/json: 793 | schema: 794 | type: array 795 | items: 796 | $ref: '#/components/schemas/User' 797 | required: true 798 | Pet: 799 | description: Pet object that needs to be added to the store 800 | content: 801 | application/json: 802 | schema: 803 | $ref: '#/components/schemas/Pet' 804 | application/xml: 805 | schema: 806 | $ref: '#/components/schemas/Pet' 807 | required: true 808 | securitySchemes: 809 | petstore_auth: 810 | type: oauth2 811 | flows: 812 | implicit: 813 | authorizationUrl: /api/oauth/dialog 814 | scopes: 815 | write:pets: modify pets in your account 816 | read:pets: read your pets 817 | api_key: 818 | type: apiKey 819 | name: api_key 820 | in: header 821 | -------------------------------------------------------------------------------- /src/main/resources/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Swagger UI 7 | 8 | 9 | 10 | 11 | 32 | 33 | 34 | 35 |
36 | 37 | 38 | 39 | 67 | 68 | --------------------------------------------------------------------------------