From b8a669309af0ceba9f550a1555a822a3f4bcef36 Mon Sep 17 00:00:00 2001 From: ajinkyac03 Date: Mon, 28 Aug 2023 19:18:50 +0530 Subject: [PATCH 1/7] Added test cases for disconnect user api. --- .../authController/PostDisconnectTest.java | 73 +++++++++++++++++++ .../authController/Disconnect.scenarios.json | 9 +++ .../authController/PostDisconnectFixture.json | 14 ++++ 3 files changed, 96 insertions(+) create mode 100644 src/test/java/com/salessparrow/api/functional/controllers/authController/PostDisconnectTest.java create mode 100644 src/test/resources/data/controllers/authController/Disconnect.scenarios.json create mode 100644 src/test/resources/fixtures/controllers/authController/PostDisconnectFixture.json diff --git a/src/test/java/com/salessparrow/api/functional/controllers/authController/PostDisconnectTest.java b/src/test/java/com/salessparrow/api/functional/controllers/authController/PostDisconnectTest.java new file mode 100644 index 00000000..c59701c0 --- /dev/null +++ b/src/test/java/com/salessparrow/api/functional/controllers/authController/PostDisconnectTest.java @@ -0,0 +1,73 @@ +package com.salessparrow.api.functional.controllers.authController; + +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.http.MediaType; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.salessparrow.api.helper.Cleanup; +import com.salessparrow.api.helper.Common; +import com.salessparrow.api.helper.Constants; +import com.salessparrow.api.helper.FixtureData; +import com.salessparrow.api.helper.LoadFixture; +import com.salessparrow.api.helper.Scenario; +import com.salessparrow.api.helper.Setup; +import com.salessparrow.api.lib.globalConstants.CookieConstants; + +import jakarta.servlet.http.Cookie; + +@SpringBootTest +@AutoConfigureMockMvc +@WebAppConfiguration +@Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) +public class PostDisconnectTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private Common common; + + @Autowired + private LoadFixture loadFixture; + + @Test + public void testPostDisconnect() throws Exception{ + String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture( + "classpath:fixtures/controllers/authController/PostDisconnectFixture.json", + currentFunctionName); + loadFixture.perform(fixtureData); + + List testDataItems = common.loadScenariosData("classpath:data/controllers/authController/PostDisconnectScenarios.json"); + + for (Scenario testDataItem : testDataItems) { + ObjectMapper objectMapper = new ObjectMapper(); + String expectedOutput = objectMapper.writeValueAsString(testDataItem.getOutput()); + String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; + + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.post("/api/v1/auth/disconnect") + .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) + .contentType(MediaType.APPLICATION_JSON)); + + String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); + + if (resultActions.andReturn().getResponse().getStatus() != 200) { + System.out.println("Expected output: " + expectedOutput); + System.out.println("Actual output: " + actualOutput); + System.out.println("Status code: " + resultActions.andReturn().getResponse().getStatus()); + common.compareErrors(testDataItem, actualOutput); + } + } + } + +} diff --git a/src/test/resources/data/controllers/authController/Disconnect.scenarios.json b/src/test/resources/data/controllers/authController/Disconnect.scenarios.json new file mode 100644 index 00000000..6d7eed10 --- /dev/null +++ b/src/test/resources/data/controllers/authController/Disconnect.scenarios.json @@ -0,0 +1,9 @@ +{ + "testPostLogout": [ + { + "description": "Should disconnect user for valid cookie", + "input": {}, + "output": {} + } + ] +} \ No newline at end of file diff --git a/src/test/resources/fixtures/controllers/authController/PostDisconnectFixture.json b/src/test/resources/fixtures/controllers/authController/PostDisconnectFixture.json new file mode 100644 index 00000000..168cac4c --- /dev/null +++ b/src/test/resources/fixtures/controllers/authController/PostDisconnectFixture.json @@ -0,0 +1,14 @@ +{ + "testPostLogout": { + "salesforce_users": [ + { + "filepath": "classpath:fixtures/repositories/salesforceUser/ActiveSalesforceUser.json" + } + ], + "salesforce_oauth_tokens": [ + { + "filepath": "classpath:fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" + } + ] + } +} \ No newline at end of file From 8ed31b95d69a0709b2ded370298f51f45fefc26b Mon Sep 17 00:00:00 2001 From: VRDighe Date: Mon, 28 Aug 2023 16:49:44 +0530 Subject: [PATCH 2/7] Added dummy disconnect API for frontend integration --- .../api/controllers/AuthController.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/salessparrow/api/controllers/AuthController.java b/src/main/java/com/salessparrow/api/controllers/AuthController.java index 3caf84b6..9ebbceea 100644 --- a/src/main/java/com/salessparrow/api/controllers/AuthController.java +++ b/src/main/java/com/salessparrow/api/controllers/AuthController.java @@ -44,9 +44,10 @@ public class AuthController { @GetMapping("/salesforce/redirect-url") public ResponseEntity getSalesforceRedirectUrl( @Valid @ModelAttribute SalesforceRedirectUrlDto salesforceRedirectUrlDto) { - - RedirectUrlFormatterDto redirectUrlFormatterDto = redirectUrlService.getSalesforceOauthUrl(salesforceRedirectUrlDto); - + + RedirectUrlFormatterDto redirectUrlFormatterDto = redirectUrlService + .getSalesforceOauthUrl(salesforceRedirectUrlDto); + return ResponseEntity.ok().body(redirectUrlFormatterDto); } @@ -75,4 +76,14 @@ public ResponseEntity logout(HttpServletRequest request) { return ResponseEntity.ok().headers(headers).body(null); } + + @PostMapping("/disconnect") + public ResponseEntity disconnect(HttpServletRequest request) { + logger.info("User disconnect request received"); + + HttpHeaders headers = new HttpHeaders(); + headers = cookieHelper.clearUserCookie(headers); + + return ResponseEntity.noContent().headers(headers).build(); + } } From 9a2c5b921c6007240f393c3cae89edaadfe3d551 Mon Sep 17 00:00:00 2001 From: VRDighe Date: Tue, 29 Aug 2023 20:24:02 +0530 Subject: [PATCH 3/7] Added user disconnect API --- docker-compose.yml | 2 +- .../api/config/DynamoDBConfiguration.java | 49 +++++++---- .../DisconnectSalesforceUser.java | 72 ++++++++++++++++ .../disconnectUser/DisconnectUser.java | 15 ++++ .../disconnectUser/DisconnectUserFactory.java | 41 +++++++++ ...ceGetTokens.java => SalesforceTokens.java} | 50 +++++++++-- .../services/auth/DisconnectUserService.java | 32 +++++++ .../api/services/salesforce/AuthService.java | 34 ++++++-- .../authController/PostDisconnectTest.java | 31 ++----- .../authController/PostLogoutTest.java | 22 +---- .../PostSalesforceConnectTest.java | 84 +++++++++++++------ .../com/salessparrow/api/helper/Common.java | 18 ++++ .../wrappers/SalesforceTokensTest.java | 69 +++++++++++++++ .../authController/Disconnect.scenarios.json | 27 ------ .../authController/Disconnect.scenarios.json | 27 ++++++ .../SalesforceConnect.scenarios.json | 38 +++++++++ .../salesforceUser/DeletedSalesforceUser.json | 4 + .../authController/PostDisconnectFixture.json | 21 ----- .../authController/PostDisconnectFixture.json | 21 +++++ .../PostSalesforceConnectFixture.json | 12 +++ 20 files changed, 519 insertions(+), 150 deletions(-) create mode 100644 src/main/java/com/salessparrow/api/lib/crmActions/disconnectUser/DisconnectSalesforceUser.java create mode 100644 src/main/java/com/salessparrow/api/lib/crmActions/disconnectUser/DisconnectUser.java create mode 100644 src/main/java/com/salessparrow/api/lib/crmActions/disconnectUser/DisconnectUserFactory.java rename src/main/java/com/salessparrow/api/lib/salesforce/wrappers/{SalesforceGetTokens.java => SalesforceTokens.java} (57%) create mode 100644 src/main/java/com/salessparrow/api/services/auth/DisconnectUserService.java create mode 100644 src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceTokensTest.java delete mode 100644 src/test/resources/data/controllers/authController/Disconnect.scenarios.json create mode 100644 src/test/resources/fixtures/common/repositories/salesforceUser/DeletedSalesforceUser.json delete mode 100644 src/test/resources/fixtures/controllers/authController/PostDisconnectFixture.json create mode 100644 src/test/resources/fixtures/functional/controllers/authController/PostDisconnectFixture.json diff --git a/docker-compose.yml b/docker-compose.yml index a57a8efa..ef4a3d10 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -38,7 +38,7 @@ services: - AWS_ACCESS_KEY_ID=local - AWS_SECRET_ACCESS_KEY=local - AWS_REGION=us-east-1 - command: ["./mvnw", "clean", "test", "-Dtest=SalesforceTokensTest"] + command: ["./mvnw", "clean", "test", "jacoco:report"] depends_on: - dynamodb - localkms diff --git a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java index a0a442b4..b65f5f52 100644 --- a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java +++ b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java @@ -6,7 +6,6 @@ import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Bean; @@ -20,28 +19,28 @@ public class DynamoDBConfiguration { @Bean public DynamoDBMapper dynamoDBMapper() { DynamoDBMapper defaultMapper = new DynamoDBMapper(buildAmazonDynamoDB(), dynamoDBMapperConfig()); - //Override DynamoDb operations to add logging. + // Override DynamoDb operations to add logging. return new DynamoDBMapper(buildAmazonDynamoDB(), dynamoDBMapperConfig()) { @Override public T load(Class clazz, Object hashKey) { T response = null; long startTimestamp = System.currentTimeMillis(); - try{ + try { response = defaultMapper.load(clazz, hashKey); } catch (Exception e) { logger.debug("DBQuery:Load: table-{} hashKey-{}", clazz.getSimpleName(), hashKey); logger.error("DBQuery:Load: exception-{}", e); throw new RuntimeException("Error during load database operation", e); } - - long duration = System.currentTimeMillis() - startTimestamp; + + long duration = System.currentTimeMillis() - startTimestamp; logger.debug("({} ms)DBQuery:Load: table-{} hashKey-{}", duration, clazz.getSimpleName(), hashKey); return response; } @Override public void save(T object) { - long startTimestamp = System.currentTimeMillis(); + long startTimestamp = System.currentTimeMillis(); try { defaultMapper.save(object); } catch (Exception e) { @@ -50,30 +49,46 @@ public void save(T object) { throw new RuntimeException("Error during save database operation", e); } - long duration = System.currentTimeMillis() - startTimestamp; + long duration = System.currentTimeMillis() - startTimestamp; + logger.debug("({} ms)DBQuery:Save: table-{}", duration, object.getClass().getSimpleName()); + } + + @Override + public void save(T object, DynamoDBMapperConfig config) { + long startTimestamp = System.currentTimeMillis(); + try { + defaultMapper.save(object, config); + } catch (Exception e) { + logger.debug("DBQuery:Save: table-{}", object.getClass().getSimpleName()); + logger.error("DBQuery:Save: exception-{}", e); + throw new RuntimeException("Error during save database operation", e); + } + + long duration = System.currentTimeMillis() - startTimestamp; logger.debug("({} ms)DBQuery:Save: table-{}", duration, object.getClass().getSimpleName()); } - // Similarly, you can override other used methods like delete, batchSave, etc. similarly + + // Similarly, you can override other used methods like delete, batchSave, etc. + // similarly }; } @Bean public AmazonDynamoDB buildAmazonDynamoDB() { return AmazonDynamoDBClientBuilder - .standard() - .withEndpointConfiguration( - new AwsClientBuilder.EndpointConfiguration( - CoreConstants.dynamoDbUrl(), - CoreConstants.awsRegion())) - .build(); + .standard() + .withEndpointConfiguration( + new AwsClientBuilder.EndpointConfiguration( + CoreConstants.dynamoDbUrl(), + CoreConstants.awsRegion())) + .build(); } @Bean DynamoDBMapperConfig dynamoDBMapperConfig() { String prefix = CoreConstants.environment() + "_"; return new DynamoDBMapperConfig.Builder() - .withTableNameOverride(DynamoDBMapperConfig.TableNameOverride.withTableNamePrefix(prefix)) - .build(); + .withTableNameOverride(DynamoDBMapperConfig.TableNameOverride.withTableNamePrefix(prefix)) + .build(); } } - diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/disconnectUser/DisconnectSalesforceUser.java b/src/main/java/com/salessparrow/api/lib/crmActions/disconnectUser/DisconnectSalesforceUser.java new file mode 100644 index 00000000..f7c42f9a --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/crmActions/disconnectUser/DisconnectSalesforceUser.java @@ -0,0 +1,72 @@ +package com.salessparrow.api.lib.crmActions.disconnectUser; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.salessparrow.api.domain.SalesforceOauthToken; +import com.salessparrow.api.domain.User; +import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.lib.AwsKms; +import com.salessparrow.api.lib.errorLib.ErrorObject; +import com.salessparrow.api.lib.salesforce.wrappers.SalesforceTokens; +import com.salessparrow.api.repositories.SalesforceOauthTokenRepository; +import com.salessparrow.api.repositories.SalesforceUserRepository; + +/** + * DisconnectSalesforceUser class to disconnect a user from Salesforce. + */ +@Component +public class DisconnectSalesforceUser implements DisconnectUser { + + @Autowired + private SalesforceOauthTokenRepository salesforceOauthTokenRepository; + + @Autowired + private SalesforceUserRepository salesforceUserRepository; + + @Autowired + private AwsKms awsKms; + + @Autowired + private SalesforceTokens salesforceTokens; + + Logger logger = LoggerFactory.getLogger(DisconnectSalesforceUser.class); + + /** + * Disconnects a user from Salesforce by revoking the tokens and deleting the + * user data from the database. + * + * @param user + * @return void + */ + public void disconnect(User user) { + + String salesforceUserId = user.getExternalUserId(); + + logger.info("Disconnecting user from Salesforce: " + salesforceUserId); + SalesforceOauthToken salesforceOauthToken = salesforceOauthTokenRepository + .getSalesforceOauthTokenByExternalUserId(salesforceUserId); + + if (salesforceOauthToken == null) { + throw new CustomException( + new ErrorObject( + "l_ca_du_dsu_d_1", + "something_went_wrong", + "No tokens data found for this user.")); + } + + String decryptedRefreshToken = awsKms.decryptToken(salesforceOauthToken.getRefreshToken()); + + logger.info("Revoking tokens from Salesforce: " + salesforceUserId); + salesforceTokens.revokeTokens(salesforceOauthToken.getInstanceUrl(), decryptedRefreshToken); + + logger.info("Deleting tokens from database: " + salesforceUserId); + salesforceOauthTokenRepository.deleteSalesforceOauthTokenBySalesforceOauthToken(salesforceOauthToken); + + logger.info("Deleting user data from database: " + salesforceUserId); + salesforceUserRepository.removeSalesforceUserData(salesforceUserId); + } + +} diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/disconnectUser/DisconnectUser.java b/src/main/java/com/salessparrow/api/lib/crmActions/disconnectUser/DisconnectUser.java new file mode 100644 index 00000000..e6e4ffeb --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/crmActions/disconnectUser/DisconnectUser.java @@ -0,0 +1,15 @@ +package com.salessparrow.api.lib.crmActions.disconnectUser; + +import org.springframework.stereotype.Component; + +import com.salessparrow.api.domain.User; + +/** + * DisconnectUser interface for disconnecting a user from the CRM. + */ +@Component +public interface DisconnectUser { + + public void disconnect(User User); + +} diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/disconnectUser/DisconnectUserFactory.java b/src/main/java/com/salessparrow/api/lib/crmActions/disconnectUser/DisconnectUserFactory.java new file mode 100644 index 00000000..28f204a2 --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/crmActions/disconnectUser/DisconnectUserFactory.java @@ -0,0 +1,41 @@ +package com.salessparrow.api.lib.crmActions.disconnectUser; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.salessparrow.api.domain.User; +import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.lib.errorLib.ErrorObject; +import com.salessparrow.api.lib.globalConstants.UserConstants; + +/** + * Factory for disconnecting a user from the CRM based on the user kind. + */ +@Component +public class DisconnectUserFactory { + + @Autowired + private DisconnectSalesforceUser disconnectSalesforceUser; + + /** + * Disconnect a user from the CRM based on the user kind. + * + * @param user + * + * @return void + */ + public void disconnect(User user) { + + switch (user.getUserKind()) { + case UserConstants.SALESFORCE_USER_KIND: + disconnectSalesforceUser.disconnect(user); + break; + default: + throw new CustomException( + new ErrorObject( + "l_ca_du_duf_d_1", + "something_went_wrong", + "Invalid user kind.")); + } + } +} diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceGetTokens.java b/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceTokens.java similarity index 57% rename from src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceGetTokens.java rename to src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceTokens.java index 22e79738..9a2db886 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceGetTokens.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceTokens.java @@ -19,13 +19,13 @@ * SalesforceGetTokens class to get tokens from Salesforce */ @Component -public class SalesforceGetTokens { +public class SalesforceTokens { @Autowired private SalesforceConstants salesforceConstants; /** - * Get tokens from Salesforce + * Get tokens from Salesforce using the authorization code. * * @param code * @param redirectUri @@ -55,11 +55,49 @@ public HttpResponse getTokens(String code, String redirectUri) { } catch (Exception e) { List paramErrorIdentifiers = new ArrayList<>(); paramErrorIdentifiers.add("invalid_code"); - + + throw new CustomException(new ParamErrorObject( + "l_s_w_sgt_gt_1", + e.getMessage(), + paramErrorIdentifiers)); + } + return response; + } + + /** + * Revokes tokens from Salesforce using the access/refresh token. + * + * @param instanceUrl Instance URL + * @param token Refresh token + * + * @return HttpResponse + */ + public HttpResponse revokeTokens(String instanceUrl, String token) { + String salesforceRevokeTokensEndpoint = instanceUrl + salesforceConstants.revokeTokensUrl(); + + String requestBody = "token=" + token; + + System.out.println("requestBody: " + requestBody); + + Map headers = new HashMap<>(); + headers.put("content-type", "application/x-www-form-urlencoded"); + + System.out.println("headers: " + headers); + HttpResponse response = null; + try { + response = HttpClient.makePostRequest( + salesforceRevokeTokensEndpoint, + headers, + requestBody, + 10000); + } catch (Exception e) { + List paramErrorIdentifiers = new ArrayList<>(); + paramErrorIdentifiers.add("invalid_code"); + throw new CustomException(new ParamErrorObject( - "l_s_w_sgt_gt_1", - e.getMessage(), - paramErrorIdentifiers)); + "l_s_w_sgt_gt_1", + e.getMessage(), + paramErrorIdentifiers)); } return response; } diff --git a/src/main/java/com/salessparrow/api/services/auth/DisconnectUserService.java b/src/main/java/com/salessparrow/api/services/auth/DisconnectUserService.java new file mode 100644 index 00000000..ea881bb3 --- /dev/null +++ b/src/main/java/com/salessparrow/api/services/auth/DisconnectUserService.java @@ -0,0 +1,32 @@ +package com.salessparrow.api.services.auth; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.salessparrow.api.domain.User; +import com.salessparrow.api.lib.crmActions.disconnectUser.DisconnectUserFactory; + +import jakarta.servlet.http.HttpServletRequest; + +/** + * Service for disconnecting a user from the CRM. + */ +@Service +public class DisconnectUserService { + + @Autowired + private DisconnectUserFactory disconnectUserFactory; + + /** + * Disconnect a user from the CRM. + * + * @param request + * + * @return void + */ + public void disconnect(HttpServletRequest request) { + User currentUser = (User) request.getAttribute("current_user"); + disconnectUserFactory.disconnect(currentUser); + } + +} diff --git a/src/main/java/com/salessparrow/api/services/salesforce/AuthService.java b/src/main/java/com/salessparrow/api/services/salesforce/AuthService.java index 4488ba3e..dbe48f0c 100644 --- a/src/main/java/com/salessparrow/api/services/salesforce/AuthService.java +++ b/src/main/java/com/salessparrow/api/services/salesforce/AuthService.java @@ -58,7 +58,7 @@ public class AuthService { @Autowired private SalesforceOauthTokenRepository salesforceOauthTokenRepository; - + @Autowired private SalesforceOrganizationRepository salesforceOrganizationRepository; @@ -85,9 +85,7 @@ public class AuthService { public AuthServiceDto connectToSalesforce(SalesforceConnectDto params, HttpServletRequest request) { this.reqApiSource = (String) request.getAttribute("api_source"); - this.isNewUser = true; // setting default value true to this variable, this will be updated based on - // conditions in further processing - + this.isNewUser = true; // setting default value true to this variable code = params.getCode(); redirectUri = params.getRedirect_uri(); @@ -206,8 +204,12 @@ private void verifyExistingSalesforceUser() { if (salesforceUser != null) { logger.info("Salesforce User already exists"); this.salesforceUser = salesforceUser; - this.isNewUser = false; - this.decryptedSalt = localCipher.decrypt(CoreConstants.encryptionKey(), salesforceUser.getEncryptionSalt()); + + if (salesforceUser.getStatus() == SalesforceUser.Status.ACTIVE) { + logger.info("Salesforce User is active"); + this.isNewUser = false; + this.decryptedSalt = localCipher.decrypt(CoreConstants.encryptionKey(), salesforceUser.getEncryptionSalt()); + } } } @@ -237,7 +239,6 @@ private void fetchUserInfoFromSalesforce() { * @return void */ private void createSalesforceUser() { - logger.info("Creating Salesforce User"); String decryptedSalt = localCipher.generateRandomSalt(); String cookieToken = localCipher.generateRandomIv(32); @@ -245,6 +246,23 @@ private void createSalesforceUser() { String encryptedSalt = localCipher.encrypt(CoreConstants.encryptionKey(), decryptedSalt); String encryptedCookieToken = localCipher.encrypt(decryptedSalt, cookieToken); + if (this.salesforceUser != null && this.salesforceUser.getStatus() == SalesforceUser.Status.DELETED) { + logger.info("Updating Salesforce User"); + this.salesforceUser.setIdentityUrl(this.userData.getSub()); + this.salesforceUser.setExternalOrganizationId(this.userData.getOrganizationId()); + this.salesforceUser.setName(this.userData.getName()); + this.salesforceUser.setEmail(this.userData.getEmail()); + this.salesforceUser.setUserKind(UserConstants.SALESFORCE_USER_KIND); + this.salesforceUser.setCookieToken(encryptedCookieToken); + this.salesforceUser.setEncryptionSalt(encryptedSalt); + this.salesforceUser.setStatus(SalesforceUser.Status.ACTIVE); + + this.salesforceUser = salesforceUserRepository.saveSalesforceUser(this.salesforceUser); + this.decryptedSalt = decryptedSalt; + return; + } + + logger.info("Creating Salesforce User"); SalesforceUser salesforceUser = new SalesforceUser(); salesforceUser.setExternalUserId(this.userData.getUserId()); salesforceUser.setIdentityUrl(this.userData.getSub()); @@ -255,7 +273,7 @@ private void createSalesforceUser() { salesforceUser.setCookieToken(encryptedCookieToken); salesforceUser.setEncryptionSalt(encryptedSalt); salesforceUser.setStatus(SalesforceUser.Status.ACTIVE); - + this.salesforceUser = salesforceUserRepository.saveSalesforceUser(salesforceUser); this.decryptedSalt = decryptedSalt; } diff --git a/src/test/java/com/salessparrow/api/functional/controllers/authController/PostDisconnectTest.java b/src/test/java/com/salessparrow/api/functional/controllers/authController/PostDisconnectTest.java index 815d3db0..f375828f 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/authController/PostDisconnectTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/authController/PostDisconnectTest.java @@ -5,9 +5,7 @@ import static org.mockito.Mockito.when; import java.io.IOException; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -18,15 +16,12 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; -import org.springframework.core.io.Resource; -import org.springframework.core.io.ResourceLoader; import org.springframework.http.MediaType; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; -import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.dynamobee.exception.DynamobeeException; import com.salessparrow.api.helper.Cleanup; @@ -48,9 +43,6 @@ @Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) public class PostDisconnectTest { - @Autowired - private ResourceLoader resourceLoader; - @Autowired private MockMvc mockMvc; @@ -85,11 +77,12 @@ public void testPostDisconnectSuccess() throws Exception { String currentFunctionName = new Object() { }.getClass().getEnclosingMethod().getName(); FixtureData fixtureData = common.loadFixture( - "classpath:fixtures/controllers/authController/PostDisconnectFixture.json", + "classpath:fixtures/functional/controllers/authController/PostDisconnectFixture.json", currentFunctionName); loadFixture.perform(fixtureData); - List testDataItems = loadTestData(currentFunctionName); + List testDataItems = common.loadScenariosData( + "classpath:data/functional/controllers/authController/Disconnect.scenarios.json", currentFunctionName); for (Scenario testDataItem : testDataItems) { ObjectMapper objectMapper = new ObjectMapper(); @@ -119,11 +112,12 @@ public void testPostDisconnectNoTokens() throws Exception { String currentFunctionName = new Object() { }.getClass().getEnclosingMethod().getName(); FixtureData fixtureData = common.loadFixture( - "classpath:fixtures/controllers/authController/PostDisconnectFixture.json", + "classpath:fixtures/functional/controllers/authController/PostDisconnectFixture.json", currentFunctionName); loadFixture.perform(fixtureData); - List testDataItems = loadTestData(currentFunctionName); + List testDataItems = common.loadScenariosData( + "classpath:data/functional/controllers/authController/Disconnect.scenarios.json", currentFunctionName); for (Scenario testDataItem : testDataItems) { ObjectMapper objectMapper = new ObjectMapper(); @@ -145,17 +139,4 @@ public void testPostDisconnectNoTokens() throws Exception { } } } - - public List loadTestData(String key) throws IOException { - String scenariosPath = "classpath:data/controllers/authController/Disconnect.scenarios.json"; - Resource resource = resourceLoader.getResource(scenariosPath); - ObjectMapper objectMapper = new ObjectMapper(); - - Map> scenariosMap = new HashMap<>(); - scenariosMap = objectMapper.readValue(resource.getInputStream(), - new TypeReference>>() { - }); - return scenariosMap.get(key); - } - } diff --git a/src/test/java/com/salessparrow/api/functional/controllers/authController/PostLogoutTest.java b/src/test/java/com/salessparrow/api/functional/controllers/authController/PostLogoutTest.java index 95cbac03..f9f1f0fe 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/authController/PostLogoutTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/authController/PostLogoutTest.java @@ -1,9 +1,7 @@ package com.salessparrow.api.functional.controllers.authController; import java.io.IOException; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -12,15 +10,12 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Import; -import org.springframework.core.io.Resource; -import org.springframework.core.io.ResourceLoader; import org.springframework.http.MediaType; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; -import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.dynamobee.exception.DynamobeeException; import com.salessparrow.api.helper.Cleanup; @@ -39,8 +34,6 @@ @WebAppConfiguration @Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) public class PostLogoutTest { - @Autowired - private ResourceLoader resourceLoader; @Autowired private MockMvc mockMvc; @@ -77,7 +70,8 @@ public void testPostLogout() throws Exception { currentFunctionName); loadFixture.perform(fixtureData); - List testDataItems = loadTestData(currentFunctionName); + List testDataItems = common.loadScenariosData( + "classpath:data/functional/controllers/authController/Logout.scenarios.json", currentFunctionName); for (Scenario testDataItem : testDataItems) { System.out.println("Test description: " + testDataItem.getDescription()); @@ -99,16 +93,4 @@ public void testPostLogout() throws Exception { } } } - - public List loadTestData(String key) throws IOException { - String scenariosPath = "classpath:data/functional/controllers/authController/Logout.scenarios.json"; - Resource resource = resourceLoader.getResource(scenariosPath); - ObjectMapper objectMapper = new ObjectMapper(); - - Map> scenariosMap = new HashMap<>(); - scenariosMap = objectMapper.readValue(resource.getInputStream(), - new TypeReference>>() { - }); - return scenariosMap.get(key); - } } diff --git a/src/test/java/com/salessparrow/api/functional/controllers/authController/PostSalesforceConnectTest.java b/src/test/java/com/salessparrow/api/functional/controllers/authController/PostSalesforceConnectTest.java index 00e2a5c6..a40dd44d 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/authController/PostSalesforceConnectTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/authController/PostSalesforceConnectTest.java @@ -12,9 +12,7 @@ import static org.mockito.Mockito.when; import java.io.IOException; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -23,15 +21,12 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; -import org.springframework.core.io.Resource; -import org.springframework.core.io.ResourceLoader; import org.springframework.http.MediaType; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; -import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.dynamobee.exception.DynamobeeException; import com.salessparrow.api.helper.Cleanup; @@ -50,8 +45,6 @@ @WebAppConfiguration @Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) public class PostSalesforceConnectTest { - @Autowired - private ResourceLoader resourceLoader; @Autowired private MockMvc mockMvc; @@ -96,7 +89,8 @@ public void testPostSalesforceConnectSignup() throws Exception { String currentFunctionName = new Object() { }.getClass().getEnclosingMethod().getName(); - List testDataItems = loadTestData(currentFunctionName); + List testDataItems = common.loadScenariosData( + "classpath:data/functional/controllers/authController/SalesforceConnect.scenarios.json", currentFunctionName); for (Scenario testDataItem : testDataItems) { System.out.println("Test description: " + testDataItem.getDescription()); @@ -108,8 +102,10 @@ public void testPostSalesforceConnectSignup() throws Exception { HttpResponse getIdentityMockRes = new HttpResponse(); getIdentityMockRes.setResponseBody(objectMapper.writeValueAsString(testDataItem.getMocks().get("getIdentity"))); - when(mockGetTokens.getTokens(anyString(), anyString())).thenReturn(getTokensMockRes); - when(mockGetIdentity.getUserIdentity(anyString(), anyString())).thenReturn(getIdentityMockRes); + when(mockGetTokens.getTokens(anyString(), + anyString())).thenReturn(getTokensMockRes); + when(mockGetIdentity.getUserIdentity(anyString(), + anyString())).thenReturn(getIdentityMockRes); ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.post("/api/v1/auth/salesforce/connect") .content(objectMapper.writeValueAsString(testDataItem.getInput().get("body"))) @@ -120,11 +116,13 @@ public void testPostSalesforceConnectSignup() throws Exception { System.out.println("actualOutput: " + actualOutput); if (resultActions.andReturn().getResponse().getStatus() == 200) { - assertEquals(objectMapper.writeValueAsString(testDataItem.getOutput()), actualOutput); + assertEquals(objectMapper.writeValueAsString(testDataItem.getOutput()), + actualOutput); } else if (resultActions.andReturn().getResponse().getStatus() == 400) { common.compareErrors(testDataItem, actualOutput); } else { - assertEquals(testDataItem.getOutput().get("http_code"), resultActions.andReturn().getResponse().getStatus()); + assertEquals(testDataItem.getOutput().get("http_code"), + resultActions.andReturn().getResponse().getStatus()); } } } @@ -139,7 +137,8 @@ public void testPostSalesforceConnectLogin() throws Exception { currentFunctionName); loadFixture.perform(fixtureData); - List testDataItems = loadTestData(currentFunctionName); + List testDataItems = common.loadScenariosData( + "classpath:data/functional/controllers/authController/SalesforceConnect.scenarios.json", currentFunctionName); for (Scenario testDataItem : testDataItems) { System.out.println("Test description: " + testDataItem.getDescription()); @@ -148,7 +147,8 @@ public void testPostSalesforceConnectLogin() throws Exception { HttpResponse getTokensMockRes = new HttpResponse(); getTokensMockRes.setResponseBody(objectMapper.writeValueAsString(testDataItem.getMocks().get("getTokens"))); - when(mockGetTokens.getTokens(anyString(), anyString())).thenReturn(getTokensMockRes); + when(mockGetTokens.getTokens(anyString(), + anyString())).thenReturn(getTokensMockRes); ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.post("/api/v1/auth/salesforce/connect") .content(objectMapper.writeValueAsString(testDataItem.getInput().get("body"))) @@ -158,28 +158,62 @@ public void testPostSalesforceConnectLogin() throws Exception { String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); if (resultActions.andReturn().getResponse().getStatus() == 200) { - assertEquals(objectMapper.writeValueAsString(testDataItem.getOutput()), actualOutput); + assertEquals(objectMapper.writeValueAsString(testDataItem.getOutput()), + actualOutput); verify(mockGetTokens, times(1)).getTokens(anyString(), anyString()); verify(mockGetIdentity, times(0)).getUserIdentity(anyString(), anyString()); } else if (resultActions.andReturn().getResponse().getStatus() == 400) { common.compareErrors(testDataItem, actualOutput); } else { - assertEquals(testDataItem.getOutput().get("http_code"), resultActions.andReturn().getResponse().getStatus()); + assertEquals(testDataItem.getOutput().get("http_code"), + resultActions.andReturn().getResponse().getStatus()); } } } - public List loadTestData(String key) throws IOException { - String scenariosPath = "classpath:data/functional/controllers/authController/SalesforceConnect.scenarios.json"; - Resource resource = resourceLoader.getResource(scenariosPath); - ObjectMapper objectMapper = new ObjectMapper(); + @Test + public void testPostSalesforceConnectDisconnectedUserSignup() throws Exception { + String currentFunctionName = new Object() { + }.getClass().getEnclosingMethod().getName(); + + FixtureData fixtureData = common.loadFixture( + "classpath:fixtures/functional/controllers/authController/PostSalesforceConnectFixture.json", + currentFunctionName); + loadFixture.perform(fixtureData); + + List testDataItems = common.loadScenariosData( + "classpath:data/functional/controllers/authController/SalesforceConnect.scenarios.json", currentFunctionName); + for (Scenario testDataItem : testDataItems) { + System.out.println( + "testPostSalesforceConnectDisconnectedUserSignup Test description: " + testDataItem.getDescription()); + ObjectMapper objectMapper = new ObjectMapper(); + + HttpResponse getTokensMockRes = new HttpResponse(); + getTokensMockRes.setResponseBody(objectMapper.writeValueAsString(testDataItem.getMocks().get("getTokens"))); + + HttpResponse getIdentityMockRes = new HttpResponse(); + getIdentityMockRes.setResponseBody(objectMapper.writeValueAsString(testDataItem.getMocks().get("getIdentity"))); + + when(mockGetTokens.getTokens(anyString(), anyString())).thenReturn(getTokensMockRes); + when(mockGetIdentity.getUserIdentity(anyString(), anyString())).thenReturn(getIdentityMockRes); + + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.post("/api/v1/auth/salesforce/connect") + .content(objectMapper.writeValueAsString(testDataItem.getInput().get("body"))) + .accept(MediaType.APPLICATION_JSON).characterEncoding("UTF-8") + .contentType(MediaType.APPLICATION_JSON)); + + String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); + System.out.println("actualOutput: " + actualOutput); - Map> scenariosMap = new HashMap<>(); - scenariosMap = objectMapper.readValue(resource.getInputStream(), - new TypeReference>>() { - }); - return scenariosMap.get(key); + if (resultActions.andReturn().getResponse().getStatus() == 200) { + assertEquals(objectMapper.writeValueAsString(testDataItem.getOutput()), actualOutput); + } else if (resultActions.andReturn().getResponse().getStatus() == 400) { + common.compareErrors(testDataItem, actualOutput); + } else { + assertEquals(testDataItem.getOutput().get("http_code"), resultActions.andReturn().getResponse().getStatus()); + } + } } } diff --git a/src/test/java/com/salessparrow/api/helper/Common.java b/src/test/java/com/salessparrow/api/helper/Common.java index 45ff3eda..8cb79f25 100644 --- a/src/test/java/com/salessparrow/api/helper/Common.java +++ b/src/test/java/com/salessparrow/api/helper/Common.java @@ -55,6 +55,24 @@ public List loadScenariosData(String location) throws IOException { }); } + /** + * Load the test scenario data from the given location and key. + * + * @param location - location of the test data + * @param key - key of the test data + * @return List + * @throws IOException + */ + public List loadScenariosData(String location, String key) throws IOException { + Resource resource = resourceLoader.getResource(location); + ObjectMapper objectMapper = new ObjectMapper(); + Map> scenarioMap = new HashMap<>(); + scenarioMap = objectMapper.readValue(resource.getInputStream(), + new TypeReference>>() { + }); + return scenarioMap.get(key); + } + /** * Compare the errors from the test data with the actual errors. * diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceTokensTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceTokensTest.java new file mode 100644 index 00000000..da1054e3 --- /dev/null +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceTokensTest.java @@ -0,0 +1,69 @@ +package com.salessparrow.api.unit.lib.salesforce.wrappers; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyMap; +import static org.mockito.ArgumentMatchers.anyString; + +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; + +import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.lib.httpLib.HttpClient; +import com.salessparrow.api.lib.httpLib.HttpClient.HttpResponse; +import com.salessparrow.api.lib.salesforce.wrappers.SalesforceTokens; + +@SpringBootTest +@Import({ SalesforceTokens.class }) +public class SalesforceTokensTest { + + @MockBean + private HttpClient httpClientMock; + + @Autowired + private SalesforceTokens salesforceTokens; + + @Test + public void testRevokeTokensSuccess() throws Exception { + MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); + + String instanceUrl = "https://example.com"; + String refreshToken = "your-refresh-token"; + + HttpResponse expectedResponse = new HttpResponse(); + expectedResponse.setResponseBody(""); + + httpClientMockedStatic.when(() -> HttpClient.makePostRequest(anyString(), anyMap(), any(), anyInt())) + .thenReturn(expectedResponse); + + HttpResponse response = salesforceTokens.revokeTokens(instanceUrl, refreshToken); + + assertEquals(expectedResponse, response); + + httpClientMockedStatic.close(); + } + + @Test + public void testRevokeTokensFailure() throws Exception { + MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); + + String instanceUrl = "https://example.com"; + String refreshToken = "invalid-refresh-token"; + + httpClientMockedStatic.when(() -> HttpClient.makePostRequest(anyString(), anyMap(), any(), anyInt())) + .thenThrow(new RuntimeException("Invalid refresh token")); + + assertThrows(CustomException.class, () -> { + salesforceTokens.revokeTokens(instanceUrl, refreshToken); + }); + httpClientMockedStatic.close(); + } + +} diff --git a/src/test/resources/data/controllers/authController/Disconnect.scenarios.json b/src/test/resources/data/controllers/authController/Disconnect.scenarios.json deleted file mode 100644 index a420a653..00000000 --- a/src/test/resources/data/controllers/authController/Disconnect.scenarios.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "testPostDisconnectSuccess": [ - { - "description": "Should disconnect user for valid cookie", - "input": {}, - "mocks": { - "revokeTokens": {} - }, - "output": { - "success": true - } - } - ], - "testPostDisconnectNoTokens": [ - { - "description": "Should return error if no data present ", - "input": {}, - "mocks": { - "revokeTokens": {} - }, - "output": { - "http_code": 500, - "code": "INTERNAL_SERVER_ERROR" - } - } - ] -} \ No newline at end of file diff --git a/src/test/resources/data/functional/controllers/authController/Disconnect.scenarios.json b/src/test/resources/data/functional/controllers/authController/Disconnect.scenarios.json index e69de29b..07eca2cc 100644 --- a/src/test/resources/data/functional/controllers/authController/Disconnect.scenarios.json +++ b/src/test/resources/data/functional/controllers/authController/Disconnect.scenarios.json @@ -0,0 +1,27 @@ +{ + "testPostDisconnectSuccess": [ + { + "description": "Should disconnect user for valid cookie", + "input": {}, + "mocks": { + "revokeTokens": {} + }, + "output": { + "success": true + } + } + ], + "testPostDisconnectNoTokens": [ + { + "description": "Should return error if no data present ", + "input": {}, + "mocks": { + "revokeTokens": {} + }, + "output": { + "http_code": 500, + "code": "INTERNAL_SERVER_ERROR" + } + } + ] +} \ No newline at end of file diff --git a/src/test/resources/data/functional/controllers/authController/SalesforceConnect.scenarios.json b/src/test/resources/data/functional/controllers/authController/SalesforceConnect.scenarios.json index 2a7b8c90..4bd25546 100644 --- a/src/test/resources/data/functional/controllers/authController/SalesforceConnect.scenarios.json +++ b/src/test/resources/data/functional/controllers/authController/SalesforceConnect.scenarios.json @@ -160,5 +160,43 @@ "message": "Forbidden API request. You do not have the necessary permissions." } } + ], + "testPostSalesforceConnectDisconnectedUserSignup":[ + { + "description": "Should return the current user for valid code and redirect_uri while signup of disconnected user", + "input": { + "body": { + "code": "1234567", + "redirect_uri": "http://localhost:3000" + } + }, + "mocks": { + "getTokens": { + "access_token": "xyz", + "refresh_token": "xyz", + "signature": "xyz", + "scope": "xyz", + "id_token": "xyz", + "instance_url": "xyz", + "id": "https://test.salesforce.com/id/000Org-id/00112233445566AAA15", + "token_type": "Bearer", + "issued_at": "1690520247198" + }, + "getIdentity": { + "sub": "https://test.salesforce.com/id/000Org-id/00112233445566AAA15", + "user_id": "00112233445566AAA15", + "organization_id": "000Org-id", + "name": "Test User", + "email": "test@test.com" + } + }, + "output": { + "current_user": { + "id": "SALESFORCE-00112233445566AAA15", + "name": "Test User", + "email": "test@test.com" + } + } + } ] } \ No newline at end of file diff --git a/src/test/resources/fixtures/common/repositories/salesforceUser/DeletedSalesforceUser.json b/src/test/resources/fixtures/common/repositories/salesforceUser/DeletedSalesforceUser.json new file mode 100644 index 00000000..6c9b1d39 --- /dev/null +++ b/src/test/resources/fixtures/common/repositories/salesforceUser/DeletedSalesforceUser.json @@ -0,0 +1,4 @@ +{ + "externalUserId": "00112233445566AAA15", + "status": "DELETED" +} \ No newline at end of file diff --git a/src/test/resources/fixtures/controllers/authController/PostDisconnectFixture.json b/src/test/resources/fixtures/controllers/authController/PostDisconnectFixture.json deleted file mode 100644 index 5e168fa1..00000000 --- a/src/test/resources/fixtures/controllers/authController/PostDisconnectFixture.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "testPostDisconnectSuccess": { - "salesforce_users": [ - { - "filepath": "classpath:fixtures/repositories/salesforceUser/ActiveSalesforceUser.json" - } - ], - "salesforce_oauth_tokens": [ - { - "filepath": "classpath:fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" - } - ] - }, - "testPostDisconnectNoTokens": { - "salesforce_users": [ - { - "filepath": "classpath:fixtures/repositories/salesforceUser/ActiveSalesforceUser.json" - } - ] - } -} \ No newline at end of file diff --git a/src/test/resources/fixtures/functional/controllers/authController/PostDisconnectFixture.json b/src/test/resources/fixtures/functional/controllers/authController/PostDisconnectFixture.json new file mode 100644 index 00000000..4cb807ce --- /dev/null +++ b/src/test/resources/fixtures/functional/controllers/authController/PostDisconnectFixture.json @@ -0,0 +1,21 @@ +{ + "testPostDisconnectSuccess": { + "salesforce_users": [ + { + "filepath": "classpath:fixtures/common/repositories/salesforceUser/ActiveSalesforceUser.json" + } + ], + "salesforce_oauth_tokens": [ + { + "filepath": "classpath:fixtures/common/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" + } + ] + }, + "testPostDisconnectNoTokens": { + "salesforce_users": [ + { + "filepath": "classpath:fixtures/common/repositories/salesforceUser/ActiveSalesforceUser.json" + } + ] + } +} \ No newline at end of file diff --git a/src/test/resources/fixtures/functional/controllers/authController/PostSalesforceConnectFixture.json b/src/test/resources/fixtures/functional/controllers/authController/PostSalesforceConnectFixture.json index d81e1ddd..e616d089 100644 --- a/src/test/resources/fixtures/functional/controllers/authController/PostSalesforceConnectFixture.json +++ b/src/test/resources/fixtures/functional/controllers/authController/PostSalesforceConnectFixture.json @@ -21,5 +21,17 @@ "filepath": "classpath:fixtures/common/repositories/salesforceOrganization/DeletedSalesforceOrganization.json" } ] + }, + "testPostSalesforceConnectDisconnectedUserSignup": { + "salesforce_users": [ + { + "filepath": "classpath:fixtures/common/repositories/salesforceUser/DeletedSalesforceUser.json" + } + ], + "salesforce_organizations": [ + { + "filepath": "classpath:fixtures/common/repositories/salesforceOrganization/ActiveSalesforceOrganization.json" + } + ] } } \ No newline at end of file From 66e69d31bc22b3e81bdcfceba36835506e284b74 Mon Sep 17 00:00:00 2001 From: ajinkyac03 Date: Wed, 30 Aug 2023 13:04:24 +0530 Subject: [PATCH 4/7] Removed unnecessary loggers. --- .../com/salessparrow/api/config/DynamoDBConfiguration.java | 1 - .../crmActions/disconnectUser/DisconnectSalesforceUser.java | 2 +- .../api/lib/salesforce/wrappers/SalesforceTokens.java | 5 +---- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java index 8804afb1..01f7f98d 100644 --- a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java +++ b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java @@ -70,7 +70,6 @@ public void save(T object, DynamoDBMapperConfig config) { } // Similarly, you can override other used methods like delete, batchSave, etc. - // similarly }; } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/disconnectUser/DisconnectSalesforceUser.java b/src/main/java/com/salessparrow/api/lib/crmActions/disconnectUser/DisconnectSalesforceUser.java index f7c42f9a..c3f7ec92 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/disconnectUser/DisconnectSalesforceUser.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/disconnectUser/DisconnectSalesforceUser.java @@ -32,7 +32,7 @@ public class DisconnectSalesforceUser implements DisconnectUser { @Autowired private SalesforceTokens salesforceTokens; - Logger logger = LoggerFactory.getLogger(DisconnectSalesforceUser.class); + private static final Logger logger = LoggerFactory.getLogger(DisconnectSalesforceUser.class); /** * Disconnects a user from Salesforce by revoking the tokens and deleting the diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceTokens.java b/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceTokens.java index 9a2db886..377a7577 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceTokens.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceTokens.java @@ -16,7 +16,7 @@ import java.util.List; /** - * SalesforceGetTokens class to get tokens from Salesforce + * SalesforceTokens class to handle token operations with Salesforce */ @Component public class SalesforceTokens { @@ -77,12 +77,9 @@ public HttpResponse revokeTokens(String instanceUrl, String token) { String requestBody = "token=" + token; - System.out.println("requestBody: " + requestBody); - Map headers = new HashMap<>(); headers.put("content-type", "application/x-www-form-urlencoded"); - System.out.println("headers: " + headers); HttpResponse response = null; try { response = HttpClient.makePostRequest( From 0b109ae63736aafdba5b98cfb63778151a6a4bb0 Mon Sep 17 00:00:00 2001 From: ajinkyac03 Date: Wed, 30 Aug 2023 14:15:41 +0530 Subject: [PATCH 5/7] Updated revokeTokens error. --- .../lib/salesforce/wrappers/SalesforceTokens.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceTokens.java b/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceTokens.java index 377a7577..95fe9a5b 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceTokens.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceTokens.java @@ -9,6 +9,7 @@ import com.salessparrow.api.config.CoreConstants; import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.lib.errorLib.ErrorObject; import com.salessparrow.api.lib.errorLib.ParamErrorObject; import com.salessparrow.api.lib.globalConstants.SalesforceConstants; import com.salessparrow.api.lib.httpLib.HttpClient; @@ -88,13 +89,11 @@ public HttpResponse revokeTokens(String instanceUrl, String token) { requestBody, 10000); } catch (Exception e) { - List paramErrorIdentifiers = new ArrayList<>(); - paramErrorIdentifiers.add("invalid_code"); - - throw new CustomException(new ParamErrorObject( - "l_s_w_sgt_gt_1", - e.getMessage(), - paramErrorIdentifiers)); + throw new CustomException( + new ErrorObject( + "l_s_w_srt_rt_1", + "something_went_wrong", + e.getMessage())); } return response; } From 336619b2cb0cc3c70abb4230113537059f735782 Mon Sep 17 00:00:00 2001 From: ajinkyac03 Date: Wed, 30 Aug 2023 14:39:29 +0530 Subject: [PATCH 6/7] Removed requiresSecure check. --- .../java/com/salessparrow/api/config/SecurityConfig.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/main/java/com/salessparrow/api/config/SecurityConfig.java b/src/main/java/com/salessparrow/api/config/SecurityConfig.java index 02e7dfc7..353ab45a 100644 --- a/src/main/java/com/salessparrow/api/config/SecurityConfig.java +++ b/src/main/java/com/salessparrow/api/config/SecurityConfig.java @@ -70,12 +70,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti ); - // Enable for production and staging - if (!CoreConstants.isDevEnvironment() && !CoreConstants.isTestEnvironment() && - !CoreConstants.isLocalTestEnvironment()) { - // All requests must be secure - http.requiresChannel(channel -> channel.anyRequest().requiresSecure()); - } + // http rediect to https is handled by the reverse proxy server (nginx). So no need to handle it here. return http.build(); } From b4f183373d3d05166bd5ea2c615eba06102f7967 Mon Sep 17 00:00:00 2001 From: VRDighe Date: Wed, 30 Aug 2023 15:25:11 +0530 Subject: [PATCH 7/7] Removed test log --- src/main/java/com/salessparrow/api/lib/AwsKms.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/salessparrow/api/lib/AwsKms.java b/src/main/java/com/salessparrow/api/lib/AwsKms.java index e7470eed..527b4bf3 100644 --- a/src/main/java/com/salessparrow/api/lib/AwsKms.java +++ b/src/main/java/com/salessparrow/api/lib/AwsKms.java @@ -78,7 +78,6 @@ public String decryptToken(String encryptedToken) { try { result = kmsClient.decrypt(request); } catch (Exception e) { - System.out.println(e.getMessage()); throw new CustomException( new ErrorObject( "l_ak_dt_1",