diff --git a/demo-client-app/.eslintcache b/demo-client-app/.eslintcache index 42a3ec0..ab4dbfc 100644 --- a/demo-client-app/.eslintcache +++ b/demo-client-app/.eslintcache @@ -1 +1 @@ -[{"/Users/dima/Projects/jce/auth-flow/demo-client-app/src/reportWebVitals.js":"1","/Users/dima/Projects/jce/auth-flow/demo-client-app/src/App.js":"2","/Users/dima/Projects/jce/auth-flow/demo-client-app/src/index.js":"3"},{"size":362,"mtime":1611244349228,"results":"4","hashOfConfig":"5"},{"size":1216,"mtime":1611250955596,"results":"6","hashOfConfig":"5"},{"size":1404,"mtime":1611250251472,"results":"7","hashOfConfig":"5"},{"filePath":"8","messages":"9","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"ewyx7q",{"filePath":"10","messages":"11","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"12","messages":"13","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/Users/dima/Projects/jce/auth-flow/demo-client-app/src/reportWebVitals.js",[],"/Users/dima/Projects/jce/auth-flow/demo-client-app/src/App.js",[],"/Users/dima/Projects/jce/auth-flow/demo-client-app/src/index.js",[]] \ No newline at end of file +[{"/Users/dima/Projects/jce/auth-flow/demo-client-app/src/reportWebVitals.js":"1","/Users/dima/Projects/jce/auth-flow/demo-client-app/src/App.js":"2","/Users/dima/Projects/jce/auth-flow/demo-client-app/src/index.js":"3"},{"size":362,"mtime":1611244349228,"results":"4","hashOfConfig":"5"},{"size":1212,"mtime":1611308679793,"results":"6","hashOfConfig":"5"},{"size":1404,"mtime":1611250251472,"results":"7","hashOfConfig":"5"},{"filePath":"8","messages":"9","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"ewyx7q",{"filePath":"10","messages":"11","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"12","messages":"13","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/Users/dima/Projects/jce/auth-flow/demo-client-app/src/reportWebVitals.js",[],"/Users/dima/Projects/jce/auth-flow/demo-client-app/src/App.js",[],"/Users/dima/Projects/jce/auth-flow/demo-client-app/src/index.js",[]] \ No newline at end of file diff --git a/demo-client-app/package.json b/demo-client-app/package.json index d1e5af6..1d8ac5c 100644 --- a/demo-client-app/package.json +++ b/demo-client-app/package.json @@ -2,6 +2,7 @@ "name": "demo-client-app", "version": "0.1.0", "private": true, + "proxy": "http://localhost:8081", "dependencies": { "@testing-library/jest-dom": "^5.11.4", "@testing-library/react": "^11.1.0", diff --git a/demo-client-app/src/App.js b/demo-client-app/src/App.js index e318849..43bf387 100644 --- a/demo-client-app/src/App.js +++ b/demo-client-app/src/App.js @@ -4,7 +4,7 @@ import "./App.css"; function App({ keycloak }) { const callApi = useCallback(async () => { - const response = await fetch("http://localhost:8081/api/userinfo", { + const response = await fetch("http://localhost:8081/userinfo", { headers: { Authorization: `Bearer ${keycloak.token}`, }, diff --git a/demo-resource-server/build.gradle b/demo-resource-server/build.gradle index eb2d096..bf0076d 100644 --- a/demo-resource-server/build.gradle +++ b/demo-resource-server/build.gradle @@ -2,6 +2,7 @@ plugins { id 'org.springframework.boot' version '2.4.2' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' + id "io.freefair.lombok" version "5.3.0" } group = 'ru.digitalbanana' @@ -18,10 +19,11 @@ repositories { } dependencies { - implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-data-r2dbc' implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server' - implementation 'org.springframework.boot:spring-boot-starter-web' - runtimeOnly 'org.postgresql:postgresql' + implementation 'org.springframework.boot:spring-boot-starter-webflux' + runtimeOnly 'io.r2dbc:r2dbc-postgresql' + // runtimeOnly 'org.postgresql:postgresql' developmentOnly 'org.springframework.boot:spring-boot-devtools' testImplementation 'org.springframework.boot:spring-boot-starter-test' } diff --git a/demo-resource-server/lombok.config b/demo-resource-server/lombok.config new file mode 100644 index 0000000..6aa51d7 --- /dev/null +++ b/demo-resource-server/lombok.config @@ -0,0 +1,2 @@ +# This file is generated by the 'io.freefair.lombok' Gradle plugin +config.stopBubbling = true diff --git a/demo-resource-server/src/main/java/ru/digitalbanana/demoresourceserver/config/WebSecurityConfig.java b/demo-resource-server/src/main/java/ru/digitalbanana/demoresourceserver/config/WebSecurityConfig.java index d2235f9..7d74f51 100644 --- a/demo-resource-server/src/main/java/ru/digitalbanana/demoresourceserver/config/WebSecurityConfig.java +++ b/demo-resource-server/src/main/java/ru/digitalbanana/demoresourceserver/config/WebSecurityConfig.java @@ -1,25 +1,29 @@ package ru.digitalbanana.demoresourceserver.config; +import static org.springframework.security.config.Customizer.withDefaults; + +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; +import org.springframework.security.config.web.server.ServerHttpSecurity; +import org.springframework.security.web.server.SecurityWebFilterChain; @Configuration -public class WebSecurityConfig extends WebSecurityConfigurerAdapter { +@EnableWebFluxSecurity +public class WebSecurityConfig { + + @Bean + public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { + http + .authorizeExchange() + .pathMatchers(HttpMethod.OPTIONS).permitAll() + .anyExchange().authenticated() + .and() + .httpBasic().disable() + .oauth2ResourceServer() + .jwt(withDefaults()); - @Override - protected void configure(HttpSecurity http) throws Exception { - http.cors() - .and() - .authorizeRequests() - .antMatchers(HttpMethod.GET, "/userinfo", "/user/**") - .authenticated() - // .hasAuthority("SCOPE_web-api") - .anyRequest() - .authenticated() - .and() - .oauth2ResourceServer() - .jwt(); - } + return http.build(); + } } diff --git a/demo-resource-server/src/main/java/ru/digitalbanana/demoresourceserver/persistence/model/UserEntity.java b/demo-resource-server/src/main/java/ru/digitalbanana/demoresourceserver/persistence/model/UserEntity.java index 03fd69f..2c065a4 100644 --- a/demo-resource-server/src/main/java/ru/digitalbanana/demoresourceserver/persistence/model/UserEntity.java +++ b/demo-resource-server/src/main/java/ru/digitalbanana/demoresourceserver/persistence/model/UserEntity.java @@ -1,39 +1,25 @@ package ru.digitalbanana.demoresourceserver.persistence.model; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.Table; - -@Entity -@Table(name = "user_entity") +import org.springframework.data.annotation.Id; +import org.springframework.data.relational.core.mapping.Column; +import org.springframework.data.relational.core.mapping.Table; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Table("user_entity") public class UserEntity { - + @Id - @Column(name = "id") + @Column("id") private String id; - @Column(name = "email") - public String email; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - @Override - public String toString() { - return "Foo [id=" + id + ", email=" + email + "]"; - } + @Column("email") + private String email; } diff --git a/demo-resource-server/src/main/java/ru/digitalbanana/demoresourceserver/persistence/repository/IUserEntityRepository.java b/demo-resource-server/src/main/java/ru/digitalbanana/demoresourceserver/persistence/repository/IUserEntityRepository.java index 4cd83aa..7bd9c02 100644 --- a/demo-resource-server/src/main/java/ru/digitalbanana/demoresourceserver/persistence/repository/IUserEntityRepository.java +++ b/demo-resource-server/src/main/java/ru/digitalbanana/demoresourceserver/persistence/repository/IUserEntityRepository.java @@ -1,11 +1,12 @@ package ru.digitalbanana.demoresourceserver.persistence.repository; -import java.util.List; - -import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.reactive.ReactiveCrudRepository; +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Flux; import ru.digitalbanana.demoresourceserver.persistence.model.UserEntity; -public interface IUserEntityRepository extends CrudRepository { - List findByEmailContainingIgnoreCase(String email); +@Repository +public interface IUserEntityRepository extends ReactiveCrudRepository { + Flux findByEmailContainingIgnoreCase(String email); } diff --git a/demo-resource-server/src/main/java/ru/digitalbanana/demoresourceserver/service/UserService.java b/demo-resource-server/src/main/java/ru/digitalbanana/demoresourceserver/service/UserService.java index 89d432f..ca1711f 100644 --- a/demo-resource-server/src/main/java/ru/digitalbanana/demoresourceserver/service/UserService.java +++ b/demo-resource-server/src/main/java/ru/digitalbanana/demoresourceserver/service/UserService.java @@ -1,10 +1,9 @@ package ru.digitalbanana.demoresourceserver.service; -import java.util.List; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import reactor.core.publisher.Flux; import ru.digitalbanana.demoresourceserver.persistence.model.UserEntity; import ru.digitalbanana.demoresourceserver.persistence.repository.IUserEntityRepository; @@ -13,11 +12,11 @@ public class UserService { @Autowired IUserEntityRepository userRepository; - public Iterable findAll() { + public Flux findAll() { return userRepository.findAll(); } - public List findByEmail(String email) { + public Flux findByEmail(String email) { return userRepository.findByEmailContainingIgnoreCase(email); } } diff --git a/demo-resource-server/src/main/java/ru/digitalbanana/demoresourceserver/web/controller/UserInfoController.java b/demo-resource-server/src/main/java/ru/digitalbanana/demoresourceserver/web/controller/UserInfoController.java index 4d39c5e..ef6c96a 100644 --- a/demo-resource-server/src/main/java/ru/digitalbanana/demoresourceserver/web/controller/UserInfoController.java +++ b/demo-resource-server/src/main/java/ru/digitalbanana/demoresourceserver/web/controller/UserInfoController.java @@ -1,7 +1,6 @@ package ru.digitalbanana.demoresourceserver.web.controller; import java.util.Collections; -import java.util.List; import java.util.Map; import org.slf4j.Logger; @@ -13,10 +12,11 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Flux; import ru.digitalbanana.demoresourceserver.persistence.model.UserEntity; import ru.digitalbanana.demoresourceserver.service.UserService; -@CrossOrigin(origins = "*") +@CrossOrigin @RestController public class UserInfoController { @@ -36,9 +36,8 @@ public class UserInfoController { } @GetMapping(value = "/user/{email}") - public List getMethodName(@PathVariable String email) { + public Flux getMethodName(@PathVariable String email) { logger.debug("Request user by email {}", email); return userService.findByEmail(email); } - } diff --git a/demo-resource-server/src/main/resources/application.yml b/demo-resource-server/src/main/resources/application.yml index d77c7da..85265e3 100644 --- a/demo-resource-server/src/main/resources/application.yml +++ b/demo-resource-server/src/main/resources/application.yml @@ -1,12 +1,20 @@ + server: port: 8081 - servlet: - context-path: /api forward-headers-strategy: framework # nginx reverse proxy logging.level: '[org.springframework.web]': debug ####### resource server configuration properties spring: + r2dbc: + username: postgres + password: P4$$W0RddD + url: r2dbc:postgresql://localhost:5432/keycloak + pool.enabled: true + pool.initial-size: 10 + pool.max-idle-time: 1m + pool.max-size: 30 + data.r2dbc.repositories.enabled: true jpa.hibernate.ddl-auto: none datasource: initialization-mode: always