diff --git a/README.md b/README.md index f5d77c07..b571cff0 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ This project is governed by the [Spring Code of Conduct](CODE_OF_CONDUCT.adoc). ## Documentation This project has reference documentation ([published](https://docs.spring.io/spring-graphql/docs/current-SNAPSHOT/reference/html/) and [source](spring-graphql-docs/src/docs/asciidoc)), an -[API reference](https://docs.spring.io/spring-graphql/docs/current-SNAPSHOT/api/), and [samples](samples). +[API reference](https://docs.spring.io/spring-graphql/docs/current-SNAPSHOT/api/). The are [samples](https://github.com/spring-projects/spring-graphql/tree/1.0.x/samples) in the 1.0.x branch that will be [moved out](https://github.com/spring-projects/spring-graphql/issues/208) into a separate repository. ## Continuous Integration Builds diff --git a/samples/README.md b/samples/README.md deleted file mode 100644 index c1e93e93..00000000 --- a/samples/README.md +++ /dev/null @@ -1,8 +0,0 @@ -This directory contains samples to test scenarios and features with. - -All samples have integration tests you can run or debug, and expose a GraphiQL page at "/graphiql". - -To run a sample from the command line: -```shell script -$ ./gradlew :samples:{sample-directory-name}:bootRun -``` \ No newline at end of file diff --git a/samples/webflux-security/.graphqlconfig b/samples/webflux-security/.graphqlconfig deleted file mode 100644 index 607e05c0..00000000 --- a/samples/webflux-security/.graphqlconfig +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "Spring WebFlux Security Sample Schema", - "schemaPath": "src/main/resources/graphql/schema.graphqls", - "extensions": {} -} \ No newline at end of file diff --git a/samples/webflux-security/README.md b/samples/webflux-security/README.md deleted file mode 100644 index 5194a5d8..00000000 --- a/samples/webflux-security/README.md +++ /dev/null @@ -1,6 +0,0 @@ -**Spring Security for GraphQL HTTP Endpoint with WebFlux** - - - Spring Security [config](src/main/java/io/spring/sample/graphql/SecurityConfig.java) secures GraphQL HTTP endpoint. - - Fine-grained, method-level security on [SalaryService](src/main/java/io/spring/sample/graphql/SalaryService.java). - - `AuthenticationException` and `AccessDeniedException` resolved to GraphQL errors. - - [Tests](src/test/java/io/spring/sample/graphql/WebFluxSecuritySampleTests.java) with `WebGraphQlTester` and WebFlux without a server. \ No newline at end of file diff --git a/samples/webflux-security/build.gradle b/samples/webflux-security/build.gradle deleted file mode 100644 index a40d2810..00000000 --- a/samples/webflux-security/build.gradle +++ /dev/null @@ -1,31 +0,0 @@ -plugins { - id 'org.springframework.boot' version "${bootVersion}" - id 'io.spring.dependency-management' version '1.0.13.RELEASE' - id 'java' -} -group = 'com.example' -description = "GraphQL webflux security example" -sourceCompatibility = '1.8' - -ext['spring-graphql.version'] = version - -repositories { - mavenCentral() - maven { url 'https://repo.spring.io/milestone' } - maven { url 'https://repo.spring.io/snapshot' } -} - -dependencies { - implementation 'org.springframework.boot:spring-boot-starter-graphql' - implementation 'org.springframework.boot:spring-boot-starter-webflux' - implementation 'org.springframework.boot:spring-boot-starter-security' - implementation 'org.springframework.boot:spring-boot-starter-actuator' - developmentOnly 'org.springframework.boot:spring-boot-devtools' - testImplementation project(':spring-graphql') - testImplementation project(':spring-graphql-test') - testImplementation 'org.springframework.boot:spring-boot-starter-test' - testImplementation 'org.springframework.security:spring-security-test' -} -test { - useJUnitPlatform() -} diff --git a/samples/webflux-security/src/main/java/io/spring/sample/graphql/Employee.java b/samples/webflux-security/src/main/java/io/spring/sample/graphql/Employee.java deleted file mode 100644 index d447d80c..00000000 --- a/samples/webflux-security/src/main/java/io/spring/sample/graphql/Employee.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2002-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.spring.sample.graphql; - -public class Employee { - - private String id; - - private String name; - - public Employee(String id, String name) { - this.id = id; - this.name = name; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - -} diff --git a/samples/webflux-security/src/main/java/io/spring/sample/graphql/EmployeeService.java b/samples/webflux-security/src/main/java/io/spring/sample/graphql/EmployeeService.java deleted file mode 100644 index 954ba96c..00000000 --- a/samples/webflux-security/src/main/java/io/spring/sample/graphql/EmployeeService.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2002-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.spring.sample.graphql; - -import java.util.Collections; -import java.util.List; - -import org.springframework.stereotype.Component; - -@Component -public class EmployeeService { - - public List getAllEmployees() { - return Collections.singletonList(new Employee("1", "Andi")); - } - -} diff --git a/samples/webflux-security/src/main/java/io/spring/sample/graphql/SalaryController.java b/samples/webflux-security/src/main/java/io/spring/sample/graphql/SalaryController.java deleted file mode 100644 index 08834f66..00000000 --- a/samples/webflux-security/src/main/java/io/spring/sample/graphql/SalaryController.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2002-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.spring.sample.graphql; - -import java.math.BigDecimal; -import java.util.List; - -import reactor.core.publisher.Mono; - -import org.springframework.graphql.data.method.annotation.Argument; -import org.springframework.graphql.data.method.annotation.MutationMapping; -import org.springframework.graphql.data.method.annotation.QueryMapping; -import org.springframework.graphql.data.method.annotation.SchemaMapping; -import org.springframework.stereotype.Controller; - -@Controller -public class SalaryController { - - private final EmployeeService employeeService; - - private final SalaryService salaryService; - - public SalaryController(EmployeeService employeeService, SalaryService salaryService) { - this.employeeService = employeeService; - this.salaryService = salaryService; - } - - @QueryMapping - public List employees() { - return this.employeeService.getAllEmployees(); - } - - @SchemaMapping - public Mono salary(Employee employee) { - return this.salaryService.getSalaryForEmployee(employee); - } - - @MutationMapping - public Mono updateSalary(@Argument("input") SalaryInput salaryInput) { - String employeeId = salaryInput.getEmployeeId(); - BigDecimal salary = salaryInput.getNewSalary(); - return this.salaryService.updateSalary(employeeId, salary); - } - -} diff --git a/samples/webflux-security/src/main/java/io/spring/sample/graphql/SalaryInput.java b/samples/webflux-security/src/main/java/io/spring/sample/graphql/SalaryInput.java deleted file mode 100644 index c40652c9..00000000 --- a/samples/webflux-security/src/main/java/io/spring/sample/graphql/SalaryInput.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2002-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.spring.sample.graphql; - -import java.math.BigDecimal; - -public class SalaryInput { - - private String employeeId; - - private BigDecimal newSalary; - - public SalaryInput(String employeeId, BigDecimal newSalary) { - this.employeeId = employeeId; - this.newSalary = newSalary; - } - - public String getEmployeeId() { - return employeeId; - } - - public void setEmployeeId(String employeeId) { - this.employeeId = employeeId; - } - - public BigDecimal getNewSalary() { - return newSalary; - } - - public void setNewSalary(BigDecimal newSalary) { - this.newSalary = newSalary; - } - -} diff --git a/samples/webflux-security/src/main/java/io/spring/sample/graphql/SalaryService.java b/samples/webflux-security/src/main/java/io/spring/sample/graphql/SalaryService.java deleted file mode 100644 index aeddd7f7..00000000 --- a/samples/webflux-security/src/main/java/io/spring/sample/graphql/SalaryService.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2002-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.spring.sample.graphql; - -import java.math.BigDecimal; - -import reactor.core.publisher.Mono; - -import org.springframework.security.access.annotation.Secured; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.stereotype.Component; - -@Component -public class SalaryService { - - - @PreAuthorize("hasRole('ADMIN')") - public Mono getSalaryForEmployee(Employee employee) { - return Mono.just(new BigDecimal("42")); - } - - @Secured("ROLE_HR") - public Mono updateSalary(String employeeId, BigDecimal newSalary) { - return Mono.empty(); - } - -} diff --git a/samples/webflux-security/src/main/java/io/spring/sample/graphql/SampleApplication.java b/samples/webflux-security/src/main/java/io/spring/sample/graphql/SampleApplication.java deleted file mode 100644 index a86bf68c..00000000 --- a/samples/webflux-security/src/main/java/io/spring/sample/graphql/SampleApplication.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2002-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.spring.sample.graphql; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class SampleApplication { - - public static void main(String[] args) { - SpringApplication.run(SampleApplication.class, args); - } -} diff --git a/samples/webflux-security/src/main/java/io/spring/sample/graphql/SecurityConfig.java b/samples/webflux-security/src/main/java/io/spring/sample/graphql/SecurityConfig.java deleted file mode 100644 index 32502df1..00000000 --- a/samples/webflux-security/src/main/java/io/spring/sample/graphql/SecurityConfig.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2002-2022 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.spring.sample.graphql; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity; -import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; -import org.springframework.security.config.web.server.ServerHttpSecurity; -import org.springframework.security.core.userdetails.MapReactiveUserDetailsService; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.web.server.SecurityWebFilterChain; - -import static org.springframework.security.config.Customizer.withDefaults; - -@Configuration -@EnableWebFluxSecurity -@EnableReactiveMethodSecurity -public class SecurityConfig { - - @Bean - SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) throws Exception { - return http - .csrf(c -> c.disable()) - // Demonstrate that method security works - // Best practice to use both for defense in depth - .authorizeExchange(requests -> requests.anyExchange().permitAll()) - .httpBasic(withDefaults()) - .build(); - } - - @Bean - @SuppressWarnings("deprecation") - public MapReactiveUserDetailsService userDetailsService() { - User.UserBuilder userBuilder = User.withDefaultPasswordEncoder(); - UserDetails rob = userBuilder.username("rob").password("rob").roles("USER").build(); - UserDetails admin = userBuilder.username("admin").password("admin").roles("USER", "ADMIN").build(); - return new MapReactiveUserDetailsService(rob, admin); - } - -} diff --git a/samples/webflux-security/src/main/resources/application.properties b/samples/webflux-security/src/main/resources/application.properties deleted file mode 100644 index cc94084b..00000000 --- a/samples/webflux-security/src/main/resources/application.properties +++ /dev/null @@ -1,7 +0,0 @@ -spring.graphql.websocket.path=/graphql -management.endpoints.web.exposure.include=health,metrics,info -logging.level.org.springframework.web=debug -logging.level.org.springframework.http=debug -logging.level.org.springframework.graphql=debug -logging.level.org.springframework.security=debug -logging.level.reactor.netty=debug \ No newline at end of file diff --git a/samples/webflux-security/src/main/resources/graphql/schema.graphqls b/samples/webflux-security/src/main/resources/graphql/schema.graphqls deleted file mode 100644 index af5236b6..00000000 --- a/samples/webflux-security/src/main/resources/graphql/schema.graphqls +++ /dev/null @@ -1,22 +0,0 @@ -type Query { - employees: [Employee] -} -type Mutation { - # restricted - updateSalary(input: UpdateSalaryInput!): UpdateSalaryPayload -} -type Employee { - id: ID! - name: String - # restricted - salary: String -} - -input UpdateSalaryInput { - employeeId: ID! - newSalary: String! -} -type UpdateSalaryPayload { - success: Boolean! - employee: Employee -} diff --git a/samples/webflux-security/src/test/java/io/spring/sample/graphql/WebFluxSecuritySampleTests.java b/samples/webflux-security/src/test/java/io/spring/sample/graphql/WebFluxSecuritySampleTests.java deleted file mode 100644 index e3767e6a..00000000 --- a/samples/webflux-security/src/test/java/io/spring/sample/graphql/WebFluxSecuritySampleTests.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright 2002-2022 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.spring.sample.graphql; - -import java.math.BigDecimal; -import java.net.URI; -import java.time.Duration; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.graphql.execution.ErrorType; -import org.springframework.graphql.test.tester.WebGraphQlTester; -import org.springframework.graphql.test.tester.WebSocketGraphQlTester; -import org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) -class WebFluxSecuritySampleTests { - - @LocalServerPort - private int port; - - private WebSocketGraphQlTester graphQlTester; - - @BeforeEach - public void setUp() { - URI url = URI.create("http://localhost:" + this.port + "/graphql"); - this.graphQlTester = WebSocketGraphQlTester.create(url, new ReactorNettyWebSocketClient()); - } - - @AfterEach - void tearDown() { - this.graphQlTester.stop().block(Duration.ofSeconds(5)); - } - - @Test - void printError() { - this.graphQlTester.documentName("employeesNamesAndSalaries") - .execute() - .errors() - .satisfy(System.out::println); - } - - @Test - void anonymousThenUnauthorized() { - this.graphQlTester.documentName("employeesNamesAndSalaries") - .execute() - .errors() - .satisfy(errors -> { - assertThat(errors).hasSize(1); - assertThat(errors.get(0).getErrorType()).isEqualTo(ErrorType.UNAUTHORIZED); - }); - } - - @Test - void userRoleThenForbidden() { - - WebGraphQlTester authTester = this.graphQlTester.mutate() - .headers(headers -> headers.setBasicAuth("rob", "rob")) - .build(); - - authTester.documentName("employeesNamesAndSalaries") - .execute() - .errors() - .satisfy(errors -> { - assertThat(errors).hasSize(1); - assertThat(errors.get(0).getErrorType()).isEqualTo(ErrorType.FORBIDDEN); - }); - } - - @Test - void canQueryName() { - this.graphQlTester.documentName("employeesNames") - .execute() - .path("employees[0].name").entity(String.class).isEqualTo("Andi"); - } - - @Test - void canNotQuerySalary() { - this.graphQlTester.documentName("employeesNamesAndSalaries") - .execute() - .errors() - .satisfy(errors -> { - assertThat(errors).hasSize(1); - assertThat(errors.get(0).getErrorType()).isEqualTo(ErrorType.UNAUTHORIZED); - }); - } - - @Disabled // This does not work currently - @Test - void canNotMutateUpdateSalary() { - SalaryInput salaryInput = new SalaryInput("1", BigDecimal.valueOf(44)); - - this.graphQlTester.documentName("updateSalary") - .variable("salaryInput", salaryInput) - .execute() - .errors() - .satisfy(errors -> { - assertThat(errors).hasSize(1); - assertThat(errors.get(0).getErrorType()).isEqualTo(ErrorType.UNAUTHORIZED); - }); - } - - @Test - void canQuerySalaryAsAdmin() { - - WebGraphQlTester authTester = this.graphQlTester.mutate() - .headers(headers -> headers.setBasicAuth("admin", "admin")) - .build(); - - authTester.documentName("employeesNamesAndSalaries") - .execute() - .path("employees[0].name").entity(String.class).isEqualTo("Andi") - .path("employees[0].salary").entity(int.class).isEqualTo(42); - } - - @Test - void invalidCredentials() { - assertThatThrownBy(() -> - this.graphQlTester.mutate() - .headers(headers -> headers.setBasicAuth("admin", "INVALID")) - .build() - .documentName("employeesNamesAndSalaries") - .executeAndVerify()) - .hasMessage( - "GraphQlTransport error: Invalid handshake response getStatus: 401 Unauthorized; " + - "nested exception is io.netty.handler.codec.http.websocketx.WebSocketClientHandshakeException: " + - "Invalid handshake response getStatus: 401 Unauthorized"); - } - -} \ No newline at end of file diff --git a/samples/webflux-security/src/test/resources/graphql-test/employeesNames.graphql b/samples/webflux-security/src/test/resources/graphql-test/employeesNames.graphql deleted file mode 100644 index 31b61667..00000000 --- a/samples/webflux-security/src/test/resources/graphql-test/employeesNames.graphql +++ /dev/null @@ -1,5 +0,0 @@ -query { - employees { - name - } -} \ No newline at end of file diff --git a/samples/webflux-security/src/test/resources/graphql-test/employeesNamesAndSalaries.graphql b/samples/webflux-security/src/test/resources/graphql-test/employeesNamesAndSalaries.graphql deleted file mode 100644 index 38cd30a5..00000000 --- a/samples/webflux-security/src/test/resources/graphql-test/employeesNamesAndSalaries.graphql +++ /dev/null @@ -1,6 +0,0 @@ -query { - employees { - name, - salary - } -} \ No newline at end of file diff --git a/samples/webflux-security/src/test/resources/graphql-test/updateSalary.graphql b/samples/webflux-security/src/test/resources/graphql-test/updateSalary.graphql deleted file mode 100644 index 02eda7d7..00000000 --- a/samples/webflux-security/src/test/resources/graphql-test/updateSalary.graphql +++ /dev/null @@ -1,9 +0,0 @@ -mutation updateSalary($salaryInput: UpdateSalaryInput!) { - updateSalary(input: $salaryInput) { - success - employee { - id - name - } - } -} \ No newline at end of file diff --git a/samples/webflux-websocket/.graphqlconfig b/samples/webflux-websocket/.graphqlconfig deleted file mode 100644 index 54ea7cdf..00000000 --- a/samples/webflux-websocket/.graphqlconfig +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "Spring WebFlux WebSocket Sample Schema", - "schemaPath": "src/main/resources/graphql/schema.graphqls", - "extensions": {} -} \ No newline at end of file diff --git a/samples/webflux-websocket/README.md b/samples/webflux-websocket/README.md deleted file mode 100644 index 2ce6addc..00000000 --- a/samples/webflux-websocket/README.md +++ /dev/null @@ -1,8 +0,0 @@ -**GraphQL WebSocket Endpoint with Spring WebFlux** - - - [Data Controller](src/main/java/io/spring/sample/graphql/SampleController.java) with reactive methods for queries and subscriptions. - - [WebFilter](src/main/java/io/spring/sample/graphql/ContextWebFilter.java) to insert Reactor `Context` and check it can be accessed in [DataRepository](src/main/java/io/spring/sample/graphql/DataRepository.java). - - [Server tests](src/test/java/io/spring/sample/graphql/WebFluxWebSocketSampleTests.java) without a client. - - [Integration tests](src/test/java/io/spring/sample/graphql/WebFluxWebSocketSampleIntegrationTests.java) via `WebSocketGraphQlTester`. - - GraphiQL does not support subscriptions. There is a basic index.html page that logs subscriptions the console. \ No newline at end of file diff --git a/samples/webflux-websocket/build.gradle b/samples/webflux-websocket/build.gradle deleted file mode 100644 index 8b7b778a..00000000 --- a/samples/webflux-websocket/build.gradle +++ /dev/null @@ -1,30 +0,0 @@ -plugins { - id 'org.springframework.boot' version "${bootVersion}" - id 'io.spring.dependency-management' version '1.0.13.RELEASE' - id 'java' -} -group = 'com.example' -description = "GraphQL over WebSocket With Spring WebFlux Sample" -sourceCompatibility = '1.8' - -ext['spring-graphql.version'] = version - -repositories { - mavenCentral() - maven { url 'https://repo.spring.io/milestone' } - maven { url 'https://repo.spring.io/snapshot' } -} - -dependencies { - implementation 'org.springframework.boot:spring-boot-starter-graphql' - implementation 'org.springframework.boot:spring-boot-starter-webflux' - implementation 'org.springframework.boot:spring-boot-starter-actuator' - developmentOnly 'org.springframework.boot:spring-boot-devtools' - testImplementation project(':spring-graphql') - testImplementation project(':spring-graphql-test') - testImplementation 'org.springframework.boot:spring-boot-starter-test' - testImplementation 'io.projectreactor:reactor-test' -} -test { - useJUnitPlatform() -} \ No newline at end of file diff --git a/samples/webflux-websocket/src/main/java/io/spring/sample/graphql/DataRepository.java b/samples/webflux-websocket/src/main/java/io/spring/sample/graphql/DataRepository.java deleted file mode 100644 index ff97e77e..00000000 --- a/samples/webflux-websocket/src/main/java/io/spring/sample/graphql/DataRepository.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2002-2022 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.spring.sample.graphql; - -import java.time.Duration; - -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.stereotype.Repository; - -/** - * Repository with data fetcher methods. - */ -@Repository -public class DataRepository { - - public String getBasic() { - return "Hello world!"; - } - - public Mono getGreeting() { - return Mono.delay(Duration.ofMillis(50)).map(aLong -> "Hello!"); - } - - public Flux getGreetings() { - return Mono.delay(Duration.ofMillis(50)) - .flatMapMany(aLong -> Flux.just("Hi!", "Bonjour!", "Hola!", "Ciao!", "Zdravo!")); - } - - public Flux getGreetingsStream() { - return Mono.delay(Duration.ofMillis(50)) - .flatMapMany(aLong -> Flux.just("Hi!", "Bonjour!", "Hola!", "Ciao!", "Zdravo!")); - } - -} diff --git a/samples/webflux-websocket/src/main/java/io/spring/sample/graphql/SampleApplication.java b/samples/webflux-websocket/src/main/java/io/spring/sample/graphql/SampleApplication.java deleted file mode 100644 index 1dc9ba00..00000000 --- a/samples/webflux-websocket/src/main/java/io/spring/sample/graphql/SampleApplication.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2002-2022 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.spring.sample.graphql; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class SampleApplication { - - public static void main(String[] args) { - SpringApplication.run(SampleApplication.class, args); - } - -} diff --git a/samples/webflux-websocket/src/main/java/io/spring/sample/graphql/SampleController.java b/samples/webflux-websocket/src/main/java/io/spring/sample/graphql/SampleController.java deleted file mode 100644 index c615cf95..00000000 --- a/samples/webflux-websocket/src/main/java/io/spring/sample/graphql/SampleController.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2002-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.spring.sample.graphql; - -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.graphql.data.method.annotation.QueryMapping; -import org.springframework.graphql.data.method.annotation.SubscriptionMapping; -import org.springframework.stereotype.Controller; - -@Controller -public class SampleController { - - private final DataRepository repository; - - public SampleController(DataRepository dataRepository) { - this.repository = dataRepository; - } - - @QueryMapping - public String greeting() { - return this.repository.getBasic(); - } - - @QueryMapping - public Mono greetingMono() { - return this.repository.getGreeting(); - } - - @QueryMapping - public Flux greetingsFlux() { - return this.repository.getGreetings(); - } - - @SubscriptionMapping - public Flux greetings() { - return this.repository.getGreetingsStream(); - } - -} diff --git a/samples/webflux-websocket/src/main/resources/application.properties b/samples/webflux-websocket/src/main/resources/application.properties deleted file mode 100644 index 4aabf3df..00000000 --- a/samples/webflux-websocket/src/main/resources/application.properties +++ /dev/null @@ -1,9 +0,0 @@ -spring.graphql.websocket.path=/graphql -spring.graphql.schema.printer.enabled=true - -management.endpoints.web.exposure.include=health,metrics,info - -logging.level.org.springframework.web=debug -logging.level.org.springframework.http=debug -logging.level.org.springframework.graphql=debug -logging.level.reactor.netty=debug diff --git a/samples/webflux-websocket/src/main/resources/graphql/schema.graphqls b/samples/webflux-websocket/src/main/resources/graphql/schema.graphqls deleted file mode 100644 index 3e296ff0..00000000 --- a/samples/webflux-websocket/src/main/resources/graphql/schema.graphqls +++ /dev/null @@ -1,8 +0,0 @@ -type Query { - greeting: String - greetingMono : String - greetingsFlux : [String] -} -type Subscription { - greetings: String -} \ No newline at end of file diff --git a/samples/webflux-websocket/src/main/resources/static/index.html b/samples/webflux-websocket/src/main/resources/static/index.html deleted file mode 100644 index db9148ad..00000000 --- a/samples/webflux-websocket/src/main/resources/static/index.html +++ /dev/null @@ -1,56 +0,0 @@ - - - - - GraphQL over WebSocket - - - -

Check the console for subscription messages.

- - - \ No newline at end of file diff --git a/samples/webflux-websocket/src/test/java/io/spring/sample/graphql/WebFluxWebSocketSampleIntegrationTests.java b/samples/webflux-websocket/src/test/java/io/spring/sample/graphql/WebFluxWebSocketSampleIntegrationTests.java deleted file mode 100644 index fca21379..00000000 --- a/samples/webflux-websocket/src/test/java/io/spring/sample/graphql/WebFluxWebSocketSampleIntegrationTests.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2002-2022 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.spring.sample.graphql; - -import java.net.URI; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; -import reactor.test.StepVerifier; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.graphql.test.tester.GraphQlTester; -import org.springframework.graphql.test.tester.WebSocketGraphQlTester; -import org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient; - -/** - * GraphQL over WebSocket integration tests. - */ -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class WebFluxWebSocketSampleIntegrationTests { - - @LocalServerPort - private int port; - - @Value("http://localhost:${local.server.port}${spring.graphql.websocket.path}") - private String baseUrl; - - private GraphQlTester graphQlTester; - - - @BeforeEach - void setUp() { - URI url = URI.create(baseUrl); - this.graphQlTester = WebSocketGraphQlTester.builder(url, new ReactorNettyWebSocketClient()).build(); - } - - @Test - void greetingMono() { - this.graphQlTester.document("{greetingMono}") - .execute() - .path("greetingMono") - .entity(String.class) - .isEqualTo("Hello!"); - } - - @Test - void greetingsFlux() { - this.graphQlTester.document("{greetingsFlux}") - .execute() - .path("greetingsFlux") - .entityList(String.class) - .containsExactly("Hi!", "Bonjour!", "Hola!", "Ciao!", "Zdravo!"); - } - - @Test - void subscriptionWithEntityPath() { - Flux result = this.graphQlTester.document("subscription { greetings }") - .executeSubscription() - .toFlux("greetings", String.class); - - StepVerifier.create(result) - .expectNext("Hi!") - .expectNext("Bonjour!") - .expectNext("Hola!") - .expectNext("Ciao!") - .expectNext("Zdravo!") - .verifyComplete(); - } - - @Test - void subscriptionWithResponse() { - Flux result = this.graphQlTester.document("subscription { greetings }") - .executeSubscription() - .toFlux(); - - StepVerifier.create(result) - .consumeNextWith(response -> response.path("greetings").hasValue()) - .consumeNextWith(response -> response.path("greetings").matchesJson("\"Bonjour!\"")) - .consumeNextWith(response -> response.path("greetings").matchesJson("\"Hola!\"")) - .expectNextCount(2) - .verifyComplete(); - } - -} diff --git a/samples/webflux-websocket/src/test/java/io/spring/sample/graphql/WebFluxWebSocketSampleTests.java b/samples/webflux-websocket/src/test/java/io/spring/sample/graphql/WebFluxWebSocketSampleTests.java deleted file mode 100644 index 54c82ae1..00000000 --- a/samples/webflux-websocket/src/test/java/io/spring/sample/graphql/WebFluxWebSocketSampleTests.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2002-2022 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.spring.sample.graphql; - -import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; -import reactor.test.StepVerifier; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.graphql.GraphQlTest; -import org.springframework.context.annotation.Import; -import org.springframework.graphql.test.tester.GraphQlTester; - -/** - * GraphQL over WebSocket, server-side tests, i.e. without a client. - */ -@GraphQlTest(SampleController.class) -@Import(DataRepository.class) -public class WebFluxWebSocketSampleTests { - - @Autowired - private GraphQlTester graphQlTester; - - - @Test - void greetingMono() { - this.graphQlTester.document("{greetingMono}") - .execute() - .path("greetingMono") - .entity(String.class) - .isEqualTo("Hello!"); - } - - @Test - void greetingsFlux() { - this.graphQlTester.document("{greetingsFlux}") - .execute() - .path("greetingsFlux") - .entityList(String.class) - .containsExactly("Hi!", "Bonjour!", "Hola!", "Ciao!", "Zdravo!"); - } - - @Test - void subscriptionWithEntityPath() { - Flux result = this.graphQlTester.document("subscription { greetings }") - .executeSubscription() - .toFlux("greetings", String.class); - - StepVerifier.create(result) - .expectNext("Hi!") - .expectNext("Bonjour!") - .expectNext("Hola!") - .expectNext("Ciao!") - .expectNext("Zdravo!") - .verifyComplete(); - } - - @Test - void subscriptionWithResponse() { - Flux result = this.graphQlTester.document("subscription { greetings }") - .executeSubscription() - .toFlux(); - - StepVerifier.create(result) - .consumeNextWith(response -> response.path("greetings").hasValue()) - .consumeNextWith(response -> response.path("greetings").matchesJson("\"Bonjour!\"")) - .consumeNextWith(response -> response.path("greetings").matchesJson("\"Hola!\"")) - .expectNextCount(2) - .verifyComplete(); - } - -} diff --git a/samples/webmvc-http-security/.graphqlconfig b/samples/webmvc-http-security/.graphqlconfig deleted file mode 100644 index 8a8ee379..00000000 --- a/samples/webmvc-http-security/.graphqlconfig +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "Spring MVC HTTP Security Sample Schema", - "schemaPath": "src/main/resources/graphql/schema.graphqls", - "extensions": {} -} \ No newline at end of file diff --git a/samples/webmvc-http-security/README.md b/samples/webmvc-http-security/README.md deleted file mode 100644 index f05e2c0d..00000000 --- a/samples/webmvc-http-security/README.md +++ /dev/null @@ -1,6 +0,0 @@ -**Spring Security for GraphQL HTTP Endpoint with Spring MVC** - - - Spring Security [config](src/main/java/io/spring/sample/graphql/SecurityConfig.java) secures GraphQL HTTP endpoint. - - Fine-grained, method-level security on [SalaryService](src/main/java/io/spring/sample/graphql/SalaryService.java). - - `AuthenticationException` and `AccessDeniedException` resolved to GraphQL errors. - - [Tests](src/test/java/io/spring/sample/graphql/WebMvcHttpSecuritySampleTests.java) with `WebGraphQlTester` without a server. \ No newline at end of file diff --git a/samples/webmvc-http-security/build.gradle b/samples/webmvc-http-security/build.gradle deleted file mode 100644 index d496f9f8..00000000 --- a/samples/webmvc-http-security/build.gradle +++ /dev/null @@ -1,31 +0,0 @@ -plugins { - id 'org.springframework.boot' version "${bootVersion}" - id 'io.spring.dependency-management' version '1.0.13.RELEASE' - id 'java' -} -group = 'com.example' -description = "Secure GraphQL over HTTP with Spring MVC Sample" -sourceCompatibility = '1.8' - -ext['spring-graphql.version'] = version - -repositories { - mavenCentral() - maven { url 'https://repo.spring.io/milestone' } - maven { url 'https://repo.spring.io/snapshot' } -} - -dependencies { - implementation 'org.springframework.boot:spring-boot-starter-graphql' - implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'org.springframework.boot:spring-boot-starter-security' - implementation 'org.springframework.boot:spring-boot-starter-actuator' - developmentOnly 'org.springframework.boot:spring-boot-devtools' - testImplementation project(':spring-graphql') - testImplementation project(':spring-graphql-test') - testImplementation 'org.springframework:spring-webflux' - testImplementation 'org.springframework.boot:spring-boot-starter-test' -} -test { - useJUnitPlatform() -} \ No newline at end of file diff --git a/samples/webmvc-http-security/src/main/java/io/spring/sample/graphql/Employee.java b/samples/webmvc-http-security/src/main/java/io/spring/sample/graphql/Employee.java deleted file mode 100644 index 0737dada..00000000 --- a/samples/webmvc-http-security/src/main/java/io/spring/sample/graphql/Employee.java +++ /dev/null @@ -1,30 +0,0 @@ -package io.spring.sample.graphql; - -public class Employee { - - private String id; - - private String name; - - public Employee(String id, String name) { - this.id = id; - this.name = name; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - -} diff --git a/samples/webmvc-http-security/src/main/java/io/spring/sample/graphql/EmployeeService.java b/samples/webmvc-http-security/src/main/java/io/spring/sample/graphql/EmployeeService.java deleted file mode 100644 index b131f583..00000000 --- a/samples/webmvc-http-security/src/main/java/io/spring/sample/graphql/EmployeeService.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.spring.sample.graphql; - -import java.util.Arrays; -import java.util.List; - -import org.springframework.stereotype.Component; - -@Component -public class EmployeeService { - - public List getAllEmployees() { - return Arrays.asList(new Employee("1", "Andi")); - } - -} diff --git a/samples/webmvc-http-security/src/main/java/io/spring/sample/graphql/SalaryController.java b/samples/webmvc-http-security/src/main/java/io/spring/sample/graphql/SalaryController.java deleted file mode 100644 index 88590091..00000000 --- a/samples/webmvc-http-security/src/main/java/io/spring/sample/graphql/SalaryController.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2002-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.spring.sample.graphql; - -import java.math.BigDecimal; -import java.util.List; - -import org.springframework.graphql.data.method.annotation.Argument; -import org.springframework.graphql.data.method.annotation.MutationMapping; -import org.springframework.graphql.data.method.annotation.QueryMapping; -import org.springframework.graphql.data.method.annotation.SchemaMapping; -import org.springframework.stereotype.Controller; - -@Controller -public class SalaryController { - - private final EmployeeService employeeService; - - private final SalaryService salaryService; - - public SalaryController(EmployeeService employeeService, SalaryService salaryService) { - this.employeeService = employeeService; - this.salaryService = salaryService; - } - - @QueryMapping - public List employees() { - return this.employeeService.getAllEmployees(); - } - - @SchemaMapping - public BigDecimal salary(Employee employee) { - return this.salaryService.getSalaryForEmployee(employee); - } - - @MutationMapping - public void updateSalary(@Argument("input") SalaryInput salaryInput) { - String employeeId = salaryInput.getEmployeeId(); - BigDecimal salary = salaryInput.getNewSalary(); - this.salaryService.updateSalary(employeeId, salary); - } - -} diff --git a/samples/webmvc-http-security/src/main/java/io/spring/sample/graphql/SalaryInput.java b/samples/webmvc-http-security/src/main/java/io/spring/sample/graphql/SalaryInput.java deleted file mode 100644 index c40652c9..00000000 --- a/samples/webmvc-http-security/src/main/java/io/spring/sample/graphql/SalaryInput.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2002-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.spring.sample.graphql; - -import java.math.BigDecimal; - -public class SalaryInput { - - private String employeeId; - - private BigDecimal newSalary; - - public SalaryInput(String employeeId, BigDecimal newSalary) { - this.employeeId = employeeId; - this.newSalary = newSalary; - } - - public String getEmployeeId() { - return employeeId; - } - - public void setEmployeeId(String employeeId) { - this.employeeId = employeeId; - } - - public BigDecimal getNewSalary() { - return newSalary; - } - - public void setNewSalary(BigDecimal newSalary) { - this.newSalary = newSalary; - } - -} diff --git a/samples/webmvc-http-security/src/main/java/io/spring/sample/graphql/SalaryService.java b/samples/webmvc-http-security/src/main/java/io/spring/sample/graphql/SalaryService.java deleted file mode 100644 index e62dd516..00000000 --- a/samples/webmvc-http-security/src/main/java/io/spring/sample/graphql/SalaryService.java +++ /dev/null @@ -1,22 +0,0 @@ -package io.spring.sample.graphql; - -import java.math.BigDecimal; - -import org.springframework.security.access.annotation.Secured; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.stereotype.Component; - -@Component -public class SalaryService { - - - @PreAuthorize("hasRole('ADMIN')") - public BigDecimal getSalaryForEmployee(Employee employee) { - return new BigDecimal("42"); - } - - @Secured("ROLE_HR") - public void updateSalary(String employeeId, BigDecimal newSalary) { - - } -} diff --git a/samples/webmvc-http-security/src/main/java/io/spring/sample/graphql/SampleApplication.java b/samples/webmvc-http-security/src/main/java/io/spring/sample/graphql/SampleApplication.java deleted file mode 100644 index 68e56f91..00000000 --- a/samples/webmvc-http-security/src/main/java/io/spring/sample/graphql/SampleApplication.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2002-2022 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.spring.sample.graphql; - -import java.time.Duration; - -import reactor.core.publisher.Mono; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; -import org.springframework.graphql.server.WebGraphQlInterceptor; - -@SpringBootApplication -public class SampleApplication { - - public static void main(String[] args) { - SpringApplication.run(SampleApplication.class, args); - } - - @Bean - public WebGraphQlInterceptor interceptor() { - return (webInput, interceptorChain) -> { - // Switch threads to prove ThreadLocal context propagation works - return Mono.delay(Duration.ofMillis(10)).flatMap(aLong -> interceptorChain.next(webInput)); - }; - } - -} diff --git a/samples/webmvc-http-security/src/main/java/io/spring/sample/graphql/SecurityConfig.java b/samples/webmvc-http-security/src/main/java/io/spring/sample/graphql/SecurityConfig.java deleted file mode 100644 index ecea65cf..00000000 --- a/samples/webmvc-http-security/src/main/java/io/spring/sample/graphql/SecurityConfig.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2002-2022 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.spring.sample.graphql; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.provisioning.InMemoryUserDetailsManager; -import org.springframework.security.web.DefaultSecurityFilterChain; - -import static org.springframework.security.config.Customizer.withDefaults; - -@Configuration -@EnableWebSecurity -@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) -public class SecurityConfig { - - @Bean - DefaultSecurityFilterChain springWebFilterChain(HttpSecurity http) throws Exception { - return http - .csrf(c -> c.disable()) - // Demonstrate that method security works - // Best practice to use both for defense in depth - .authorizeRequests(requests -> requests.anyRequest().permitAll()) - .httpBasic(withDefaults()) - .build(); - } - - @Bean - public static InMemoryUserDetailsManager userDetailsService() { - User.UserBuilder userBuilder = User.withDefaultPasswordEncoder(); - UserDetails rob = userBuilder.username("rob").password("rob").roles("USER").build(); - UserDetails admin = userBuilder.username("admin").password("admin").roles("USER", "ADMIN").build(); - return new InMemoryUserDetailsManager(rob, admin); - } - -} diff --git a/samples/webmvc-http-security/src/main/resources/application.properties b/samples/webmvc-http-security/src/main/resources/application.properties deleted file mode 100644 index 28e043a8..00000000 --- a/samples/webmvc-http-security/src/main/resources/application.properties +++ /dev/null @@ -1,3 +0,0 @@ -management.endpoints.web.exposure.include=health,metrics,info - -spring.graphql.schema.printer.enabled=true \ No newline at end of file diff --git a/samples/webmvc-http-security/src/main/resources/graphql/schema.graphqls b/samples/webmvc-http-security/src/main/resources/graphql/schema.graphqls deleted file mode 100644 index af5236b6..00000000 --- a/samples/webmvc-http-security/src/main/resources/graphql/schema.graphqls +++ /dev/null @@ -1,22 +0,0 @@ -type Query { - employees: [Employee] -} -type Mutation { - # restricted - updateSalary(input: UpdateSalaryInput!): UpdateSalaryPayload -} -type Employee { - id: ID! - name: String - # restricted - salary: String -} - -input UpdateSalaryInput { - employeeId: ID! - newSalary: String! -} -type UpdateSalaryPayload { - success: Boolean! - employee: Employee -} diff --git a/samples/webmvc-http-security/src/test/java/io/spring/sample/graphql/WebMvcHttpSecuritySampleTests.java b/samples/webmvc-http-security/src/test/java/io/spring/sample/graphql/WebMvcHttpSecuritySampleTests.java deleted file mode 100644 index 2dab137e..00000000 --- a/samples/webmvc-http-security/src/test/java/io/spring/sample/graphql/WebMvcHttpSecuritySampleTests.java +++ /dev/null @@ -1,115 +0,0 @@ -package io.spring.sample.graphql; - -import org.junit.jupiter.api.Test; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.graphql.tester.AutoConfigureHttpGraphQlTester; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.graphql.execution.ErrorType; -import org.springframework.graphql.test.tester.WebGraphQlTester; - -import java.math.BigDecimal; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -@SpringBootTest -@AutoConfigureHttpGraphQlTester -class WebMvcHttpSecuritySampleTests { - - @Autowired - private WebGraphQlTester graphQlTester; - - - @Test - void printError() { - this.graphQlTester.documentName("employeesNamesAndSalaries") - .execute() - .errors() - .satisfy(System.out::println); - } - - @Test - void anonymousThenUnauthorized() { - this.graphQlTester.documentName("employeesNamesAndSalaries") - .execute() - .errors() - .satisfy(errors -> { - assertThat(errors).hasSize(1); - assertThat(errors.get(0).getErrorType()).isEqualTo(ErrorType.UNAUTHORIZED); - }); - } - - @Test - void userRoleThenForbidden() { - - WebGraphQlTester tester = this.graphQlTester.mutate() - .headers(headers -> headers.setBasicAuth("rob", "rob")) - .build(); - - tester.documentName("employeesNamesAndSalaries") - .execute() - .errors() - .satisfy(errors -> { - assertThat(errors).hasSize(1); - assertThat(errors.get(0).getErrorType()).isEqualTo(ErrorType.FORBIDDEN); - }); - } - - @Test - void candocumentName() { - this.graphQlTester.documentName("employeesNames") - .execute() - .path("employees[0].name").entity(String.class).isEqualTo("Andi"); - } - - @Test - void canNotQuerySalary() { - this.graphQlTester.documentName("employeesNamesAndSalaries") - .execute() - .errors() - .satisfy(errors -> { - assertThat(errors).hasSize(1); - assertThat(errors.get(0).getErrorType()).isEqualTo(ErrorType.UNAUTHORIZED); - }); - } - - @Test - void canNotMutateUpdateSalary() { - SalaryInput salaryInput = new SalaryInput("1", BigDecimal.valueOf(44)); - - this.graphQlTester.documentName("updateSalary") - .variable("salaryInput", salaryInput) - .execute() - .errors() - .satisfy(errors -> { - assertThat(errors).hasSize(1); - assertThat(errors.get(0).getErrorType()).isEqualTo(ErrorType.UNAUTHORIZED); - }); - } - - @Test - void canQuerySalaryAsAdmin() { - - WebGraphQlTester tester = this.graphQlTester.mutate() - .headers(headers -> headers.setBasicAuth("admin", "admin")) - .build(); - - tester.documentName("employeesNamesAndSalaries") - .execute() - .path("employees[0].name").entity(String.class).isEqualTo("Andi") - .path("employees[0].salary").entity(int.class).isEqualTo(42); - } - - @Test - void invalidCredentials() { - assertThatThrownBy(() -> - this.graphQlTester.mutate() - .headers(headers -> headers.setBasicAuth("admin", "INVALID")) - .build() - .documentName("employeesNamesAndSalaries") - .executeAndVerify()) - .hasMessage("Status expected:<200 OK> but was:<401 UNAUTHORIZED>"); - } - -} diff --git a/samples/webmvc-http-security/src/test/resources/graphql-test/employeesNames.graphql b/samples/webmvc-http-security/src/test/resources/graphql-test/employeesNames.graphql deleted file mode 100644 index 31b61667..00000000 --- a/samples/webmvc-http-security/src/test/resources/graphql-test/employeesNames.graphql +++ /dev/null @@ -1,5 +0,0 @@ -query { - employees { - name - } -} \ No newline at end of file diff --git a/samples/webmvc-http-security/src/test/resources/graphql-test/employeesNamesAndSalaries.graphql b/samples/webmvc-http-security/src/test/resources/graphql-test/employeesNamesAndSalaries.graphql deleted file mode 100644 index 38cd30a5..00000000 --- a/samples/webmvc-http-security/src/test/resources/graphql-test/employeesNamesAndSalaries.graphql +++ /dev/null @@ -1,6 +0,0 @@ -query { - employees { - name, - salary - } -} \ No newline at end of file diff --git a/samples/webmvc-http-security/src/test/resources/graphql-test/updateSalary.graphql b/samples/webmvc-http-security/src/test/resources/graphql-test/updateSalary.graphql deleted file mode 100644 index 02eda7d7..00000000 --- a/samples/webmvc-http-security/src/test/resources/graphql-test/updateSalary.graphql +++ /dev/null @@ -1,9 +0,0 @@ -mutation updateSalary($salaryInput: UpdateSalaryInput!) { - updateSalary(input: $salaryInput) { - success - employee { - id - name - } - } -} \ No newline at end of file diff --git a/samples/webmvc-http/.graphqlconfig b/samples/webmvc-http/.graphqlconfig deleted file mode 100644 index 7e0d5852..00000000 --- a/samples/webmvc-http/.graphqlconfig +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "Spring MVC HTTP Sample Schema", - "schemaPath": "src/main/resources/graphql/schema.graphqls", - "extensions": {} -} \ No newline at end of file diff --git a/samples/webmvc-http/README.md b/samples/webmvc-http/README.md deleted file mode 100644 index bb272b6e..00000000 --- a/samples/webmvc-http/README.md +++ /dev/null @@ -1,7 +0,0 @@ -**GraphQL HTTP Endpoint with Spring MVC** - - - [Data Controller](src/main/java/io/spring/sample/graphql/project/ProjectController.java) with Spring HATEOAS calls to spring.io. - - Querydsl [GraphQlRepository](src/main/java/io/spring/sample/graphql/repository/ArtifactRepositories.java) making JPA queries. - - Use of [ThreadLocalAccessor](src/main/java/io/spring/sample/graphql/greeting/RequestAttributesAccessor.java) to propagate context to data fetchers. - - Schema printing enabled at "/graphql/schema". - - [Tests](src/test/java/io/spring/sample/graphql/project/ProjectControllerTests.java) with `GraphQlTester`. \ No newline at end of file diff --git a/samples/webmvc-http/build.gradle b/samples/webmvc-http/build.gradle deleted file mode 100644 index 5194ed96..00000000 --- a/samples/webmvc-http/build.gradle +++ /dev/null @@ -1,44 +0,0 @@ -plugins { - id 'org.springframework.boot' version "${bootVersion}" - id 'io.spring.dependency-management' version '1.0.13.RELEASE' - id 'java' -} -group = 'com.example' -description = "GraphQL over HTTP with Spring MVC Sample" -sourceCompatibility = '1.8' - -ext['spring-graphql.version'] = version - -repositories { - mavenCentral() - maven { url 'https://repo.spring.io/milestone' } - maven { url 'https://repo.spring.io/snapshot' } -} - -dependencies { - implementation 'org.springframework.boot:spring-boot-starter-graphql' - implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'org.springframework.boot:spring-boot-starter-hateoas' - implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - implementation 'org.springframework.boot:spring-boot-starter-actuator' - implementation 'com.querydsl:querydsl-core' - implementation 'com.querydsl:querydsl-jpa' - developmentOnly 'org.springframework.boot:spring-boot-devtools' - runtimeOnly 'com.h2database:h2' - testImplementation project(':spring-graphql') - testImplementation project(':spring-graphql-test') - testImplementation 'org.springframework:spring-webflux' - testImplementation 'org.springframework.boot:spring-boot-starter-test' - - annotationProcessor 'com.querydsl:querydsl-apt:5.0.0:jpa', - 'org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.2.Final', - 'javax.annotation:javax.annotation-api' -} - -compileJava { - options.annotationProcessorPath = configurations.annotationProcessor -} - -test { - useJUnitPlatform() -} diff --git a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/SampleApplication.java b/samples/webmvc-http/src/main/java/io/spring/sample/graphql/SampleApplication.java deleted file mode 100644 index 400baa49..00000000 --- a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/SampleApplication.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2002-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.spring.sample.graphql; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class SampleApplication { - - public static void main(String[] args) { - SpringApplication.run(SampleApplication.class, args); - } - -} diff --git a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/greeting/GreetingController.java b/samples/webmvc-http/src/main/java/io/spring/sample/graphql/greeting/GreetingController.java deleted file mode 100644 index 88e170f5..00000000 --- a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/greeting/GreetingController.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2002-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.spring.sample.graphql.greeting; - -import org.springframework.graphql.data.method.annotation.QueryMapping; -import org.springframework.stereotype.Controller; -import org.springframework.web.context.request.RequestAttributes; -import org.springframework.web.context.request.RequestContextHolder; - -import static org.springframework.web.context.request.RequestAttributes.SCOPE_REQUEST; - -@Controller -public class GreetingController { - - @QueryMapping - public String greeting() { - RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); - return "Hello " + attributes.getAttribute(RequestAttributeFilter.NAME_ATTRIBUTE, SCOPE_REQUEST); - } - -} diff --git a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/greeting/RequestAttributeFilter.java b/samples/webmvc-http/src/main/java/io/spring/sample/graphql/greeting/RequestAttributeFilter.java deleted file mode 100644 index 036a767b..00000000 --- a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/greeting/RequestAttributeFilter.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2002-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.spring.sample.graphql.greeting; - -import java.io.IOException; - -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; - -import org.springframework.stereotype.Component; - -/** - * Servlet Filter that adds a Servlet request attribute. - */ -@Component -public class RequestAttributeFilter implements Filter { - - public static final String NAME_ATTRIBUTE = RequestAttributeFilter.class.getName() + ".name"; - - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) - throws IOException, ServletException { - request.setAttribute(NAME_ATTRIBUTE, "007"); - chain.doFilter(request, response); - } - -} diff --git a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/greeting/RequestAttributesAccessor.java b/samples/webmvc-http/src/main/java/io/spring/sample/graphql/greeting/RequestAttributesAccessor.java deleted file mode 100644 index e4e6e911..00000000 --- a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/greeting/RequestAttributesAccessor.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2002-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.spring.sample.graphql.greeting; - -import java.util.Map; - -import org.springframework.graphql.execution.ThreadLocalAccessor; -import org.springframework.stereotype.Component; -import org.springframework.web.context.request.RequestAttributes; -import org.springframework.web.context.request.RequestContextHolder; - -/** - * {@link ThreadLocalAccessor} to expose a thread-bound RequestAttributes object to data - * fetchers in Spring for GraphQL. - */ -@Component -public class RequestAttributesAccessor implements ThreadLocalAccessor { - - private static final String KEY = RequestAttributesAccessor.class.getName(); - - @Override - public void extractValues(Map container) { - container.put(KEY, RequestContextHolder.getRequestAttributes()); - } - - @Override - public void restoreValues(Map values) { - if (values.containsKey(KEY)) { - RequestContextHolder.setRequestAttributes((RequestAttributes) values.get(KEY)); - } - } - - @Override - public void resetValues(Map values) { - RequestContextHolder.resetRequestAttributes(); - } - -} diff --git a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/greeting/package-info.java b/samples/webmvc-http/src/main/java/io/spring/sample/graphql/greeting/package-info.java deleted file mode 100644 index 3220fa71..00000000 --- a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/greeting/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -@NonNullApi -@NonNullFields -package io.spring.sample.graphql.greeting; - -import org.springframework.lang.NonNullApi; -import org.springframework.lang.NonNullFields; diff --git a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/package-info.java b/samples/webmvc-http/src/main/java/io/spring/sample/graphql/package-info.java deleted file mode 100644 index 78414e7f..00000000 --- a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -@NonNullApi -@NonNullFields -package io.spring.sample.graphql; - -import org.springframework.lang.NonNullApi; -import org.springframework.lang.NonNullFields; diff --git a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/project/Project.java b/samples/webmvc-http/src/main/java/io/spring/sample/graphql/project/Project.java deleted file mode 100644 index 5a3c452f..00000000 --- a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/project/Project.java +++ /dev/null @@ -1,67 +0,0 @@ -package io.spring.sample.graphql.project; - -import java.util.List; - -public class Project { - - private String slug; - - private String name; - - private String repositoryUrl; - - private ProjectStatus status; - - private List releases; - - public Project() { - } - - public Project(String slug, String name, String repositoryUrl, ProjectStatus status) { - this.slug = slug; - this.name = name; - this.repositoryUrl = repositoryUrl; - this.status = status; - } - - public String getSlug() { - return this.slug; - } - - public void setSlug(String slug) { - this.slug = slug; - } - - public String getName() { - return this.name; - } - - public void setName(String name) { - this.name = name; - } - - public String getRepositoryUrl() { - return this.repositoryUrl; - } - - public void setRepositoryUrl(String repositoryUrl) { - this.repositoryUrl = repositoryUrl; - } - - public ProjectStatus getStatus() { - return this.status; - } - - public void setStatus(ProjectStatus status) { - this.status = status; - } - - public List getReleases() { - return this.releases; - } - - public void setReleases(List releases) { - this.releases = releases; - } - -} diff --git a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/project/ProjectController.java b/samples/webmvc-http/src/main/java/io/spring/sample/graphql/project/ProjectController.java deleted file mode 100644 index ed021132..00000000 --- a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/project/ProjectController.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2002-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.spring.sample.graphql.project; - -import java.util.List; - -import org.springframework.graphql.data.method.annotation.Argument; -import org.springframework.graphql.data.method.annotation.QueryMapping; -import org.springframework.graphql.data.method.annotation.SchemaMapping; -import org.springframework.stereotype.Controller; - -@Controller -public class ProjectController { - - private final SpringProjectsClient client; - - public ProjectController(SpringProjectsClient client) { - this.client = client; - } - - @QueryMapping - public Project project(@Argument String slug) { - return client.fetchProject(slug); - } - - @SchemaMapping - public List releases(Project project) { - return client.fetchProjectReleases(project.getSlug()); - } - -} diff --git a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/project/ProjectStatus.java b/samples/webmvc-http/src/main/java/io/spring/sample/graphql/project/ProjectStatus.java deleted file mode 100644 index 75f8b151..00000000 --- a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/project/ProjectStatus.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.spring.sample.graphql.project; - -import java.util.Arrays; - -import com.fasterxml.jackson.annotation.JsonCreator; - -public enum ProjectStatus { - - ACTIVE, COMMUNITY, INCUBATING, ATTIC; - - @JsonCreator - public static ProjectStatus fromName(String name) { - return Arrays.stream(ProjectStatus.values()) - .filter(type -> type.name().equals(name)) - .findFirst() - .orElse(ProjectStatus.ACTIVE); - } - -} diff --git a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/project/Release.java b/samples/webmvc-http/src/main/java/io/spring/sample/graphql/project/Release.java deleted file mode 100644 index baab58b8..00000000 --- a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/project/Release.java +++ /dev/null @@ -1,65 +0,0 @@ -package io.spring.sample.graphql.project; - -public class Release { - - private String version; - - private ReleaseStatus status; - - private String referenceDocUrl; - - private String apiDocUrl; - - private boolean current; - - public Release() { - } - - public Release(Project project, String version, ReleaseStatus status) { - this.version = version; - this.status = status; - this.apiDocUrl = String.format("https://docs.spring.io/%s/docs/%s/javadoc-api/", project.getSlug(), version); - this.referenceDocUrl = String.format("https://docs.spring.io/%s/docs/%s/reference/html/", project.getSlug(), version); - } - - public String getVersion() { - return this.version; - } - - public void setVersion(String version) { - this.version = version; - } - - public ReleaseStatus getStatus() { - return this.status; - } - - public void setStatus(ReleaseStatus status) { - this.status = status; - } - - public String getReferenceDocUrl() { - return this.referenceDocUrl; - } - - public void setReferenceDocUrl(String referenceDocUrl) { - this.referenceDocUrl = referenceDocUrl; - } - - public String getApiDocUrl() { - return this.apiDocUrl; - } - - public void setApiDocUrl(String apiDocUrl) { - this.apiDocUrl = apiDocUrl; - } - - public boolean isCurrent() { - return this.current; - } - - public void setCurrent(boolean current) { - this.current = current; - } - -} diff --git a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/project/ReleaseStatus.java b/samples/webmvc-http/src/main/java/io/spring/sample/graphql/project/ReleaseStatus.java deleted file mode 100644 index 9caa64ab..00000000 --- a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/project/ReleaseStatus.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.spring.sample.graphql.project; - -import java.util.Arrays; - -import com.fasterxml.jackson.annotation.JsonCreator; - -public enum ReleaseStatus { - - GENERAL_AVAILABILITY, MILESTONE, SNAPSHOT; - - @JsonCreator - public static ReleaseStatus fromName(String name) { - return Arrays.stream(ReleaseStatus.values()) - .filter(type -> type.name().equals(name)) - .findFirst() - .orElse(ReleaseStatus.GENERAL_AVAILABILITY); - } - -} diff --git a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/project/SpringProjectsClient.java b/samples/webmvc-http/src/main/java/io/spring/sample/graphql/project/SpringProjectsClient.java deleted file mode 100644 index 0c236172..00000000 --- a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/project/SpringProjectsClient.java +++ /dev/null @@ -1,45 +0,0 @@ -package io.spring.sample.graphql.project; - -import java.net.URI; -import java.util.ArrayList; -import java.util.List; - -import org.springframework.boot.web.client.RestTemplateBuilder; -import org.springframework.hateoas.CollectionModel; -import org.springframework.hateoas.MediaTypes; -import org.springframework.hateoas.client.Hop; -import org.springframework.hateoas.client.Traverson; -import org.springframework.hateoas.server.core.TypeReferences; -import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.stereotype.Component; -import org.springframework.web.client.RestTemplate; - -@Component -public class SpringProjectsClient { - - private static final TypeReferences.CollectionModelType releaseCollection = - new TypeReferences.CollectionModelType() {}; - - private final Traverson traverson; - - public SpringProjectsClient(RestTemplateBuilder builder) { - List> converters = Traverson.getDefaultMessageConverters(MediaTypes.HAL_JSON); - RestTemplate restTemplate = builder.messageConverters(converters).build(); - this.traverson = new Traverson(URI.create("https://spring.io/api/"), MediaTypes.HAL_JSON); - this.traverson.setRestOperations(restTemplate); - } - - public Project fetchProject(String projectSlug) { - return this.traverson.follow("projects") - .follow(Hop.rel("project").withParameter("id", projectSlug)) - .toObject(Project.class); - } - - public List fetchProjectReleases(String projectSlug) { - CollectionModel releases = this.traverson.follow("projects") - .follow(Hop.rel("project").withParameter("id", projectSlug)).follow(Hop.rel("releases")) - .toObject(releaseCollection); - return new ArrayList(releases.getContent()); - } - -} diff --git a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/project/package-info.java b/samples/webmvc-http/src/main/java/io/spring/sample/graphql/project/package-info.java deleted file mode 100644 index 67a9733d..00000000 --- a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/project/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -@NonNullApi -@NonNullFields -package io.spring.sample.graphql.project; - -import org.springframework.lang.NonNullApi; -import org.springframework.lang.NonNullFields; diff --git a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/repository/ArtifactRepositories.java b/samples/webmvc-http/src/main/java/io/spring/sample/graphql/repository/ArtifactRepositories.java deleted file mode 100644 index f134809f..00000000 --- a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/repository/ArtifactRepositories.java +++ /dev/null @@ -1,11 +0,0 @@ -package io.spring.sample.graphql.repository; - -import org.springframework.data.querydsl.QuerydslPredicateExecutor; -import org.springframework.data.repository.CrudRepository; -import org.springframework.graphql.data.GraphQlRepository; - -@GraphQlRepository -public interface ArtifactRepositories extends - CrudRepository, QuerydslPredicateExecutor { - -} diff --git a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/repository/ArtifactRepositoriesInitializer.java b/samples/webmvc-http/src/main/java/io/spring/sample/graphql/repository/ArtifactRepositoriesInitializer.java deleted file mode 100644 index 9fdd925b..00000000 --- a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/repository/ArtifactRepositoriesInitializer.java +++ /dev/null @@ -1,28 +0,0 @@ -package io.spring.sample.graphql.repository; - -import java.util.Arrays; -import java.util.List; - -import org.springframework.boot.ApplicationArguments; -import org.springframework.boot.ApplicationRunner; -import org.springframework.stereotype.Component; - -@Component -public class ArtifactRepositoriesInitializer implements ApplicationRunner { - - private final ArtifactRepositories repositories; - - public ArtifactRepositoriesInitializer(ArtifactRepositories repositories) { - this.repositories = repositories; - } - - @Override - public void run(ApplicationArguments args) throws Exception { - List repositoryList = Arrays.asList( - new ArtifactRepository("spring-releases", "Spring Releases", "https://repo.spring.io/libs-releases"), - new ArtifactRepository("spring-milestones", "Spring Milestones", "https://repo.spring.io/libs-milestones"), - new ArtifactRepository("spring-snapshots", "Spring Snapshots", "https://repo.spring.io/libs-snapshots")); - repositories.saveAll(repositoryList); - } - -} diff --git a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/repository/ArtifactRepository.java b/samples/webmvc-http/src/main/java/io/spring/sample/graphql/repository/ArtifactRepository.java deleted file mode 100644 index 40f4db6d..00000000 --- a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/repository/ArtifactRepository.java +++ /dev/null @@ -1,59 +0,0 @@ -package io.spring.sample.graphql.repository; - -import javax.persistence.Entity; -import javax.persistence.Id; - -@Entity -public class ArtifactRepository { - - @Id - private String id; - - private String name; - - private String url; - - private boolean snapshotsEnabled; - - public ArtifactRepository(String id, String name, String url) { - this.id = id; - this.name = name; - this.url = url; - } - - public ArtifactRepository() { - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public boolean isSnapshotsEnabled() { - return snapshotsEnabled; - } - - public void setSnapshotsEnabled(boolean snapshotsEnabled) { - this.snapshotsEnabled = snapshotsEnabled; - } - -} diff --git a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/repository/package-info.java b/samples/webmvc-http/src/main/java/io/spring/sample/graphql/repository/package-info.java deleted file mode 100644 index 08f88984..00000000 --- a/samples/webmvc-http/src/main/java/io/spring/sample/graphql/repository/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -@NonNullApi -@NonNullFields -package io.spring.sample.graphql.repository; - -import org.springframework.lang.NonNullApi; -import org.springframework.lang.NonNullFields; diff --git a/samples/webmvc-http/src/main/resources/application.properties b/samples/webmvc-http/src/main/resources/application.properties deleted file mode 100644 index 80387b27..00000000 --- a/samples/webmvc-http/src/main/resources/application.properties +++ /dev/null @@ -1,3 +0,0 @@ -management.endpoints.web.exposure.include=health,metrics,info - -spring.graphql.schema.printer.enabled=true diff --git a/samples/webmvc-http/src/main/resources/graphql/schema.graphqls b/samples/webmvc-http/src/main/resources/graphql/schema.graphqls deleted file mode 100644 index 9d4d995e..00000000 --- a/samples/webmvc-http/src/main/resources/graphql/schema.graphqls +++ /dev/null @@ -1,40 +0,0 @@ -type Query { - greeting: String - artifactRepositories : [ArtifactRepository] - artifactRepository(id : ID!) : ArtifactRepository - project(slug: ID!): Project -} - -type ArtifactRepository { - id: ID! - name: String! - url: String! - snapshotsEnabled: Boolean -} - -type Project { - slug: ID! - name: String! - repositoryUrl: String! - status: ProjectStatus! - releases: [Release] -} - -type Release { - version: String! - status: ReleaseStatus! - current: Boolean -} - -enum ProjectStatus { - ACTIVE - COMMUNITY - INCUBATING - ATTIC -} - -enum ReleaseStatus { - GENERAL_AVAILABILITY - MILESTONE - SNAPSHOT -} \ No newline at end of file diff --git a/samples/webmvc-http/src/test/java/io/spring/sample/graphql/project/ProjectControllerTests.java b/samples/webmvc-http/src/test/java/io/spring/sample/graphql/project/ProjectControllerTests.java deleted file mode 100644 index 032d6a74..00000000 --- a/samples/webmvc-http/src/test/java/io/spring/sample/graphql/project/ProjectControllerTests.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2002-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.spring.sample.graphql.project; - -import java.util.Collections; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.graphql.GraphQlTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.graphql.test.tester.GraphQlTester; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; - -/** - * GraphQL requests via {@link GraphQlTester}. - */ -@GraphQlTest(ProjectController.class) -public class ProjectControllerTests { - - @Autowired - private GraphQlTester graphQlTester; - - @MockBean - private SpringProjectsClient projectsClient; - - private Project springFramework; - - private Release latestRelease; - - @BeforeEach - void setup() { - this.springFramework = new Project("spring-framework", "Spring Framework", - "http://github.com/spring-projects/spring-framework", ProjectStatus.ACTIVE); - this.latestRelease = new Release(this.springFramework, "5.3.0", ReleaseStatus.GENERAL_AVAILABILITY); - } - - @Test - void jsonPath() { - - given(this.projectsClient.fetchProject(eq("spring-framework"))) - .willReturn(this.springFramework); - - given(this.projectsClient.fetchProjectReleases(eq("spring-framework"))) - .willReturn(Collections.singletonList(this.latestRelease)); - - this.graphQlTester.documentName("projectReleases") - .variable("slug", "spring-framework") - .execute() - .path("project.releases[*].version") - .entityList(String.class) - .hasSize(1); - - } - - @Test - void jsonContent() { - given(this.projectsClient.fetchProject(eq("spring-framework"))).willReturn(this.springFramework); - this.graphQlTester.documentName("projectRepositoryUrl") - .variable("slug", "spring-framework") - .execute() - .path("project") - .matchesJson("{\"repositoryUrl\":\"http://github.com/spring-projects/spring-framework\"}"); - } - - @Test - void decodedResponse() { - - given(this.projectsClient.fetchProject(eq("spring-framework"))) - .willReturn(this.springFramework); - - given(this.projectsClient.fetchProjectReleases(eq("spring-framework"))) - .willReturn(Collections.singletonList(this.latestRelease)); - - this.graphQlTester.documentName("projectReleases") - .variable("slug", "spring-framework") - .execute() - .path("project") - .entity(Project.class) - .satisfies(project -> assertThat(project.getReleases()).hasSize(1)); - } - -} diff --git a/samples/webmvc-http/src/test/java/io/spring/sample/graphql/repository/ArtifactRepositoriesTests.java b/samples/webmvc-http/src/test/java/io/spring/sample/graphql/repository/ArtifactRepositoriesTests.java deleted file mode 100644 index 4fface62..00000000 --- a/samples/webmvc-http/src/test/java/io/spring/sample/graphql/repository/ArtifactRepositoriesTests.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2020-2022 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.spring.sample.graphql.repository; - -import org.junit.jupiter.api.Test; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.graphql.tester.AutoConfigureGraphQlTester; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.graphql.test.tester.GraphQlTester; - -@SpringBootTest -@AutoConfigureGraphQlTester -class ArtifactRepositoriesTests { - - @Autowired - private GraphQlTester graphQlTester; - - @Test - void querydslRepositorySingle() { - this.graphQlTester.documentName("artifactRepository") - .variable("id", "spring-releases") - .execute() - .path("artifactRepository.name") - .entity(String.class).isEqualTo("Spring Releases"); - } - - @Test - void querydslRepositoryMany() { - this.graphQlTester.documentName("artifactRepositories") - .execute() - .path("artifactRepositories[*].id") - .entityList(String.class).containsExactly("spring-releases", "spring-milestones", "spring-snapshots"); - } - -} \ No newline at end of file diff --git a/samples/webmvc-http/src/test/resources/application.properties b/samples/webmvc-http/src/test/resources/application.properties deleted file mode 100644 index 7ecf7b5e..00000000 --- a/samples/webmvc-http/src/test/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -logging.level.org.springframework.web=DEBUG \ No newline at end of file diff --git a/samples/webmvc-http/src/test/resources/graphql-test/artifactRepositories.graphql b/samples/webmvc-http/src/test/resources/graphql-test/artifactRepositories.graphql deleted file mode 100644 index 0da76c92..00000000 --- a/samples/webmvc-http/src/test/resources/graphql-test/artifactRepositories.graphql +++ /dev/null @@ -1,5 +0,0 @@ -query { - artifactRepositories { - id - } -} \ No newline at end of file diff --git a/samples/webmvc-http/src/test/resources/graphql-test/artifactRepository.graphql b/samples/webmvc-http/src/test/resources/graphql-test/artifactRepository.graphql deleted file mode 100644 index 1b64d983..00000000 --- a/samples/webmvc-http/src/test/resources/graphql-test/artifactRepository.graphql +++ /dev/null @@ -1,5 +0,0 @@ -query artifactRepository($id: ID!) { - artifactRepository(id: $id) { - name - } -} \ No newline at end of file diff --git a/samples/webmvc-http/src/test/resources/graphql-test/projectReleases.graphql b/samples/webmvc-http/src/test/resources/graphql-test/projectReleases.graphql deleted file mode 100644 index 9c8b96af..00000000 --- a/samples/webmvc-http/src/test/resources/graphql-test/projectReleases.graphql +++ /dev/null @@ -1,8 +0,0 @@ -query project($slug: ID!) { - project(slug: $slug) { - repositoryUrl - releases { - version - } - } -} \ No newline at end of file diff --git a/samples/webmvc-http/src/test/resources/graphql-test/projectRepositoryUrl.graphql b/samples/webmvc-http/src/test/resources/graphql-test/projectRepositoryUrl.graphql deleted file mode 100644 index 09f479a0..00000000 --- a/samples/webmvc-http/src/test/resources/graphql-test/projectRepositoryUrl.graphql +++ /dev/null @@ -1,5 +0,0 @@ -query project($slug: ID!) { - project(slug: $slug) { - repositoryUrl - } -} \ No newline at end of file diff --git a/spring-graphql-docs/src/docs/asciidoc/attributes.adoc b/spring-graphql-docs/src/docs/asciidoc/attributes.adoc index d8f2f635..1d32dfa5 100644 --- a/spring-graphql-docs/src/docs/asciidoc/attributes.adoc +++ b/spring-graphql-docs/src/docs/asciidoc/attributes.adoc @@ -12,6 +12,7 @@ :github-raw: https://raw.githubusercontent.com/{github-repo}/{github-tag} :github-issues: https://github.com/{github-repo}/issues/ :github-main-branch: https://github.com/{github-repo}/tree/main +:github-10x-branch: https://github.com/{github-repo}/tree/1.0.x :github-wiki: https://github.com/{github-repo}/wiki :graphql-java-docs: https://www.graphql-java.com/documentation :javadoc: https://docs.spring.io/spring-graphql/docs/{spring-graphql-version}/api diff --git a/spring-graphql-docs/src/docs/asciidoc/index.adoc b/spring-graphql-docs/src/docs/asciidoc/index.adoc index b6d63a22..b116003e 100644 --- a/spring-graphql-docs/src/docs/asciidoc/index.adoc +++ b/spring-graphql-docs/src/docs/asciidoc/index.adoc @@ -21,8 +21,8 @@ Please, see our https://github.com/spring-projects/spring-graphql/wiki[Wiki]. for what's new, baseline requirements, and upgrade notes, and other cross-version information. -To get started, check the Spring GraphQL starter on https://start.spring.io and the -<> in this repository. +To get started, check the Spring GraphQL starter on https://start.spring.io. +The are also https://github.com/spring-projects/spring-graphql/tree/1.0.x/samples[samples] in the 1.0.x branch, which will be https://github.com/spring-projects/spring-graphql/issues/208[moved out] into a separate repository. @@ -59,8 +59,8 @@ Boot starter does this, see the details, or check `GraphQlWebMvcAutoConfiguration` or `GraphQlWebFluxAutoConfiguration` it contains, for the actual config. -The Spring for GraphQL repository contains a Spring MVC -{github-main-branch}/samples/webmvc-http[HTTP sample] application. +The 1.0.x branch of this repository contains a Spring MVC +{github-10x-branch}/samples/webmvc-http[HTTP sample] application. @@ -103,8 +103,8 @@ enable it by adding a property for the endpoint path. Please, see the section for details, or check the `GraphQlWebMvcAutoConfiguration` or the `GraphQlWebFluxAutoConfiguration` for the actual Boot starter config. -The Spring for GraphQL repository contains a WebFlux -{github-main-branch}/samples/webflux-websocket[WebSocket sample] application. +The 1.0.x branch of this repository contains a WebFlux +{github-10x-branch}/samples/webflux-websocket[WebSocket sample] application. @@ -892,7 +892,7 @@ compileJava { ---- -The {github-main-branch}/samples/webmvc-http[webmvc-http] sample uses Querydsl for +The {github-10x-branch}/samples/webmvc-http[webmvc-http] sample uses Querydsl for `artifactRepositories`. @@ -1748,9 +1748,9 @@ To apply more fine-grained security, add Spring Security annotations such as the GraphQL response. This should work due to <> that aims to make Security, and other context, available at the data fetching level. -The Spring for GraphQL repository contains samples for -{github-main-branch}/samples/webmvc-http-security[Spring MVC] and for -{github-main-branch}/samples/webflux-security[WebFlux]. +The 1.0.x branch of this repository contains samples for +{github-10x-branch}/samples/webmvc-http-security[Spring MVC] and for +{github-10x-branch}/samples/webflux-security[WebFlux]. @@ -1768,11 +1768,9 @@ include::testing.adoc[leveloffset=+1] [[samples]] == Samples -This Spring for GraphQL repository contains {github-main-branch}/samples[sample applications] for -various scenarios. +The 1.0.x branch of this repository contains {github-10x-branch}/samples[sample applications] for various scenarios. -You can run those by cloning this repository and running main application classes from -your IDE or by typing the following on the command line: +You can run those by cloning this repository and running main application classes from your IDE or by typing the following on the command line: [source,bash,indent=0,subs="verbatim,quotes"] ----