Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of signed transaction jwt validation real #200

Merged
Merged
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
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.adorsys.webank.obs.resource;

import com.adorsys.webank.obs.dto.PayoutRequest;
import com.adorsys.webank.obs.dto.MoneyTransferRequestDto;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
Expand All @@ -25,6 +25,6 @@ public interface PayoutRestApi {

})
@PostMapping(value = "/payout", consumes = "application/json", produces = "application/json")
ResponseEntity<String> payout(@RequestHeader(HttpHeaders.AUTHORIZATION) String authorizationHeader, @RequestBody PayoutRequest request);
ResponseEntity<String> payout(@RequestHeader(HttpHeaders.AUTHORIZATION) String authorizationHeader, @RequestBody MoneyTransferRequestDto request);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.adorsys.webank.obs.resource;

import com.adorsys.webank.obs.dto.MoneyTransferRequestDto;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;

@Tag(name = "Trans", description = "Operations related to transaction processing")
@RequestMapping("/api/accounts/")
public interface WithdrawRestApi {

@Operation(summary = "Withdraw from an account", description = "Withdraw funds from an account to another account (Payout)")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Account withdrawal successful"),
@ApiResponse(responseCode = "400", description = "Invalid request to withdraw funds"),
@ApiResponse(responseCode = "500", description = "Internal server error")
})
@PostMapping(value = "/withdraw", consumes = "application/json", produces = "application/json")
ResponseEntity<String> withdraw(@RequestHeader(HttpHeaders.AUTHORIZATION) String authorizationHeader, @RequestBody MoneyTransferRequestDto request);
}
6 changes: 6 additions & 0 deletions obs/obs-rest/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.adorsys.webank</groupId>
<artifactId>obs-service-impl</artifactId>
<version>0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>

<!-- Other existing dependencies -->
</dependencies>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package com.adorsys.webank.obs.resource;

import com.adorsys.webank.obs.dto.*;
import com.adorsys.webank.obs.security.JwtValidator;
import com.adorsys.webank.obs.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;

@RestController
public class BalanceRest implements BalanceRestApi {

private static final Logger log = LoggerFactory.getLogger(BalanceRest.class);
private BalanceServiceApi balanceService;

public BalanceRest( BalanceServiceApi balanceService) {
Expand All @@ -23,6 +27,8 @@ public ResponseEntity<String> getBalance(@RequestHeader(HttpHeaders.AUTHORIZATIO

try {
String jwtToken = extractJwtFromHeader(authorizationHeader);
JwtValidator.validateAndExtract(jwtToken, balanceRequest.getAccountID());
log.info("balance request validated successfully");
String result = balanceService.getBalance(balanceRequest, jwtToken) ;
return ResponseEntity.status(HttpStatus.CREATED).body(result);
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.adorsys.webank.obs.resource;

import com.adorsys.webank.obs.dto.PayoutRequest;
import com.adorsys.webank.obs.dto.MoneyTransferRequestDto;
import com.adorsys.webank.obs.security.JwtValidator;
import com.adorsys.webank.obs.service.PayoutServiceApi;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
Expand All @@ -12,6 +15,7 @@
@RestController
public class PayoutRest implements PayoutRestApi {

private static final Logger log = LoggerFactory.getLogger(PayoutRest.class);
private final PayoutServiceApi payoutService;

public PayoutRest(PayoutServiceApi payoutService) {
Expand All @@ -20,13 +24,15 @@ public PayoutRest(PayoutServiceApi payoutService) {


@Override
public ResponseEntity<String> payout(@RequestHeader(HttpHeaders.AUTHORIZATION) String authorizationHeader, @RequestBody PayoutRequest request) {
public ResponseEntity<String> payout(@RequestHeader(HttpHeaders.AUTHORIZATION) String authorizationHeader, @RequestBody MoneyTransferRequestDto request) {
if (request == null) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Request body cannot be null.");
}
try {
String jwtToken = extractJwtFromHeader(authorizationHeader);
String result = payoutService.payout(request, jwtToken) ;
JwtValidator.validateAndExtract(jwtToken, request.getSenderAccountId(), request.getAmount(), request.getRecipientAccountId());
log.info("Payout request validated successfully");
return ResponseEntity.status(HttpStatus.CREATED).body(result);
} catch (Exception e) {
// Log the exception (optional)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.adorsys.webank.obs.resource;

import com.adorsys.webank.obs.dto.*;
import com.adorsys.webank.obs.security.JwtValidator;
import com.adorsys.webank.obs.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;

Expand All @@ -10,6 +13,7 @@
public class RegistrationResource implements RegistrationResourceApi {


private static final Logger log = LoggerFactory.getLogger(RegistrationResource.class);
private RegistrationServiceApi registrationService;

public RegistrationResource( RegistrationServiceApi registrationService) {
Expand All @@ -24,6 +28,8 @@ public ResponseEntity<String> registerAccount(@RequestHeader(HttpHeaders.AUTHORI
}
try {
String jwtToken = extractJwtFromHeader(authorizationHeader);
JwtValidator.validateAndExtract(jwtToken, registrationRequest.getPhoneNumber(), registrationRequest.getPublicKey());
log.info("Registration request validated successfully");
String result = registrationService.registerAccount(registrationRequest, jwtToken);
return ResponseEntity.status(HttpStatus.CREATED).body(result);
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package com.adorsys.webank.obs.resource;

import com.adorsys.webank.obs.dto.*;
import com.adorsys.webank.obs.security.JwtValidator;
import com.adorsys.webank.obs.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;

@RestController
public class TransRest implements TransRestApi {

private static final Logger log = LoggerFactory.getLogger(TransRest.class);
private TransServiceApi transService;
public TransRest( TransServiceApi transService) {
this.transService = transService;
Expand All @@ -20,6 +24,8 @@ public ResponseEntity<String> getTrans(@RequestHeader(HttpHeaders.AUTHORIZATION)
}
try {
String jwtToken = extractJwtFromHeader(authorizationHeader);
JwtValidator.validateAndExtract(jwtToken, request.getAccountID());
log.info("Transaction request validated successfully");
String result = transService.getTrans(request, jwtToken) ;
return ResponseEntity.status(HttpStatus.CREATED).body(result);
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.adorsys.webank.obs.resource;

import com.adorsys.webank.obs.dto.MoneyTransferRequestDto;
import com.adorsys.webank.obs.security.JwtValidator;
import com.adorsys.webank.obs.service.WithdrawServiceApi;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class WithdrawRestServer implements WithdrawRestApi {

private static final Logger log = LoggerFactory.getLogger(WithdrawRestServer.class);
private final WithdrawServiceApi withdrawServiceApi;

public WithdrawRestServer(WithdrawServiceApi withdrawServiceApi) {
this.withdrawServiceApi = withdrawServiceApi;
}

@Override
public ResponseEntity<String> withdraw(@RequestHeader(HttpHeaders.AUTHORIZATION) String authorizationHeader, @RequestBody MoneyTransferRequestDto request) {
if (request == null) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Request body cannot be null.");
}
try {
String jwtToken = extractJwtFromHeader(authorizationHeader);
JwtValidator.validateAndExtract(jwtToken, request.getSenderAccountId(), request.getAmount(), request.getRecipientAccountId());
log.info("Withdrawal request validated successfully");
String result = withdrawServiceApi.withdraw(request, jwtToken) ;
return ResponseEntity.status(HttpStatus.CREATED).body(result);
} catch (Exception e) {
// Log the exception (optional)
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("An error occurred while processing the request.");
}
}
private String extractJwtFromHeader(String authorizationHeader) {
if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) {
throw new IllegalArgumentException("Authorization header must start with 'Bearer '");
}
return authorizationHeader.substring(7); // Remove "Bearer " prefix
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
package com.adorsys.webank.obs.resource;

import com.adorsys.webank.obs.dto.*;
import com.adorsys.webank.obs.service.*;
import org.junit.jupiter.api.*;
import org.mockito.*;
import org.springframework.http.*;

import static org.junit.jupiter.api.Assertions.*;
import com.adorsys.webank.obs.dto.BalanceRequest;
import com.adorsys.webank.obs.security.JwtValidator;
import com.adorsys.webank.obs.service.BalanceServiceApi;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.MockitoAnnotations;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;

class BalanceRestTest {
Expand All @@ -29,15 +36,21 @@ void testGetBalance_SuccessfulResponse() {
BalanceRequest balanceRequest = new BalanceRequest();
String expectedResponse = "Balance Retrieved Successfully";

when(balanceService.getBalance(balanceRequest, jwtToken)).thenReturn(expectedResponse);
// Stub the static JwtValidator.validateAndExtract to do nothing.
try (MockedStatic<JwtValidator> jwtValidatorMock = mockStatic(JwtValidator.class)) {
jwtValidatorMock.when(() -> JwtValidator.validateAndExtract(any(), any()))
.thenAnswer(invocation -> null);

// Act
ResponseEntity<String> response = balanceRest.getBalance("Bearer " + jwtToken, balanceRequest);
when(balanceService.getBalance(balanceRequest, jwtToken)).thenReturn(expectedResponse);

// Assert
assertEquals(HttpStatus.CREATED, response.getStatusCode());
assertEquals(expectedResponse, response.getBody());
verify(balanceService, times(1)).getBalance(balanceRequest, jwtToken);
// Act
ResponseEntity<String> response = balanceRest.getBalance("Bearer " + jwtToken, balanceRequest);

// Assert
assertEquals(HttpStatus.CREATED, response.getStatusCode());
assertEquals(expectedResponse, response.getBody());
verify(balanceService, times(1)).getBalance(balanceRequest, jwtToken);
}
}

@Test
Expand All @@ -46,7 +59,7 @@ void testGetBalance_InvalidAuthorizationHeader_MissingBearer() {
String invalidAuthorizationHeader = "invalid-header";
BalanceRequest balanceRequest = new BalanceRequest();

// Act
// No need to mock the static call since the error happens before JwtValidator is invoked.
ResponseEntity<String> response = balanceRest.getBalance(invalidAuthorizationHeader, balanceRequest);

// Assert
Expand All @@ -60,7 +73,6 @@ void testGetBalance_InvalidAuthorizationHeader_NullHeader() {
// Arrange
BalanceRequest balanceRequest = new BalanceRequest();

// Act
ResponseEntity<String> response = balanceRest.getBalance(null, balanceRequest);

// Assert
Expand All @@ -75,29 +87,32 @@ void testGetBalance_ServiceThrowsException() {
String jwtToken = "valid-jwt-token";
BalanceRequest balanceRequest = new BalanceRequest();

when(balanceService.getBalance(balanceRequest, jwtToken)).thenThrow(new RuntimeException("Service Error"));
try (MockedStatic<JwtValidator> jwtValidatorMock = mockStatic(JwtValidator.class)) {
jwtValidatorMock.when(() -> JwtValidator.validateAndExtract(any(), any()))
.thenAnswer(invocation -> null);

// Act
ResponseEntity<String> response = balanceRest.getBalance("Bearer " + jwtToken, balanceRequest);
when(balanceService.getBalance(balanceRequest, jwtToken)).thenThrow(new RuntimeException("Service Error"));

// Assert
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
assertEquals("An error occurred while processing the request.", response.getBody());
verify(balanceService, times(1)).getBalance(balanceRequest, jwtToken);
// Act
ResponseEntity<String> response = balanceRest.getBalance("Bearer " + jwtToken, balanceRequest);

// Assert
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, response.getStatusCode());
assertEquals("An error occurred while processing the request.", response.getBody());
verify(balanceService, times(1)).getBalance(balanceRequest, jwtToken);
}
}

@Test
void testGetBalance_NullRequestBody() {
// Arrange
String jwtToken = "valid-jwt-token";

// Act
ResponseEntity<String> response = balanceRest.getBalance("Bearer " + jwtToken, null);

// Assert
assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
assertEquals("Request body cannot be null.", response.getBody());
verify(balanceService, never()).getBalance(any(), any());
}

}
}
Loading