Skip to content
This repository was archived by the owner on Aug 27, 2020. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-webflux'
implementation 'org.springframework.boot:spring-boot-starter-amqp'
implementation 'org.springframework:spring-context-support'
implementation 'org.springframework.boot:spring-boot-starter-security'
// implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'io.vertx:vertx-pg-client:3.9.0'
implementation 'log4j:log4j:1.2.17'
implementation 'com.google.guava:guava:29.0-jre'
Expand Down
17 changes: 17 additions & 0 deletions src/main/java/in/projecteka/uos/Error.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package in.projecteka.uos;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@JsonIgnoreProperties(ignoreUnknown = true)
@AllArgsConstructor
@Builder
@NoArgsConstructor
@Data
public class Error {
private ErrorCode code;
private String message;
}
5 changes: 4 additions & 1 deletion src/main/java/in/projecteka/uos/ErrorCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@

public enum ErrorCode {
UNKNOWN_ERROR(1002),
UNAUTHORIZED_REQUESTER(1005);
UNAUTHORIZED_REQUESTER(1005),
NETWORK_SERVICE_ERROR(2000),
USERNAME_OR_PASSWORD_INCORRECT(1018);

private final int value;

ErrorCode(int val) {
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/in/projecteka/uos/UOSApplication.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package in.projecteka.uos;

import in.projecteka.uos.clients.properties.IdentityServiceProperties;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;

@SpringBootApplication
@EnableConfigurationProperties({UOSProperties.class})
@EnableConfigurationProperties({UOSProperties.class,
IdentityServiceProperties.class})
public class UOSApplication {

public static void main(String[] args) {
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/in/projecteka/uos/UOSConfiguration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package in.projecteka.uos;

import in.projecteka.uos.clients.IdentityServiceClient;
import in.projecteka.uos.clients.properties.IdentityServiceProperties;
import in.projecteka.uos.user.TokenService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;

@Configuration
public class UOSConfiguration {

@Bean
public TokenService tokenService(IdentityServiceProperties identityServiceProperties,
IdentityServiceClient identityServiceClient) {
return new TokenService(identityServiceProperties, identityServiceClient);
}
}
1 change: 0 additions & 1 deletion src/main/java/in/projecteka/uos/UOSProperties.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,5 @@
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PACKAGE)
@AllArgsConstructor
public class UOSProperties {
}
36 changes: 36 additions & 0 deletions src/main/java/in/projecteka/uos/clients/ClientError.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package in.projecteka.uos.clients;

import in.projecteka.uos.Error;
import in.projecteka.uos.ErrorRepresentation;
import lombok.Getter;
import lombok.ToString;
import org.springframework.http.HttpStatus;

import static in.projecteka.uos.ErrorCode.NETWORK_SERVICE_ERROR;
import static in.projecteka.uos.ErrorCode.USERNAME_OR_PASSWORD_INCORRECT;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import static org.springframework.http.HttpStatus.UNAUTHORIZED;

@Getter
@ToString
public class ClientError extends Throwable {
private static final String CANNOT_PROCESS_REQUEST_TRY_LATER = "Cannot process the request at the moment, please try later.";
private final HttpStatus httpStatus;
private final ErrorRepresentation error;

public ClientError(HttpStatus httpStatus, ErrorRepresentation errorRepresentation) {
this.httpStatus = httpStatus;
error = errorRepresentation;
}

public static ClientError unAuthorizedRequest() {
return new ClientError(UNAUTHORIZED,
new ErrorRepresentation(new Error(USERNAME_OR_PASSWORD_INCORRECT,
"Username or password is incorrect")));
}

public static ClientError networkServiceCallFailed() {
return new ClientError(INTERNAL_SERVER_ERROR,
new ErrorRepresentation(new Error(NETWORK_SERVICE_ERROR, CANNOT_PROCESS_REQUEST_TRY_LATER)));
}
}
33 changes: 33 additions & 0 deletions src/main/java/in/projecteka/uos/clients/IdentityServiceClient.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package in.projecteka.uos.clients;

import in.projecteka.uos.clients.model.Session;
import in.projecteka.uos.clients.properties.IdentityServiceProperties;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

public class IdentityServiceClient {
private final WebClient.Builder webClientBuilder;

public IdentityServiceClient(WebClient.Builder webClientBuilder,
IdentityServiceProperties identityServiceProperties) {
this.webClientBuilder = webClientBuilder;
this.webClientBuilder.baseUrl(identityServiceProperties.getBaseUrl());
}

public Mono<Session> getToken(MultiValueMap<String, String> formData) {
return webClientBuilder.build()
.post()
.uri(uriBuilder ->
uriBuilder.path("/realms/Uos-manager/protocol/openid-connect/token").build())
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.accept(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromFormData(formData))
.retrieve()
.onStatus(HttpStatus::isError, clientResponse -> Mono.error(ClientError.networkServiceCallFailed()))
.bodyToMono(Session.class);
}
}
32 changes: 32 additions & 0 deletions src/main/java/in/projecteka/uos/clients/model/ErrorCode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package in.projecteka.uos.clients.model;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;

import java.util.Arrays;

public enum ErrorCode {
UNKNOWN_ERROR_OCCURRED(1012),
NETWORK_SERVICE_ERROR(2000),
USERNAME_OR_PASSWORD_INCORRECT(1018);

private final int value;

ErrorCode(int val) {
value = val;
}

// Adding @JsonValue annotation that tells the 'value' to be of integer type while de-serializing.
@JsonValue
public int getValue() {
return value;
}

@JsonCreator
public static ErrorCode getNameByValue(int value) {
return Arrays.stream(ErrorCode.values())
.filter(errorCode -> errorCode.value == value)
.findAny()
.orElse(ErrorCode.UNKNOWN_ERROR_OCCURRED);
}
}
30 changes: 30 additions & 0 deletions src/main/java/in/projecteka/uos/clients/model/Session.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package in.projecteka.uos.clients.model;

import com.fasterxml.jackson.annotation.JsonAlias;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class Session {
@JsonAlias({"access_token"})
private String accessToken;

@JsonAlias({"expires_in"})
private int expiresIn;

@JsonAlias({"refresh_expires_in"})
private int refreshExpiresIn;

@JsonAlias({"refresh_token"})
private String refreshToken;

@JsonAlias({"token_type"})
private String tokenType;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package in.projecteka.uos.clients.properties;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConstructorBinding;

@Builder
@ConfigurationProperties(prefix = "uos.keycloak")
@AllArgsConstructor
@ConstructorBinding
@Getter
public class IdentityServiceProperties {
private final String baseUrl;
private final String clientId;
private final String clientSecret;
private final String jwkUrl;
private final String issuer;
}
20 changes: 20 additions & 0 deletions src/main/java/in/projecteka/uos/user/SessionController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package in.projecteka.uos.user;

import in.projecteka.uos.clients.model.Session;
import in.projecteka.uos.user.model.SessionRequest;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

@RestController
@AllArgsConstructor
public class SessionController {
private final SessionService sessionService;

@PostMapping("/sessions")
public Mono<Session> forNew(@RequestBody SessionRequest sessionRequest) {
return sessionService.forNew(sessionRequest);
}
}
24 changes: 24 additions & 0 deletions src/main/java/in/projecteka/uos/user/SessionService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package in.projecteka.uos.user;

import in.projecteka.uos.clients.ClientError;
import in.projecteka.uos.clients.model.Session;
import in.projecteka.uos.user.model.SessionRequest;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import reactor.core.publisher.Mono;

@AllArgsConstructor
public class SessionService {
private final TokenService tokenService;
private final Logger logger = LoggerFactory.getLogger(SessionService.class);

public Mono<Session> forNew(SessionRequest request) {
if (StringUtils.isEmpty(request.getUsername()) || StringUtils.isEmpty(request.getPassword()))
return Mono.error(ClientError.unAuthorizedRequest());
return tokenService.tokenForUser(request.getUsername(), request.getPassword())
.doOnError(error -> logger.error(error.getMessage(), error))
.onErrorResume(error -> Mono.error(ClientError.unAuthorizedRequest()));
}
}
30 changes: 30 additions & 0 deletions src/main/java/in/projecteka/uos/user/TokenService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package in.projecteka.uos.user;

import in.projecteka.uos.clients.IdentityServiceClient;
import in.projecteka.uos.clients.model.Session;
import in.projecteka.uos.clients.properties.IdentityServiceProperties;
import lombok.AllArgsConstructor;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import reactor.core.publisher.Mono;

@AllArgsConstructor
public class TokenService {
private final IdentityServiceProperties keyCloakProperties;
private final IdentityServiceClient identityServiceClient;

public Mono<Session> tokenForUser(String userName, String password) {
return identityServiceClient.getToken(loginRequestWith(userName, password));
}

private MultiValueMap<String, String> loginRequestWith(String username, String password) {
var formData = new LinkedMultiValueMap<String, String>();
formData.add("grant_type", "password");
formData.add("scope", "openid");
formData.add("client_id", keyCloakProperties.getClientId());
formData.add("client_secret", keyCloakProperties.getClientSecret());
formData.add("username", username);
formData.add("password", password);
return formData;
}
}
21 changes: 21 additions & 0 deletions src/main/java/in/projecteka/uos/user/UserConfiguration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package in.projecteka.uos.user;

import in.projecteka.uos.clients.IdentityServiceClient;
import in.projecteka.uos.clients.properties.IdentityServiceProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;

@Configuration
public class UserConfiguration {
@Bean
public IdentityServiceClient keycloakClient(WebClient.Builder builder,
IdentityServiceProperties identityServiceProperties) {
return new IdentityServiceClient(builder, identityServiceProperties);
}

@Bean
public SessionService sessionService(TokenService tokenService) {
return new SessionService(tokenService);
}
}
18 changes: 18 additions & 0 deletions src/main/java/in/projecteka/uos/user/model/GrantType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package in.projecteka.uos.user.model;

import com.fasterxml.jackson.annotation.JsonValue;

public enum GrantType {
PASSWORD("password");

private final String grantType;

GrantType(String value) {
grantType = value;
}

@JsonValue
public String getValue() {
return grantType;
}
}
14 changes: 14 additions & 0 deletions src/main/java/in/projecteka/uos/user/model/SessionRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package in.projecteka.uos.user.model;

import lombok.Builder;
import lombok.Value;

@Value
@Builder
public class SessionRequest {
GrantType grantType;

String username;

String password;
}
11 changes: 10 additions & 1 deletion src/main/resources/application-dev.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
server:
port: 9060

uos:
id: CM_USER_ONBOARDING_SERVICE
keycloak:
baseUrl: http://localhost:9001/auth
clientId: uos-service
clientSecret: 75ab5d05-3422-43ff-ba85-11f442aa22cf
jwkUrl: http://localhost:9001/auth/realms/Uos-manager/protocol/openid-connect/certs
issuer: http://localhost:9001/auth/realms/Uos-manager

spring:
codec:
max-in-memory-size: 500MB
max-in-memory-size: 500MB

Loading