From 0ed4bfecb4d03185c4e20f4d44558e62dcb00d9f Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Tue, 22 Aug 2023 11:16:42 +0530 Subject: [PATCH 001/195] use secrets from secret manager --- .gitignore | 1 + pom.xml | 8 +- secrets.sample.json | 16 ++ set_env_vars-sample.sh | 25 --- set_testing_env_vars-sample.sh | 25 --- .../com/salessparrow/api/SalesSparrowApi.java | 1 - .../api/config/CoreConstants.java | 47 ++--- .../api/config/DynamoDBConfiguration.java | 1 - .../DynamoDbTableNameConstants.java | 10 +- .../lib/globalConstants/SecretConstants.java | 162 ++++++++++++++++++ 10 files changed, 217 insertions(+), 79 deletions(-) create mode 100644 secrets.sample.json create mode 100644 src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java diff --git a/.gitignore b/.gitignore index 4bee3dd4..75d35479 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,7 @@ build/ ### Environment Variables ### .env set*_env_vars.sh +secrets.json ### Logs files ### *.log diff --git a/pom.xml b/pom.xml index 17f637e0..54fce04e 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ com.salessparrow salessparrow-api - 0.0.1 + 0.1.0 api Salessparrow apis @@ -128,6 +128,12 @@ 0.6 + + com.amazonaws.secretsmanager + aws-secretsmanager-caching-java + 2.0.0 + + diff --git a/secrets.sample.json b/secrets.sample.json new file mode 100644 index 00000000..70d77fa8 --- /dev/null +++ b/secrets.sample.json @@ -0,0 +1,16 @@ +{ + "ENCRYPTION_KEY": "", + "API_COOKIE_SECRET": "", + "AWS_IAM_ACCESS_KEY_ID": "", + "AWS_IAM_SECRET_ACCESS_KEY": "", + "AWS_IAM_REGION": "", + "KMS_KEY_ID": "", + "SALESFORCE_CLIENT_ID": "", + "SALESFORCE_CLIENT_SECRET": "", + "SALESFORCE_AUTH_URL": "", + "SALESFORCE_WHITELISTED_REDIRECT_URIS": "", + "MEMCACHED_CACHE_HOST": "", + "MEMCACHED_CACHE_PORT": "", + "LOG_LEVEL": "", + "DYNAMO_DB_URL": "" +} \ No newline at end of file diff --git a/set_env_vars-sample.sh b/set_env_vars-sample.sh index fa928f46..3acf15b2 100644 --- a/set_env_vars-sample.sh +++ b/set_env_vars-sample.sh @@ -1,32 +1,7 @@ # Application export ENVIRONMENT='development' -export SALESFORCE_WHITELISTED_REDIRECT_URIS='' - -# Authentication -export ENCRYPTION_KEY='1234567890' -export API_COOKIE_SECRET='1234567890' # AWS export AWS_IAM_ACCESS_KEY_ID='' export AWS_IAM_SECRET_ACCESS_KEY='' export AWS_IAM_REGION='' -export KMS_KEY_ID='' - -# Dynamo DB -export DYNAMO_DB_URL='http://dynamodb:8000' - -# Salesforce -export SALESFORCE_AUTH_URL='https://test.salesforce.com' -export SALESFORCE_CLIENT_ID='' -export SALESFORCE_CLIENT_SECRET='' - -# Memcached -export MEMCACHED_CACHE_HOST='localhost' -export MEMCACHED_CACHE_PORT='11211' - -# Error Email -export ERROR_MAIL_FROM='' -export ERROR_MAIL_TO='' - -# Logging -export LOG_LEVEL='info' diff --git a/set_testing_env_vars-sample.sh b/set_testing_env_vars-sample.sh index 929c6d4b..37f6a1b2 100644 --- a/set_testing_env_vars-sample.sh +++ b/set_testing_env_vars-sample.sh @@ -1,32 +1,7 @@ # Application export ENVIRONMENT='test' -export SALESFORCE_WHITELISTED_REDIRECT_URIS='' - -# Authentication -export ENCRYPTION_KEY='1234567890' -export API_COOKIE_SECRET='1234567890' # AWS export AWS_IAM_ACCESS_KEY_ID='accessKeyId' export AWS_IAM_SECRET_ACCESS_KEY='secretAccessKey' export AWS_IAM_REGION='region' -export KMS_KEY_ID='' - -# Database -export DYNAMO_DB_URL='http://localhost:8000' - -# Salesforce -export SALESFORCE_CLIENT_ID='' -export SALESFORCE_CLIENT_SECRET='' -export SALESFORCE_AUTH_URL='' - -# Memcached -export MEMCACHED_CACHE_HOST='localhost' -export MEMCACHED_CACHE_PORT='11211' - -# Error Email -export ERROR_MAIL_FROM='' -export ERROR_MAIL_TO='' - -# Logging -export LOG_LEVEL='info' \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/SalesSparrowApi.java b/src/main/java/com/salessparrow/api/SalesSparrowApi.java index 63981bc6..e58a080b 100644 --- a/src/main/java/com/salessparrow/api/SalesSparrowApi.java +++ b/src/main/java/com/salessparrow/api/SalesSparrowApi.java @@ -5,7 +5,6 @@ import org.springframework.cache.annotation.EnableCaching; import org.springframework.scheduling.annotation.EnableAsync; - @SpringBootApplication @EnableCaching // This enables caching @EnableAsync // This enables asynchronous processing in Spring diff --git a/src/main/java/com/salessparrow/api/config/CoreConstants.java b/src/main/java/com/salessparrow/api/config/CoreConstants.java index b381cbe6..78aa19e1 100644 --- a/src/main/java/com/salessparrow/api/config/CoreConstants.java +++ b/src/main/java/com/salessparrow/api/config/CoreConstants.java @@ -1,20 +1,27 @@ package com.salessparrow.api.config; +import com.salessparrow.api.lib.globalConstants.SecretConstants; + /** * Class to get the environment variables. */ public class CoreConstants { + /* Start: Env variables required before spring application context is initialized */ - public static String encryptionKey() { - return System.getenv("ENCRYPTION_KEY"); + public static String environment() { + return System.getenv("ENVIRONMENT"); } - public static String apiCookieSecret() { - return System.getenv("API_COOKIE_SECRET"); + public static String awsAccessKeyId() { + return System.getenv("AWS_IAM_ACCESS_KEY_ID"); } - public static String environment() { - return System.getenv("ENVIRONMENT"); + public static String awsSecretAccessKey() { + return System.getenv("AWS_IAM_SECRET_ACCESS_KEY"); + } + + public static String awsRegion() { + return System.getenv("AWS_IAM_REGION"); } public static Boolean isDevEnvironment() { @@ -25,32 +32,30 @@ public static Boolean isTestEnvironment() { return environment().equals("test"); } - public static String awsAccessKeyId() { - return System.getenv("AWS_IAM_ACCESS_KEY_ID"); - } + /* End: Env variables required before spring application context is initialized */ - public static String awsSecretAccessKey() { - return System.getenv("AWS_IAM_SECRET_ACCESS_KEY"); + public static String encryptionKey() { + return SecretConstants.encryptionKey(); } - public static String awsRegion() { - return System.getenv("AWS_IAM_REGION"); + public static String apiCookieSecret() { + return SecretConstants.apiCookieSecret(); } public static String kmsKeyId() { - return System.getenv("KMS_KEY_ID"); + return SecretConstants.kmsKeyId(); } public static String salesforceAuthUrl() { - return System.getenv("SALESFORCE_AUTH_URL"); + return SecretConstants.salesforceAuthUrl(); } public static String salesforceClientId() { - return System.getenv("SALESFORCE_CLIENT_ID"); + return SecretConstants.salesforceClientId(); } public static String salesforceClientSecret() { - return System.getenv("SALESFORCE_CLIENT_SECRET"); + return SecretConstants.salesforceClientSecret(); } /** @@ -59,7 +64,7 @@ public static String salesforceClientSecret() { * @return String */ public static String memcachedAddress() { - return System.getenv("MEMCACHED_CACHE_HOST") + ":" + System.getenv("MEMCACHED_CACHE_PORT"); + return SecretConstants.memcachedHost() + ":" + SecretConstants.memcachedPort(); } /** @@ -69,7 +74,7 @@ public static String memcachedAddress() { * @return String[] */ public static String[] getWhitelistedRedirectUris() { - String redirectUrisJson = System.getenv("SALESFORCE_WHITELISTED_REDIRECT_URIS"); + String redirectUrisJson = SecretConstants.salesforceWhitelistedRedirectUris(); return redirectUrisJson.split(","); } @@ -80,7 +85,7 @@ public static String[] getWhitelistedRedirectUris() { * @return String */ public static String errorEmailFrom() { - return System.getenv("ERROR_MAIL_FROM"); + return SecretConstants.errorEmailFrom(); } /** @@ -89,7 +94,7 @@ public static String errorEmailFrom() { * @return String */ public static String errorEmailTo() { - return System.getenv("ERROR_MAIL_TO"); + return SecretConstants.errorEmailTo(); } } diff --git a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java index 16052285..42b8fd13 100644 --- a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java +++ b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java @@ -19,7 +19,6 @@ public class DynamoDBConfiguration { Logger logger = LoggerFactory.getLogger(DynamoDBConfiguration.class); - @Value("${aws.dynamodb.endpoint}") private String dynamodbEndpoint; diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/DynamoDbTableNameConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/DynamoDbTableNameConstants.java index 3a0512b9..51f9013e 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/DynamoDbTableNameConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/DynamoDbTableNameConstants.java @@ -1,18 +1,18 @@ package com.salessparrow.api.lib.globalConstants; +import com.salessparrow.api.config.CoreConstants; + /** * This class contains the names of the DynamoDB tables used by the application. */ public class DynamoDbTableNameConstants { - private static String environment = System.getenv("ENVIRONMENT"); - /** * Returns the name of the table that contains the Salesforce organizations. * @return */ public static String salesforceOrganizationsTableName() { - return environment + "_salesforce_organizations"; + return CoreConstants.environment() + "_salesforce_organizations"; } /** @@ -20,7 +20,7 @@ public static String salesforceOrganizationsTableName() { * @return */ public static String salesforceOauthTokensTableName() { - return environment + "_salesforce_oauth_tokens"; + return CoreConstants.environment() + "_salesforce_oauth_tokens"; } /** @@ -28,6 +28,6 @@ public static String salesforceOauthTokensTableName() { * @return */ public static String salesforceUsersTableName() { - return environment + "_salesforce_users"; + return CoreConstants.environment() + "_salesforce_users"; } } diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java new file mode 100644 index 00000000..c60bdb5e --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java @@ -0,0 +1,162 @@ +package com.salessparrow.api.lib.globalConstants; + +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; + +import com.amazonaws.secretsmanager.caching.SecretCache; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.salessparrow.api.config.CoreConstants; +import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.lib.errorLib.ErrorObject; + +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; +import software.amazon.awssdk.services.secretsmanager.SecretsManagerClientBuilder; + +/** + * Class to get the environment variables from aws secret manager. + */ +public class SecretConstants { + + /* Secret manager configuration start */ + + /** + * This is the credentials that are going to be used to access the secrets manager. + */ + public static AwsBasicCredentials credentials = AwsBasicCredentials.create( + CoreConstants.awsAccessKeyId(), + CoreConstants.awsSecretAccessKey()); + + /** + * This is the builder that is going to be used to access the secrets manager. + */ + public static SecretsManagerClientBuilder secretsManagerClientBuilder = SecretsManagerClient.builder() + .region(Region.of(CoreConstants.awsRegion())) + .credentialsProvider(() -> credentials); + + /** + * This method returns the secrets from the secrets manager. + * @return + * @throws JsonProcessingException + * @throws JsonMappingException + */ + public static String getSecret(String key) { + String secretJson = ""; + + if (CoreConstants.isDevEnvironment()) { + secretJson = getLocalEnvVars(); + } else { + SecretCache cache = new SecretCache(secretsManagerClientBuilder); + secretJson = cache.getSecretString(getSecretId()); + cache.close(); + } + + ObjectMapper objectMapper = new ObjectMapper(); + String specificValue = ""; + try { + JsonNode jsonNode = objectMapper.readTree(secretJson); + specificValue = jsonNode.get(key).asText(); + } catch (Exception e) { + throw new CustomException( + new ErrorObject( + "l_gc_s_gs_1", + "something_went_wrong", + e.getMessage())); + } + + return specificValue; + } + + /** + * This method returns the secret id that is going to be used to access the secrets manager. + * @return + */ + private static String getSecretId() { + return "ai-sales-sparrow-api-" + CoreConstants.environment(); + } + + /* Secret manager configuration function end */ + + /* Secrets start */ + + public static String encryptionKey() { + return getSecret("ENCRYPTION_KEY"); + } + + public static String apiCookieSecret() { + return getSecret("API_COOKIE_SECRET"); + } + + public static String kmsKeyId() { + return getSecret("KMS_KEY_ID"); + } + + public static String salesforceAuthUrl() { + return getSecret("SALESFORCE_AUTH_URL"); + } + + public static String salesforceClientId() { + return getSecret("SALESFORCE_CLIENT_ID"); + } + + public static String salesforceClientSecret() { + return getSecret("SALESFORCE_CLIENT_SECRET"); + } + + public static String memcachedHost() { + return getSecret("MEMCACHED_HOST"); + } + + public static String memcachedPort() { + return getSecret("MEMCACHED_PORT"); + } + + public static String salesforceWhitelistedRedirectUris() { + return getSecret("SALESFORCE_WHITELISTED_REDIRECT_URIS"); + } + + public static String errorEmailFrom() { + return getSecret("ERROR_EMAIL_FROM"); + } + + public static String errorEmailTo() { + return getSecret("ERROR_EMAIL_TO"); + } + + /* Secrets end */ + + /** + * This method returns the local environment variables. + * + * @return String + */ + private static String getLocalEnvVars() { + try (FileReader fileReader = new FileReader("secrets.json")) { + int ch; + StringBuilder secretJsonBuilder = new StringBuilder(); + + while ((ch = fileReader.read()) != -1) { + secretJsonBuilder.append((char) ch); + } + + return secretJsonBuilder.toString(); + } catch (FileNotFoundException e) { + throw new CustomException( + new ErrorObject( + "l_gc_s_glev_1", + "something_went_wrong", + e.getMessage())); + } catch (IOException e) { + throw new CustomException( + new ErrorObject( + "l_gc_s_glev_2", + "something_went_wrong", + e.getMessage())); + } + } +} From a8f10d07eac00e0ce95022a97a23780b6c603e47 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Tue, 22 Aug 2023 12:41:53 +0530 Subject: [PATCH 002/195] feat: config aws services with default credentials --- pom.xml | 6 +++++ .../salessparrow/api/config/AwsConfig.java | 5 ----- .../api/config/CoreConstants.java | 8 +++++++ .../api/config/DynamoDBConfiguration.java | 22 +++---------------- .../lib/globalConstants/SecretConstants.java | 4 ++++ src/main/resources/application.properties | 6 ----- 6 files changed, 21 insertions(+), 30 deletions(-) diff --git a/pom.xml b/pom.xml index 54fce04e..ce18e8c7 100644 --- a/pom.xml +++ b/pom.xml @@ -134,6 +134,12 @@ 2.0.0 + + software.amazon.awssdk + secretsmanager + 2.20.130 + + diff --git a/src/main/java/com/salessparrow/api/config/AwsConfig.java b/src/main/java/com/salessparrow/api/config/AwsConfig.java index 7e175e74..06f7587d 100644 --- a/src/main/java/com/salessparrow/api/config/AwsConfig.java +++ b/src/main/java/com/salessparrow/api/config/AwsConfig.java @@ -24,12 +24,7 @@ public class AwsConfig { */ @Bean public AWSKMS kmsClient() { - BasicAWSCredentials awsCredentials = new BasicAWSCredentials( - CoreConstants.awsAccessKeyId(), - CoreConstants.awsSecretAccessKey()); - return AWSKMSClientBuilder.standard() - .withCredentials(new AWSStaticCredentialsProvider(awsCredentials)) .withRegion(CoreConstants.awsRegion()) .build(); } diff --git a/src/main/java/com/salessparrow/api/config/CoreConstants.java b/src/main/java/com/salessparrow/api/config/CoreConstants.java index 78aa19e1..7c509208 100644 --- a/src/main/java/com/salessparrow/api/config/CoreConstants.java +++ b/src/main/java/com/salessparrow/api/config/CoreConstants.java @@ -97,4 +97,12 @@ public static String errorEmailTo() { return SecretConstants.errorEmailTo(); } + /** + * This method returns the dynamodb url. + * @return + */ + public static String dynamoDbUrl() { + return SecretConstants.dynamoDbUrl(); + } + } diff --git a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java index 42b8fd13..caf5b383 100644 --- a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java +++ b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java @@ -1,7 +1,5 @@ package com.salessparrow.api.config; -import com.amazonaws.auth.AWSStaticCredentialsProvider; -import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.client.builder.AwsClientBuilder; import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder; @@ -10,7 +8,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -19,19 +16,6 @@ public class DynamoDBConfiguration { Logger logger = LoggerFactory.getLogger(DynamoDBConfiguration.class); - @Value("${aws.dynamodb.endpoint}") - private String dynamodbEndpoint; - - @Value("${aws.region}") - private String awsRegion; - - @Value("${aws.dynamodb.accessKey}") - private String dynamodbAccessKey; - - @Value("${aws.dynamodb.secretKey}") - private String dynamodbSecretKey; - - @Bean public DynamoDBMapper dynamoDBMapper() { DynamoDBMapper defaultMapper = new DynamoDBMapper(buildAmazonDynamoDB(), dynamoDBMapperConfig()); @@ -59,9 +43,9 @@ public AmazonDynamoDB buildAmazonDynamoDB() { return AmazonDynamoDBClientBuilder .standard() .withEndpointConfiguration( - new AwsClientBuilder.EndpointConfiguration(dynamodbEndpoint,awsRegion)) - .withCredentials(new AWSStaticCredentialsProvider( - new BasicAWSCredentials(dynamodbAccessKey,dynamodbSecretKey))) + new AwsClientBuilder.EndpointConfiguration( + CoreConstants.dynamoDbUrl(), + CoreConstants.awsRegion())) .build(); } diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java index c60bdb5e..57f89478 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java @@ -128,6 +128,10 @@ public static String errorEmailTo() { return getSecret("ERROR_EMAIL_TO"); } + public static String dynamoDbUrl() { + return getSecret("DYNAMO_DB_URL"); + } + /* Secrets end */ /** diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index d2821b57..7c346b57 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,12 +1,6 @@ # Server server.port=80 -# Dynamodb -aws.dynamodb.endpoint=${DYNAMO_DB_URL} -aws.dynamodb.accessKey=${AWS_IAM_ACCESS_KEY_ID} -aws.dynamodb.secretKey=${AWS_IAM_SECRET_ACCESS_KEY} -aws.region=${AWS_IAM_REGION} - # Spring boot profile spring.profiles.active=${ENVIRONMENT} From 5ab8de33fb28c15844083976397b1756fa1888b1 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Tue, 22 Aug 2023 13:32:45 +0530 Subject: [PATCH 003/195] added logs to deployment issue --- .../com/salessparrow/api/config/AwsConfig.java | 5 ----- .../lib/globalConstants/SecretConstants.java | 17 +++++++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/salessparrow/api/config/AwsConfig.java b/src/main/java/com/salessparrow/api/config/AwsConfig.java index 06f7587d..d5b1ba36 100644 --- a/src/main/java/com/salessparrow/api/config/AwsConfig.java +++ b/src/main/java/com/salessparrow/api/config/AwsConfig.java @@ -36,12 +36,7 @@ public AWSKMS kmsClient() { */ @Bean public AmazonSimpleEmailService sesClient() { - BasicAWSCredentials awsCredentials = new BasicAWSCredentials( - CoreConstants.awsAccessKeyId(), - CoreConstants.awsSecretAccessKey()); - return AmazonSimpleEmailServiceClientBuilder.standard() - .withCredentials(new AWSStaticCredentialsProvider(awsCredentials)) .withRegion(CoreConstants.awsRegion()) .build(); } diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java index 57f89478..ba8ca279 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java @@ -28,16 +28,16 @@ public class SecretConstants { /** * This is the credentials that are going to be used to access the secrets manager. */ - public static AwsBasicCredentials credentials = AwsBasicCredentials.create( - CoreConstants.awsAccessKeyId(), - CoreConstants.awsSecretAccessKey()); + // public static AwsBasicCredentials credentials = AwsBasicCredentials.create( + // CoreConstants.awsAccessKeyId(), + // CoreConstants.awsSecretAccessKey()); /** * This is the builder that is going to be used to access the secrets manager. */ public static SecretsManagerClientBuilder secretsManagerClientBuilder = SecretsManagerClient.builder() - .region(Region.of(CoreConstants.awsRegion())) - .credentialsProvider(() -> credentials); + .region(Region.of(CoreConstants.awsRegion())); + // .credentialsProvider(() -> credentials); /** * This method returns the secrets from the secrets manager. @@ -48,14 +48,19 @@ public class SecretConstants { public static String getSecret(String key) { String secretJson = ""; + System.out.println("CoreConstants.isDevEnvironment(): ---" + CoreConstants.isDevEnvironment()); if (CoreConstants.isDevEnvironment()) { secretJson = getLocalEnvVars(); } else { SecretCache cache = new SecretCache(secretsManagerClientBuilder); - secretJson = cache.getSecretString(getSecretId()); + String secretId = getSecretId(); + System.out.println("secretId: ---" + secretId); + secretJson = cache.getSecretString(secretId); cache.close(); } + System.out.print("secretJson: ---" + secretJson); + ObjectMapper objectMapper = new ObjectMapper(); String specificValue = ""; try { From 17f8aed6c0b6c491de90aaaa55d986a915c2904d Mon Sep 17 00:00:00 2001 From: VRDighe Date: Tue, 22 Aug 2023 13:43:08 +0530 Subject: [PATCH 004/195] Merge branch 'upsert_fix' into 41-bug-dynamodb-upsert-behavior-updates-all-fields-instead-of-specific-ones --- .../api/config/DynamoDBConfiguration.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java index 16052285..0622732c 100644 --- a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java +++ b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java @@ -7,6 +7,7 @@ import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig; +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig.SaveBehavior; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -19,7 +20,6 @@ public class DynamoDBConfiguration { Logger logger = LoggerFactory.getLogger(DynamoDBConfiguration.class); - @Value("${aws.dynamodb.endpoint}") private String dynamodbEndpoint; @@ -32,12 +32,11 @@ public class DynamoDBConfiguration { @Value("${aws.dynamodb.secretKey}") private String dynamodbSecretKey; - @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 @@ -51,7 +50,8 @@ public void save(T object) { logger.debug("DBQuery:Save: table-{}", object.getClass().getSimpleName()); defaultMapper.save(object); } - // Similarly, you can override other used methods like delete, batchSave, etc. similarly + // Similarly, you can override other used methods like delete, batchSave, etc. + // similarly }; } @@ -60,9 +60,9 @@ public AmazonDynamoDB buildAmazonDynamoDB() { return AmazonDynamoDBClientBuilder .standard() .withEndpointConfiguration( - new AwsClientBuilder.EndpointConfiguration(dynamodbEndpoint,awsRegion)) + new AwsClientBuilder.EndpointConfiguration(dynamodbEndpoint, awsRegion)) .withCredentials(new AWSStaticCredentialsProvider( - new BasicAWSCredentials(dynamodbAccessKey,dynamodbSecretKey))) + new BasicAWSCredentials(dynamodbAccessKey, dynamodbSecretKey))) .build(); } @@ -71,7 +71,7 @@ DynamoDBMapperConfig dynamoDBMapperConfig() { String prefix = CoreConstants.environment() + "_"; return new DynamoDBMapperConfig.Builder() .withTableNameOverride(DynamoDBMapperConfig.TableNameOverride.withTableNamePrefix(prefix)) + .withSaveBehavior(SaveBehavior.UPDATE_SKIP_NULL_ATTRIBUTES) .build(); } } - From 0190a6dbe7b4b866df769028e2682cacfd019df0 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Tue, 22 Aug 2023 13:46:03 +0530 Subject: [PATCH 005/195] moved aws region to secret manager constants --- .../java/com/salessparrow/api/config/CoreConstants.java | 8 ++++---- .../api/lib/globalConstants/SecretConstants.java | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/salessparrow/api/config/CoreConstants.java b/src/main/java/com/salessparrow/api/config/CoreConstants.java index 7c509208..08da28cc 100644 --- a/src/main/java/com/salessparrow/api/config/CoreConstants.java +++ b/src/main/java/com/salessparrow/api/config/CoreConstants.java @@ -20,10 +20,6 @@ public static String awsSecretAccessKey() { return System.getenv("AWS_IAM_SECRET_ACCESS_KEY"); } - public static String awsRegion() { - return System.getenv("AWS_IAM_REGION"); - } - public static Boolean isDevEnvironment() { return environment().equals("development"); } @@ -34,6 +30,10 @@ public static Boolean isTestEnvironment() { /* End: Env variables required before spring application context is initialized */ + public static String awsRegion() { + return SecretConstants.awsRegion(); + } + public static String encryptionKey() { return SecretConstants.encryptionKey(); } diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java index ba8ca279..7ff00395 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java @@ -89,6 +89,10 @@ private static String getSecretId() { /* Secrets start */ + public static String awsRegion() { + return getSecret("AWS_IAM_REGION"); + } + public static String encryptionKey() { return getSecret("ENCRYPTION_KEY"); } From 64427357f446f9b2eaffe6b97995e8474b3bd406 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Tue, 22 Aug 2023 13:57:35 +0530 Subject: [PATCH 006/195] added logs for debugging --- src/main/java/com/salessparrow/api/SalesSparrowApi.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/com/salessparrow/api/SalesSparrowApi.java b/src/main/java/com/salessparrow/api/SalesSparrowApi.java index e58a080b..1cf5e873 100644 --- a/src/main/java/com/salessparrow/api/SalesSparrowApi.java +++ b/src/main/java/com/salessparrow/api/SalesSparrowApi.java @@ -5,12 +5,17 @@ import org.springframework.cache.annotation.EnableCaching; import org.springframework.scheduling.annotation.EnableAsync; +import com.salessparrow.api.config.CoreConstants; + @SpringBootApplication @EnableCaching // This enables caching @EnableAsync // This enables asynchronous processing in Spring public class SalesSparrowApi { public static void main(String[] args) { + + System.out.println("Env variables ---- environment: " + CoreConstants.environment()); + System.out.println("Env variables ---- aws region: " + CoreConstants.awsRegion()); SpringApplication.run(SalesSparrowApi.class, args); } } From fa87ff28e8d9a09a0853ef0ca4266ba88c15a01a Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Tue, 22 Aug 2023 14:12:09 +0530 Subject: [PATCH 007/195] added log for debugging --- src/main/java/com/salessparrow/api/SalesSparrowApi.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/salessparrow/api/SalesSparrowApi.java b/src/main/java/com/salessparrow/api/SalesSparrowApi.java index 1cf5e873..71c028e9 100644 --- a/src/main/java/com/salessparrow/api/SalesSparrowApi.java +++ b/src/main/java/com/salessparrow/api/SalesSparrowApi.java @@ -14,6 +14,7 @@ public class SalesSparrowApi { public static void main(String[] args) { + System.out.println("Env variables ---- : " + System.getenv()); System.out.println("Env variables ---- environment: " + CoreConstants.environment()); System.out.println("Env variables ---- aws region: " + CoreConstants.awsRegion()); SpringApplication.run(SalesSparrowApi.class, args); From 520c41464e02ae50b3019a83b19db242833257f5 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Tue, 22 Aug 2023 14:21:09 +0530 Subject: [PATCH 008/195] use instance profile credential provider --- .../api/lib/globalConstants/SecretConstants.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java index 7ff00395..79db6203 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java @@ -14,6 +14,7 @@ import com.salessparrow.api.lib.errorLib.ErrorObject; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.InstanceProfileCredentialsProvider; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClientBuilder; @@ -36,8 +37,8 @@ public class SecretConstants { * This is the builder that is going to be used to access the secrets manager. */ public static SecretsManagerClientBuilder secretsManagerClientBuilder = SecretsManagerClient.builder() - .region(Region.of(CoreConstants.awsRegion())); - // .credentialsProvider(() -> credentials); + .region(Region.of(CoreConstants.awsRegion())) + .credentialsProvider(InstanceProfileCredentialsProvider.builder().build()); /** * This method returns the secrets from the secrets manager. From c118d2e45efead1c206e53df96827a8850c588af Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Tue, 22 Aug 2023 14:24:43 +0530 Subject: [PATCH 009/195] added instance cred provider --- .../salessparrow/api/lib/globalConstants/SecretConstants.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java index 79db6203..b969f36c 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java @@ -37,7 +37,6 @@ public class SecretConstants { * This is the builder that is going to be used to access the secrets manager. */ public static SecretsManagerClientBuilder secretsManagerClientBuilder = SecretsManagerClient.builder() - .region(Region.of(CoreConstants.awsRegion())) .credentialsProvider(InstanceProfileCredentialsProvider.builder().build()); /** From b596682df6c3ced4987855bd06e3e30b03ae5269 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Tue, 22 Aug 2023 14:35:47 +0530 Subject: [PATCH 010/195] updated env vars --- .../api/lib/globalConstants/SecretConstants.java | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java index b969f36c..b2fbd5d6 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java @@ -13,9 +13,7 @@ import com.salessparrow.api.exception.CustomException; import com.salessparrow.api.lib.errorLib.ErrorObject; -import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.InstanceProfileCredentialsProvider; -import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClientBuilder; @@ -26,13 +24,6 @@ public class SecretConstants { /* Secret manager configuration start */ - /** - * This is the credentials that are going to be used to access the secrets manager. - */ - // public static AwsBasicCredentials credentials = AwsBasicCredentials.create( - // CoreConstants.awsAccessKeyId(), - // CoreConstants.awsSecretAccessKey()); - /** * This is the builder that is going to be used to access the secrets manager. */ @@ -118,11 +109,11 @@ public static String salesforceClientSecret() { } public static String memcachedHost() { - return getSecret("MEMCACHED_HOST"); + return getSecret("MEMCACHED_CACHE_HOST"); } public static String memcachedPort() { - return getSecret("MEMCACHED_PORT"); + return getSecret("MEMCACHED_CACHE_PORT"); } public static String salesforceWhitelistedRedirectUris() { From a5af01ca990081d9b12e9435506e0ff70286c83f Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Tue, 22 Aug 2023 14:38:09 +0530 Subject: [PATCH 011/195] updated api port --- src/main/resources/application.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 7c346b57..e50add78 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,5 +1,5 @@ # Server -server.port=80 +server.port=8080 # Spring boot profile spring.profiles.active=${ENVIRONMENT} From 6bf0b71c76decf6d150861b7f31a6cea9ade326b Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Tue, 22 Aug 2023 14:50:13 +0530 Subject: [PATCH 012/195] added health check route --- .../api/controllers/HealthCheck.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/main/java/com/salessparrow/api/controllers/HealthCheck.java diff --git a/src/main/java/com/salessparrow/api/controllers/HealthCheck.java b/src/main/java/com/salessparrow/api/controllers/HealthCheck.java new file mode 100644 index 00000000..572189a6 --- /dev/null +++ b/src/main/java/com/salessparrow/api/controllers/HealthCheck.java @@ -0,0 +1,16 @@ +package com.salessparrow.api.controllers; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/health-check") +public class HealthCheck { + + @GetMapping("") + public ResponseEntity HealthCheck() { + return ResponseEntity.ok().body("OK"); + } +} From 574ae81124cb35f990d00d120276b69854032a61 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Tue, 22 Aug 2023 14:57:07 +0530 Subject: [PATCH 013/195] updated health check route --- .../java/com/salessparrow/api/controllers/HealthCheck.java | 2 +- .../salessparrow/api/lib/globalConstants/SecretConstants.java | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/java/com/salessparrow/api/controllers/HealthCheck.java b/src/main/java/com/salessparrow/api/controllers/HealthCheck.java index 572189a6..e8213da9 100644 --- a/src/main/java/com/salessparrow/api/controllers/HealthCheck.java +++ b/src/main/java/com/salessparrow/api/controllers/HealthCheck.java @@ -6,7 +6,7 @@ import org.springframework.web.bind.annotation.RestController; @RestController -@RequestMapping("/health-check") +@RequestMapping("/api/v1/health-check") public class HealthCheck { @GetMapping("") diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java index b2fbd5d6..6a2c9839 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java @@ -39,19 +39,15 @@ public class SecretConstants { public static String getSecret(String key) { String secretJson = ""; - System.out.println("CoreConstants.isDevEnvironment(): ---" + CoreConstants.isDevEnvironment()); if (CoreConstants.isDevEnvironment()) { secretJson = getLocalEnvVars(); } else { SecretCache cache = new SecretCache(secretsManagerClientBuilder); String secretId = getSecretId(); - System.out.println("secretId: ---" + secretId); secretJson = cache.getSecretString(secretId); cache.close(); } - System.out.print("secretJson: ---" + secretJson); - ObjectMapper objectMapper = new ObjectMapper(); String specificValue = ""; try { From 5fe8d04033ae1bfd77b96dd5894978b952e536af Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Tue, 22 Aug 2023 16:09:57 +0530 Subject: [PATCH 014/195] removed logs added for debugging --- src/main/java/com/salessparrow/api/SalesSparrowApi.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main/java/com/salessparrow/api/SalesSparrowApi.java b/src/main/java/com/salessparrow/api/SalesSparrowApi.java index 71c028e9..e58a080b 100644 --- a/src/main/java/com/salessparrow/api/SalesSparrowApi.java +++ b/src/main/java/com/salessparrow/api/SalesSparrowApi.java @@ -5,18 +5,12 @@ import org.springframework.cache.annotation.EnableCaching; import org.springframework.scheduling.annotation.EnableAsync; -import com.salessparrow.api.config.CoreConstants; - @SpringBootApplication @EnableCaching // This enables caching @EnableAsync // This enables asynchronous processing in Spring public class SalesSparrowApi { public static void main(String[] args) { - - System.out.println("Env variables ---- : " + System.getenv()); - System.out.println("Env variables ---- environment: " + CoreConstants.environment()); - System.out.println("Env variables ---- aws region: " + CoreConstants.awsRegion()); SpringApplication.run(SalesSparrowApi.class, args); } } From 2eb78cb3bc64328b062e4cfcbfc8aee647958554 Mon Sep 17 00:00:00 2001 From: Yagnik Thummar Date: Tue, 22 Aug 2023 16:25:29 +0530 Subject: [PATCH 015/195] Added test cases for create task api. --- .../accountTaskController/CreateTaskTest.java | 118 +++++++++++++++ .../createTask.scenarios.json | 141 ++++++++++++++++++ .../createTask.fixtures.json | 14 ++ 3 files changed, 273 insertions(+) create mode 100644 src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/CreateTaskTest.java create mode 100644 src/test/resources/data/controllers/accountTaskController/createTask.scenarios.json create mode 100644 src/test/resources/fixtures/controllers/accountTaskController/createTask.fixtures.json diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/CreateTaskTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/CreateTaskTest.java new file mode 100644 index 00000000..8cf6e7b1 --- /dev/null +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/CreateTaskTest.java @@ -0,0 +1,118 @@ +package com.salessparrow.api.functional.controllers.accountTaskController; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Stream; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +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.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +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; +import com.salessparrow.api.helper.Common; +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 com.salessparrow.api.lib.httpLib.HttpClient.HttpResponse; +import com.salessparrow.api.lib.salesforce.helper.MakeCompositeRequest; + +import jakarta.servlet.http.Cookie; + +@SpringBootTest +@AutoConfigureMockMvc +@WebAppConfiguration +@Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) +public class CreateTaskTest { + + @Autowired + private MockMvc mockMvc; + @Autowired + private Common common; + @Autowired + private LoadFixture loadFixture; + @Autowired + private Setup setup; + @Autowired + private Cleanup cleanup; + + @MockBean + private MakeCompositeRequest makeCompositeRequestMock; + + @BeforeEach + public void setUp() throws DynamobeeException { + setup.perform(); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + @ParameterizedTest + @MethodSource("testScenariosProvider") + public void createTask(Scenario testScenario) throws Exception { + + // Load fixture data + String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/controllers/accountTaskController/createTask.fixtures.json", currentFunctionName); + loadFixture.perform(fixtureData); + + // Read data from the scenario + ObjectMapper objectMapper = new ObjectMapper(); + String cookieValue = (String) testScenario.getInput().get("cookie"); + String accountId = (String) testScenario.getInput().get("accountId"); + + // Prepare mock responses + HttpResponse createNoteMockResponse = new HttpResponse(); + createNoteMockResponse.setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest"))); + when(makeCompositeRequestMock.makePostRequest(any(), any())).thenReturn(createNoteMockResponse); + + // Perform the request + String requestBody = objectMapper.writeValueAsString(testScenario.getInput().get("body")); + String url = "/api/v1/accounts/" + accountId + "/tasks"; + + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.post(url) + .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) + .content(requestBody) + .contentType(MediaType.APPLICATION_JSON)); + + // Check the response + String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); + String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); + assertEquals(expectedOutput, actualOutput); + } + + static Stream testScenariosProvider() throws IOException { + List testScenarios = loadScenarios(); + return testScenarios.stream(); + } + + private static List loadScenarios() throws IOException { + String scenariosPath = "classpath:data/controllers/accountTaskController/createTask.scenarios.json"; + Resource resource = new DefaultResourceLoader().getResource(scenariosPath); + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); + } +} diff --git a/src/test/resources/data/controllers/accountTaskController/createTask.scenarios.json b/src/test/resources/data/controllers/accountTaskController/createTask.scenarios.json new file mode 100644 index 00000000..8bb46e13 --- /dev/null +++ b/src/test/resources/data/controllers/accountTaskController/createTask.scenarios.json @@ -0,0 +1,141 @@ +[ + { + "description": "Should successfully create the note", + "input": { + "body": { + "crm_organization_user_id":"0011e00000bWSxdAA1", + "description":"Update remaining documentations", + "due_date":"2023-12-01" + }, + "accountId": "0011e00000bWSxdAAG", + "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + }, + "mocks": { + "makeCompositeRequest": { + "compositeResponse": [ + { + "body": { + "id": "00T1e000007mDA7EAM", + "success": true, + "errors": [] + }, + "httpHeaders": { + "Location": "/services/data/v58.0/sobjects/Task/00T1e000007mDA7EAM" + }, + "httpStatusCode": 201, + "referenceId": "CreateTask" + } + ] + } + }, + "output": { + "task_id": "00T1e000007mDA7EAM" + } + }, + { + "description": "Should fail when the task description is empty", + "input": { + "body": { + "crm_organization_user_id":"0011e00000bWSxdAA1", + "description":"", + "due_date":"2023-12-01" + }, + "accountId": "0011e00000bWSxdAAG", + "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + }, + "mocks": {}, + "output": { + "http_code": 400, + "message": "At least one parameter is invalid or missing.", + "code": "INVALID_PARAMS", + "internal_error_identifier": "b_2", + "param_errors": [ + { + "parameter": "description", + "param_error_identifier": "missing_description", + "message": "description is required parameter. Please provide description." + } + ] + } + }, + { + "description": "Should fail when the note description is not provided", + "input": { + "body": { + "crm_organization_user_id":"0011e00000bWSxdAA1", + "due_date":"2023-12-01" + }, + "accountId": "0011e00000bWSxdAAG", + "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + }, + "mocks": {}, + "output": { + "http_code": 400, + "message": "At least one parameter is invalid or missing.", + "code": "INVALID_PARAMS", + "internal_error_identifier": "b_2", + "param_errors": [ + { + "parameter": "description", + "param_error_identifier": "missing_description", + "message": "description is required parameter. Please provide description." + } + ] + } + }, + { + "description": "Should fail when the cookie is invalid", + "input": { + "body": {}, + "accountId": "0011e00000bWSxdAAG", + "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:invalid" + }, + "mocks": {}, + "output": { + "http_code": 401, + "message": "Unauthorized API request. Please check your API key.", + "code": "UNAUTHORIZED", + "internal_error_identifier": "l_ulca_vct_2", + "param_errors": [] + } + }, + { + "description": "Should fail when the account id invalid", + "input": { + "body": { + "crm_organization_user_id":"0011e00000bWSxdAA1", + "description":"Update remaining documentations", + "due_date":"2023-12-01" + }, + "accountId": "invalid", + "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + }, + "mocks": { + "makeCompositeRequest": { + "compositeResponse": [ + { + "body": [ + { + "message": "Related To ID: id value of incorrect type: 0011e00000bWSxdAA1", + "errorCode": "MALFORMED_ID", + "fields": [ + "WhatId" + ] + } + ], + "httpHeaders": {}, + "httpStatusCode": 400, + "referenceId": "refTask" + } + ] + } + }, + "output": { + "http_code": 500, + "message": "Something went wrong.", + "code": "INTERNAL_SERVER_ERROR", + "internal_error_identifier": "l_s_fse_fscn_fcn_2", + "param_errors": [] + } + } + ] \ No newline at end of file diff --git a/src/test/resources/fixtures/controllers/accountTaskController/createTask.fixtures.json b/src/test/resources/fixtures/controllers/accountTaskController/createTask.fixtures.json new file mode 100644 index 00000000..49f7f52b --- /dev/null +++ b/src/test/resources/fixtures/controllers/accountTaskController/createTask.fixtures.json @@ -0,0 +1,14 @@ +{ + "createTask": { + "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 a3ff34e3c41573b37a26d7d7e55d64f5982c55dc Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Tue, 22 Aug 2023 16:25:32 +0530 Subject: [PATCH 016/195] excluded health check route from auth intercepter --- .../java/com/salessparrow/api/config/InterceptorConfig.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/salessparrow/api/config/InterceptorConfig.java b/src/main/java/com/salessparrow/api/config/InterceptorConfig.java index c82c0026..d7a1f4b5 100644 --- a/src/main/java/com/salessparrow/api/config/InterceptorConfig.java +++ b/src/main/java/com/salessparrow/api/config/InterceptorConfig.java @@ -37,6 +37,7 @@ public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(userAuthInterceptor) .addPathPatterns("/**") - .excludePathPatterns("/api/v1/auth/salesforce/**"); + .excludePathPatterns("/api/v1/auth/salesforce/**") + .excludePathPatterns("/api/v1/health-check"); } } \ No newline at end of file From 4953d3f070483a2110cf1464e11b6ae03d6d68b2 Mon Sep 17 00:00:00 2001 From: Yagnik Thummar Date: Wed, 23 Aug 2023 12:22:54 +0530 Subject: [PATCH 017/195] Added create task and assign to user api. --- .../controllers/AccountTaskController.java | 41 ++++++ .../dto/formatter/CreateTaskFormatterDto.java | 12 ++ .../api/dto/requestMapper/CreateTaskDto.java | 21 +++ .../createTask/CreateSalesforceTask.java | 137 ++++++++++++++++++ .../lib/crmActions/createTask/CreateTask.java | 15 ++ .../createTask/CreateTaskFactory.java | 49 +++++++ .../customAnnotations/ValidDateFormat.java | 18 +++ .../globalConstants/SalesforceConstants.java | 4 + .../dto/SalesforceCreateTaskDto.java | 8 + .../lib/validators/DateFormatValidator.java | 43 ++++++ .../accountTask/CreateTaskService.java | 40 +++++ .../resources/config/ParamErrorConfig.json | 10 ++ .../createTask.scenarios.json | 18 +-- 13 files changed, 407 insertions(+), 9 deletions(-) create mode 100644 src/main/java/com/salessparrow/api/controllers/AccountTaskController.java create mode 100644 src/main/java/com/salessparrow/api/dto/formatter/CreateTaskFormatterDto.java create mode 100644 src/main/java/com/salessparrow/api/dto/requestMapper/CreateTaskDto.java create mode 100644 src/main/java/com/salessparrow/api/lib/crmActions/createTask/CreateSalesforceTask.java create mode 100644 src/main/java/com/salessparrow/api/lib/crmActions/createTask/CreateTask.java create mode 100644 src/main/java/com/salessparrow/api/lib/crmActions/createTask/CreateTaskFactory.java create mode 100644 src/main/java/com/salessparrow/api/lib/customAnnotations/ValidDateFormat.java create mode 100644 src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceCreateTaskDto.java create mode 100644 src/main/java/com/salessparrow/api/lib/validators/DateFormatValidator.java create mode 100644 src/main/java/com/salessparrow/api/services/accountTask/CreateTaskService.java diff --git a/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java b/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java new file mode 100644 index 00000000..0b9439e3 --- /dev/null +++ b/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java @@ -0,0 +1,41 @@ +package com.salessparrow.api.controllers; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.salessparrow.api.dto.formatter.CreateTaskFormatterDto; +import com.salessparrow.api.dto.requestMapper.CreateTaskDto; +import com.salessparrow.api.services.accountTask.CreateTaskService; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.Valid; + + +@RestController +@RequestMapping("/api/v1/accounts") +@Validated +public class AccountTaskController { + + Logger logger = LoggerFactory.getLogger(AccountTaskController.class); + @Autowired + private CreateTaskService createTaskService; + + @PostMapping("/{account_id}/tasks") + public ResponseEntity createTask( + HttpServletRequest request, + @PathVariable("account_id") String accountId, + @Valid @RequestBody CreateTaskDto task + ){ + logger.info("Create task request received"); + CreateTaskFormatterDto createTaskFormatterDto = createTaskService.createTask(request, accountId, task); + return ResponseEntity.ok().body(createTaskFormatterDto); + } +} diff --git a/src/main/java/com/salessparrow/api/dto/formatter/CreateTaskFormatterDto.java b/src/main/java/com/salessparrow/api/dto/formatter/CreateTaskFormatterDto.java new file mode 100644 index 00000000..690ddabd --- /dev/null +++ b/src/main/java/com/salessparrow/api/dto/formatter/CreateTaskFormatterDto.java @@ -0,0 +1,12 @@ +package com.salessparrow.api.dto.formatter; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; + +import lombok.Data; + +@Data +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) +public class CreateTaskFormatterDto { + private String taskId; +} diff --git a/src/main/java/com/salessparrow/api/dto/requestMapper/CreateTaskDto.java b/src/main/java/com/salessparrow/api/dto/requestMapper/CreateTaskDto.java new file mode 100644 index 00000000..b4132972 --- /dev/null +++ b/src/main/java/com/salessparrow/api/dto/requestMapper/CreateTaskDto.java @@ -0,0 +1,21 @@ +package com.salessparrow.api.dto.requestMapper; + +import com.salessparrow.api.lib.customAnnotations.ValidDateFormat; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; +import lombok.Data; + +@Data +public class CreateTaskDto { + + @NotBlank(message = "missing_crm_organization_user_id") + private String crmOrganizationUserId; + + @NotBlank(message = "missing_description") + @Size(max = 32000, message = "description_too_long") + private String description; + + @ValidDateFormat(message = "invalid_due_date") + private String dueDate; +} diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createTask/CreateSalesforceTask.java b/src/main/java/com/salessparrow/api/lib/crmActions/createTask/CreateSalesforceTask.java new file mode 100644 index 00000000..8fb1079b --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createTask/CreateSalesforceTask.java @@ -0,0 +1,137 @@ +package com.salessparrow.api.lib.crmActions.createTask; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.salessparrow.api.controllers.AccountTaskController; +import com.salessparrow.api.domain.User; +import com.salessparrow.api.dto.formatter.CreateTaskFormatterDto; +import com.salessparrow.api.dto.requestMapper.CreateTaskDto; +import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.lib.Util; +import com.salessparrow.api.lib.errorLib.ErrorObject; +import com.salessparrow.api.lib.globalConstants.SalesforceConstants; +import com.salessparrow.api.lib.httpLib.HttpClient; +import com.salessparrow.api.lib.salesforce.dto.CompositeRequestDto; +import com.salessparrow.api.lib.salesforce.dto.SalesforceCreateTaskDto; +import com.salessparrow.api.lib.salesforce.helper.MakeCompositeRequest; + +/** + * CreateSalesforceTask class is responsible for creating a task in Salesforce + */ +@Component +public class CreateSalesforceTask implements CreateTask{ + + Logger logger = LoggerFactory.getLogger(AccountTaskController.class); + + @Autowired + private SalesforceConstants salesforceConstants; + + @Autowired + private MakeCompositeRequest makeCompositeRequest; + + /** + * Create a task in Salesforce + * + * @param User User object + * @param accountId Salesforce account id + * @param task CreateTaskDto object + * + * @return CreateTaskFormatterDto object + */ + public CreateTaskFormatterDto createTask(User User, String accountId, CreateTaskDto task) { + String salesforceUserId = User.getExternalUserId(); + + String taskSubject = getTaskSubjectFromDescription(task); + + logger.info("performing create task in salesforce"); + + Map taskBody = new HashMap(); + taskBody.put("Subject", taskSubject); + taskBody.put("Description", task.getDescription()); + taskBody.put("OwnerId", task.getCrmOrganizationUserId()); + taskBody.put("ActivityDate", task.getDueDate()); + taskBody.put("WhatId", accountId); + + CompositeRequestDto createTaskCompositeRequestDto = new CompositeRequestDto( + "POST", + salesforceConstants.salesforceCreateTaskUrl(), + "CreateTask", + taskBody + ); + + List compositeRequests = new ArrayList(); + compositeRequests.add(createTaskCompositeRequestDto); + + logger.info("making composite request to salesforce"); + + HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, salesforceUserId); + + return parseResponse(response.getResponseBody()); + } + + /** + * Parse the response from Salesforce + * + * @param createTaskResponse String response from Salesforce + * + * @return CreateTaskFormatterDto object + */ + private CreateTaskFormatterDto parseResponse(String createTaskResponse){ + Util util = new Util(); + JsonNode rootNode = util.getJsonNode(createTaskResponse); + + logger.info("parsing response from salesforce"); + + JsonNode createTaskCompositeResponse = rootNode.get("compositeResponse").get(0); + String createTaskStatusCode = createTaskCompositeResponse.get("httpStatusCode").asText(); + + if (!createTaskStatusCode.equals("200") && !createTaskStatusCode.equals("201")) { + String errorBody = createTaskCompositeResponse.get("body").asText(); + + throw new CustomException( + new ErrorObject( + "l_ca_ct_cst_1", + "internal_server_error", + errorBody + )); + } + + JsonNode createTaskNodeResponseBody = rootNode.get("compositeResponse").get(0).get("body"); + + ObjectMapper mapper = new ObjectMapper(); + mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + SalesforceCreateTaskDto salesforceCreateTaskDto = mapper.convertValue(createTaskNodeResponseBody, SalesforceCreateTaskDto.class); + + CreateTaskFormatterDto createTaskFormatterDto = new CreateTaskFormatterDto(); + createTaskFormatterDto.setTaskId(salesforceCreateTaskDto.getId()); + + return createTaskFormatterDto; + } + + /** + * Get task subject from description + * + * @param task CreateTaskDto object + * + * @return String task subject + */ + private String getTaskSubjectFromDescription(CreateTaskDto task) { + logger.info("getting task subject from description"); + if (task.getDescription().length() < 60) { + return task.getDescription(); + } + + return task.getDescription().substring(0, 60); + } +} diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createTask/CreateTask.java b/src/main/java/com/salessparrow/api/lib/crmActions/createTask/CreateTask.java new file mode 100644 index 00000000..984ecbcd --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createTask/CreateTask.java @@ -0,0 +1,15 @@ +package com.salessparrow.api.lib.crmActions.createTask; + +import org.springframework.stereotype.Component; + +import com.salessparrow.api.domain.User; +import com.salessparrow.api.dto.formatter.CreateTaskFormatterDto; +import com.salessparrow.api.dto.requestMapper.CreateTaskDto; + +/** + * CreateTask interface is interface for createTask for various CRM services + */ +@Component +public interface CreateTask { + public CreateTaskFormatterDto createTask(User User,String accountId, CreateTaskDto task); +} diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createTask/CreateTaskFactory.java b/src/main/java/com/salessparrow/api/lib/crmActions/createTask/CreateTaskFactory.java new file mode 100644 index 00000000..66a1d23a --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createTask/CreateTaskFactory.java @@ -0,0 +1,49 @@ +package com.salessparrow.api.lib.crmActions.createTask; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.salessparrow.api.controllers.AccountTaskController; +import com.salessparrow.api.domain.User; +import com.salessparrow.api.dto.formatter.CreateTaskFormatterDto; +import com.salessparrow.api.dto.requestMapper.CreateTaskDto; +import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.lib.errorLib.ErrorObject; +import com.salessparrow.api.lib.globalConstants.UserConstants; + +/** + * CreateTaskFactory class is responsible for creating a task in CRM + */ +@Component +public class CreateTaskFactory { + + Logger logger = LoggerFactory.getLogger(AccountTaskController.class); + + @Autowired + CreateSalesforceTask createSalesforceTask; + + /** + * Create a task in CRM + * + * @param user User object + * @param accountId CRM account id + * @param task CreateTaskDto object + * + * @return CreateTaskFormatterDto object + */ + public CreateTaskFormatterDto createTask(User user, String accountId, CreateTaskDto task) { + switch(user.getUserKind()) { + case UserConstants.SALESFORCE_USER_KIND: + logger.info("calling createTask of salesforceCreateTask"); + return createSalesforceTask.createTask(user, accountId, task); + default: + throw new CustomException( + new ErrorObject( + "l_ca_ct_ctf_1", + "something_went_wrong", + "Invalid user kind.")); + } + } +} diff --git a/src/main/java/com/salessparrow/api/lib/customAnnotations/ValidDateFormat.java b/src/main/java/com/salessparrow/api/lib/customAnnotations/ValidDateFormat.java new file mode 100644 index 00000000..f416ecc9 --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/customAnnotations/ValidDateFormat.java @@ -0,0 +1,18 @@ +package com.salessparrow.api.lib.customAnnotations; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import java.lang.annotation.*; + +import com.salessparrow.api.lib.validators.DateFormatValidator; + +@Target({ ElementType.FIELD }) +@Retention(RetentionPolicy.RUNTIME) +@Constraint(validatedBy = DateFormatValidator.class) +public @interface ValidDateFormat { + String message() default "Invalid redirect URI"; + + Class[] groups() default {}; + + Class[] payload() default {}; +} \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/SalesforceConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/SalesforceConstants.java index d379d8d0..47fd777e 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/SalesforceConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/SalesforceConstants.java @@ -57,4 +57,8 @@ public Integer timeoutMillis() { public String salesforceNotesContentUrl(String urlPrefix, String noteId){ return urlPrefix + "/services/data/v58.0/sobjects/ContentNote/" + noteId + "/Content"; } + + public String salesforceCreateTaskUrl(){ + return sObjectsPath() + "/Task"; + } } diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceCreateTaskDto.java b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceCreateTaskDto.java new file mode 100644 index 00000000..a3b476e4 --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceCreateTaskDto.java @@ -0,0 +1,8 @@ +package com.salessparrow.api.lib.salesforce.dto; + +import lombok.Data; + +@Data +public class SalesforceCreateTaskDto { + String id; +} diff --git a/src/main/java/com/salessparrow/api/lib/validators/DateFormatValidator.java b/src/main/java/com/salessparrow/api/lib/validators/DateFormatValidator.java new file mode 100644 index 00000000..9f2a9d3b --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/validators/DateFormatValidator.java @@ -0,0 +1,43 @@ +package com.salessparrow.api.lib.validators; + +import java.text.SimpleDateFormat; +import java.util.Date; + +import com.salessparrow.api.lib.customAnnotations.ValidDateFormat; + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; + +/** + * Validate date format with regular expression + * + */ +public class DateFormatValidator implements ConstraintValidator { + + private static final String DATE_FORMAT = "yyyy-MM-dd"; + + /** + * Validate date format with regular expression + * + * @param date date address for validation + * + * @return true valid date format, false invalid date format + */ + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + if(value == null) { + return false; + } + + SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT); + sdf.setLenient(false); + + try { + Date parsedDate = sdf.parse(value); + String dateString = sdf.format(parsedDate); + return dateString.equals(value.toString()); + } catch (Exception ex) { + return false; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/services/accountTask/CreateTaskService.java b/src/main/java/com/salessparrow/api/services/accountTask/CreateTaskService.java new file mode 100644 index 00000000..87762080 --- /dev/null +++ b/src/main/java/com/salessparrow/api/services/accountTask/CreateTaskService.java @@ -0,0 +1,40 @@ +package com.salessparrow.api.services.accountTask; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.salessparrow.api.controllers.AccountTaskController; +import com.salessparrow.api.domain.User; +import com.salessparrow.api.dto.formatter.CreateTaskFormatterDto; +import com.salessparrow.api.dto.requestMapper.CreateTaskDto; +import com.salessparrow.api.lib.crmActions.createTask.CreateTaskFactory; + +import jakarta.servlet.http.HttpServletRequest; + +/** + * CreateTaskService class is responsible for creating a task in CRM + */ +@Service +public class CreateTaskService { + Logger logger = LoggerFactory.getLogger(AccountTaskController.class); + + @Autowired + private CreateTaskFactory createTaskFactory; + + /** + * Create a task in CRM + * + * @param request HttpServletRequest object + * @param accountId CRM account id + * @param task CreateTaskDto object + * + * @return CreateTaskFormatterDto object + */ + public CreateTaskFormatterDto createTask(HttpServletRequest request, String accountId, CreateTaskDto task) { + logger.info("inside createTask Service"); + User currentUser = (User) request.getAttribute("current_user"); + return createTaskFactory.createTask(currentUser, accountId, task); + } +} diff --git a/src/main/resources/config/ParamErrorConfig.json b/src/main/resources/config/ParamErrorConfig.json index 0b724abb..781bbd08 100644 --- a/src/main/resources/config/ParamErrorConfig.json +++ b/src/main/resources/config/ParamErrorConfig.json @@ -13,5 +13,15 @@ "parameter": "q", "param_error_identifier": "search_term_too_long", "message": "Search term too long. Please shorten and try again." + }, + "invalid_due_date":{ + "parameter": "due_date", + "param_error_identifier": "invalid_due_date", + "message": "Invalid due date. Please double check and try again." + }, + "description_too_long":{ + "parameter": "description", + "param_error_identifier": "description_too_long", + "message": "Description too long. Please shorten and try again." } } \ No newline at end of file diff --git a/src/test/resources/data/controllers/accountTaskController/createTask.scenarios.json b/src/test/resources/data/controllers/accountTaskController/createTask.scenarios.json index 8bb46e13..a264bbf1 100644 --- a/src/test/resources/data/controllers/accountTaskController/createTask.scenarios.json +++ b/src/test/resources/data/controllers/accountTaskController/createTask.scenarios.json @@ -3,9 +3,9 @@ "description": "Should successfully create the note", "input": { "body": { - "crm_organization_user_id":"0011e00000bWSxdAA1", + "crmOrganizationUserId":"0011e00000bWSxdAA1", "description":"Update remaining documentations", - "due_date":"2023-12-01" + "dueDate":"2023-12-01" }, "accountId": "0011e00000bWSxdAAG", "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" @@ -36,9 +36,9 @@ "description": "Should fail when the task description is empty", "input": { "body": { - "crm_organization_user_id":"0011e00000bWSxdAA1", + "crmOrganizationUserId":"0011e00000bWSxdAA1", "description":"", - "due_date":"2023-12-01" + "dueDate":"2023-12-01" }, "accountId": "0011e00000bWSxdAAG", "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" @@ -62,8 +62,8 @@ "description": "Should fail when the note description is not provided", "input": { "body": { - "crm_organization_user_id":"0011e00000bWSxdAA1", - "due_date":"2023-12-01" + "crmOrganizationUserId":"0011e00000bWSxdAA1", + "dueDate":"2023-12-01" }, "accountId": "0011e00000bWSxdAAG", "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" @@ -103,9 +103,9 @@ "description": "Should fail when the account id invalid", "input": { "body": { - "crm_organization_user_id":"0011e00000bWSxdAA1", + "crmOrganizationUserId":"0011e00000bWSxdAA1", "description":"Update remaining documentations", - "due_date":"2023-12-01" + "dueDate":"2023-12-01" }, "accountId": "invalid", "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" @@ -134,7 +134,7 @@ "http_code": 500, "message": "Something went wrong.", "code": "INTERNAL_SERVER_ERROR", - "internal_error_identifier": "l_s_fse_fscn_fcn_2", + "internal_error_identifier": "l_ca_ct_cst_1", "param_errors": [] } } From 085fa07654ff1ba1c308e1086c5034546fb58fcf Mon Sep 17 00:00:00 2001 From: Yagnik Thummar Date: Wed, 23 Aug 2023 12:26:52 +0530 Subject: [PATCH 018/195] Updated statusCode as Created in response. --- .../salessparrow/api/controllers/AccountTaskController.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java b/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java index 0b9439e3..888f3ad0 100644 --- a/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java +++ b/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java @@ -3,6 +3,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PathVariable; @@ -36,6 +37,6 @@ public ResponseEntity createTask( ){ logger.info("Create task request received"); CreateTaskFormatterDto createTaskFormatterDto = createTaskService.createTask(request, accountId, task); - return ResponseEntity.ok().body(createTaskFormatterDto); + return ResponseEntity.status(HttpStatus.CREATED).body(createTaskFormatterDto); } } From 1c730ab8ea1e93c560a12688fd40b3d7a8b3073a Mon Sep 17 00:00:00 2001 From: Yagnik Thummar Date: Wed, 23 Aug 2023 13:21:41 +0530 Subject: [PATCH 019/195] Updated property naming strategies. --- .../api/dto/requestMapper/CreateTaskDto.java | 3 +++ .../createTask.scenarios.json | 16 ++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/salessparrow/api/dto/requestMapper/CreateTaskDto.java b/src/main/java/com/salessparrow/api/dto/requestMapper/CreateTaskDto.java index b4132972..af8135a5 100644 --- a/src/main/java/com/salessparrow/api/dto/requestMapper/CreateTaskDto.java +++ b/src/main/java/com/salessparrow/api/dto/requestMapper/CreateTaskDto.java @@ -1,5 +1,7 @@ package com.salessparrow.api.dto.requestMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; import com.salessparrow.api.lib.customAnnotations.ValidDateFormat; import jakarta.validation.constraints.NotBlank; @@ -7,6 +9,7 @@ import lombok.Data; @Data +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) public class CreateTaskDto { @NotBlank(message = "missing_crm_organization_user_id") diff --git a/src/test/resources/data/controllers/accountTaskController/createTask.scenarios.json b/src/test/resources/data/controllers/accountTaskController/createTask.scenarios.json index a264bbf1..383aa418 100644 --- a/src/test/resources/data/controllers/accountTaskController/createTask.scenarios.json +++ b/src/test/resources/data/controllers/accountTaskController/createTask.scenarios.json @@ -3,9 +3,9 @@ "description": "Should successfully create the note", "input": { "body": { - "crmOrganizationUserId":"0011e00000bWSxdAA1", + "crm_organization_user_id":"0011e00000bWSxdAA1", "description":"Update remaining documentations", - "dueDate":"2023-12-01" + "due_date":"2023-12-01" }, "accountId": "0011e00000bWSxdAAG", "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" @@ -36,9 +36,9 @@ "description": "Should fail when the task description is empty", "input": { "body": { - "crmOrganizationUserId":"0011e00000bWSxdAA1", + "crm_organization_user_id":"0011e00000bWSxdAA1", "description":"", - "dueDate":"2023-12-01" + "due_date":"2023-12-01" }, "accountId": "0011e00000bWSxdAAG", "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" @@ -62,8 +62,8 @@ "description": "Should fail when the note description is not provided", "input": { "body": { - "crmOrganizationUserId":"0011e00000bWSxdAA1", - "dueDate":"2023-12-01" + "crm_organization_user_id":"0011e00000bWSxdAA1", + "due_date":"2023-12-01" }, "accountId": "0011e00000bWSxdAAG", "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" @@ -103,9 +103,9 @@ "description": "Should fail when the account id invalid", "input": { "body": { - "crmOrganizationUserId":"0011e00000bWSxdAA1", + "crm_organization_user_id":"0011e00000bWSxdAA1", "description":"Update remaining documentations", - "dueDate":"2023-12-01" + "due_date":"2023-12-01" }, "accountId": "invalid", "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" From 391c93ee9328328e52878ce7c5ee57925b14d2f3 Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Wed, 23 Aug 2023 13:29:44 +0530 Subject: [PATCH 020/195] Restructured and renamed Account Notes controller and services --- .../api/controllers/AccountController.java | 50 ------------ .../controllers/AccountNoteController.java | 78 +++++++++++++++++++ .../CreateNoteService.java | 2 +- .../GetNoteDetailsService.java | 2 +- .../GetNotesListService.java | 2 +- 5 files changed, 81 insertions(+), 53 deletions(-) create mode 100644 src/main/java/com/salessparrow/api/controllers/AccountNoteController.java rename src/main/java/com/salessparrow/api/services/{accounts => accountNotes}/CreateNoteService.java (95%) rename src/main/java/com/salessparrow/api/services/{accounts => accountNotes}/GetNoteDetailsService.java (94%) rename src/main/java/com/salessparrow/api/services/{accounts => accountNotes}/GetNotesListService.java (94%) diff --git a/src/main/java/com/salessparrow/api/controllers/AccountController.java b/src/main/java/com/salessparrow/api/controllers/AccountController.java index 44058227..18829e72 100644 --- a/src/main/java/com/salessparrow/api/controllers/AccountController.java +++ b/src/main/java/com/salessparrow/api/controllers/AccountController.java @@ -6,22 +6,12 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import com.salessparrow.api.dto.formatter.CreateNoteFormatterDto; import com.salessparrow.api.dto.formatter.GetAccountsFormatterDto; -import com.salessparrow.api.dto.formatter.GetNoteDetailsFormatterDto; -import com.salessparrow.api.dto.formatter.GetNotesListFormatterDto; import com.salessparrow.api.dto.requestMapper.GetAccountsDto; -import com.salessparrow.api.dto.requestMapper.NoteDto; -import com.salessparrow.api.services.accounts.CreateNoteService; import com.salessparrow.api.services.accounts.GetAccountListService; -import com.salessparrow.api.services.accounts.GetNoteDetailsService; -import com.salessparrow.api.services.accounts.GetNotesListService; import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; @@ -36,26 +26,6 @@ public class AccountController { @Autowired private GetAccountListService getAccountListService; - @Autowired - private GetNotesListService getNotesListService; - - @Autowired - private GetNoteDetailsService getNoteDetailsService; - - @Autowired - private CreateNoteService createNoteService; - - @PostMapping("/{account_id}/notes") - public ResponseEntity addNoteToAccount( - HttpServletRequest request, - @PathVariable("account_id") String accountId, - @Valid @RequestBody NoteDto note - ) { - CreateNoteFormatterDto createNoteFormatterDto = createNoteService.createNote(request, accountId, note); - - return ResponseEntity.ok().body(createNoteFormatterDto); - } - @GetMapping("") public ResponseEntity getAccounts( HttpServletRequest request, @@ -66,24 +36,4 @@ public ResponseEntity getAccounts( return ResponseEntity.ok().body(getAccountsResponse); } - - @GetMapping("/{account_id}/notes") - public ResponseEntity getNotesList(HttpServletRequest request,@PathVariable("account_id") String accountId) { - - GetNotesListFormatterDto getNotesListResponse = getNotesListService.getNotesList(request, accountId); - - return ResponseEntity.ok().body(getNotesListResponse); - } - - @GetMapping("/{account_id}/notes/{note_id}") - public ResponseEntity getNoteFromAccount( - HttpServletRequest request, - @PathVariable("account_id") String accountId, - @PathVariable("note_id") String noteId - ) { - - GetNoteDetailsFormatterDto getNoteDetailsResponse = getNoteDetailsService.getNoteDetails(request, noteId); - - return ResponseEntity.ok().body(getNoteDetailsResponse); - } } diff --git a/src/main/java/com/salessparrow/api/controllers/AccountNoteController.java b/src/main/java/com/salessparrow/api/controllers/AccountNoteController.java new file mode 100644 index 00000000..98ec5340 --- /dev/null +++ b/src/main/java/com/salessparrow/api/controllers/AccountNoteController.java @@ -0,0 +1,78 @@ +package com.salessparrow.api.controllers; + +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.salessparrow.api.dto.formatter.CreateNoteFormatterDto; +import com.salessparrow.api.dto.formatter.GetNoteDetailsFormatterDto; +import com.salessparrow.api.dto.formatter.GetNotesListFormatterDto; +import com.salessparrow.api.dto.requestMapper.NoteDto; +import com.salessparrow.api.services.accountNotes.CreateNoteService; +import com.salessparrow.api.services.accountNotes.GetNoteDetailsService; +import com.salessparrow.api.services.accountNotes.GetNotesListService; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.Valid; + +@RestController +@RequestMapping("/api/v1/accounts/{account_id}/notes") +@Validated +public class AccountNoteController { + + private Logger logger = org.slf4j.LoggerFactory.getLogger(AccountController.class); + + @Autowired + private GetNotesListService getNotesListService; + + @Autowired + private GetNoteDetailsService getNoteDetailsService; + + @Autowired + private CreateNoteService createNoteService; + + @PostMapping("") + public ResponseEntity addNoteToAccount( + HttpServletRequest request, + @PathVariable("account_id") String accountId, + @Valid @RequestBody NoteDto note + ) { + logger.info("Create Note request received"); + + CreateNoteFormatterDto createNoteFormatterDto = createNoteService.createNote(request, accountId, note); + + return ResponseEntity.ok().body(createNoteFormatterDto); + } + + @GetMapping("") + public ResponseEntity getNotesList( + HttpServletRequest request, + @PathVariable("account_id") String accountId + ) { + logger.info("Get Note List request received"); + + GetNotesListFormatterDto getNotesListResponse = getNotesListService.getNotesList(request, accountId); + + return ResponseEntity.ok().body(getNotesListResponse); + } + + @GetMapping("/{note_id}") + public ResponseEntity getNoteFromAccount( + HttpServletRequest request, + @PathVariable("account_id") String accountId, + @PathVariable("note_id") String noteId + ) { + logger.info("Get Note request received"); + + GetNoteDetailsFormatterDto getNoteDetailsResponse = getNoteDetailsService.getNoteDetails(request, noteId); + + return ResponseEntity.ok().body(getNoteDetailsResponse); + } +} diff --git a/src/main/java/com/salessparrow/api/services/accounts/CreateNoteService.java b/src/main/java/com/salessparrow/api/services/accountNotes/CreateNoteService.java similarity index 95% rename from src/main/java/com/salessparrow/api/services/accounts/CreateNoteService.java rename to src/main/java/com/salessparrow/api/services/accountNotes/CreateNoteService.java index 5793ebcf..636ee823 100644 --- a/src/main/java/com/salessparrow/api/services/accounts/CreateNoteService.java +++ b/src/main/java/com/salessparrow/api/services/accountNotes/CreateNoteService.java @@ -1,4 +1,4 @@ -package com.salessparrow.api.services.accounts; +package com.salessparrow.api.services.accountNotes; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/salessparrow/api/services/accounts/GetNoteDetailsService.java b/src/main/java/com/salessparrow/api/services/accountNotes/GetNoteDetailsService.java similarity index 94% rename from src/main/java/com/salessparrow/api/services/accounts/GetNoteDetailsService.java rename to src/main/java/com/salessparrow/api/services/accountNotes/GetNoteDetailsService.java index a4af37df..131e4f79 100644 --- a/src/main/java/com/salessparrow/api/services/accounts/GetNoteDetailsService.java +++ b/src/main/java/com/salessparrow/api/services/accountNotes/GetNoteDetailsService.java @@ -1,4 +1,4 @@ -package com.salessparrow.api.services.accounts; +package com.salessparrow.api.services.accountNotes; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/salessparrow/api/services/accounts/GetNotesListService.java b/src/main/java/com/salessparrow/api/services/accountNotes/GetNotesListService.java similarity index 94% rename from src/main/java/com/salessparrow/api/services/accounts/GetNotesListService.java rename to src/main/java/com/salessparrow/api/services/accountNotes/GetNotesListService.java index 2d59f3bd..3e349806 100644 --- a/src/main/java/com/salessparrow/api/services/accounts/GetNotesListService.java +++ b/src/main/java/com/salessparrow/api/services/accountNotes/GetNotesListService.java @@ -1,4 +1,4 @@ -package com.salessparrow.api.services.accounts; +package com.salessparrow.api.services.accountNotes; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; From 6a5def9d4ff3d98f81ab06786aecf64e9e24a11f Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Wed, 23 Aug 2023 16:58:52 +0530 Subject: [PATCH 021/195] feat: run tests in docker with local kms --- .gitignore | 1 + docker-compose.yml | 35 +++++++++++++++++-- init/seed.yaml | 17 +++++++++ secrets.sample.json | 4 ++- ...v_vars-sample.sh => set_env_vars.sample.sh | 0 set_testing_env_vars-sample.sh | 7 ---- .../salessparrow/api/config/AwsConfig.java | 12 +++++++ .../api/config/CoreConstants.java | 16 ++++----- .../api/lib/ErrorEmailService.java | 2 +- .../lib/globalConstants/SecretConstants.java | 16 ++++++--- .../accountController/CreateNoteTest.java | 7 +++- .../accountController/GetNoteDetailsTest.java | 7 +++- .../salessparrow/api/helper/DropTables.java | 2 +- .../createNote.scenarios.json | 31 +++------------- start_local.sh | 6 +++- test_start_local.sh | 8 +++++ 16 files changed, 117 insertions(+), 54 deletions(-) create mode 100644 init/seed.yaml rename set_env_vars-sample.sh => set_env_vars.sample.sh (100%) delete mode 100644 set_testing_env_vars-sample.sh create mode 100644 test_start_local.sh diff --git a/.gitignore b/.gitignore index 75d35479..7b369379 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,7 @@ build/ .env set*_env_vars.sh secrets.json +test.secrets.json ### Logs files ### *.log diff --git a/docker-compose.yml b/docker-compose.yml index 10902f9e..4aa240db 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,5 @@ version: '3' services: - # App server provisioning api: build: context: . @@ -13,7 +12,22 @@ services: - './:/app' command: bash -c 'sh start_local.sh' - # Memcached provisioning + test: + build: + context: . + dockerfile: Dockerfile.local + ports: + - '8080:8080' + networks: + - localdev + volumes: + - './:/app' + command: bash -c 'sh test_start_local.sh' + depends_on: + - dynamodb + - localkms + - memcached + memcached: image: memcached ports: @@ -21,7 +35,22 @@ services: networks: - localdev - # DynamoDB provisioning + localkms: + image: nsmithuk/local-kms + ports: + - '4599:8080' + volumes: + - ./init:/init + networks: + - localdev + environment: + - AWS_ACCESS_KEY_ID='local' + - AWS_SECRET_ACCESS_KEY='local' + - AWS_REGION='us-east-1' + - KMS_ACCOUNT_ID='111122223333' + - KMS_REGION='us-east-1' + - KMS_SEED_PATH=init/seed.yaml + dynamodb: image: amazon/dynamodb-local:latest ports: diff --git a/init/seed.yaml b/init/seed.yaml new file mode 100644 index 00000000..9e4ff9d1 --- /dev/null +++ b/init/seed.yaml @@ -0,0 +1,17 @@ +# This file is used to seed the local KMS instance with keys and aliases. +# The keys and aliases defined here will be created when the KMS instance is +# first started. If the keys or aliases already exist, they will not be +# modified. +# This is for testing purposes only. + +Keys: + Symmetric: + Aes: + - Metadata: + KeyId: bc436485-5092-42b8-92a3-0aa8b93536dc + BackingKeys: + - 5cdaead27fe7da2de47945d73cd6d79e36494e73802f3cd3869f1d2cb0b5d7a9 + +Aliases: + - AliasName: alias/testing + TargetKeyId: bc436485-5092-42b8-92a3-0aa8b93536dc diff --git a/secrets.sample.json b/secrets.sample.json index 70d77fa8..e815a44d 100644 --- a/secrets.sample.json +++ b/secrets.sample.json @@ -12,5 +12,7 @@ "MEMCACHED_CACHE_HOST": "", "MEMCACHED_CACHE_PORT": "", "LOG_LEVEL": "", - "DYNAMO_DB_URL": "" + "DYNAMO_DB_URL": "", + "ERROR_MAIL_FROM": "", + "ERROR_MAIL_TO": "" } \ No newline at end of file diff --git a/set_env_vars-sample.sh b/set_env_vars.sample.sh similarity index 100% rename from set_env_vars-sample.sh rename to set_env_vars.sample.sh diff --git a/set_testing_env_vars-sample.sh b/set_testing_env_vars-sample.sh deleted file mode 100644 index 37f6a1b2..00000000 --- a/set_testing_env_vars-sample.sh +++ /dev/null @@ -1,7 +0,0 @@ -# Application -export ENVIRONMENT='test' - -# AWS -export AWS_IAM_ACCESS_KEY_ID='accessKeyId' -export AWS_IAM_SECRET_ACCESS_KEY='secretAccessKey' -export AWS_IAM_REGION='region' diff --git a/src/main/java/com/salessparrow/api/config/AwsConfig.java b/src/main/java/com/salessparrow/api/config/AwsConfig.java index d5b1ba36..d7f9646e 100644 --- a/src/main/java/com/salessparrow/api/config/AwsConfig.java +++ b/src/main/java/com/salessparrow/api/config/AwsConfig.java @@ -2,6 +2,7 @@ import com.amazonaws.auth.AWSStaticCredentialsProvider; import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.client.builder.AwsClientBuilder; import com.amazonaws.services.kms.AWSKMS; import com.amazonaws.services.kms.AWSKMSClientBuilder; @@ -24,6 +25,17 @@ public class AwsConfig { */ @Bean public AWSKMS kmsClient() { + if (CoreConstants.isTestEnvironment() || CoreConstants.isLocalTestEnvironment()) { + AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder.EndpointConfiguration( + CoreConstants.localKmsEndpoint(), + CoreConstants.awsRegion() + ); + + return AWSKMSClientBuilder.standard() + .withEndpointConfiguration(endpointConfiguration) + .build(); + } + return AWSKMSClientBuilder.standard() .withRegion(CoreConstants.awsRegion()) .build(); diff --git a/src/main/java/com/salessparrow/api/config/CoreConstants.java b/src/main/java/com/salessparrow/api/config/CoreConstants.java index 08da28cc..b55474df 100644 --- a/src/main/java/com/salessparrow/api/config/CoreConstants.java +++ b/src/main/java/com/salessparrow/api/config/CoreConstants.java @@ -12,14 +12,6 @@ public static String environment() { return System.getenv("ENVIRONMENT"); } - public static String awsAccessKeyId() { - return System.getenv("AWS_IAM_ACCESS_KEY_ID"); - } - - public static String awsSecretAccessKey() { - return System.getenv("AWS_IAM_SECRET_ACCESS_KEY"); - } - public static Boolean isDevEnvironment() { return environment().equals("development"); } @@ -28,6 +20,10 @@ public static Boolean isTestEnvironment() { return environment().equals("test"); } + public static Boolean isLocalTestEnvironment() { + return environment().equals("local-test"); + } + /* End: Env variables required before spring application context is initialized */ public static String awsRegion() { @@ -58,6 +54,10 @@ public static String salesforceClientSecret() { return SecretConstants.salesforceClientSecret(); } + public static String localKmsEndpoint() { + return SecretConstants.localKmsEndpoint(); + } + /** * This method returns the memcached address that is going to be used for locals * diff --git a/src/main/java/com/salessparrow/api/lib/ErrorEmailService.java b/src/main/java/com/salessparrow/api/lib/ErrorEmailService.java index 7d523779..ec386105 100644 --- a/src/main/java/com/salessparrow/api/lib/ErrorEmailService.java +++ b/src/main/java/com/salessparrow/api/lib/ErrorEmailService.java @@ -52,7 +52,7 @@ public void sendErrorMail(String contextString, ErrorResponseObject errorObj, + "-" + errorObj.getMessage(); // Send email only if not in dev environment - if (!CoreConstants.isDevEnvironment() && !CoreConstants.isTestEnvironment()) { + if (!CoreConstants.isDevEnvironment() && !CoreConstants.isTestEnvironment() && !CoreConstants.isLocalTestEnvironment()) { sendEmail(CoreConstants.errorEmailFrom(), CoreConstants.errorEmailTo(), subject, body); } else { logger.info("Skip email for development.\n\n subject {} \n body {}", subject, body); diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java index 6a2c9839..10b2e0d0 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java @@ -40,7 +40,9 @@ public static String getSecret(String key) { String secretJson = ""; if (CoreConstants.isDevEnvironment()) { - secretJson = getLocalEnvVars(); + secretJson = getLocalEnvVars("secrets.json"); + } else if (CoreConstants.isLocalTestEnvironment()) { + secretJson = getLocalEnvVars("test.secrets.json"); } else { SecretCache cache = new SecretCache(secretsManagerClientBuilder); String secretId = getSecretId(); @@ -65,7 +67,9 @@ public static String getSecret(String key) { } /** - * This method returns the secret id that is going to be used to access the secrets manager. + * This method returns the secret id that is going to be + * used to access the secrets manager. + * * @return */ private static String getSecretId() { @@ -128,6 +132,10 @@ public static String dynamoDbUrl() { return getSecret("DYNAMO_DB_URL"); } + public static String localKmsEndpoint() { + return getSecret("LOCAL_KMS_ENDPOINT"); + } + /* Secrets end */ /** @@ -135,8 +143,8 @@ public static String dynamoDbUrl() { * * @return String */ - private static String getLocalEnvVars() { - try (FileReader fileReader = new FileReader("secrets.json")) { + private static String getLocalEnvVars(String filename) { + try (FileReader fileReader = new FileReader(filename)) { int ch; StringBuilder secretJsonBuilder = new StringBuilder(); diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/CreateNoteTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/CreateNoteTest.java index 05517248..4d877fd8 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/CreateNoteTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/CreateNoteTest.java @@ -101,7 +101,12 @@ public void createNote(Scenario testScenario) throws Exception { // Check the response String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); - assertEquals(expectedOutput, actualOutput); + + if(resultActions.andReturn().getResponse().getStatus() == 200) { + assertEquals(expectedOutput, actualOutput); + } else { + common.compareErrors(testScenario, actualOutput); + } } static Stream testScenariosProvider() throws IOException { diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java index 8aa54afb..62c65ad6 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java @@ -112,9 +112,14 @@ public void getNoteDetails(Scenario testScenario) throws Exception{ .contentType(MediaType.APPLICATION_JSON)); String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); - String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); + + if(resultActions.andReturn().getResponse().getStatus() == 200) { assertEquals(expectedOutput, actualOutput); + } else { + common.compareErrors(testScenario, actualOutput); + } + } static Stream testScenariosProvider() throws IOException { diff --git a/src/test/java/com/salessparrow/api/helper/DropTables.java b/src/test/java/com/salessparrow/api/helper/DropTables.java index b9ccad92..573b55b4 100644 --- a/src/test/java/com/salessparrow/api/helper/DropTables.java +++ b/src/test/java/com/salessparrow/api/helper/DropTables.java @@ -26,7 +26,7 @@ public class DropTables { * This method is used to drop the tables. */ public void perform() { - if (!CoreConstants.environment().equals("test")) { + if (!CoreConstants.isTestEnvironment() && !CoreConstants.isLocalTestEnvironment()) { throw new RuntimeException("Cannot drop tables in non test environment"); } diff --git a/src/test/resources/data/controllers/accountController/createNote.scenarios.json b/src/test/resources/data/controllers/accountController/createNote.scenarios.json index 76a7eb37..9ccbfb91 100644 --- a/src/test/resources/data/controllers/accountController/createNote.scenarios.json +++ b/src/test/resources/data/controllers/accountController/createNote.scenarios.json @@ -54,15 +54,9 @@ "mocks": {}, "output": { "http_code": 400, - "message": "At least one parameter is invalid or missing.", "code": "INVALID_PARAMS", - "internal_error_identifier": "b_2", "param_errors": [ - { - "parameter": "text", - "param_error_identifier": "missing_text", - "message": "text is required parameter. Please provide text." - } + "missing_text" ] } }, @@ -76,15 +70,9 @@ "mocks": {}, "output": { "http_code": 400, - "message": "At least one parameter is invalid or missing.", "code": "INVALID_PARAMS", - "internal_error_identifier": "b_2", "param_errors": [ - { - "parameter": "text", - "param_error_identifier": "missing_text", - "message": "text is required parameter. Please provide text." - } + "missing_text" ] } }, @@ -98,10 +86,7 @@ "mocks": {}, "output": { "http_code": 401, - "message": "Unauthorized API request. Please check your API key.", - "code": "UNAUTHORIZED", - "internal_error_identifier": "l_ulca_vct_2", - "param_errors": [] + "code": "UNAUTHORIZED" } }, { @@ -147,10 +132,7 @@ }, "output": { "http_code": 500, - "message": "Something went wrong.", - "code": "INTERNAL_SERVER_ERROR", - "internal_error_identifier": "l_s_fse_fscn_fcn_2", - "param_errors": [] + "code": "INTERNAL_SERVER_ERROR" } }, { @@ -194,10 +176,7 @@ }, "output": { "http_code": 500, - "message": "Something went wrong.", - "code": "INTERNAL_SERVER_ERROR", - "internal_error_identifier": "l_s_fse_fscn_fcn_1", - "param_errors": [] + "code": "INTERNAL_SERVER_ERROR" } } ] \ No newline at end of file diff --git a/start_local.sh b/start_local.sh index f1c01049..8ab76672 100644 --- a/start_local.sh +++ b/start_local.sh @@ -1,4 +1,8 @@ #!/usr/bin/env bash -. ./set_env_vars.sh +export ENVIRONMENT='development' +export AWS_ACCESS_KEY_ID='local' +export AWS_SECRET_ACCESS_KEY='local' +export AWS_REGION='us-east-1' + ./mvnw spring-boot:run \ No newline at end of file diff --git a/test_start_local.sh b/test_start_local.sh new file mode 100644 index 00000000..e15478e9 --- /dev/null +++ b/test_start_local.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +export ENVIRONMENT='local-test' +export AWS_ACCESS_KEY_ID='local' +export AWS_SECRET_ACCESS_KEY='local' +export AWS_REGION='us-east-1' + +./mvnw test \ No newline at end of file From 24fbcf83b3ff14b54139be7c3e39bc17a020cc62 Mon Sep 17 00:00:00 2001 From: Yagnik Thummar Date: Wed, 23 Aug 2023 17:03:57 +0530 Subject: [PATCH 022/195] Code review changes. --- .../CreateSalesforceTask.java | 6 +-- .../CreateTaskInAccount.java} | 4 +- .../CreateTaskInAccountFactory.java} | 4 +- .../customAnnotations/ValidDateFormat.java | 2 +- .../helper/MakeCompositeRequest.java | 7 +++ .../accountTask/CreateTaskService.java | 6 +-- .../createTask.scenarios.json | 54 ++++++++++++++++++- 7 files changed, 70 insertions(+), 13 deletions(-) rename src/main/java/com/salessparrow/api/lib/crmActions/{createTask => createTaskInAccount}/CreateSalesforceTask.java (96%) rename src/main/java/com/salessparrow/api/lib/crmActions/{createTask/CreateTask.java => createTaskInAccount/CreateTaskInAccount.java} (79%) rename src/main/java/com/salessparrow/api/lib/crmActions/{createTask/CreateTaskFactory.java => createTaskInAccount/CreateTaskInAccountFactory.java} (93%) diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createTask/CreateSalesforceTask.java b/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateSalesforceTask.java similarity index 96% rename from src/main/java/com/salessparrow/api/lib/crmActions/createTask/CreateSalesforceTask.java rename to src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateSalesforceTask.java index 8fb1079b..a337b9bf 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createTask/CreateSalesforceTask.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateSalesforceTask.java @@ -1,4 +1,4 @@ -package com.salessparrow.api.lib.crmActions.createTask; +package com.salessparrow.api.lib.crmActions.createTaskInAccount; import java.util.ArrayList; import java.util.HashMap; @@ -30,7 +30,7 @@ * CreateSalesforceTask class is responsible for creating a task in Salesforce */ @Component -public class CreateSalesforceTask implements CreateTask{ +public class CreateSalesforceTask implements CreateTaskInAccount{ Logger logger = LoggerFactory.getLogger(AccountTaskController.class); @@ -73,8 +73,6 @@ public CreateTaskFormatterDto createTask(User User, String accountId, CreateTask List compositeRequests = new ArrayList(); compositeRequests.add(createTaskCompositeRequestDto); - logger.info("making composite request to salesforce"); - HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, salesforceUserId); return parseResponse(response.getResponseBody()); diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createTask/CreateTask.java b/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccount.java similarity index 79% rename from src/main/java/com/salessparrow/api/lib/crmActions/createTask/CreateTask.java rename to src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccount.java index 984ecbcd..915cd7aa 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createTask/CreateTask.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccount.java @@ -1,4 +1,4 @@ -package com.salessparrow.api.lib.crmActions.createTask; +package com.salessparrow.api.lib.crmActions.createTaskInAccount; import org.springframework.stereotype.Component; @@ -10,6 +10,6 @@ * CreateTask interface is interface for createTask for various CRM services */ @Component -public interface CreateTask { +public interface CreateTaskInAccount { public CreateTaskFormatterDto createTask(User User,String accountId, CreateTaskDto task); } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createTask/CreateTaskFactory.java b/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccountFactory.java similarity index 93% rename from src/main/java/com/salessparrow/api/lib/crmActions/createTask/CreateTaskFactory.java rename to src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccountFactory.java index 66a1d23a..a7370428 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createTask/CreateTaskFactory.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccountFactory.java @@ -1,4 +1,4 @@ -package com.salessparrow.api.lib.crmActions.createTask; +package com.salessparrow.api.lib.crmActions.createTaskInAccount; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -17,7 +17,7 @@ * CreateTaskFactory class is responsible for creating a task in CRM */ @Component -public class CreateTaskFactory { +public class CreateTaskInAccountFactory { Logger logger = LoggerFactory.getLogger(AccountTaskController.class); diff --git a/src/main/java/com/salessparrow/api/lib/customAnnotations/ValidDateFormat.java b/src/main/java/com/salessparrow/api/lib/customAnnotations/ValidDateFormat.java index f416ecc9..c0965df6 100644 --- a/src/main/java/com/salessparrow/api/lib/customAnnotations/ValidDateFormat.java +++ b/src/main/java/com/salessparrow/api/lib/customAnnotations/ValidDateFormat.java @@ -10,7 +10,7 @@ @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = DateFormatValidator.class) public @interface ValidDateFormat { - String message() default "Invalid redirect URI"; + String message() default "Invalid Date Format"; Class[] groups() default {}; diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/helper/MakeCompositeRequest.java b/src/main/java/com/salessparrow/api/lib/salesforce/helper/MakeCompositeRequest.java index 5e28ec31..952a2b74 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/helper/MakeCompositeRequest.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/helper/MakeCompositeRequest.java @@ -4,9 +4,12 @@ import java.util.List; import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import com.salessparrow.api.controllers.AccountTaskController; import com.salessparrow.api.lib.globalConstants.SalesforceConstants; import com.salessparrow.api.lib.httpLib.HttpClient; import com.salessparrow.api.lib.salesforce.dto.CompositeRequestDto; @@ -17,6 +20,8 @@ @Component public class MakeCompositeRequest { + Logger logger = LoggerFactory.getLogger(AccountTaskController.class); + @Autowired private SalesforceRequest salesforceOauthRequest; @@ -54,6 +59,8 @@ public HttpClient.HttpResponse makePostRequest( }; HttpClient.HttpResponse response = null; + + logger.info("making composite request to salesforce"); response = salesforceOauthRequest.makeRequest(salesforceUserId, request); return response; diff --git a/src/main/java/com/salessparrow/api/services/accountTask/CreateTaskService.java b/src/main/java/com/salessparrow/api/services/accountTask/CreateTaskService.java index 87762080..9da09c97 100644 --- a/src/main/java/com/salessparrow/api/services/accountTask/CreateTaskService.java +++ b/src/main/java/com/salessparrow/api/services/accountTask/CreateTaskService.java @@ -9,7 +9,7 @@ import com.salessparrow.api.domain.User; import com.salessparrow.api.dto.formatter.CreateTaskFormatterDto; import com.salessparrow.api.dto.requestMapper.CreateTaskDto; -import com.salessparrow.api.lib.crmActions.createTask.CreateTaskFactory; +import com.salessparrow.api.lib.crmActions.createTaskInAccount.CreateTaskInAccountFactory; import jakarta.servlet.http.HttpServletRequest; @@ -21,7 +21,7 @@ public class CreateTaskService { Logger logger = LoggerFactory.getLogger(AccountTaskController.class); @Autowired - private CreateTaskFactory createTaskFactory; + private CreateTaskInAccountFactory createTaskInAccountFactory; /** * Create a task in CRM @@ -35,6 +35,6 @@ public class CreateTaskService { public CreateTaskFormatterDto createTask(HttpServletRequest request, String accountId, CreateTaskDto task) { logger.info("inside createTask Service"); User currentUser = (User) request.getAttribute("current_user"); - return createTaskFactory.createTask(currentUser, accountId, task); + return createTaskInAccountFactory.createTask(currentUser, accountId, task); } } diff --git a/src/test/resources/data/controllers/accountTaskController/createTask.scenarios.json b/src/test/resources/data/controllers/accountTaskController/createTask.scenarios.json index 383aa418..8b58be1d 100644 --- a/src/test/resources/data/controllers/accountTaskController/createTask.scenarios.json +++ b/src/test/resources/data/controllers/accountTaskController/createTask.scenarios.json @@ -59,7 +59,7 @@ } }, { - "description": "Should fail when the note description is not provided", + "description": "Should fail when the task description is not provided", "input": { "body": { "crm_organization_user_id":"0011e00000bWSxdAA1", @@ -83,6 +83,58 @@ ] } }, + { + "description": "Should fail when the task Due is not valid", + "input": { + "body": { + "crm_organization_user_id":"0011e00000bWSxdAA1", + "description":"Update remaining documentations", + "due_date":"2023-120-01" + }, + "accountId": "0011e00000bWSxdAAG", + "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + }, + "mocks": {}, + "output": { + "http_code": 400, + "message": "At least one parameter is invalid or missing.", + "code": "INVALID_PARAMS", + "internal_error_identifier": "b_2", + "param_errors": [ + { + "parameter": "due_date", + "param_error_identifier": "invalid_due_date", + "message": "Invalid due date. Please double check and try again." + } + ] + } + }, + { + "description": "Should fail when the task description is too long", + "input": { + "body": { + "crm_organization_user_id":"0011e00000bWSxdAA1", + "description":"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc, quis gravida magna mi a libero. Fusce vulputate eleifend sapien. Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Nullam accumsan lorem in dui. Cras ultricies mi eu turpis hendrerit fringilla. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; In ac dui quis mi consectetuer lacinia. Nam pretium turpis et arcu. Duis arcu tortor, suscipit eget, imperdiet nec, imperdiet iaculis, ipsum. Sed aliquam ultrices mauris. Integer ante arcu, accumsan a, consectetuer eget, posuere ut, mauris. Praesent adipiscing. Phasellus ullamcorper ipsum rutrum nunc. Nunc nonummy metus. Vestibulum volutpat pretium libero. Cras id dui. Aenean ut eros et nisl sagittis vestibulum. Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Sed lectus. Donec mollis hendrerit risus. Phasellus nec sem in justo pellentesque facilisis. Etiam imperdiet imperdiet orci. Nunc nec neque. Phasellus leo dolor, tempus non, auctor et, hendrerit quis, nisi. Curabitur ligula sapien, tincidunt non, euismod vitae, posuere imperdiet, leo. Maecenas malesuada. Praesent congue erat at massa. Sed cursus turpis vitae tortor. Donec posuere vulputate arcu. Phasellus accumsan cursus velit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed aliquam, nisi quis porttitor congue, elit erat euismod orci, ac placerat dolor lectus quis orci. Phasellus consectetuer vestibulum elit. Aenean tellus metus, bibendum sed, posuere ac, mattis non, nunc. Vestibulum fringilla pede sit amet augue. In turpis. Pellentesque posuere. Praesent turpis. Aenean posuere, tortor sed cursus feugiat, nunc augue blandit nunc, eu sollicitudin urna dolor sagittis lacus. Donec elit libero, sodales nec, volutpat a, suscipit non, turpis. Nullam sagittis. Suspendisse pulvinar, augue ac venenatis condimentum, sem libero volutpat nibh, nec pellentesque velit pede quis nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Fusce id purus. Ut varius tincidunt libero. Phasellus dolor. Maecenas vestibulum mollis diam. Pellentesque ut neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. In dui magna, posuere eget, vestibulum et, tempor auctor, justo. In ac felis quis tortor malesuada pretium. Pellentesque auctor neque nec urna. Proin sapien ipsum, porta a, auctor quis, euismod ut, mi. Aenean viverra rhoncus pede. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Ut non enim eleifend felis pretium feugiat. Vivamus quis mi. Phasellus a est. Phasellus magna. In hac habitasse platea dictumst. Curabitur at lacus ac velit ornare lobortis. Curabitur a felis in nunc fringilla tristique. Morbi mattis ullamcorper velit. Phasellus gravida semper nisi. Nullam vel sem. Pellentesque libero tortor, tincidunt et, tincidunt eget, semper nec, quam. Sed hendrerit. Morbi ac felis. Nunc egestas, augue at pellentesque laoreet, felis eros vehicula leo, at malesuada velit leo quis pede. Donec interdum, metus et hendrerit aliquet, dolor diam sagittis ligula, eget egestas libero turpis vel mi. Nunc nulla. Fusce risus nisl, viverra et, tempor et, pretium in, sapien. Donec venenatis vulputate lorem. Morbi nec metus. Phasellus blandit leo ut odio. Maecenas ullamcorper, dui et placerat feugiat, eros pede varius nisi, condimentum viverra felis nunc et lorem. Sed magna purus, fermentum eu, tincidunt eu, varius ut, felis. In auctor lobortis lacus. Quisque libero metus, condimentum nec, tempor a, commodo mollis, magna. Vestibulum ullamcorper mauris at ligula. Fusce fermentum. Nullam cursus lacinia erat. Praesent blandit laoreet nibh. Fusce convallis metus id felis luctus adipiscing. Pellentesque egestas, neque sit amet convallis pulvinar, justo nulla eleifend augue, ac auctor orci leo non est. Quisque id mi. Ut tincidunt tincidunt erat. Etiam feugiat lorem non metus. Vestibulum dapibus nunc ac augue. Curabitur vestibulum aliquam leo. Praesent egestas neque eu enim. In hac habitasse platea dictumst. Fusce a quam. Etiam ut purus mattis mauris sodales aliquam. Curabitur nisi. Quisque malesuada placerat nisl. Nam ipsum risus, rutrum vitae, vestibulum eu, molestie vel, lacus. Sed augue ipsum, egestas nec, vestibulum et, malesuada adipiscing, dui. Vestibulum facilisis, purus nec pulvinar iaculis, ligula mi congue nunc, vitae euismod ligula urna in dolor. Mauris sollicitudin fermentum libero. Praesent nonummy mi in odio. Nunc interdum lacus sit amet orci. Vestibulum rutrum, mi nec elementum vehicula, eros quam gravida nisl, id fringilla neque ante vel mi. Morbi mollis tellus ac sapien. Phasellus volutpat, metus eget egestas mollis, lacus lacus blandit dui, id egestas quam mauris ut lacus. Fusce vel dui. Sed in libero ut nibh placerat accumsan. Proin faucibus arcu quis ante. In consectetuer turpis ut velit. Nulla sit amet est. Praesent metus tellus, elementum eu, semper a, adipiscing nec, purus. Cras risus ipsum, faucibus ut, ullamcorper id, varius ac, leo. Suspendisse feugiat. Suspendisse enim turpis, dictum sed, iaculis a, condimentum nec, nisi. Praesent nec nisl a purus blandit viverra. Praesent ac massa at ligula laoreet iaculis. Nulla neque dolor, sagittis eget, iaculis quis, molestie non, velit. Mauris turpis nunc, blandit et, volutpat molestie, porta ut, ligula. Fusce pharetra convallis urna. Quisque ut nisi. Donec mi odio, faucibus at, scelerisque quis, convallis in, nisi. Suspendisse non nisl sit amet velit hendrerit rutrum. Ut leo. Ut a nisl id ante tempus hendrerit. Proin pretium, leo ac pellentesque mollis, felis nunc ultrices eros, sed gravida augue augue mollis justo. Suspendisse eu ligula. Nulla facilisi. Donec id justo. Praesent porttitor, nulla vitae posuere iaculis, arcu nisl dignissim dolor, a pretium mi sem ut ipsum. Curabitur suscipit suscipit tellus. Praesent vestibulum dapibus nibh. Etiam iaculis nunc ac metus. Ut id nisl quis enim dignissim sagittis. Etiam sollicitudin, ipsum eu pulvinar rutrum, tellus ipsum laoreet sapien, quis venenatis ante odio sit amet eros. Proin magna. Duis vel nibh at velit scelerisque suscipit. Curabitur turpis. Vestibulum suscipit nulla quis orci. Fusce ac felis sit amet ligula pharetra condimentum. Maecenas egestas arcu quis ligula mattis placerat. Duis lobortis massa imperdiet quam. Suspendisse potenti. Pellentesque commodo eros a enim. Vestibulum turpis sem, aliquet eget, lobortis pellentesque, rutrum eu, nisl. Sed libero. Aliquam erat volutpat. Etiam vitae tortor. Morbi vestibulum volutpat enim. Aliquam eu nunc. Nunc sed turpis. Sed mollis, eros et ultrices tempus, mauris ipsum aliquam libero, non adipiscing dolor urna a orci. Nulla porta dolor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Pellentesque dapibus hendrerit tortor. Praesent egestas tristique nibh. Sed a libero. Cras varius. Donec vitae orci sed dolor rutrum auctor. Fusce egestas elit eget lorem. Suspendisse nisl elit, rhoncus eget, elementum ac, condimentum eget, diam. Nam at tortor in tellus interdum sagittis. Aliquam lobortis. Donec orci lectus, aliquam ut, faucibus non, euismod id, nulla. Curabitur blandit mollis lacus. Nam adipiscing. Vestibulum eu odio. Vivamus laoreet. Nullam tincidunt adipiscing enim. Phasellus tempus. Proin viverra, ligula sit amet ultrices semper, ligula arcu tristique sapien, a accumsan nisi mauris ac eros. Fusce neque. Suspendisse faucibus, nunc et pellentesque egestas, lacus ante convallis tellus, vitae iaculis lacus elit id tortor. Vivamus aliquet elit ac nisl. Fusce fermentum odio nec arcu. Vivamus euismod mauris. In ut quam vitae odio lacinia tincidunt. Praesent ut ligula non mi varius sagittis. Cras sagittis. Praesent ac sem eget est egestas volutpat. Vivamus consectetuer hendrerit lacus. Cras non dolor. Vivamus in erat ut urna cursus vestibulum. Fusce commodo aliquam arcu. Nam commodo suscipit quam. Quisque id odio. Praesent venenatis metus at tortor pulvinar varius. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc, quis gravida magna mi a libero. Fusce vulputate eleifend sapien. Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Nullam accumsan lorem in dui. Cras ultricies mi eu turpis hendrerit fringilla. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; In ac dui quis mi consectetuer lacinia. Nam pretium turpis et arcu. Duis arcu tortor, suscipit eget, imperdiet nec, imperdiet iaculis, ipsum. Sed aliquam ultrices mauris. Integer ante arcu, accumsan a, consectetuer eget, posuere ut, mauris. Praesent adipiscing. Phasellus ullamcorper ipsum rutrum nunc. Nunc nonummy metus. Vestibulum volutpat pretium libero. Cras id dui. Aenean ut eros et nisl sagittis vestibulum. Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Sed lectus. Donec mollis hendrerit risus. Phasellus nec sem in justo pellentesque facilisis. Etiam imperdiet imperdiet orci. Nunc nec neque. Phasellus leo dolor, tempus non, auctor et, hendrerit quis, nisi. Curabitur ligula sapien, tincidunt non, euismod vitae, posuere imperdiet, leo. Maecenas malesuada. Praesent congue erat at massa. Sed cursus turpis vitae tortor. Donec posuere vulputate arcu. Phasellus accumsan cursus velit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed aliquam, nisi quis porttitor congue, elit erat euismod orci, ac placerat dolor lectus quis orci. Phasellus consectetuer vestibulum elit. Aenean tellus metus, bibendum sed, posuere ac, mattis non, nunc. Vestibulum fringilla pede sit amet augue. In turpis. Pellentesque posuere. Praesent turpis. Aenean posuere, tortor sed cursus feugiat, nunc augue blandit nunc, eu sollicitudin urna dolor sagittis lacus. Donec elit libero, sodales nec, volutpat a, suscipit non, turpis. Nullam sagittis. Suspendisse pulvinar, augue ac venenatis condimentum, sem libero volutpat nibh, nec pellentesque velit pede quis nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Fusce id purus. Ut varius tincidunt libero. Phasellus dolor. Maecenas vestibulum mollis diam. Pellentesque ut neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. In dui magna, posuere eget, vestibulum et, tempor auctor, justo. In ac felis quis tortor malesuada pretium. Pellentesque auctor neque nec urna. Proin sapien ipsum, porta a, auctor quis, euismod ut, mi. Aenean viverra rhoncus pede. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Ut non enim eleifend felis pretium feugiat. Vivamus quis mi. Phasellus a est. Phasellus magna. In hac habitasse platea dictumst. Curabitur at lacus ac velit ornare lobortis. Curabitur a felis in nunc fringilla tristique. Morbi mattis ullamcorper velit. Phasellus gravida semper nisi. Nullam vel sem. Pellentesque libero tortor, tincidunt et, tincidunt eget, semper nec, quam. Sed hendrerit. Morbi ac felis. Nunc egestas, augue at pellentesque laoreet, felis eros vehicula leo, at malesuada velit leo quis pede. Donec interdum, metus et hendrerit aliquet, dolor diam sagittis ligula, eget egestas libero turpis vel mi. Nunc nulla. Fusce risus nisl, viverra et, tempor et, pretium in, sapien. Donec venenatis vulputate lorem. Morbi nec metus. Phasellus blandit leo ut odio. Maecenas ullamcorper, dui et placerat feugiat, eros pede varius nisi, condimentum viverra felis nunc et lorem. Sed magna purus, fermentum eu, tincidunt eu, varius ut, felis. In auctor lobortis lacus. Quisque libero metus, condimentum nec, tempor a, commodo mollis, magna. Vestibulum ullamcorper mauris at ligula. Fusce fermentum. Nullam cursus lacinia erat. Praesent blandit laoreet nibh. Fusce convallis metus id felis luctus adipiscing. Pellentesque egestas, neque sit amet convallis pulvinar, justo nulla eleifend augue, ac auctor orci leo non est. Quisque id mi. Ut tincidunt tincidunt erat. Etiam feugiat lorem non metus. Vestibulum dapibus nunc ac augue. Curabitur vestibulum aliquam leo. Praesent egestas neque eu enim. In hac habitasse platea dictumst. Fusce a quam. Etiam ut purus mattis mauris sodales aliquam. Curabitur nisi. Quisque malesuada placerat nisl. Nam ipsum risus, rutrum vitae, vestibulum eu, molestie vel, lacus. Sed augue ipsum, egestas nec, vestibulum et, malesuada adipiscing, dui. Vestibulum facilisis, purus nec pulvinar iaculis, ligula mi congue nunc, vitae euismod ligula urna in dolor. Mauris sollicitudin fermentum libero. Praesent nonummy mi in odio. Nunc interdum lacus sit amet orci. Vestibulum rutrum, mi nec elementum vehicula, eros quam gravida nisl, id fringilla neque ante vel mi. Morbi mollis tellus ac sapien. Phasellus volutpat, metus eget egestas mollis, lacus lacus blandit dui, id egestas quam mauris ut lacus. Fusce vel dui. Sed in libero ut nibh placerat accumsan. Proin faucibus arcu quis ante. In consectetuer turpis ut velit. Nulla sit amet est. Praesent metus tellus, elementum eu, semper a, adipiscing nec, purus. Cras risus ipsum, faucibus ut, ullamcorper id, varius ac, leo. Suspendisse feugiat. Suspendisse enim turpis, dictum sed, iaculis a, condimentum nec, nisi. Praesent nec nisl a purus blandit viverra. Praesent ac massa at ligula laoreet iaculis. Nulla neque dolor, sagittis eget, iaculis quis, molestie non, velit. Mauris turpis nunc, blandit et, volutpat molestie, porta ut, ligula. Fusce pharetra convallis urna. Quisque ut nisi. Donec mi odio, faucibus at, scelerisque quis, convallis in, nisi. Suspendisse non nisl sit amet velit hendrerit rutrum. Ut leo. Ut a nisl id ante tempus hendrerit. Proin pretium, leo ac pellentesque mollis, felis nunc ultrices eros, sed gravida augue augue mollis justo. Suspendisse eu ligula. Nulla facilisi. Donec id justo. Praesent porttitor, nulla vitae posuere iaculis, arcu nisl dignissim dolor, a pretium mi sem ut ipsum. Curabitur suscipit suscipit tellus. Praesent vestibulum dapibus nibh. Etiam iaculis nunc ac metus. Ut id nisl quis enim dignissim sagittis. Etiam sollicitudin, ipsum eu pulvinar rutrum, tellus ipsum laoreet sapien, quis venenatis ante odio sit amet eros. Proin magna. Duis vel nibh at velit scelerisque suscipit. Curabitur turpis. Vestibulum suscipit nulla quis orci. Fusce ac felis sit amet ligula pharetra condimentum. Maecenas egestas arcu quis ligula mattis placerat. Duis lobortis massa imperdiet quam. Suspendisse potenti. Pellentesque commodo eros a enim. Vestibulum turpis sem, aliquet eget, lobortis pellentesque, rutrum eu, nisl. Sed libero. Aliquam erat volutpat. Etiam vitae tortor. Morbi vestibulum volutpat enim. Aliquam eu nunc. Nunc sed turpis. Sed mollis, eros et ultrices tempus, mauris ipsum aliquam libero, non adipiscing dolor urna a orci. Nulla porta dolor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Pellentesque dapibus hendrerit tortor. Praesent egestas tristique nibh. Sed a libero. Cras varius. Donec vitae orci sed dolor rutrum auctor. Fusce egestas elit eget lorem. Suspendisse nisl elit, rhoncus eget, elementum ac, condimentum eget, diam. Nam at tortor in tellus interdum sagittis. Aliquam lobortis. Donec orci lectus, aliquam ut, faucibus non, euismod id, nulla. Curabitur blandit mollis lacus. Nam adipiscing. Vestibulum eu odio. Vivamus laoreet. Nullam tincidunt adipiscing enim. Phasellus tempus. Proin viverra, ligula sit amet ultrices semper, ligula arcu tristique sapien, a accumsan nisi mauris ac eros. Fusce neque. Suspendisse faucibus, nunc et pellentesque egestas, lacus ante convallis tellus, vitae iaculis lacus elit id tortor. Vivamus aliquet elit ac nisl. Fusce fermentum odio nec arcu. Vivamus euismod mauris. In ut quam vitae odio lacinia tincidunt. Praesent ut ligula non mi varius sagittis. Cras sagittis. Praesent ac sem eget est egestas volutpat. Vivamus consectetuer hendrerit lacus. Cras non dolor. Vivamus in erat ut urna cursus vestibulum. Fusce commodo aliquam arcu. Nam commodo suscipit quam. Quisque id odio. Praesent venenatis metus at tortor pulvinar varius. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc, quis gravida magna mi a libero. Fusce vulputate eleifend sapien. Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Nullam accumsan lorem in dui. Cras ultricies mi eu turpis hendrerit fringilla. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; In ac dui quis mi consectetuer lacinia. Nam pretium turpis et arcu. Duis arcu tortor, suscipit eget, imperdiet nec, imperdiet iaculis, ipsum. Sed aliquam ultrices mauris. Integer ante arcu, accumsan a, consectetuer eget, posuere ut, mauris. Praesent adipiscing. Phasellus ullamcorper ipsum rutrum nunc. Nunc nonummy metus. Vestibulum volutpat pretium libero. Cras id dui. Aenean ut eros et nisl sagittis vestibulum. Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Sed lectus. Donec mollis hendrerit risus. Phasellus nec sem in justo pellentesque facilisis. Etiam imperdiet imperdiet orci. Nunc nec neque. Phasellus leo dolor, tempus non, auctor et, hendrerit quis, nisi. Curabitur ligula sapien, tincidunt non, euismod vitae, posuere imperdiet, leo. Maecenas malesuada. Praesent congue erat at massa. Sed cursus turpis vitae tortor. Donec posuere vulputate arcu. Phasellus accumsan cursus velit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed aliquam, nisi quis porttitor congue, elit erat euismod orci, ac placerat dolor lectus quis orci. Phasellus consectetuer vestibulum elit. Aenean tellus metus, bibendum sed, posuere ac, mattis non, nunc. Vestibulum fringilla pede sit amet augue. In turpis. Pellentesque posuere. Praesent turpis. Aenean posuere, tortor sed cursus feugiat, nunc augue blandit nunc, eu sollicitudin urna dolor sagittis lacus. Donec elit libero, sodales nec, volutpat a, suscipit non, turpis. Nullam sagittis. Suspendisse pulvinar, augue ac venenatis condimentum, sem libero volutpat nibh, nec pellentesque velit pede quis nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Fusce id purus. Ut varius tincidunt libero. Phasellus dolor. Maecenas vestibulum mollis diam. Pellentesque ut neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. In dui magna, posuere eget, vestibulum et, tempor auctor, justo. In ac felis quis tortor malesuada pretium. Pellentesque auctor neque nec urna. Proin sapien ipsum, porta a, auctor quis, euismod ut, mi. Aenean viverra rhoncus pede. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Ut non enim eleifend felis pretium feugiat. Vivamus quis mi. Phasellus a est. Phasellus magna. In hac habitasse platea dictumst. Curabitur at lacus ac velit ornare lobortis. Curabitur a felis in nunc fringilla tristique. Morbi mattis ullamcorper velit. Phasellus gravida semper nisi. Nullam vel sem. Pellentesque libero tortor, tincidunt et, tincidunt eget, semper nec, quam. Sed hendrerit. Morbi ac felis. Nunc egestas, augue at pellentesque laoreet, felis eros vehicula leo, at malesuada velit leo quis pede. Donec interdum, metus et hendrerit aliquet, dolor diam sagittis ligula, eget egestas libero turpis vel mi. Nunc nulla. Fusce risus nisl, viverra et, tempor et, pretium in, sapien. Donec venenatis vulputate lorem. Morbi nec metus. Phasellus blandit leo ut odio. Maecenas ullamcorper, dui et placerat feugiat, eros pede varius nisi, condimentum viverra felis nunc et lorem. Sed magna purus, fermentum eu, tincidunt eu, varius ut, felis. In auctor lobortis lacus. Quisque libero metus, condimentum nec, tempor a, commodo mollis, magna. Vestibulum ullamcorper mauris at ligula. Fusce fermentum. Nullam cursus lacinia erat. Praesent blandit laoreet nibh. Fusce convallis metus id felis luctus adipiscing. Pellentesque egestas, neque sit amet convallis pulvinar, justo nulla eleifend augue, ac auctor orci leo non est. Quisque id mi. Ut tincidunt tincidunt erat. Etiam feugiat lorem non metus. Vestibulum dapibus nunc ac augue. Curabitur vestibulum aliquam leo. Praesent egestas neque eu enim. In hac habitasse platea dictumst. Fusce a quam. Etiam ut purus mattis mauris sodales aliquam. Curabitur nisi. Quisque malesuada placerat nisl. Nam ipsum risus, rutrum vitae, vestibulum eu, molestie vel, lacus. Sed augue ipsum, egestas nec, vestibulum et, malesuada adipiscing, dui. Vestibulum facilisis, purus nec pulvinar iaculis, ligula mi congue nunc, vitae euismod ligula urna in dolor. Mauris sollicitudin fermentum libero. Praesent nonummy mi in odio. Nunc interdum lacus sit amet orci. Vestibulum rutrum, mi nec elementum vehicula, eros quam gravida nisl, id fringilla neque ante vel mi. Morbi mollis tellus ac sapien. Phasellus volutpat, metus eget egestas mollis, lacus lacus blandit dui, id egestas quam mauris ut lacus. Fusce vel dui. Sed in libero ut nibh placerat accumsan. Proin faucibus arcu quis ante. In consectetuer turpis ut velit. Nulla sit amet est. Praesent metus tellus, elementum eu, semper a, adipiscing nec, purus. Cras risus ipsum, faucibus ut, ullamcorper id, varius ac, leo. Suspendisse feugiat. Suspendisse enim turpis, dictum sed, iaculis a, condimentum nec, nisi. Praesent nec nisl a purus blandit viverra. Praesent ac massa at ligula laoreet iaculis. Nulla neque dolor, sagittis eget, iaculis quis, molestie non, velit. Mauris turpis nunc, blandit et, volutpat molestie, porta ut, ligula. Fusce pharetra convallis urna. Quisque ut nisi. Donec mi odio, faucibus at, scelerisque quis, convallis in, nisi. Suspendisse non nisl sit amet velit hendrerit rutrum. Ut leo. Ut a nisl id ante tempus hendrerit. Proin pretium, leo ac pellentesque mollis, felis nunc ultrices eros, sed gravida augue augue mollis justo. Suspendisse eu ligula. Nulla facilisi. Donec id justo. Praesent porttitor, nulla vitae posuere iaculis, arcu nisl dignissim dolor, a pretium mi sem ut ipsum. Curabitur suscipit suscipit tellus. Praesent vestibulum dapibus nibh. Etiam iaculis nunc ac metus. Ut id nisl quis enim dignissim sagittis. Etiam sollicitudin, ipsum eu pulvinar rutrum, tellus ipsum laoreet sapien, quis venenatis ante odio sit amet eros. Proin magna. Duis vel nibh at velit scelerisque suscipit. Curabitur turpis. Vestibulum suscipit nulla quis orci. Fusce ac felis sit amet ligula pharetra condimentum. Maecenas egestas arcu quis ligula mattis placerat. Duis lobortis massa imperdiet quam. Suspendisse potenti. Pellentesque commodo eros a enim. Vestibulum turpis sem, aliquet eget, lobortis pellentesque, rutrum eu, nisl. Sed libero. Aliquam erat volutpat. Etiam vitae tortor. Morbi vestibulum volutpat enim. Aliquam eu nunc. Nunc sed turpis. Sed mollis, eros et ultrices tempus, mauris ipsum aliquam libero, non adipiscing dolor urna a orci. Nulla porta dolor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Pellentesque dapibus hendrerit tortor. Praesent egestas tristique nibh. Sed a libero. Cras varius. Donec vitae orci sed dolor rutrum auctor. Fusce egestas elit eget lorem. Suspendisse nisl elit, rhoncus eget, elementum ac, condimentum eget, diam. Nam at tortor in tellus interdum sagittis. Aliquam lobortis. Donec orci lectus, aliquam ut, faucibus non, euismod id, nulla. Curabitur blandit mollis lacus. Nam adipiscing. Vestibulum eu odio. Vivamus laoreet. Nullam tincidunt adipiscing enim. Phasellus tempus. Proin viverra, ligula sit amet ultrices semper, ligula arcu tristique sapien, a accumsan nisi mauris ac eros. Fusce neque. Suspendisse faucibus, nunc et pellentesque egestas, lacus ante convallis tellus, vitae iaculis lacus elit id tortor. Vivamus aliquet elit ac nisl. Fusce fermentum odio nec arcu. Vivamus euismod mauris. In ut quam vitae odio lacinia tincidunt. Praesent ut ligula non mi varius sagittis. Cras sagittis. Praesent ac sem eget est egestas volutpat. Vivamus consectetuer hendrerit lacus. Cras non dolor. Vivamus in erat ut urna cursus vestibulum. Fusce commodo aliquam arcu. Nam commodo suscipit quam. Quisque id odio. Praesent venenatis metus at tortor pulvinar varius. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc, quis gravida magna mi a libero. Fusce vulputate eleifend sapien. Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Nullam accumsan lorem in dui. Cras ultricies mi eu turpis hendrerit fringilla. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; In ac dui quis mi consectetuer lacinia. Nam pretium turpis et arcu. Duis arcu tortor, suscipit eget, imperdiet nec, imperdiet iaculis, ipsum. Sed aliquam ultrices mauris. Integer ante arcu, accumsan a, consectetuer eget, posuere ut, mauris. Praesent adipiscing. Phasellus ullamcorper ipsum rutrum nunc. Nunc nonummy metus. Vestibulum volutpat pretium libero. Cras id dui. Aenean ut eros et nisl sagittis vestibulum. Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Sed lectus. Donec mollis hendrerit risus. Phasellus nec sem in justo pellentesque facilisis. Etiam imperdiet imperdiet orci. Nunc nec neque. Phasellus leo dolor, tempus non, auctor et, hendrerit quis, nisi. Curabitur ligula sapien, tincidunt non, euismod vitae, posuere imperdiet, leo. Maecenas malesuada. Praesent congue erat at massa. Sed cursus turpis vitae tortor. Donec posuere vulputate arcu. Phasellus accumsan cursus velit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed aliquam, nisi quis porttitor congue, elit erat euismod orci, ac placerat dolor lectus quis orci. Phasellus consectetuer vestibulum elit. Aenean tellus metus, bibendum sed, posuere ac, mattis non, nunc. Vestibulum fringilla pede sit amet augue. In turpis. Pellentesque posuere. Praesent turpis. Aenean posuere, tortor sed cursus feugiat, nunc augue blandit nunc, eu sollicitudin urna dolor sagittis lacus. Donec elit libero, sodales nec, volutpat a, suscipit non, turpis. Nullam sagittis. Suspendisse pulvinar, augue ac venenatis condimentum, sem libero volutpat nibh, nec pellentesque velit pede quis nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Fusce id purus. Ut varius tincidunt libero. Phasellus dolor. Maecenas vestibulum mollis diam. Pellentesque ut neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. In dui magna, posuere eget, vestibulum et, tempor auctor, justo. In ac felis quis tortor malesuada pretium. Pellentesque auctor neque nec urna. Proin sapien ipsum, porta a, auctor quis, euismod ut, mi. Aenean viverra rhoncus pede. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Ut non enim eleifend felis pretium feugiat. Vivamus quis mi. Phasellus a est. Phasellus magna. In hac habitasse platea dictumst. Curabitur at lacus ac velit ornare lobortis. Curabitur a felis in nunc fringilla tristique. Morbi mattis ullamcorper velit. Phasellus gravida semper nisi. Nullam vel sem. Pellentesque libero tortor, tincidunt et, tincidunt eget, semper nec, quam. Sed hendrerit. Morbi ac felis. Nunc egestas, augue at pellentesque laoreet, felis eros vehicula leo, at malesuada velit leo quis pede. Donec interdum, metus et hendrerit aliquet, dolor diam sagittis ligula, eget egestas libero turpis vel mi. Nunc nulla. Fusce risus nisl, viverra et, tempor et, pretium in, sapien. Donec venenatis vulputate lorem. Morbi nec metus. Phasellus blandit leo ut odio. Maecenas ullamcorper, dui et placerat feugiat, eros pede varius nisi, condimentum viverra felis nunc et lorem. Sed magna purus, fermentum eu, tincidunt eu,", + "due_date":"2023-12-01" + }, + "accountId": "0011e00000bWSxdAAG", + "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + }, + "mocks": {}, + "output": { + "http_code": 400, + "message": "At least one parameter is invalid or missing.", + "code": "INVALID_PARAMS", + "internal_error_identifier": "b_2", + "param_errors": [ + { + "parameter": "description", + "param_error_identifier": "description_too_long", + "message": "Description too long. Please shorten and try again." + } + ] + } + }, { "description": "Should fail when the cookie is invalid", "input": { From e55764f6d5c776d4b9e3384152411c98aa45b132 Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Wed, 23 Aug 2023 18:08:23 +0530 Subject: [PATCH 023/195] Added delete account note endpoint and logic --- .../controllers/AccountNoteController.java | 20 ++- .../DeleteAccountNoteFactory.java | 48 +++++++ .../DeleteAccountNoteInterface.java | 13 ++ .../DeleteSalesforceAccountNote.java | 83 ++++++++++++ .../globalConstants/SalesforceConstants.java | 4 + .../DeleteAccountNoteService.java | 37 +++++ .../DeleteAccountNoteTest.java | 128 ++++++++++++++++++ .../deleteAccountNote.scenarios.json | 53 ++++++++ .../deleteAccountNote.fixtures.json | 14 ++ 9 files changed, 399 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteAccountNoteFactory.java create mode 100644 src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteAccountNoteInterface.java create mode 100644 src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteSalesforceAccountNote.java create mode 100644 src/main/java/com/salessparrow/api/services/accountNotes/DeleteAccountNoteService.java create mode 100644 src/test/java/com/salessparrow/api/functional/controllers/accountNoteController/DeleteAccountNoteTest.java create mode 100644 src/test/resources/data/controllers/accountNoteController/deleteAccountNote.scenarios.json create mode 100644 src/test/resources/fixtures/controllers/accountNoteController/deleteAccountNote.fixtures.json diff --git a/src/main/java/com/salessparrow/api/controllers/AccountNoteController.java b/src/main/java/com/salessparrow/api/controllers/AccountNoteController.java index 98ec5340..ca635531 100644 --- a/src/main/java/com/salessparrow/api/controllers/AccountNoteController.java +++ b/src/main/java/com/salessparrow/api/controllers/AccountNoteController.java @@ -4,6 +4,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @@ -16,6 +17,7 @@ import com.salessparrow.api.dto.formatter.GetNotesListFormatterDto; import com.salessparrow.api.dto.requestMapper.NoteDto; import com.salessparrow.api.services.accountNotes.CreateNoteService; +import com.salessparrow.api.services.accountNotes.DeleteAccountNoteService; import com.salessparrow.api.services.accountNotes.GetNoteDetailsService; import com.salessparrow.api.services.accountNotes.GetNotesListService; @@ -27,7 +29,7 @@ @Validated public class AccountNoteController { - private Logger logger = org.slf4j.LoggerFactory.getLogger(AccountController.class); + private Logger logger = org.slf4j.LoggerFactory.getLogger(AccountNoteController.class); @Autowired private GetNotesListService getNotesListService; @@ -38,6 +40,9 @@ public class AccountNoteController { @Autowired private CreateNoteService createNoteService; + @Autowired + private DeleteAccountNoteService deleteAccountNoteService; + @PostMapping("") public ResponseEntity addNoteToAccount( HttpServletRequest request, @@ -75,4 +80,17 @@ public ResponseEntity getNoteFromAccount( return ResponseEntity.ok().body(getNoteDetailsResponse); } + + @DeleteMapping("/{note_id}") + public ResponseEntity deleteNote( + HttpServletRequest request, + @PathVariable("account_id") String accountId, + @PathVariable("note_id") String noteId + ) { + logger.info("Delete Note request received"); + + deleteAccountNoteService.deleteAcountNote(request, accountId, noteId); + + return ResponseEntity.noContent().build(); + } } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteAccountNoteFactory.java b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteAccountNoteFactory.java new file mode 100644 index 00000000..1774cb63 --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteAccountNoteFactory.java @@ -0,0 +1,48 @@ +package com.salessparrow.api.lib.crmActions.deleteAccountNote; + +import org.slf4j.Logger; +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; + +/** + * DeleteAccountNoteFactory is a factory class for the DeleteAccountNote action for the CRM. + */ +@Component +public class DeleteAccountNoteFactory { + private Logger logger = org.slf4j.LoggerFactory.getLogger(DeleteAccountNoteFactory.class); + + @Autowired + DeleteSalesforceAccountNote getSalesforceNoteDetails; + + @Autowired + DeleteSalesforceAccountNote deleteAccountSalesforceNote; + + /** + * deleteAccountNote is a method that makes call to delete note based on user kind. + * + * @param user + * @param noteId + * + * @return void + */ + public void deleteAccountNote(User user, String noteId) { + logger.info("Delete Account Note Factory called"); + + switch(user.getUserKind()) { + case UserConstants.SALESFORCE_USER_KIND: + deleteAccountSalesforceNote.deleteAccountNote(user, noteId); + break; + default: + throw new CustomException( + new ErrorObject( + "l_ca_dan_danf_dn_1", + "something_went_wrong", + "Invalid user kind.")); + } + } +} diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteAccountNoteInterface.java b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteAccountNoteInterface.java new file mode 100644 index 00000000..59c43a34 --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteAccountNoteInterface.java @@ -0,0 +1,13 @@ +package com.salessparrow.api.lib.crmActions.deleteAccountNote; + +import org.springframework.stereotype.Component; + +import com.salessparrow.api.domain.User; + +/** + * DeleteAccountNoteInterface is an interface for the DeleteAccountNote action for the CRM. + */ +@Component +public interface DeleteAccountNoteInterface { + public void deleteAccountNote(User user, String noteId); +} diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteSalesforceAccountNote.java b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteSalesforceAccountNote.java new file mode 100644 index 00000000..5509fb4d --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteSalesforceAccountNote.java @@ -0,0 +1,83 @@ +package com.salessparrow.api.lib.crmActions.deleteAccountNote; + +import java.util.ArrayList; +import java.util.List; + +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.fasterxml.jackson.databind.JsonNode; +import com.salessparrow.api.domain.User; +import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.lib.Util; +import com.salessparrow.api.lib.errorLib.ErrorObject; +import com.salessparrow.api.lib.globalConstants.SalesforceConstants; +import com.salessparrow.api.lib.httpLib.HttpClient; +import com.salessparrow.api.lib.salesforce.dto.CompositeRequestDto; +import com.salessparrow.api.lib.salesforce.helper.MakeCompositeRequest; + +/** + * DeleteAccountSalesforceNote is a class for the DeleteAccountNote service for the Salesforce CRM. + **/ +@Component +public class DeleteSalesforceAccountNote implements DeleteAccountNoteInterface { + private Logger logger = org.slf4j.LoggerFactory.getLogger(DeleteSalesforceAccountNote.class); + + @Autowired + private SalesforceConstants salesforceConstants; + + @Autowired + private MakeCompositeRequest makeCompositeRequest; + + /** + * Deletes a note from salesforce + * + * @param user + * @param noteId + * + * @return void + **/ + public void deleteAccountNote(User user, String noteId) { + logger.info("Delete Salesforce Account Note called"); + + String salesforceUserId = user.getExternalUserId(); + + String url = salesforceConstants.salesforceDeleteNoteUrl(noteId); + + CompositeRequestDto compositeReq = new CompositeRequestDto("DELETE", url, "DeleteNote"); + + List compositeRequests = new ArrayList(); + compositeRequests.add(compositeReq); + + HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, salesforceUserId); + + parseResponse(response.getResponseBody()); + } + + /** + * Parse Response + * + * @param responseBody + * + * @return void + **/ + public void parseResponse(String responseBody) { + + Util util = new Util(); + JsonNode rootNode = util.getJsonNode(responseBody); + + JsonNode deleteNoteCompositeResponse = rootNode.get("compositeResponse").get(0); + Integer deleteNoteStatusCode = deleteNoteCompositeResponse.get("httpStatusCode").asInt(); + + if (deleteNoteStatusCode != 200 && deleteNoteStatusCode != 201 && deleteNoteStatusCode != 204) { + String errorBody = deleteNoteCompositeResponse.get("body").asText(); + + throw new CustomException( + new ErrorObject( + "l_ca_dan_dasn_pr_1", + "internal_server_error", + errorBody)); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/SalesforceConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/SalesforceConstants.java index d379d8d0..cda58fdb 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/SalesforceConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/SalesforceConstants.java @@ -34,6 +34,10 @@ public String salesforceCreateNoteUrl() { return sObjectsPath() + "/ContentNote"; } + public String salesforceDeleteNoteUrl(String noteId) { + return sObjectsPath() + "/ContentNote/" + noteId; + } + public String salesforceAttachNoteUrl() { return sObjectsPath() + "/ContentDocumentLink"; } diff --git a/src/main/java/com/salessparrow/api/services/accountNotes/DeleteAccountNoteService.java b/src/main/java/com/salessparrow/api/services/accountNotes/DeleteAccountNoteService.java new file mode 100644 index 00000000..7246b832 --- /dev/null +++ b/src/main/java/com/salessparrow/api/services/accountNotes/DeleteAccountNoteService.java @@ -0,0 +1,37 @@ +package com.salessparrow.api.services.accountNotes; + +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.salessparrow.api.domain.User; +import com.salessparrow.api.lib.crmActions.deleteAccountNote.DeleteAccountNoteFactory; + +import jakarta.servlet.http.HttpServletRequest; + +/** + * DeleteAccountNoteService is a service class for the DeleteAccountNote action for the CRM. + */ +@Service +public class DeleteAccountNoteService { + private Logger logger = org.slf4j.LoggerFactory.getLogger(DeleteAccountNoteService.class); + + @Autowired + private DeleteAccountNoteFactory deleteAccountNoteFactory; + + /** + * Delete note for the given note id + * + * @param accountId + * @param noteId + * + * @return void + */ + public void deleteAcountNote(HttpServletRequest request, String accountId, String noteId) { + logger.info("Delete Account Note Service called"); + + User currentUser = (User) request.getAttribute("current_user"); + + deleteAccountNoteFactory.deleteAccountNote(currentUser, noteId); + } +} diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountNoteController/DeleteAccountNoteTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountNoteController/DeleteAccountNoteTest.java new file mode 100644 index 00000000..3bbee4c1 --- /dev/null +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountNoteController/DeleteAccountNoteTest.java @@ -0,0 +1,128 @@ +package com.salessparrow.api.functional.controllers.accountNoteController; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Stream; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +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.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +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; +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 com.salessparrow.api.lib.httpLib.HttpClient.HttpResponse; +import com.salessparrow.api.lib.salesforce.helper.MakeCompositeRequest; + +import jakarta.servlet.http.Cookie; + +@SpringBootTest +@AutoConfigureMockMvc +@WebAppConfiguration +@Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) +public class DeleteAccountNoteTest { + + @Autowired + private MockMvc mockMvc; + @Autowired + private Common common; + @Autowired + private LoadFixture loadFixture; + @Autowired + private Setup setup; + @Autowired + private Cleanup cleanup; + + @MockBean + private MakeCompositeRequest makeCompositeRequestMock; + + @BeforeEach + public void setUp() throws DynamobeeException { + setup.perform(); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + @ParameterizedTest + @MethodSource("testScenariosProvider") + public void deleteAccountNote(Scenario testScenario) throws Exception { + + // Load fixture data + String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/controllers/accountNoteController/deleteAccountNote.fixtures.json", currentFunctionName); + loadFixture.perform(fixtureData); + + // Read data from the scenario + ObjectMapper objectMapper = new ObjectMapper(); + String cookieValue = Constants.SALESFORCE_ACTIVE_USET_COOKIE_VALUE; + String accountId = (String) testScenario.getInput().get("accountId"); + String noteId = (String) testScenario.getInput().get("noteId"); + + // Prepare mock responses + HttpResponse deleteNoteMockResponse = new HttpResponse(); + deleteNoteMockResponse.setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest"))); + when(makeCompositeRequestMock.makePostRequest(any(), any())).thenReturn(deleteNoteMockResponse); + + // Perform the request + String url = "/api/v1/accounts/" + accountId + "/notes/" + noteId ; + + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.delete(url) + .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) + .contentType(MediaType.APPLICATION_JSON)); + + // Check the response + String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); + String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); + assertCustomEquals(expectedOutput, actualOutput); + } + + static Stream testScenariosProvider() throws IOException { + List testScenarios = loadScenarios(); + return testScenarios.stream(); + } + + private static List loadScenarios() throws IOException { + String scenariosPath = "classpath:data/controllers/accountNoteController/deleteAccountNote.scenarios.json"; + Resource resource = new DefaultResourceLoader().getResource(scenariosPath); + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); + } + + // Custom assertion method that treats and <> as the same + public static void assertCustomEquals(String expected, String actual) { + + if (expected.equals("{}")) { + expected = ""; + } + + assertEquals(expected, actual); + } +} diff --git a/src/test/resources/data/controllers/accountNoteController/deleteAccountNote.scenarios.json b/src/test/resources/data/controllers/accountNoteController/deleteAccountNote.scenarios.json new file mode 100644 index 00000000..1fb5d853 --- /dev/null +++ b/src/test/resources/data/controllers/accountNoteController/deleteAccountNote.scenarios.json @@ -0,0 +1,53 @@ +[ + { + "description": "Should successfully delete the note for given note id", + "input": { + "accountId": "0011e00000bWSxdAAG", + "noteId":"0691e000001X1yTAAS" + }, + "mocks": { + "makeCompositeRequest": { + "compositeResponse": [ + { + "body": null, + "httpHeaders": {}, + "httpStatusCode": 204, + "referenceId": "DeleteNote" + } + ] + } + }, + "output": {} + }, + { + "description": "should return error response when note id is invalid", + "input": { + "accountId": "0011e00000bWSxdAAG", + "noteId":"invalidNoteId" + }, + "mocks": { + "makeCompositeRequest": { + "compositeResponse": [ + { + "body": [ + { + "errorCode": "NOT_FOUND", + "message": "Provided external ID field does not exist or is not accessible: INVALID_NOTE_ID" + } + ], + "httpHeaders": {}, + "httpStatusCode": 404, + "referenceId": "DeleteNote" + } + ] + } + }, + "output": { + "http_code": 500, + "message": "Something went wrong.", + "code": "INTERNAL_SERVER_ERROR", + "internal_error_identifier": "l_ca_dan_dasn_pr_1", + "param_errors": [] + } + } +] \ No newline at end of file diff --git a/src/test/resources/fixtures/controllers/accountNoteController/deleteAccountNote.fixtures.json b/src/test/resources/fixtures/controllers/accountNoteController/deleteAccountNote.fixtures.json new file mode 100644 index 00000000..bb801c75 --- /dev/null +++ b/src/test/resources/fixtures/controllers/accountNoteController/deleteAccountNote.fixtures.json @@ -0,0 +1,14 @@ +{ + "deleteAccountNote": { + "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 3ff3bd1f38fe033b1701ee9bc42fea9aa8354a6c Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Wed, 23 Aug 2023 18:10:57 +0530 Subject: [PATCH 024/195] Removed unused import --- .../java/com/salessparrow/api/unit/utility/MemcachedTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/com/salessparrow/api/unit/utility/MemcachedTest.java b/src/test/java/com/salessparrow/api/unit/utility/MemcachedTest.java index 5316e39b..a3941aee 100644 --- a/src/test/java/com/salessparrow/api/unit/utility/MemcachedTest.java +++ b/src/test/java/com/salessparrow/api/unit/utility/MemcachedTest.java @@ -4,7 +4,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mock; -import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.springframework.cache.Cache; From 6cd8503e950cad6ab2f77c74bd1320e1c37120f2 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Wed, 23 Aug 2023 18:17:41 +0530 Subject: [PATCH 025/195] updated env usage in docker for api and test cases --- Dockerfile.local | 4 +--- docker-compose.yml | 18 +++++++++++++-- secrets.sample.json | 2 -- set_env_vars.sample.sh | 7 ------ .../salessparrow/api/config/AwsConfig.java | 22 +++++++++++++++---- start_local.sh | 8 ------- test_start_local.sh | 8 ------- 7 files changed, 35 insertions(+), 34 deletions(-) delete mode 100644 set_env_vars.sample.sh delete mode 100644 start_local.sh delete mode 100644 test_start_local.sh diff --git a/Dockerfile.local b/Dockerfile.local index a2cf669e..66deb042 100644 --- a/Dockerfile.local +++ b/Dockerfile.local @@ -9,6 +9,4 @@ COPY . /app # Expose port 8080 for the app to listen on EXPOSE 8080 # Start the app -RUN apk add --no-cache bash - -CMD ["sh", "-c", "start_local.sh"] \ No newline at end of file +RUN apk add --no-cache bash \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 4aa240db..c85a90bb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,7 +10,16 @@ services: - localdev volumes: - './:/app' - command: bash -c 'sh start_local.sh' + environment: + - ENVIRONMENT=development + - AWS_ACCESS_KEY_ID=local + - AWS_SECRET_ACCESS_KEY=local + - AWS_REGION=us-east-1 + command: ["./mvnw", "spring-boot:run"] + depends_on: + - dynamodb + - localkms + - memcached test: build: @@ -22,7 +31,12 @@ services: - localdev volumes: - './:/app' - command: bash -c 'sh test_start_local.sh' + environment: + - ENVIRONMENT=local-test + - AWS_ACCESS_KEY_ID=local + - AWS_SECRET_ACCESS_KEY=local + - AWS_REGION=us-east-1 + command: ["./mvnw", "clean", "test"] depends_on: - dynamodb - localkms diff --git a/secrets.sample.json b/secrets.sample.json index e815a44d..1f784c95 100644 --- a/secrets.sample.json +++ b/secrets.sample.json @@ -1,8 +1,6 @@ { "ENCRYPTION_KEY": "", "API_COOKIE_SECRET": "", - "AWS_IAM_ACCESS_KEY_ID": "", - "AWS_IAM_SECRET_ACCESS_KEY": "", "AWS_IAM_REGION": "", "KMS_KEY_ID": "", "SALESFORCE_CLIENT_ID": "", diff --git a/set_env_vars.sample.sh b/set_env_vars.sample.sh deleted file mode 100644 index 3acf15b2..00000000 --- a/set_env_vars.sample.sh +++ /dev/null @@ -1,7 +0,0 @@ -# Application -export ENVIRONMENT='development' - -# AWS -export AWS_IAM_ACCESS_KEY_ID='' -export AWS_IAM_SECRET_ACCESS_KEY='' -export AWS_IAM_REGION='' diff --git a/src/main/java/com/salessparrow/api/config/AwsConfig.java b/src/main/java/com/salessparrow/api/config/AwsConfig.java index d7f9646e..9030f53e 100644 --- a/src/main/java/com/salessparrow/api/config/AwsConfig.java +++ b/src/main/java/com/salessparrow/api/config/AwsConfig.java @@ -19,13 +19,27 @@ public class AwsConfig { /** - * Creates and configures an AWS KMS (Key Management Service) client. - * - * @return An instance of AWSKMS that allows access to AWS KMS operations. + * Returns an instance of the AWS Key Management Service (KMS) + * client based on the environment. + * + * @implNote - Client is configured to use the local KMS endpoint for following environments + * - development + * - test + * - local-test + * For test and production environments, the client is configured to use the AWS KMS endpoint + * + * @return An instance of the AWSKMS client configured + * for the appropriate environment. + * */ @Bean public AWSKMS kmsClient() { - if (CoreConstants.isTestEnvironment() || CoreConstants.isLocalTestEnvironment()) { + if ( + CoreConstants.isDevEnvironment() || + CoreConstants.isTestEnvironment() || + CoreConstants.isLocalTestEnvironment() + ) { + AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder.EndpointConfiguration( CoreConstants.localKmsEndpoint(), CoreConstants.awsRegion() diff --git a/start_local.sh b/start_local.sh deleted file mode 100644 index 8ab76672..00000000 --- a/start_local.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -export ENVIRONMENT='development' -export AWS_ACCESS_KEY_ID='local' -export AWS_SECRET_ACCESS_KEY='local' -export AWS_REGION='us-east-1' - -./mvnw spring-boot:run \ No newline at end of file diff --git a/test_start_local.sh b/test_start_local.sh deleted file mode 100644 index e15478e9..00000000 --- a/test_start_local.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -export ENVIRONMENT='local-test' -export AWS_ACCESS_KEY_ID='local' -export AWS_SECRET_ACCESS_KEY='local' -export AWS_REGION='us-east-1' - -./mvnw test \ No newline at end of file From de964a092b370c72c6e3d301526c361ee130fe85 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Wed, 23 Aug 2023 18:18:21 +0530 Subject: [PATCH 026/195] added github workflow to run test cases in standalone environment --- .github/workflows/run_tests.yml | 42 +++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 .github/workflows/run_tests.yml diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml new file mode 100644 index 00000000..c6907106 --- /dev/null +++ b/.github/workflows/run_tests.yml @@ -0,0 +1,42 @@ +name: Run Test Cases + +on: + pull_request: + branches: + - master +env: + ENVIRONMENT: test + AWS_ACCESS_KEY_ID: local + AWS_SECRET_ACCESS_KEY: local + AWS_REGION: us-east-1 + +jobs: + test: + runs-on: ubuntu-latest + services: + memcached: + image: memcached:1.6.21 + ports: + - 11211:11211 + dynamodb: + image: amazon/dynamodb-local:latest + ports: + - 8000:8000 + localkms: + image: nsmithuk/local-kms + ports: + - 4599:8080 + + steps: + - uses: actions/checkout@v3 + + - name: Set up JDK 17 + uses: actions/setup-java@v2 + with: + java-version: '17' + distribution: 'adopt' + + - run: |- + echo "Start: test case run" + sh ./mvnw clean test + echo "Done: test case run" \ No newline at end of file From 687e6f23238f23023b2ecdacfb6391bb1ebe71b0 Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Wed, 23 Aug 2023 18:45:40 +0530 Subject: [PATCH 027/195] Renamed and Restructured Notes to Account Notes --- .../api/controllers/AccountNoteController.java | 12 ++++++------ .../CreateNoteFactory.java | 2 +- .../CreateNoteInterface.java | 2 +- .../CreateSalesforceNote.java | 2 +- .../GetAccountNoteDetails.java} | 4 ++-- .../GetAccountNoteDetailsFactory.java} | 6 +++--- .../GetSalesforceAccountNoteDetails.java} | 4 ++-- .../GetAccountNoteListFactory.java} | 6 +++--- .../GetAccountNotesList.java} | 4 ++-- .../GetSalesforceAccountNotesList.java} | 4 ++-- ...oteService.java => CreateAccountNoteService.java} | 4 ++-- ...ervice.java => GetAccountNoteDetailsService.java} | 6 +++--- ...tService.java => GetAccountNotesListService.java} | 6 +++--- 13 files changed, 31 insertions(+), 31 deletions(-) rename src/main/java/com/salessparrow/api/lib/crmActions/{createNote => createAccountNote}/CreateNoteFactory.java (94%) rename src/main/java/com/salessparrow/api/lib/crmActions/{createNote => createAccountNote}/CreateNoteInterface.java (88%) rename src/main/java/com/salessparrow/api/lib/crmActions/{createNote => createAccountNote}/CreateSalesforceNote.java (98%) rename src/main/java/com/salessparrow/api/lib/crmActions/{getNoteDetails/GetNoteDetails.java => getAccountNoteDetails/GetAccountNoteDetails.java} (75%) rename src/main/java/com/salessparrow/api/lib/crmActions/{getNoteDetails/GetNoteDetailsFactory.java => getAccountNoteDetails/GetAccountNoteDetailsFactory.java} (86%) rename src/main/java/com/salessparrow/api/lib/crmActions/{getNoteDetails/GetSalesforceNoteDetails.java => getAccountNoteDetails/GetSalesforceAccountNoteDetails.java} (97%) rename src/main/java/com/salessparrow/api/lib/crmActions/{getNotesList/GetNoteListFactory.java => getAccountNotesList/GetAccountNoteListFactory.java} (86%) rename src/main/java/com/salessparrow/api/lib/crmActions/{getNotesList/GetNotesList.java => getAccountNotesList/GetAccountNotesList.java} (76%) rename src/main/java/com/salessparrow/api/lib/crmActions/{getNotesList/GetSalesforceNotesList.java => getAccountNotesList/GetSalesforceAccountNotesList.java} (98%) rename src/main/java/com/salessparrow/api/services/accountNotes/{CreateNoteService.java => CreateAccountNoteService.java} (88%) rename src/main/java/com/salessparrow/api/services/accountNotes/{GetNoteDetailsService.java => GetAccountNoteDetailsService.java} (80%) rename src/main/java/com/salessparrow/api/services/accountNotes/{GetNotesListService.java => GetAccountNotesListService.java} (81%) diff --git a/src/main/java/com/salessparrow/api/controllers/AccountNoteController.java b/src/main/java/com/salessparrow/api/controllers/AccountNoteController.java index ca635531..6c1a0eff 100644 --- a/src/main/java/com/salessparrow/api/controllers/AccountNoteController.java +++ b/src/main/java/com/salessparrow/api/controllers/AccountNoteController.java @@ -16,10 +16,10 @@ import com.salessparrow.api.dto.formatter.GetNoteDetailsFormatterDto; import com.salessparrow.api.dto.formatter.GetNotesListFormatterDto; import com.salessparrow.api.dto.requestMapper.NoteDto; -import com.salessparrow.api.services.accountNotes.CreateNoteService; +import com.salessparrow.api.services.accountNotes.CreateAccountNoteService; import com.salessparrow.api.services.accountNotes.DeleteAccountNoteService; -import com.salessparrow.api.services.accountNotes.GetNoteDetailsService; -import com.salessparrow.api.services.accountNotes.GetNotesListService; +import com.salessparrow.api.services.accountNotes.GetAccountNoteDetailsService; +import com.salessparrow.api.services.accountNotes.GetAccountNotesListService; import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; @@ -32,13 +32,13 @@ public class AccountNoteController { private Logger logger = org.slf4j.LoggerFactory.getLogger(AccountNoteController.class); @Autowired - private GetNotesListService getNotesListService; + private GetAccountNotesListService getNotesListService; @Autowired - private GetNoteDetailsService getNoteDetailsService; + private GetAccountNoteDetailsService getNoteDetailsService; @Autowired - private CreateNoteService createNoteService; + private CreateAccountNoteService createNoteService; @Autowired private DeleteAccountNoteService deleteAccountNoteService; diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createNote/CreateNoteFactory.java b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateNoteFactory.java similarity index 94% rename from src/main/java/com/salessparrow/api/lib/crmActions/createNote/CreateNoteFactory.java rename to src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateNoteFactory.java index 99b4dfee..86d5e17e 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createNote/CreateNoteFactory.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateNoteFactory.java @@ -1,4 +1,4 @@ -package com.salessparrow.api.lib.crmActions.createNote; +package com.salessparrow.api.lib.crmActions.createAccountNote; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createNote/CreateNoteInterface.java b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateNoteInterface.java similarity index 88% rename from src/main/java/com/salessparrow/api/lib/crmActions/createNote/CreateNoteInterface.java rename to src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateNoteInterface.java index 0d3903db..29a8301e 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createNote/CreateNoteInterface.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateNoteInterface.java @@ -1,4 +1,4 @@ -package com.salessparrow.api.lib.crmActions.createNote; +package com.salessparrow.api.lib.crmActions.createAccountNote; import org.springframework.stereotype.Component; diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createNote/CreateSalesforceNote.java b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java similarity index 98% rename from src/main/java/com/salessparrow/api/lib/crmActions/createNote/CreateSalesforceNote.java rename to src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java index 0665a8ff..c3742d16 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createNote/CreateSalesforceNote.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java @@ -1,4 +1,4 @@ -package com.salessparrow.api.lib.crmActions.createNote; +package com.salessparrow.api.lib.crmActions.createAccountNote; import java.util.ArrayList; import java.util.HashMap; diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getNoteDetails/GetNoteDetails.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNoteDetails/GetAccountNoteDetails.java similarity index 75% rename from src/main/java/com/salessparrow/api/lib/crmActions/getNoteDetails/GetNoteDetails.java rename to src/main/java/com/salessparrow/api/lib/crmActions/getAccountNoteDetails/GetAccountNoteDetails.java index f774626c..a8a0677a 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getNoteDetails/GetNoteDetails.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNoteDetails/GetAccountNoteDetails.java @@ -1,4 +1,4 @@ -package com.salessparrow.api.lib.crmActions.getNoteDetails; +package com.salessparrow.api.lib.crmActions.getAccountNoteDetails; import org.springframework.stereotype.Component; @@ -9,6 +9,6 @@ * GetNoteDetails is an interface for the GetNoteDetails action for the CRM. */ @Component -public interface GetNoteDetails { +public interface GetAccountNoteDetails { public GetNoteDetailsFormatterDto getNoteDetails(User user, String noteId); } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getNoteDetails/GetNoteDetailsFactory.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNoteDetails/GetAccountNoteDetailsFactory.java similarity index 86% rename from src/main/java/com/salessparrow/api/lib/crmActions/getNoteDetails/GetNoteDetailsFactory.java rename to src/main/java/com/salessparrow/api/lib/crmActions/getAccountNoteDetails/GetAccountNoteDetailsFactory.java index 41754968..fa9b715b 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getNoteDetails/GetNoteDetailsFactory.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNoteDetails/GetAccountNoteDetailsFactory.java @@ -1,4 +1,4 @@ -package com.salessparrow.api.lib.crmActions.getNoteDetails; +package com.salessparrow.api.lib.crmActions.getAccountNoteDetails; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -13,9 +13,9 @@ * GetNoteDetailsFactory is a factory class for the GetNoteDetails action for the CRM. */ @Component -public class GetNoteDetailsFactory { +public class GetAccountNoteDetailsFactory { @Autowired - GetSalesforceNoteDetails getSalesforceNoteDetails; + GetSalesforceAccountNoteDetails getSalesforceNoteDetails; /** * getNoteDetails is a method that returns the details of a note. diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getNoteDetails/GetSalesforceNoteDetails.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNoteDetails/GetSalesforceAccountNoteDetails.java similarity index 97% rename from src/main/java/com/salessparrow/api/lib/crmActions/getNoteDetails/GetSalesforceNoteDetails.java rename to src/main/java/com/salessparrow/api/lib/crmActions/getAccountNoteDetails/GetSalesforceAccountNoteDetails.java index bac6f1ea..183ae279 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getNoteDetails/GetSalesforceNoteDetails.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNoteDetails/GetSalesforceAccountNoteDetails.java @@ -1,4 +1,4 @@ -package com.salessparrow.api.lib.crmActions.getNoteDetails; +package com.salessparrow.api.lib.crmActions.getAccountNoteDetails; import java.util.ArrayList; import java.util.List; @@ -24,7 +24,7 @@ import com.salessparrow.api.lib.salesforce.helper.SalesforceQueryBuilder; @Component -public class GetSalesforceNoteDetails implements GetNoteDetails { +public class GetSalesforceAccountNoteDetails implements GetAccountNoteDetails { @Autowired private SalesforceConstants salesforceConstants; diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getNotesList/GetNoteListFactory.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNotesList/GetAccountNoteListFactory.java similarity index 86% rename from src/main/java/com/salessparrow/api/lib/crmActions/getNotesList/GetNoteListFactory.java rename to src/main/java/com/salessparrow/api/lib/crmActions/getAccountNotesList/GetAccountNoteListFactory.java index 3556e5db..462d11ca 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getNotesList/GetNoteListFactory.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNotesList/GetAccountNoteListFactory.java @@ -1,4 +1,4 @@ -package com.salessparrow.api.lib.crmActions.getNotesList; +package com.salessparrow.api.lib.crmActions.getAccountNotesList; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -14,9 +14,9 @@ * CRM. */ @Component -public class GetNoteListFactory { +public class GetAccountNoteListFactory { @Autowired - private GetSalesforceNotesList getSalesforceNotesList; + private GetSalesforceAccountNotesList getSalesforceNotesList; /** * Get the list of notes for a given account. diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getNotesList/GetNotesList.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNotesList/GetAccountNotesList.java similarity index 76% rename from src/main/java/com/salessparrow/api/lib/crmActions/getNotesList/GetNotesList.java rename to src/main/java/com/salessparrow/api/lib/crmActions/getAccountNotesList/GetAccountNotesList.java index 7d4ba68e..1bc60ac7 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getNotesList/GetNotesList.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNotesList/GetAccountNotesList.java @@ -1,4 +1,4 @@ -package com.salessparrow.api.lib.crmActions.getNotesList; +package com.salessparrow.api.lib.crmActions.getAccountNotesList; import org.springframework.stereotype.Component; @@ -9,7 +9,7 @@ * GetNotesList is an interface for the GetNotesList action for the CRM. */ @Component -public interface GetNotesList { +public interface GetAccountNotesList { public GetNotesListFormatterDto getNotesList(User user, String accountId); } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getNotesList/GetSalesforceNotesList.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNotesList/GetSalesforceAccountNotesList.java similarity index 98% rename from src/main/java/com/salessparrow/api/lib/crmActions/getNotesList/GetSalesforceNotesList.java rename to src/main/java/com/salessparrow/api/lib/crmActions/getAccountNotesList/GetSalesforceAccountNotesList.java index c6bb9ba9..0618e186 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getNotesList/GetSalesforceNotesList.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNotesList/GetSalesforceAccountNotesList.java @@ -1,4 +1,4 @@ -package com.salessparrow.api.lib.crmActions.getNotesList; +package com.salessparrow.api.lib.crmActions.getAccountNotesList; import java.util.ArrayList; import java.util.HashMap; @@ -29,7 +29,7 @@ * GetSalesforceNotesList is a class for the GetNotesList service for the Salesforce CRM. */ @Component -public class GetSalesforceNotesList implements GetNotesList{ +public class GetSalesforceAccountNotesList implements GetAccountNotesList{ @Autowired private SalesforceConstants salesforceConstants; diff --git a/src/main/java/com/salessparrow/api/services/accountNotes/CreateNoteService.java b/src/main/java/com/salessparrow/api/services/accountNotes/CreateAccountNoteService.java similarity index 88% rename from src/main/java/com/salessparrow/api/services/accountNotes/CreateNoteService.java rename to src/main/java/com/salessparrow/api/services/accountNotes/CreateAccountNoteService.java index 636ee823..0105fe9c 100644 --- a/src/main/java/com/salessparrow/api/services/accountNotes/CreateNoteService.java +++ b/src/main/java/com/salessparrow/api/services/accountNotes/CreateAccountNoteService.java @@ -6,7 +6,7 @@ import com.salessparrow.api.domain.SalesforceUser; import com.salessparrow.api.dto.formatter.CreateNoteFormatterDto; import com.salessparrow.api.dto.requestMapper.NoteDto; -import com.salessparrow.api.lib.crmActions.createNote.CreateNoteFactory; +import com.salessparrow.api.lib.crmActions.createAccountNote.CreateNoteFactory; import jakarta.servlet.http.HttpServletRequest; @@ -14,7 +14,7 @@ * CreateNoteService is a service class for the create note action for the CRM. */ @Service -public class CreateNoteService { +public class CreateAccountNoteService { @Autowired private CreateNoteFactory createNoteFactory; diff --git a/src/main/java/com/salessparrow/api/services/accountNotes/GetNoteDetailsService.java b/src/main/java/com/salessparrow/api/services/accountNotes/GetAccountNoteDetailsService.java similarity index 80% rename from src/main/java/com/salessparrow/api/services/accountNotes/GetNoteDetailsService.java rename to src/main/java/com/salessparrow/api/services/accountNotes/GetAccountNoteDetailsService.java index 131e4f79..342328d7 100644 --- a/src/main/java/com/salessparrow/api/services/accountNotes/GetNoteDetailsService.java +++ b/src/main/java/com/salessparrow/api/services/accountNotes/GetAccountNoteDetailsService.java @@ -5,7 +5,7 @@ import com.salessparrow.api.domain.User; import com.salessparrow.api.dto.formatter.GetNoteDetailsFormatterDto; -import com.salessparrow.api.lib.crmActions.getNoteDetails.GetNoteDetailsFactory; +import com.salessparrow.api.lib.crmActions.getAccountNoteDetails.GetAccountNoteDetailsFactory; import jakarta.servlet.http.HttpServletRequest; @@ -13,9 +13,9 @@ * GetNoteDetailsService is a service class for the GetNoteDetails action for the CRM. */ @Service -public class GetNoteDetailsService { +public class GetAccountNoteDetailsService { @Autowired - private GetNoteDetailsFactory getNoteDetailsFactory; + private GetAccountNoteDetailsFactory getNoteDetailsFactory; /** * Get the details of a note diff --git a/src/main/java/com/salessparrow/api/services/accountNotes/GetNotesListService.java b/src/main/java/com/salessparrow/api/services/accountNotes/GetAccountNotesListService.java similarity index 81% rename from src/main/java/com/salessparrow/api/services/accountNotes/GetNotesListService.java rename to src/main/java/com/salessparrow/api/services/accountNotes/GetAccountNotesListService.java index 3e349806..16da0d23 100644 --- a/src/main/java/com/salessparrow/api/services/accountNotes/GetNotesListService.java +++ b/src/main/java/com/salessparrow/api/services/accountNotes/GetAccountNotesListService.java @@ -7,15 +7,15 @@ import com.salessparrow.api.domain.User; import com.salessparrow.api.dto.formatter.GetNotesListFormatterDto; -import com.salessparrow.api.lib.crmActions.getNotesList.GetNoteListFactory; +import com.salessparrow.api.lib.crmActions.getAccountNotesList.GetAccountNoteListFactory; /** * GetNotesListService is a service class for the GetNotesList action for the CRM. */ @Service -public class GetNotesListService { +public class GetAccountNotesListService { @Autowired - private GetNoteListFactory getNotesListFactory; + private GetAccountNoteListFactory getNotesListFactory; /** * Get the list of notes for a given account From f724b8820b530c3f34d1d2f56e2b7015887a30ee Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Wed, 23 Aug 2023 19:22:35 +0530 Subject: [PATCH 028/195] updated run test cases workflow --- .github/workflows/run_tests.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index c6907106..290da34f 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -18,14 +18,22 @@ jobs: image: memcached:1.6.21 ports: - 11211:11211 + dynamodb: image: amazon/dynamodb-local:latest ports: - 8000:8000 + localkms: image: nsmithuk/local-kms ports: - 4599:8080 + volumes: + - ./init:/init + env: + KMS_ACCOUNT_ID: '111122223333' + KMS_REGION: 'us-east-1' + KMS_SEED_PATH: init/seed.yaml steps: - uses: actions/checkout@v3 From 8f6e4719734a28a7ff0d37088fb813f117ebaedc Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Wed, 23 Aug 2023 19:26:36 +0530 Subject: [PATCH 029/195] committing to test github workflow --- .github/workflows/run_tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index 290da34f..fe8e241f 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -45,6 +45,6 @@ jobs: distribution: 'adopt' - run: |- - echo "Start: test case run" + echo "Start: run test cases" sh ./mvnw clean test - echo "Done: test case run" \ No newline at end of file + echo "Done: run test cases" \ No newline at end of file From 7fabd8c1b5199552529a07b412483717e85db3f8 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 24 Aug 2023 10:20:31 +0530 Subject: [PATCH 030/195] added logs for debugging run test workflow --- .../com/salessparrow/api/config/DynamoDBConfiguration.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java index caf5b383..374ae91e 100644 --- a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java +++ b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java @@ -51,6 +51,10 @@ public AmazonDynamoDB buildAmazonDynamoDB() { @Bean DynamoDBMapperConfig dynamoDBMapperConfig() { + System.out.println("Environment: --- " + CoreConstants.environment()); + + System.out.println("AWS_ACCESS_KEY_ID: --- " + System.getenv("AWS_ACCESS_KEY_ID")); + String prefix = CoreConstants.environment() + "_"; return new DynamoDBMapperConfig.Builder() .withTableNameOverride(DynamoDBMapperConfig.TableNameOverride.withTableNamePrefix(prefix)) From 081957c369d791772f2011cce5846080559b215b Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 24 Aug 2023 10:32:37 +0530 Subject: [PATCH 031/195] updated secret manager provider to use default credentials --- .../api/config/DynamoDBConfiguration.java | 90 +++++++++---------- .../lib/globalConstants/SecretConstants.java | 6 +- 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java index 374ae91e..071eb0e9 100644 --- a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java +++ b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java @@ -14,51 +14,49 @@ @Configuration public class DynamoDBConfiguration { - Logger logger = LoggerFactory.getLogger(DynamoDBConfiguration.class); - - @Bean - public DynamoDBMapper dynamoDBMapper() { - DynamoDBMapper defaultMapper = new DynamoDBMapper(buildAmazonDynamoDB(), dynamoDBMapperConfig()); - - //Override DynamoDb operations to add logging. - return new DynamoDBMapper(buildAmazonDynamoDB(), dynamoDBMapperConfig()) { - - @Override - public T load(Class clazz, Object hashKey) { - logger.debug("DBQuery:Load: table-{} hashKey-{}", clazz.getSimpleName(), hashKey); - return defaultMapper.load(clazz, hashKey); - } - - @Override - public void save(T object) { - logger.debug("DBQuery:Save: table-{}", object.getClass().getSimpleName()); - defaultMapper.save(object); - } - // 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(); - } - - @Bean - DynamoDBMapperConfig dynamoDBMapperConfig() { - System.out.println("Environment: --- " + CoreConstants.environment()); - - System.out.println("AWS_ACCESS_KEY_ID: --- " + System.getenv("AWS_ACCESS_KEY_ID")); - - String prefix = CoreConstants.environment() + "_"; - return new DynamoDBMapperConfig.Builder() - .withTableNameOverride(DynamoDBMapperConfig.TableNameOverride.withTableNamePrefix(prefix)) - .build(); - } + Logger logger = LoggerFactory.getLogger(DynamoDBConfiguration.class); + + @Bean + public DynamoDBMapper dynamoDBMapper() { + DynamoDBMapper defaultMapper = new DynamoDBMapper(buildAmazonDynamoDB(), dynamoDBMapperConfig()); + //Override DynamoDb operations to add logging. + return new DynamoDBMapper(buildAmazonDynamoDB(), dynamoDBMapperConfig()) { + @Override + public T load(Class clazz, Object hashKey) { + logger.debug("DBQuery:Load: table-{} hashKey-{}", clazz.getSimpleName(), hashKey); + return defaultMapper.load(clazz, hashKey); + } + + @Override + public void save(T object) { + logger.debug("DBQuery:Save: table-{}", object.getClass().getSimpleName()); + defaultMapper.save(object); + } + // 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(); + } + + @Bean + DynamoDBMapperConfig dynamoDBMapperConfig() { + System.out.println("Environment: --- " + CoreConstants.environment()); + + System.out.println("AWS_ACCESS_KEY_ID: --- " + System.getenv("AWS_ACCESS_KEY_ID")); + + String prefix = CoreConstants.environment() + "_"; + return new DynamoDBMapperConfig.Builder() + .withTableNameOverride(DynamoDBMapperConfig.TableNameOverride.withTableNamePrefix(prefix)) + .build(); + } } diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java index 10b2e0d0..fb1b2403 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java @@ -27,8 +27,10 @@ public class SecretConstants { /** * This is the builder that is going to be used to access the secrets manager. */ - public static SecretsManagerClientBuilder secretsManagerClientBuilder = SecretsManagerClient.builder() - .credentialsProvider(InstanceProfileCredentialsProvider.builder().build()); + // public static SecretsManagerClientBuilder secretsManagerClientBuilder = SecretsManagerClient.builder() + // .credentialsProvider(InstanceProfileCredentialsProvider.builder().build()); + + public static SecretsManagerClientBuilder secretsManagerClientBuilder = SecretsManagerClient.builder(); /** * This method returns the secrets from the secrets manager. From 2354f2684312393adc63fa002593ca2c97a216cb Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 24 Aug 2023 10:39:37 +0530 Subject: [PATCH 032/195] added logs for debugging run test workflow --- .../com/salessparrow/api/config/DynamoDBConfiguration.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java index 071eb0e9..33ad4814 100644 --- a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java +++ b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java @@ -38,6 +38,9 @@ public void save(T object) { @Bean public AmazonDynamoDB buildAmazonDynamoDB() { + System.out.println("buildAmazonDynamoDB Environment: --- " + CoreConstants.environment()); + + System.out.println("buildAmazonDynamoDB AWS_ACCESS_KEY_ID: --- " + System.getenv("AWS_ACCESS_KEY_ID")); return AmazonDynamoDBClientBuilder .standard() .withEndpointConfiguration( From 661dbf38205d4c016511b98b105fa5f009d74c08 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 24 Aug 2023 10:44:54 +0530 Subject: [PATCH 033/195] added logs for debugging run test workflow --- .github/workflows/run_tests.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index fe8e241f..6fbb60d9 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -46,5 +46,9 @@ jobs: - run: |- echo "Start: run test cases" + echo "ENVIRONMENT: $ENVIRONMENT" + echo "AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID" + echo "AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY" + echo "AWS_REGION: $AWS_REGION" sh ./mvnw clean test echo "Done: run test cases" \ No newline at end of file From aa961e889f5444af54d5f7578d1ba97384ddaa9e Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 24 Aug 2023 10:48:47 +0530 Subject: [PATCH 034/195] added logs for debugging run test workflow --- .../com/salessparrow/api/config/DynamoDBConfiguration.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java index 33ad4814..fe194a39 100644 --- a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java +++ b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java @@ -39,7 +39,8 @@ public void save(T object) { @Bean public AmazonDynamoDB buildAmazonDynamoDB() { System.out.println("buildAmazonDynamoDB Environment: --- " + CoreConstants.environment()); - + System.out.println("CoreConstants.dynamoDbUrl(): ----- " + CoreConstants.dynamoDbUrl()); + System.out.println("CoreConstants.awsRegion(): ----- " + CoreConstants.awsRegion()); System.out.println("buildAmazonDynamoDB AWS_ACCESS_KEY_ID: --- " + System.getenv("AWS_ACCESS_KEY_ID")); return AmazonDynamoDBClientBuilder .standard() From 185c551a9a5d614b2be60cfeff2352b8999ad6e5 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 24 Aug 2023 12:23:44 +0530 Subject: [PATCH 035/195] Removed duplicate run test workflow --- .github/workflows/run_tests.yaml | 38 +++++++++++++++++++++- .github/workflows/run_tests.yml | 54 -------------------------------- 2 files changed, 37 insertions(+), 55 deletions(-) delete mode 100644 .github/workflows/run_tests.yml diff --git a/.github/workflows/run_tests.yaml b/.github/workflows/run_tests.yaml index a632bc95..6fbb60d9 100644 --- a/.github/workflows/run_tests.yaml +++ b/.github/workflows/run_tests.yaml @@ -13,6 +13,42 @@ env: jobs: test: runs-on: ubuntu-latest + services: + memcached: + image: memcached:1.6.21 + ports: + - 11211:11211 + + dynamodb: + image: amazon/dynamodb-local:latest + ports: + - 8000:8000 + + localkms: + image: nsmithuk/local-kms + ports: + - 4599:8080 + volumes: + - ./init:/init + env: + KMS_ACCOUNT_ID: '111122223333' + KMS_REGION: 'us-east-1' + KMS_SEED_PATH: init/seed.yaml + steps: + - uses: actions/checkout@v3 + + - name: Set up JDK 17 + uses: actions/setup-java@v2 + with: + java-version: '17' + distribution: 'adopt' + - run: |- - echo "Running test cases" \ No newline at end of file + echo "Start: run test cases" + echo "ENVIRONMENT: $ENVIRONMENT" + echo "AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID" + echo "AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY" + echo "AWS_REGION: $AWS_REGION" + sh ./mvnw clean test + echo "Done: run test cases" \ No newline at end of file diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml deleted file mode 100644 index 6fbb60d9..00000000 --- a/.github/workflows/run_tests.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: Run Test Cases - -on: - pull_request: - branches: - - master -env: - ENVIRONMENT: test - AWS_ACCESS_KEY_ID: local - AWS_SECRET_ACCESS_KEY: local - AWS_REGION: us-east-1 - -jobs: - test: - runs-on: ubuntu-latest - services: - memcached: - image: memcached:1.6.21 - ports: - - 11211:11211 - - dynamodb: - image: amazon/dynamodb-local:latest - ports: - - 8000:8000 - - localkms: - image: nsmithuk/local-kms - ports: - - 4599:8080 - volumes: - - ./init:/init - env: - KMS_ACCOUNT_ID: '111122223333' - KMS_REGION: 'us-east-1' - KMS_SEED_PATH: init/seed.yaml - - steps: - - uses: actions/checkout@v3 - - - name: Set up JDK 17 - uses: actions/setup-java@v2 - with: - java-version: '17' - distribution: 'adopt' - - - run: |- - echo "Start: run test cases" - echo "ENVIRONMENT: $ENVIRONMENT" - echo "AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID" - echo "AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY" - echo "AWS_REGION: $AWS_REGION" - sh ./mvnw clean test - echo "Done: run test cases" \ No newline at end of file From cb5216d6a1564f460cc44e74d2be8eec1408b984 Mon Sep 17 00:00:00 2001 From: Yagnik Thummar Date: Thu, 24 Aug 2023 13:21:43 +0530 Subject: [PATCH 036/195] Added test cases for get crm user list api. --- .../CrmOrganizationUserController.java | 25 ++++ .../GetCrmorganizationUsersListTest.java | 122 ++++++++++++++++ .../getCrmOrganizationUserList.scenarios.json | 135 ++++++++++++++++++ .../getCrmOrganizationUserList.fixtures.json | 14 ++ 4 files changed, 296 insertions(+) create mode 100644 src/main/java/com/salessparrow/api/controllers/CrmOrganizationUserController.java create mode 100644 src/test/java/com/salessparrow/api/functional/controllers/crmOrganizationUserController/GetCrmorganizationUsersListTest.java create mode 100644 src/test/resources/data/controllers/crmOrganizationUserController/getCrmOrganizationUserList.scenarios.json create mode 100644 src/test/resources/fixtures/controllers/crmOrganizationUserController/getCrmOrganizationUserList.fixtures.json diff --git a/src/main/java/com/salessparrow/api/controllers/CrmOrganizationUserController.java b/src/main/java/com/salessparrow/api/controllers/CrmOrganizationUserController.java new file mode 100644 index 00000000..3057b635 --- /dev/null +++ b/src/main/java/com/salessparrow/api/controllers/CrmOrganizationUserController.java @@ -0,0 +1,25 @@ +package com.salessparrow.api.controllers; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import jakarta.validation.constraints.Positive; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + + +@RestController +@RequestMapping("/api/v1/crm-organization-users") +public class CrmOrganizationUserController { + Logger logger = LoggerFactory.getLogger(CrmOrganizationUserController.class); + + @PostMapping("") + public void createCrmOrganizationUser( + @Positive @RequestBody String crmOrganizationUserId + ){ + logger.info("Create crm organization user request received"); + } + +} diff --git a/src/test/java/com/salessparrow/api/functional/controllers/crmOrganizationUserController/GetCrmorganizationUsersListTest.java b/src/test/java/com/salessparrow/api/functional/controllers/crmOrganizationUserController/GetCrmorganizationUsersListTest.java new file mode 100644 index 00000000..1b471608 --- /dev/null +++ b/src/test/java/com/salessparrow/api/functional/controllers/crmOrganizationUserController/GetCrmorganizationUsersListTest.java @@ -0,0 +1,122 @@ +package com.salessparrow.api.functional.controllers.crmOrganizationUserController; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Stream; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +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.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +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.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.dynamobee.exception.DynamobeeException; +import com.salessparrow.api.helper.Cleanup; +import com.salessparrow.api.helper.Common; +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 com.salessparrow.api.lib.httpLib.HttpClient.HttpResponse; +import com.salessparrow.api.lib.salesforce.helper.MakeCompositeRequest; + +import jakarta.servlet.http.Cookie; + +@SpringBootTest +@AutoConfigureMockMvc +@WebAppConfiguration +@Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) +public class GetCrmorganizationUsersListTest { + @Autowired + private MockMvc mockMvc; + @Autowired + private Common common; + @Autowired + private LoadFixture loadFixture; + @Autowired + private Setup setup; + @Autowired + private Cleanup cleanup; + + @MockBean + private MakeCompositeRequest makeCompositeRequestMock; + + @BeforeEach + public void setUp() throws DynamobeeException { + setup.perform(); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + @ParameterizedTest + @MethodSource("testScenariosProvider") + public void getAccountList(Scenario testScenario) throws Exception { + // Load fixture data + String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/controllers/crmOrganizationUserController/getCrmOrganizationUserList.fixtures.json", currentFunctionName); + loadFixture.perform(fixtureData); + + // Read data from the scenario + ObjectMapper objectMapper = new ObjectMapper(); + + String cookieValue = (String) testScenario.getInput().get("cookieValue"); + String q = (String) testScenario.getInput().get("q"); + + // Prepare mock responses + HttpResponse getAccountMockResponse = new HttpResponse(); + getAccountMockResponse.setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest"))); + when(makeCompositeRequestMock.makePostRequest(any(), any())).thenReturn(getAccountMockResponse); + + // Perform the request + String url = "/api/v1/crm-organization-user"; + + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get(url) + .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) + .param("q", q) + .contentType(MediaType.APPLICATION_JSON)); + + + // Check the response + String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); + String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); + + JsonNode expectedOutputJson = objectMapper.readTree(expectedOutput); + JsonNode actualOutputJson = objectMapper.readTree(actualOutput); + + assertEquals(expectedOutputJson, actualOutputJson); + } + + static Stream testScenariosProvider() throws IOException { + List testScenarios = loadScenarios(); + return testScenarios.stream(); + } + + private static List loadScenarios() throws IOException { + String scenariosPath = "classpath:data/controllers/crmOrganizationUserController/getCrmOrganizationUserList.scenarios.json"; + Resource resource = new DefaultResourceLoader().getResource(scenariosPath); + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); + } +} diff --git a/src/test/resources/data/controllers/crmOrganizationUserController/getCrmOrganizationUserList.scenarios.json b/src/test/resources/data/controllers/crmOrganizationUserController/getCrmOrganizationUserList.scenarios.json new file mode 100644 index 00000000..9e694170 --- /dev/null +++ b/src/test/resources/data/controllers/crmOrganizationUserController/getCrmOrganizationUserList.scenarios.json @@ -0,0 +1,135 @@ +[ + { + "description": "Should return the list of crm Users", + "input": { + "q": "a", + "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + }, + "mocks": { + "makeCompositeRequest": { + "compositeResponse": [ + { + "body": { + "totalSize": 2, + "done": true, + "records": [ + { + "attributes": { + "type": "User", + "url": "/services/data/v58.0/sobjects/User/0051e0000047G03AAE" + }, + "Id": "0051e0000047G03AAE", + "Name": "Alpesh Modi" + }, + { + "attributes": { + "type": "User", + "url": "/services/data/v58.0/sobjects/User/0051e000004NQ6fAAG" + }, + "Id": "0051e000004NQ6fAAG", + "Name": "Aman Barbaria" + } + ] + }, + "httpHeaders": {}, + "httpStatusCode": 200, + "referenceId": "getAccounts" + } + ] + } + }, + "output": { + "account_ids": [ + "0051e0000047G03AAE", + "0051e000004NQ6fAAG" + ], + "account_map_by_id": { + "0051e0000047G03AAE": { + "id": "0051e0000047G03AAE", + "name": "Alpesh Modi" + }, + "0051e000004NQ6fAAG": { + "id": "0051e000004NQ6fAAG", + "name": "Aman Barbaria" + } + } + } + }, + { + "description": "Should return the list of crm users sorted by modified date on empty search string", + "input": { + "q": "", + "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + }, + "mocks": { + "makeCompositeRequest": { + "compositeResponse": [ + { + "body": { + "totalSize": 2, + "done": true, + "records": [ + { + "attributes": { + "type": "User", + "url": "/services/data/v58.0/sobjects/User/0051e0000047G03AAE" + }, + "Id": "0051e0000047G03AAE", + "Name": "Alpesh Modi" + }, + { + "attributes": { + "type": "User", + "url": "/services/data/v58.0/sobjects/User/0051e000004NQ6fAAG" + }, + "Id": "0051e000004NQ6fAAG", + "Name": "Aman Barbaria" + } + ] + }, + "httpHeaders": {}, + "httpStatusCode": 200, + "referenceId": "getAccounts" + } + ] + } + }, + "output": { + "account_ids": [ + "0051e0000047G03AAE", + "0051e000004NQ6fAAG" + ], + "account_map_by_id": { + "0051e0000047G03AAE": { + "id": "0051e0000047G03AAE", + "name": "Alpesh Modi" + }, + "0051e000004NQ6fAAG": { + "id": "0051e000004NQ6fAAG", + "name": "Aman Barbaria" + } + } + } + }, + { + "description": "Should return error if search string length > 200", + "input": { + "q": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", + "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + }, + "mocks": {}, + "output": { + "http_code": 400, + "message": "At least one parameter is invalid or missing.", + "code": "INVALID_PARAMS", + "internal_error_identifier": "b_2", + "param_errors": [ + { + "parameter": "q", + "param_error_identifier": "search_term_too_long", + "message": "Search term too long. Please shorten and try again." + } + ] + } + } + ] \ No newline at end of file diff --git a/src/test/resources/fixtures/controllers/crmOrganizationUserController/getCrmOrganizationUserList.fixtures.json b/src/test/resources/fixtures/controllers/crmOrganizationUserController/getCrmOrganizationUserList.fixtures.json new file mode 100644 index 00000000..f994ae5b --- /dev/null +++ b/src/test/resources/fixtures/controllers/crmOrganizationUserController/getCrmOrganizationUserList.fixtures.json @@ -0,0 +1,14 @@ +{ + "getCrmOrganizationUserList": { + "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 c9c87903c3226336a21927cea0018c6b1809a27e Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 24 Aug 2023 14:08:07 +0530 Subject: [PATCH 037/195] added environment vars documentation --- Dockerfile.local | 3 - ENVIRONMENT_VARS.md | 78 +++++++++++++++ LOCAL_SETUP.md | 111 +++++++++++++-------- README.md | 3 + docker-compose.yml | 2 +- pom.xml | 2 +- secrets.sample.json => sample.secrets.json | 0 7 files changed, 152 insertions(+), 47 deletions(-) create mode 100644 ENVIRONMENT_VARS.md rename secrets.sample.json => sample.secrets.json (100%) diff --git a/Dockerfile.local b/Dockerfile.local index 66deb042..a87cfc83 100644 --- a/Dockerfile.local +++ b/Dockerfile.local @@ -1,12 +1,9 @@ FROM openjdk:17-jdk-alpine -# Set working directory RUN mkdir -p /app WORKDIR /app COPY . /app -# Expose port 8080 for the app to listen on EXPOSE 8080 -# Start the app RUN apk add --no-cache bash \ No newline at end of file diff --git a/ENVIRONMENT_VARS.md b/ENVIRONMENT_VARS.md new file mode 100644 index 00000000..26125cbc --- /dev/null +++ b/ENVIRONMENT_VARS.md @@ -0,0 +1,78 @@ +# Environment Variables Description + +This document provides descriptions for the environment variables used in the configuration of the Sales Sparrow api. These variables are essential for configuring and customizing the behavior of the application. + +## ENCRYPTION_KEY + +- **Description:** A key used for encryption purposes. This is a random string with alphanumeric values. +- **Example Value:** `7Fh9E2jRwDpV6gYcBqXsL` + +## API_COOKIE_SECRET + +- **Description:** Secret key for encrypting API cookies. This is a random string with alphanumeric values. +- **Example Value:** `7Fh9E2jRwDpV6gYcBqXsL` + +## AWS_IAM_REGION + +- **Description:** The AWS region for IAM (Identity and Access Management) services. +- **Example Value:** `us-east-1` + +## KMS_KEY_ID + +- **Description:** Amazon Resource Name (ARN) of the KMS (Key Management Service) key used for encryption. +- **Example Value:** `arn:aws:kms:'us-east-1':'111122223333':key/bc436485-5092-42b8-92a3-0aa8b93536dc` + +## SALESFORCE_CLIENT_ID + +- **Description:** Client ID for authenticating with Salesforce APIs. +- **Example Value:** `12345asdf` + +## SALESFORCE_CLIENT_SECRET + +- **Description:** Client secret for authenticating with Salesforce APIs. +- **Example Value:** `12345asdf` + +## SALESFORCE_AUTH_URL + +- **Description:** URL for Salesforce authentication. +- **Example Value:** `https://test.salesforce.com` + +## SALESFORCE_WHITELISTED_REDIRECT_URIS + +- **Description:** Comma-separated list of URIs allowed as redirect URIs for Salesforce authentication. +- **Example Value:** `http://localhost:3000,example://oauth/success` + +## MEMCACHED_CACHE_HOST + +- **Description:** Hostname of the Memcached cache server. +- **Example Value:** `memcached` + +## MEMCACHED_CACHE_PORT + +- **Description:** Port number for connecting to the Memcached cache server. +- **Example Value:** `11211` + +## DYNAMO_DB_URL + +- **Description:** URL for connecting to the DynamoDB server. +- **Example Value:** `http://dynamodb:8000` + +## LOCAL_KMS_ENDPOINT + +- **Description:** Endpoint for the local KMS (Key Management Service) server. +- **Example Value:** `http://localkms:8080` + +## ERROR_MAIL_FROM + +- **Description:** Email address used as the sender for error notifications. +- **Example Value:** `fromtest@test.com` + +## ERROR_MAIL_TO + +- **Description:** Email address where error notifications are sent. +- **Example Value:** `totest@test.com` + +## LOG_LEVEL + +- **Description:** Logging level for the application. +- **Example Value:** `debug` diff --git a/LOCAL_SETUP.md b/LOCAL_SETUP.md index 6161cf16..d037c6dd 100644 --- a/LOCAL_SETUP.md +++ b/LOCAL_SETUP.md @@ -1,60 +1,87 @@ -### Prerequisites and System Requirements - -Before using the *Sales Sparrow* apis, make sure your development environment meets the following prerequisites and system requirements: -* For Docker **(Recommended)** - - Docker version 4.19.0 or newer -* Without Docker - - Java 17 - - You can download it from [here](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html). - - Dynamo DB Local Setup - - Download the dynamodb local jar(noSQL Workbench) from [here](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/workbench.settingup.html) - - Install and run the noSQL Workbench on your local machine - - Toggle *DDB local* option from bottom of the left sidemenu to turn it on. - - Add a local connection from the operation builder tab +# Sales Sparrow APIs: Getting Started Guide + +## Prerequisites and System Requirements + +Before using the *Sales Sparrow* APIs, make sure your development environment meets the following prerequisites and system requirements: + +### Using Docker (Recommended) + +- Docker version 4.19.0 or newer + +### Without Docker + +- Java 17 + - Download it from [Oracle's official website](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html). +- DynamoDB Local Setup + - Download the DynamoDB Local JAR (NoSQL Workbench) from [here](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/workbench.settingup.html). + - Install and run the NoSQL Workbench on your local machine. + - Toggle the *DDB local* option from the bottom of the left-side menu to turn it on. + - Add a local connection from the operation builder tab. ## Getting Started + To clone the project and install dependencies, follow these steps: -### Clone the project +### Clone the Project -``` +```sh $ git clone git@github.com:TrueSparrowSystems/AI-SalesSparrow-API.git + $ cd AI-SalesSparrow-API ``` -### Clone the AI-SalesSparrow-Docs submodule ### -``` +### Clone the AI-SalesSparrow-Docs Submodule + +```sh $ git submodule update --init ``` ### Set Environment Variables -1. Copy the contents of set_env_vars-sample.sh to set_env_vars.sh -2. Update the values of the environment variables in set_env_vars.sh - - Salesforce credentials needs to be copied from the salesforce connected app - - Aws credentials needs to be copied from the aws account -### Start servers with docker +1. Copy the contents of `sample.secrets.json` to `secrets.json`. +2. Update the values of the environment variables in secrets.json: + - Copy Salesforce credentials from the Salesforce connected app and update `SALESFORCE_CLIENT_ID`, `SALESFORCE_CLIENT_SECRET`, `SALESFORCE_AUTH_URL`. + - Update `KMS_KEY_ID` with value `arn:aws:kms:'us-east-1':'111122223333':key/bc436485-5092-42b8-92a3-0aa8b93536dc`. This local Docker setup uses the [local-kms](https://hub.docker.com/r/nsmithuk/local-kms) Docker image, and the key is already configured using [seed](init/seed.yaml). + +### Start the API Server with Docker + +```sh +$ docker-compose up api ``` -$ docker-compose up + +### Run Test Cases with Docker + +#### Set Test-Related Environment Variables + +1. Create a `test.secrets.json` file: +```sh +$ touch test.secrets.json +``` + +2. Add the following environment variables to `test.secrets.json`: +```json +{ + "ENCRYPTION_KEY": "1234567890", + "API_COOKIE_SECRET": "1234567890", + "AWS_IAM_REGION": "us-east-1", + "KMS_KEY_ID": "arn:aws:kms:'us-east-1':'111122223333':key/bc436485-5092-42b8-92a3-0aa8b93536dc", + "SALESFORCE_CLIENT_ID": "12345", + "SALESFORCE_CLIENT_SECRET": "12345", + "SALESFORCE_AUTH_URL": "https://test.salesforce.com", + "SALESFORCE_WHITELISTED_REDIRECT_URIS": "http://localhost:3000", + "MEMCACHED_CACHE_HOST": "memcached", + "MEMCACHED_CACHE_PORT": "11211", + "LOG_LEVEL": "debug", + "DYNAMO_DB_URL": "http://dynamodb:8000", + "LOCAL_KMS_ENDPOINT": "http://localkms:8080", + "ERROR_MAIL_FROM": "", + "ERROR_MAIL_TO": "" +} ``` -### Start servers without docker +#### Run Test Cases + +```sh +$ docker-compose run test ``` -$ source set_env_vars.sh -$ ./mvnw spring-boot:run - ``` - - **To install new dependencies** - ``` - $ ./mvnw clean install -Dmaven.test.skip - ``` - - **To run test cases** - ``` - $ ./mvnw clean test - ``` - - **To run test cases and generate coverage report** - ``` - $ ./mvnw clean test jacoco:report - ``` \ No newline at end of file +To view the test coverage, simply open the target/site/index.html file in a web browser. \ No newline at end of file diff --git a/README.md b/README.md index b6474fd3..6083592f 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,9 @@ This repository contains salessparrow apis. ## Local Setup Please follow the steps in [LOCAL_SETUP](LOCAL_SETUP.md) to setup the project locally. +## Environment Variables +Please refer to [ENVIRONMENT_VARS](ENVIRONMENT_VARS.md) for detailed descriptions for the environment variables. + ## Project Structure Please refer to [PROJECT_STRUCTURE](PROJECT_STRUCTURE.md) for details on the project structure. diff --git a/docker-compose.yml b/docker-compose.yml index c85a90bb..9f8347c3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -36,7 +36,7 @@ services: - AWS_ACCESS_KEY_ID=local - AWS_SECRET_ACCESS_KEY=local - AWS_REGION=us-east-1 - command: ["./mvnw", "clean", "test"] + command: ["./mvnw", "clean", "test", "jacoco:report"] depends_on: - dynamodb - localkms diff --git a/pom.xml b/pom.xml index ce18e8c7..a9fc3384 100644 --- a/pom.xml +++ b/pom.xml @@ -137,7 +137,7 @@ software.amazon.awssdk secretsmanager - 2.20.130 + 2.20.132 diff --git a/secrets.sample.json b/sample.secrets.json similarity index 100% rename from secrets.sample.json rename to sample.secrets.json From f62b57f77e841f2cf7be724286eebadde65fb9f5 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 24 Aug 2023 15:18:55 +0530 Subject: [PATCH 038/195] started using aws credentials from github secrets for run test workflow --- .github/workflows/run_tests.yaml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/run_tests.yaml b/.github/workflows/run_tests.yaml index 6fbb60d9..13181bf0 100644 --- a/.github/workflows/run_tests.yaml +++ b/.github/workflows/run_tests.yaml @@ -6,8 +6,8 @@ on: - master env: ENVIRONMENT: test - AWS_ACCESS_KEY_ID: local - AWS_SECRET_ACCESS_KEY: local + AWS_ACCESS_KEY_ID: ${{ secrets.PLG_PROD_ACCESS_KEY }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.PLG_PROD_SECRET_KEY }} AWS_REGION: us-east-1 jobs: @@ -46,9 +46,5 @@ jobs: - run: |- echo "Start: run test cases" - echo "ENVIRONMENT: $ENVIRONMENT" - echo "AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID" - echo "AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY" - echo "AWS_REGION: $AWS_REGION" sh ./mvnw clean test echo "Done: run test cases" \ No newline at end of file From 3cd0eb8030cfeb4b98a620ee1de23855638bad91 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 24 Aug 2023 15:43:42 +0530 Subject: [PATCH 039/195] removed logs added for debugging --- .../salessparrow/api/config/DynamoDBConfiguration.java | 8 -------- .../controllers/accountController/GetAccountListTest.java | 2 -- 2 files changed, 10 deletions(-) diff --git a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java index fe194a39..1cf12223 100644 --- a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java +++ b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java @@ -38,10 +38,6 @@ public void save(T object) { @Bean public AmazonDynamoDB buildAmazonDynamoDB() { - System.out.println("buildAmazonDynamoDB Environment: --- " + CoreConstants.environment()); - System.out.println("CoreConstants.dynamoDbUrl(): ----- " + CoreConstants.dynamoDbUrl()); - System.out.println("CoreConstants.awsRegion(): ----- " + CoreConstants.awsRegion()); - System.out.println("buildAmazonDynamoDB AWS_ACCESS_KEY_ID: --- " + System.getenv("AWS_ACCESS_KEY_ID")); return AmazonDynamoDBClientBuilder .standard() .withEndpointConfiguration( @@ -53,10 +49,6 @@ public AmazonDynamoDB buildAmazonDynamoDB() { @Bean DynamoDBMapperConfig dynamoDBMapperConfig() { - System.out.println("Environment: --- " + CoreConstants.environment()); - - System.out.println("AWS_ACCESS_KEY_ID: --- " + System.getenv("AWS_ACCESS_KEY_ID")); - String prefix = CoreConstants.environment() + "_"; return new DynamoDBMapperConfig.Builder() .withTableNameOverride(DynamoDBMapperConfig.TableNameOverride.withTableNamePrefix(prefix)) diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java index a472b658..1ff0a3f9 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java @@ -77,7 +77,6 @@ public void getAccountList(Scenario testScenario) throws Exception { // Load fixture data String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); FixtureData fixtureData = common.loadFixture("classpath:fixtures/controllers/accountController/getAccountList.fixtures.json", currentFunctionName); - System.out.println("fixtureData++++++ "+fixtureData); loadFixture.perform(fixtureData); // Read data from the scenario @@ -92,7 +91,6 @@ public void getAccountList(Scenario testScenario) throws Exception { // Perform the request String url = "/api/v1/accounts"; String q = objectMapper.writeValueAsString(testScenario.getInput().get("q")); - System.out.println("q++++++ "+q); ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get(url) .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) From bb2fa6a04ec2073921ff74286edc4c06f8d8250e Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 24 Aug 2023 15:49:44 +0530 Subject: [PATCH 040/195] fixed indentation for fixtures: get note details and get note list --- .../getNoteDetails.fixtures.json | 26 +++++++++---------- .../getNotesList.fixtures.json | 26 +++++++++---------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/test/resources/fixtures/controllers/accountController/getNoteDetails.fixtures.json b/src/test/resources/fixtures/controllers/accountController/getNoteDetails.fixtures.json index a8f387c8..0f64e59e 100644 --- a/src/test/resources/fixtures/controllers/accountController/getNoteDetails.fixtures.json +++ b/src/test/resources/fixtures/controllers/accountController/getNoteDetails.fixtures.json @@ -1,14 +1,14 @@ { - "getNoteDetails": { - "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 + "getNoteDetails": { + "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 diff --git a/src/test/resources/fixtures/controllers/accountController/getNotesList.fixtures.json b/src/test/resources/fixtures/controllers/accountController/getNotesList.fixtures.json index 18ff7504..8de43024 100644 --- a/src/test/resources/fixtures/controllers/accountController/getNotesList.fixtures.json +++ b/src/test/resources/fixtures/controllers/accountController/getNotesList.fixtures.json @@ -1,14 +1,14 @@ { - "getNoteList": { - "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 + "getNoteList": { + "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 2b2662f452cd7cd070586477acf8a270ef33926c Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 24 Aug 2023 16:15:25 +0530 Subject: [PATCH 041/195] added exception handling for debugging --- .../accountController/GetNoteDetailsTest.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java index 62c65ad6..3a17f691 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java @@ -82,11 +82,15 @@ public void tearDown() { @MethodSource("testScenariosProvider") public void getNoteDetails(Scenario testScenario) throws Exception{ String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture( - "classpath:fixtures/controllers/accountController/getNoteDetails.fixtures.json", - currentFunctionName - ); - loadFixture.perform(fixtureData); + try { + FixtureData fixtureData = common.loadFixture( + "classpath:fixtures/controllers/accountController/getNoteDetails.fixtures.json", + currentFunctionName + ); + loadFixture.perform(fixtureData); + } catch(Exception e) { + System.out.println("Exception in fixtures: --- " + e); + } ObjectMapper objectMapper = new ObjectMapper(); From ed49b00d6efa4957c6e3b7989cd2805492b1c045 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 24 Aug 2023 16:42:52 +0530 Subject: [PATCH 042/195] added logs for debugging test case workflow --- .../controllers/authController/PostSalesforceConnectTest.java | 1 + 1 file changed, 1 insertion(+) 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 0408bce9..5d11b5e2 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 @@ -117,6 +117,7 @@ public void testPostSalesforceConnectSignup() throws Exception { .contentType(MediaType.APPLICATION_JSON)); String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); + System.out.println("actualOutput: " + actualOutput); if (resultActions.andReturn().getResponse().getStatus() == 200) { assertEquals(objectMapper.writeValueAsString(testDataItem.getOutput()), actualOutput); From d12fa8b80decd53dd091ecd731afbe29925663ae Mon Sep 17 00:00:00 2001 From: amanbarbaria Date: Thu, 24 Aug 2023 16:51:18 +0530 Subject: [PATCH 043/195] 1. Added security related headers 2. Validate api source in cookie validation to prevent web cookie from using app routes and vice versa 3. Added spring boot security package 4. Added Filter to allow only application/json content type 5. Added SameSite=Lax for user cookies along with domain value --- pom.xml | 137 ++++++++++-------- set_env_vars-sample.sh | 3 + set_testing_env_vars-sample.sh | 5 +- .../com/salessparrow/api/SalesSparrowApi.java | 3 +- .../api/config/CoreConstants.java | 4 + .../salessparrow/api/config/FilterConfig.java | 23 +++ .../api/config/InterceptorConfig.java | 10 +- .../api/config/SecurityConfig.java | 81 +++++++++++ .../api/controllers/AuthController.java | 6 +- .../api/filter/SameSiteCookieFilter.java | 102 +++++++++++++ .../api/interceptors/JsonOnlyInterceptor.java | 45 ++++++ .../api/interceptors/UserAuthInterceptor.java | 3 +- .../salessparrow/api/lib/CookieHelper.java | 61 +++++++- .../api/lib/UserLoginCookieAuth.java | 38 ++++- .../wrappers/SalesforceGetTokens.java | 16 +- .../api/services/salesforce/AuthService.java | 11 +- src/main/resources/application.properties | 4 +- src/main/resources/config/ApiErrorConfig.json | 5 + .../resources/config/ParamErrorConfig.json | 5 + 19 files changed, 469 insertions(+), 93 deletions(-) create mode 100644 src/main/java/com/salessparrow/api/config/FilterConfig.java create mode 100644 src/main/java/com/salessparrow/api/config/SecurityConfig.java create mode 100644 src/main/java/com/salessparrow/api/filter/SameSiteCookieFilter.java create mode 100644 src/main/java/com/salessparrow/api/interceptors/JsonOnlyInterceptor.java diff --git a/pom.xml b/pom.xml index 17f637e0..ad3e1d9e 100644 --- a/pom.xml +++ b/pom.xml @@ -12,9 +12,9 @@ com.salessparrow - salessparrow-api - 0.0.1 - api + salessparrow-api + 0.0.1 + api Salessparrow apis @@ -30,22 +30,33 @@ 3.1.1 - - org.springframework.boot - spring-boot-starter-webflux + + org.springframework.boot + spring-boot-starter-webflux 3.1.1 - - + + + + org.springframework.boot + spring-boot-starter-security + 3.1.1 + + + org.springframework.security + spring-security-test + test + + org.modelmapper modelmapper 3.1.1 - + - com.fasterxml.jackson.core - jackson-databind - 2.15.2 + com.fasterxml.jackson.core + jackson-databind + 2.15.2 @@ -56,10 +67,16 @@ - org.springframework.boot - spring-boot-starter-validation + org.springframework.boot + spring-boot-starter-validation 3.1.1 - + + + + javax.xml.bind + jaxb-api + 2.4.0-b180830.0359 + com.amazonaws @@ -67,35 +84,35 @@ 1.12.523 - - com.amazonaws - aws-java-sdk-elasticache - 1.12.531 - + + com.amazonaws + aws-java-sdk-elasticache + 1.12.531 + - - org.hibernate.validator - hibernate-validator - 8.0.1.Final - + + org.hibernate.validator + hibernate-validator + 8.0.1.Final + - - org.springframework.boot - spring-boot-starter-cache + + org.springframework.boot + spring-boot-starter-cache 3.1.1 - + - - net.spy - spymemcached - 2.12.3 - + + net.spy + spymemcached + 2.12.3 + - org.slf4j - slf4j-nop - 2.0.6 - + org.slf4j + slf4j-nop + 2.0.6 + net.logstash.logback @@ -128,7 +145,7 @@ 0.6 - + @@ -137,28 +154,26 @@ spring-boot-maven-plugin - - org.jacoco - jacoco-maven-plugin - 0.8.9 - - - - prepare-agent - - - - - report - test - - report - - - - + + org.jacoco + jacoco-maven-plugin + 0.8.9 + + + + prepare-agent + + + + + report + test + + report + + + + - - diff --git a/set_env_vars-sample.sh b/set_env_vars-sample.sh index fa928f46..4f4c9a92 100644 --- a/set_env_vars-sample.sh +++ b/set_env_vars-sample.sh @@ -30,3 +30,6 @@ export ERROR_MAIL_TO='' # Logging export LOG_LEVEL='info' + +# Cookie +export COOKIE_DOMAIN='localhost' \ No newline at end of file diff --git a/set_testing_env_vars-sample.sh b/set_testing_env_vars-sample.sh index 929c6d4b..d20cd7e3 100644 --- a/set_testing_env_vars-sample.sh +++ b/set_testing_env_vars-sample.sh @@ -29,4 +29,7 @@ export ERROR_MAIL_FROM='' export ERROR_MAIL_TO='' # Logging -export LOG_LEVEL='info' \ No newline at end of file +export LOG_LEVEL='info' + +# Cookie +export COOKIE_DOMAIN='localhost' \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/SalesSparrowApi.java b/src/main/java/com/salessparrow/api/SalesSparrowApi.java index 63981bc6..69cb9031 100644 --- a/src/main/java/com/salessparrow/api/SalesSparrowApi.java +++ b/src/main/java/com/salessparrow/api/SalesSparrowApi.java @@ -2,11 +2,12 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration; import org.springframework.cache.annotation.EnableCaching; import org.springframework.scheduling.annotation.EnableAsync; -@SpringBootApplication +@SpringBootApplication(exclude= {UserDetailsServiceAutoConfiguration.class}) @EnableCaching // This enables caching @EnableAsync // This enables asynchronous processing in Spring public class SalesSparrowApi { diff --git a/src/main/java/com/salessparrow/api/config/CoreConstants.java b/src/main/java/com/salessparrow/api/config/CoreConstants.java index b381cbe6..2e3ab02c 100644 --- a/src/main/java/com/salessparrow/api/config/CoreConstants.java +++ b/src/main/java/com/salessparrow/api/config/CoreConstants.java @@ -5,6 +5,10 @@ */ public class CoreConstants { + public static String cookieDomain(){ + return System.getenv("COOKIE_DOMAIN"); + } + public static String encryptionKey() { return System.getenv("ENCRYPTION_KEY"); } diff --git a/src/main/java/com/salessparrow/api/config/FilterConfig.java b/src/main/java/com/salessparrow/api/config/FilterConfig.java new file mode 100644 index 00000000..d7d6e7b1 --- /dev/null +++ b/src/main/java/com/salessparrow/api/config/FilterConfig.java @@ -0,0 +1,23 @@ +package com.salessparrow.api.config; + +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.salessparrow.api.filter.SameSiteCookieFilter; + +@Configuration +public class FilterConfig { + /** + * Register SameSiteCookieFilter + * + * @return FilterRegistrationBean + */ + @Bean + public FilterRegistrationBean sameSiteCookieFilter() { + FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); + registrationBean.setFilter(new SameSiteCookieFilter()); + registrationBean.addUrlPatterns("/*"); // or specific URL patterns + return registrationBean; + } +} diff --git a/src/main/java/com/salessparrow/api/config/InterceptorConfig.java b/src/main/java/com/salessparrow/api/config/InterceptorConfig.java index c82c0026..8988cf4e 100644 --- a/src/main/java/com/salessparrow/api/config/InterceptorConfig.java +++ b/src/main/java/com/salessparrow/api/config/InterceptorConfig.java @@ -6,6 +6,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import com.salessparrow.api.interceptors.LoggerInterceptor; +import com.salessparrow.api.interceptors.JsonOnlyInterceptor; import com.salessparrow.api.interceptors.UserAuthInterceptor; import com.salessparrow.api.interceptors.V1Interceptor; @@ -15,16 +16,20 @@ public class InterceptorConfig implements WebMvcConfigurer { @Autowired private final LoggerInterceptor loggerInterceptor; + @Autowired + private final JsonOnlyInterceptor jsonOnlyInterceptor; + @Autowired private final V1Interceptor V1Interceptor; @Autowired private final UserAuthInterceptor userAuthInterceptor; - public InterceptorConfig(UserAuthInterceptor userAuthInterceptor, LoggerInterceptor loggerInterceptor, V1Interceptor V1Interceptor) { + public InterceptorConfig(UserAuthInterceptor userAuthInterceptor, JsonOnlyInterceptor jsonOnlyInterceptor, LoggerInterceptor loggerInterceptor, V1Interceptor V1Interceptor) { this.userAuthInterceptor = userAuthInterceptor; this.loggerInterceptor = loggerInterceptor; this.V1Interceptor = V1Interceptor; + this.jsonOnlyInterceptor = jsonOnlyInterceptor; } @Override @@ -32,6 +37,9 @@ public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(loggerInterceptor) .addPathPatterns("/**"); + registry.addInterceptor(jsonOnlyInterceptor) + .addPathPatterns("/**"); + registry.addInterceptor(V1Interceptor) .addPathPatterns("/api/v1/**"); diff --git a/src/main/java/com/salessparrow/api/config/SecurityConfig.java b/src/main/java/com/salessparrow/api/config/SecurityConfig.java new file mode 100644 index 00000000..4d6737d9 --- /dev/null +++ b/src/main/java/com/salessparrow/api/config/SecurityConfig.java @@ -0,0 +1,81 @@ +package com.salessparrow.api.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.header.writers.XXssProtectionHeaderWriter; +import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter.ReferrerPolicy; + + +@Configuration +@EnableWebSecurity +public class SecurityConfig { + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + + http + // disable authorization for all routes + .authorizeHttpRequests(authorizeRequests ->authorizeRequests.anyRequest().permitAll()) + // Disable authentication for all routes + .httpBasic(httpBasic -> httpBasic.disable()) + // Disable form login + .formLogin(formLogin -> formLogin.disable()) + // Remove csrf in app routes + .csrf((csrf) -> csrf.ignoringRequestMatchers("/api/v1/**")) + + /** + * Cache-Control header - applied by default in spring security + * The Cache-Control header is the most important header to set as it effectively disables caching on the client side. + * + * Pragma header - applied by default in spring security + * The Pragma directive is an older directive meant for HTTP/1.0 clients where + * the Cache-Control header wasn't defined. + * + * Expires header - applied by default in spring security + * The Expires header is another older way to prevent caching, especially in HTTP/1.0. + * + * X-Content-Type-Options header - applied by default in spring security + * The X-Content-Type-Options header is a security feature that prevents pages from loading when they detect + * incorrect MIME types. + * By setting the value to "nosniff", you're instructing the browser not to override the provided Content-Type + * + * HSTS header + * The Strict-Transport-Security header is a security feature implemented by web browsers + * to ensure that websites are only accessed using HTTPS. + * + * X-Frame-Options header + * The X-Frame-Options header is a security feature that prevents your web page from being put in a frame. + * + * X-XSS-Protection header - applied by default in spring security + * The X-XSS-Protection header is a security feature that prevents pages from loading when they detect + * reflected cross-site scripting (XSS) attacks. + * + * It is not needed for rest api's as they are not rendered in the browser. But it is no harm and is a + * good practice to have it.The value "1; mode=block" instructs the browser to block the response if it + * detects an attack. + * + * Referrer-Policy header + * The Referrer-Policy header is a security feature that prevents pages from leaking information about the user's + * browsing behavior.The value "same-origin" instructs the browser to send the referrer header only when the request + * is originating from the same origin as the target resource. + */ + .headers(headers -> headers + .frameOptions(frameOptions -> frameOptions.deny()) + .httpStrictTransportSecurity(hsts -> hsts.includeSubDomains(true).preload(true).maxAgeInSeconds(31536000)) + .xssProtection(xss -> xss.headerValue(XXssProtectionHeaderWriter.HeaderValue.ENABLED_MODE_BLOCK)) + .referrerPolicy(referrer -> referrer.policy(ReferrerPolicy.SAME_ORIGIN)) + ); + + + // Enable for production and staging + if (!CoreConstants.isDevEnvironment() && !CoreConstants.isTestEnvironment()) { + // All requests must be secure + http.requiresChannel(channel -> channel.anyRequest().requiresSecure()); + } + + return http.build(); + } +} diff --git a/src/main/java/com/salessparrow/api/controllers/AuthController.java b/src/main/java/com/salessparrow/api/controllers/AuthController.java index f533719b..3caf84b6 100644 --- a/src/main/java/com/salessparrow/api/controllers/AuthController.java +++ b/src/main/java/com/salessparrow/api/controllers/AuthController.java @@ -46,16 +46,16 @@ public ResponseEntity getSalesforceRedirectUrl( @Valid @ModelAttribute SalesforceRedirectUrlDto salesforceRedirectUrlDto) { RedirectUrlFormatterDto redirectUrlFormatterDto = redirectUrlService.getSalesforceOauthUrl(salesforceRedirectUrlDto); - + return ResponseEntity.ok().body(redirectUrlFormatterDto); } @PostMapping("/salesforce/connect") - public ResponseEntity connectToSalesforce( + public ResponseEntity connectToSalesforce(HttpServletRequest request, @Valid @RequestBody SalesforceConnectDto salesforceConnectDto) { logger.info("Salesforce connection request received"); - AuthServiceDto authServiceResponse = authService.connectToSalesforce(salesforceConnectDto); + AuthServiceDto authServiceResponse = authService.connectToSalesforce(salesforceConnectDto, request); HttpHeaders headers = new HttpHeaders(); headers = cookieHelper.setUserCookie(authServiceResponse.getCurrentUserLoginCookie(), headers); diff --git a/src/main/java/com/salessparrow/api/filter/SameSiteCookieFilter.java b/src/main/java/com/salessparrow/api/filter/SameSiteCookieFilter.java new file mode 100644 index 00000000..dd0e69a1 --- /dev/null +++ b/src/main/java/com/salessparrow/api/filter/SameSiteCookieFilter.java @@ -0,0 +1,102 @@ +package com.salessparrow.api.filter; + +import jakarta.servlet.*; +import jakarta.servlet.http.*; + +import java.io.IOException; + +/** + * Filter to set SameSite cookie attribute + * + * If you want to implement SameSite attribute setting in an interceptor, you can do it, + * but it won't be as efficient as doing it in a filter. That's because, by the time the interceptor + * is called, some part of the request processing within the Spring MVC framework has already happened. + * + */ +public class SameSiteCookieFilter implements Filter { + + @Override + public void init(FilterConfig filterConfig) { + } + + /** + * Set SameSite cookie attribute. + * Override the doFilter method to wrap the response object with a custom wrapper. + * + * @param request + * @param response + * @param chain + * + * @throws IOException + * @throws ServletException + * + * @return void + */ + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + + SameSiteResponseWrapper wrappedResponse = new SameSiteResponseWrapper((HttpServletResponse) response); + chain.doFilter(request, wrappedResponse); + } + + @Override + public void destroy() { + } + + /** + * Custom wrapper to intercept the setHeader calls and add SameSite attribute to the cookie. + * Set SameSite=lax + * lax will ensure that cookies are sent only if the request originates from the same site. + * It will also send the cookie if the user is navigating from an external site, + * but only if the URL in the browser’s address bar matches the URL of the current site. + */ + public class SameSiteResponseWrapper extends HttpServletResponseWrapper { + + /** + * Constructor + * + * @param response + * + * @return void + */ + public SameSiteResponseWrapper(HttpServletResponse response) { + super(response); + } + + /** + * Override the addHeader method to add SameSite attribute to the cookie + * + * @param name + * @param value + * + * @return void + * + */ + @Override + public void addHeader(String name, String value) { + if (name.equalsIgnoreCase("set-cookie") && !value.toLowerCase().contains("samesite")) { + value = String.format("%s; SameSite=lax", value); + } + super.addHeader(name, value); + } + + /** + * Override the setHeader method to add SameSite attribute to the cookie + * + * @param name + * @param value + * + * @return void + * + */ + @Override + public void setHeader(String name, String value) { + + if (name.equalsIgnoreCase("set-cookie") && !value.toLowerCase().contains("samesite")) { + value = String.format("%s; SameSite=lax", value); + } + super.setHeader(name, value); + } + } +} diff --git a/src/main/java/com/salessparrow/api/interceptors/JsonOnlyInterceptor.java b/src/main/java/com/salessparrow/api/interceptors/JsonOnlyInterceptor.java new file mode 100644 index 00000000..96a2fcb2 --- /dev/null +++ b/src/main/java/com/salessparrow/api/interceptors/JsonOnlyInterceptor.java @@ -0,0 +1,45 @@ +package com.salessparrow.api.interceptors; + +import org.springframework.web.servlet.HandlerInterceptor; + +import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.lib.errorLib.ErrorObject; + +import org.springframework.stereotype.Component; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +/** + * Interceptor for strict application/json Content-Type header + * + */ +@Component +public class JsonOnlyInterceptor implements HandlerInterceptor { + + /** + * Intercept request and validate Content-type header + * Only application/json is allowed + * + * @param request + * @param response + * @param handler + * + * @return boolean + */ + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + + String contentType = request.getHeader("Content-Type"); + if (contentType != null && !contentType.contains("application/json")) { + throw new CustomException( + new ErrorObject( + "i_joi_ph_1", + "unsupported_media_type", + "Content-Type header must be application/json")); + } + + return true; + } +} + + diff --git a/src/main/java/com/salessparrow/api/interceptors/UserAuthInterceptor.java b/src/main/java/com/salessparrow/api/interceptors/UserAuthInterceptor.java index be4b72d0..13aa70e5 100644 --- a/src/main/java/com/salessparrow/api/interceptors/UserAuthInterceptor.java +++ b/src/main/java/com/salessparrow/api/interceptors/UserAuthInterceptor.java @@ -45,8 +45,9 @@ public class UserAuthInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String cookieValue = getCookieValue(request); + String reqApiSource = (String) request.getAttribute("api_source"); - Map userLoginCookieAuthRes = userLoginCookieAuth.validateAndSetCookie(cookieValue); + Map userLoginCookieAuthRes = userLoginCookieAuth.validateAndSetCookie(cookieValue, reqApiSource); User currentUser = (User) userLoginCookieAuthRes.get("current_user"); request.setAttribute("current_user", currentUser); diff --git a/src/main/java/com/salessparrow/api/lib/CookieHelper.java b/src/main/java/com/salessparrow/api/lib/CookieHelper.java index 5ddc9933..7db1174d 100644 --- a/src/main/java/com/salessparrow/api/lib/CookieHelper.java +++ b/src/main/java/com/salessparrow/api/lib/CookieHelper.java @@ -18,10 +18,20 @@ public class CookieHelper { @Autowired private LocalCipher localCipher; - public String getCookieValue(User user, String userKind, String decryptedSalt) { + /** + * Get cookie value + * + * @param user + * @param userKind + * @param decryptedSalt + * @param apiSource + * + * @return String + */ + public String getCookieValue(User user, String userKind, String decryptedSalt, String apiSource) { Integer currentTimestamp = (int) (System.currentTimeMillis() / 1000); - String cookieToken = getCookieToken(user, decryptedSalt, currentTimestamp); + String cookieToken = getCookieToken(user, decryptedSalt, currentTimestamp, apiSource); if (user.getExternalUserId() == null) { throw new CustomException( @@ -31,16 +41,25 @@ public String getCookieValue(User user, String userKind, String decryptedSalt) { "User is null")); } - return CookieConstants.LATEST_VERSION + ':' + user.getExternalUserId() + ':' + userKind + ':' + currentTimestamp - + ':' - + cookieToken; + return CookieConstants.LATEST_VERSION + ':' + user.getExternalUserId() + ':' + userKind + + ':' + apiSource + ':' + currentTimestamp + ':' + cookieToken; } - public String getCookieToken(User user, String decryptedSalt, Integer timestamp) { + /** + * Get cookie token + * + * @param user + * @param decryptedSalt + * @param timestamp + * @param apiSource + * + * @return String + */ + public String getCookieToken(User user, String decryptedSalt, Integer timestamp, String apiSource) { String decryptedCookieToken = localCipher.decrypt(decryptedSalt, user.getCookieToken()); String strSecret = CoreConstants.apiCookieSecret(); - String stringToSign = user.getExternalUserId() + ':' + timestamp + ':' + strSecret + ':' + String stringToSign = user.getExternalUserId() + ':' + timestamp + ':' + apiSource + ':' + strSecret + ':' + decryptedCookieToken.substring(0, 16); String salt = user.getExternalUserId() + ':' + decryptedCookieToken.substring(decryptedCookieToken.length() - 16) + ':' @@ -50,6 +69,15 @@ public String getCookieToken(User user, String decryptedSalt, Integer timestamp) return encryptedCookieToken; } + /** + * Set cookie in headers + * + * @param cookieName + * @param cookieValue + * @param headers + * + * @return HttpHeaders + */ public HttpHeaders setCookieInHeaders(String cookieName, String cookieValue, HttpHeaders headers) { int cookieExpiryInSecond = CookieConstants.USER_LOGIN_COOKIE_EXPIRY_IN_SEC; @@ -58,13 +86,23 @@ public HttpHeaders setCookieInHeaders(String cookieName, String cookieValue, cookie.setHttpOnly(true); cookie.setSecure(true); cookie.setMaxAge(cookieExpiryInSecond); - + cookie.setDomain(CoreConstants.cookieDomain()); + cookie.setPath("/"); + headers.add(HttpHeaders.SET_COOKIE, String.format("%s=%s; Max-Age=%d; Path=/", cookieName, cookieValue, cookieExpiryInSecond)); return headers; } + /** + * Set user cookie + * + * @param cookieValue + * @param headers + * + * @return HttpHeaders + */ public HttpHeaders setUserCookie(String cookieValue, HttpHeaders headers) { String cookieName = CookieConstants.USER_LOGIN_COOKIE_NAME; @@ -73,6 +111,13 @@ public HttpHeaders setUserCookie(String cookieValue, HttpHeaders headers) { return headers; } + /** + * Clear user cookie + * + * @param headers + * + * @return HttpHeaders + */ public HttpHeaders clearUserCookie(HttpHeaders headers) { String cookieName = CookieConstants.USER_LOGIN_COOKIE_NAME; String cookieValue = ""; diff --git a/src/main/java/com/salessparrow/api/lib/UserLoginCookieAuth.java b/src/main/java/com/salessparrow/api/lib/UserLoginCookieAuth.java index 44314bdb..4a537faa 100644 --- a/src/main/java/com/salessparrow/api/lib/UserLoginCookieAuth.java +++ b/src/main/java/com/salessparrow/api/lib/UserLoginCookieAuth.java @@ -23,8 +23,11 @@ public class UserLoginCookieAuth { Logger logger = LoggerFactory.getLogger(UserLoginCookieAuth.class); private String cookieValue; + private String reqApiSource; + private String userId; private String userKind; + private String cookieApiSource; private Integer timestampInCookie; private String token; private User currentUser; @@ -44,17 +47,19 @@ public class UserLoginCookieAuth { * Validate and set cookie * * @param cookieValue - * @param expireTimestamp + * @param reqApiSource * * @return Map */ - public Map validateAndSetCookie(String cookieValue) { + public Map validateAndSetCookie(String cookieValue, String reqApiSource) { this.cookieValue = cookieValue; + this.reqApiSource = reqApiSource; logger.info("Validating cookie"); validate(); setParts(); validateTimestamp(); + validateApiSource(); fetchAndValidateUser(); validateCookieToken(); setCookie(); @@ -88,10 +93,10 @@ private void validate() { * * @throws RuntimeException */ - private void setParts() { + private void setParts() { List cookieValueParts = Arrays.asList(cookieValue.split(":")); - if (cookieValueParts.size() != 5) { + if (cookieValueParts.size() != 6) { throw new CustomException( new ErrorObject( "l_ulca_sp_1", @@ -102,8 +107,9 @@ private void setParts() { if (cookieValueParts.get(0).equals(CookieConstants.LATEST_VERSION)) { userId = cookieValueParts.get(1); userKind = cookieValueParts.get(2); - timestampInCookie = Integer.parseInt(cookieValueParts.get(3)); - token = cookieValueParts.get(4); + cookieApiSource = cookieValueParts.get(3); + timestampInCookie = Integer.parseInt(cookieValueParts.get(4)); + token = cookieValueParts.get(5); } else { throw new CustomException( new ErrorObject( @@ -129,6 +135,22 @@ private void validateTimestamp() { } } + /** + * Validate api source + * + * @throws RuntimeException + */ + private void validateApiSource() { + if (!cookieApiSource.equals(reqApiSource)) { + throw new CustomException( + new ErrorObject( + "l_ulca_vas_1", + "unauthorized_api_request", + "Cookie api source and request api source mismatch")); + + } + } + /** * Fetch and validate user * @@ -172,7 +194,7 @@ private void validateCookieToken() { encryptionSalt); String generatedToken = cookieHelper.getCookieToken(currentUser, - decryptedEncryptionSalt, timestampInCookie); + decryptedEncryptionSalt, timestampInCookie, reqApiSource); if (!generatedToken.equals(token)) { throw new CustomException( new ErrorObject( @@ -189,7 +211,7 @@ private void validateCookieToken() { */ private void setCookie() { userLoginCookieValue = cookieHelper.getCookieValue(currentUser, userKind, - decryptedEncryptionSalt); + decryptedEncryptionSalt, reqApiSource); } } diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceGetTokens.java b/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceGetTokens.java index db73e158..edcfd902 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceGetTokens.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceGetTokens.java @@ -1,5 +1,6 @@ package com.salessparrow.api.lib.salesforce.wrappers; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -8,10 +9,11 @@ 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; import com.salessparrow.api.lib.httpLib.HttpClient.HttpResponse; +import java.util.List; /** * SalesforceGetTokens class to get tokens from Salesforce @@ -51,11 +53,13 @@ public HttpResponse getTokens(String code, String redirectUri) { requestBody, 10000); } catch (Exception e) { - throw new CustomException( - new ErrorObject( - "l_s_w_sgt_gt_1", - "bad_request", - e.getMessage())); + List paramErrorIdentifiers = Arrays.asList("invalid_code"); + ParamErrorObject paramErrorObject = new ParamErrorObject( + "l_s_w_sgt_gt_1", + e.getMessage(), + paramErrorIdentifiers); + + throw new CustomException(paramErrorObject); } return response; } 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 67e7ab29..1622b0f1 100644 --- a/src/main/java/com/salessparrow/api/services/salesforce/AuthService.java +++ b/src/main/java/com/salessparrow/api/services/salesforce/AuthService.java @@ -29,10 +29,13 @@ import com.salessparrow.api.repositories.SalesforceOauthTokenRepository; import com.salessparrow.api.repositories.SalesforceOrganizationRepository; import com.salessparrow.api.repositories.SalesforceUserRepository; +import jakarta.servlet.http.HttpServletRequest; + @Service public class AuthService { + private String reqApiSource; private String code; private String redirectUri; @@ -76,12 +79,16 @@ public class AuthService { * Connect to Salesforce and create user if not exists. * * @param params + * @param request * * @return AuthServiceDto */ - public AuthServiceDto connectToSalesforce(SalesforceConnectDto params) { + 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 + code = params.getCode(); redirectUri = params.getRedirect_uri(); @@ -271,7 +278,7 @@ private AuthServiceDto prepareResponse() { String userLoginCookieValue = cookieHelper.getCookieValue(this.salesforceUser, UserConstants.SALESFORCE_USER_KIND, - this.decryptedSalt); + this.decryptedSalt, reqApiSource); authServiceDto.setCurrentUser(currentUserEntityDto); authServiceDto.setCurrentUserLoginCookie(userLoginCookieValue); diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index d2821b57..aa8f3270 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -15,4 +15,6 @@ spring.mvc.throw-exception-if-no-handler-found=true spring.mvc.static-path-pattern: /static # Suppress warning like o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Resolved [com.salessparrow.api.exception.CustomException] -logging.level.org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver=ERROR \ No newline at end of file +logging.level.org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver=ERROR +logging.level.org.springframework.security=INFO +logging.level.org.springframework.web=INFO \ No newline at end of file diff --git a/src/main/resources/config/ApiErrorConfig.json b/src/main/resources/config/ApiErrorConfig.json index d82d347c..e4b86a59 100644 --- a/src/main/resources/config/ApiErrorConfig.json +++ b/src/main/resources/config/ApiErrorConfig.json @@ -14,6 +14,11 @@ "code": "NOT_FOUND", "message": "Resource not found. Please check if the resource identifier passed in the URL is valid and try again." }, + "unsupported_media_type": { + "httpCode": "415", + "code": "UNSUPPORTED_MEDIA_TYPE", + "message": "Unsupported Media Type. Content-Type header should be application/json." + }, "something_went_wrong": { "httpCode": "500", "code": "INTERNAL_SERVER_ERROR", diff --git a/src/main/resources/config/ParamErrorConfig.json b/src/main/resources/config/ParamErrorConfig.json index 0b724abb..af8ee375 100644 --- a/src/main/resources/config/ParamErrorConfig.json +++ b/src/main/resources/config/ParamErrorConfig.json @@ -1,4 +1,9 @@ { + "invalid_code": { + "parameter": "code", + "param_error_identifier": "invalid_code", + "message": "The code you sent is incorrect. Please double check and try again." + }, "invalid_email": { "parameter": "email", "param_error_identifier": "invalid_email", From fee44e13478e453cbb8c94196e6084511895bf1f Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 24 Aug 2023 16:55:03 +0530 Subject: [PATCH 044/195] updated env vars for workflow --- .github/workflows/run_tests.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run_tests.yaml b/.github/workflows/run_tests.yaml index 13181bf0..bbb82169 100644 --- a/.github/workflows/run_tests.yaml +++ b/.github/workflows/run_tests.yaml @@ -4,6 +4,7 @@ on: pull_request: branches: - master + env: ENVIRONMENT: test AWS_ACCESS_KEY_ID: ${{ secrets.PLG_PROD_ACCESS_KEY }} @@ -31,8 +32,8 @@ jobs: volumes: - ./init:/init env: - KMS_ACCOUNT_ID: '111122223333' - KMS_REGION: 'us-east-1' + KMS_ACCOUNT_ID: 111122223333 + KMS_REGION: us-east-1 KMS_SEED_PATH: init/seed.yaml steps: From 58600ecf5989ae9cda8141f2bb61f8bcea11b8f8 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 24 Aug 2023 17:03:17 +0530 Subject: [PATCH 045/195] added logs for debugging --- .github/workflows/run_tests.yaml | 3 +++ src/main/java/com/salessparrow/api/lib/AwsKms.java | 3 +++ 2 files changed, 6 insertions(+) diff --git a/.github/workflows/run_tests.yaml b/.github/workflows/run_tests.yaml index bbb82169..73855766 100644 --- a/.github/workflows/run_tests.yaml +++ b/.github/workflows/run_tests.yaml @@ -32,6 +32,9 @@ jobs: volumes: - ./init:/init env: + AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }} + AWS_REGION: 'us-east-1' KMS_ACCOUNT_ID: 111122223333 KMS_REGION: us-east-1 KMS_SEED_PATH: init/seed.yaml diff --git a/src/main/java/com/salessparrow/api/lib/AwsKms.java b/src/main/java/com/salessparrow/api/lib/AwsKms.java index 527b4bf3..b80c9873 100644 --- a/src/main/java/com/salessparrow/api/lib/AwsKms.java +++ b/src/main/java/com/salessparrow/api/lib/AwsKms.java @@ -46,6 +46,9 @@ public String encryptToken(String token) { .withKeyId(CoreConstants.kmsKeyId()) .withPlaintext(ByteBuffer.wrap(token.getBytes())); + System.out.println("kmsKeyId: " + CoreConstants.kmsKeyId()); + System.out.println("local kms endpoint: " + CoreConstants.localKmsEndpoint()); + EncryptResult result = null; try { result = kmsClient.encrypt(request); From 9b402f832e14076c685d1df100f5e93c9bfd5893 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 24 Aug 2023 17:23:52 +0530 Subject: [PATCH 046/195] updated path in workflow --- .github/workflows/run_tests.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run_tests.yaml b/.github/workflows/run_tests.yaml index 73855766..392be849 100644 --- a/.github/workflows/run_tests.yaml +++ b/.github/workflows/run_tests.yaml @@ -34,10 +34,10 @@ jobs: env: AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }} - AWS_REGION: 'us-east-1' + AWS_REGION: us-east-1 KMS_ACCOUNT_ID: 111122223333 KMS_REGION: us-east-1 - KMS_SEED_PATH: init/seed.yaml + KMS_SEED_PATH: /init/seed.yaml steps: - uses: actions/checkout@v3 From 1dbf1d56e1507a7300d011ab83fb8374fc457f58 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 24 Aug 2023 17:40:04 +0530 Subject: [PATCH 047/195] updated workflow --- .github/workflows/run_tests.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/run_tests.yaml b/.github/workflows/run_tests.yaml index 392be849..9c4572f4 100644 --- a/.github/workflows/run_tests.yaml +++ b/.github/workflows/run_tests.yaml @@ -48,6 +48,19 @@ jobs: java-version: '17' distribution: 'adopt' + - name: Log into Docker Container + run: | + echo "Getting container id" + container_id=$(docker ps -q -f ancestor=nsmithuk/local-kms) + echo "Container id: $container_id" + echo "Checking seed path" + docker exec -it $container_id ls /init + + - name: Display Files + run: | + echo "Files in the container:" + docker exec localkms ls /init/ + - run: |- echo "Start: run test cases" sh ./mvnw clean test From 8038f50b5f6748b770262d768be015cf87523613 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 24 Aug 2023 17:44:44 +0530 Subject: [PATCH 048/195] updated workflow --- .github/workflows/run_tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run_tests.yaml b/.github/workflows/run_tests.yaml index 9c4572f4..61cf7594 100644 --- a/.github/workflows/run_tests.yaml +++ b/.github/workflows/run_tests.yaml @@ -54,7 +54,7 @@ jobs: container_id=$(docker ps -q -f ancestor=nsmithuk/local-kms) echo "Container id: $container_id" echo "Checking seed path" - docker exec -it $container_id ls /init + docker exec $container_id ls /init - name: Display Files run: | From c5f7fd8a3a132a8f1bebfd8a5c8a4ee5ff638d37 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 24 Aug 2023 17:46:50 +0530 Subject: [PATCH 049/195] updated workflow --- .github/workflows/run_tests.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/run_tests.yaml b/.github/workflows/run_tests.yaml index 61cf7594..710a0ea1 100644 --- a/.github/workflows/run_tests.yaml +++ b/.github/workflows/run_tests.yaml @@ -54,7 +54,8 @@ jobs: container_id=$(docker ps -q -f ancestor=nsmithuk/local-kms) echo "Container id: $container_id" echo "Checking seed path" - docker exec $container_id ls /init + seed_path=$(docker exec $container_id ls /init) + echo "Seed path: $seed_path" - name: Display Files run: | From a50df5f66ecb1174415965d7f9e32d76e3512083 Mon Sep 17 00:00:00 2001 From: Abhishek Roy <43261722+roy-cse@users.noreply.github.com> Date: Thu, 24 Aug 2023 18:06:31 +0530 Subject: [PATCH 050/195] Modified github workflow for test cases --- .github/workflows/run_tests.yaml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/run_tests.yaml b/.github/workflows/run_tests.yaml index 710a0ea1..80b660a9 100644 --- a/.github/workflows/run_tests.yaml +++ b/.github/workflows/run_tests.yaml @@ -47,6 +47,13 @@ jobs: with: java-version: '17' distribution: 'adopt' + + - name: Build Custom docker file for KMS + run: | + echo "Building docker image" + docker build -t local-kms -f Dockerfile.github . + echo "Starting docker container for local-kms" + docker run -d --name localkms -e AWS_ACCESS_KEY_ID=${{ env.AWS_ACCESS_KEY_ID }} -e AWS_SECRET_ACCESS_KEY=${{ env.AWS_SECRET_ACCESS_KEY }} -e AWS_REGION=us-east-1 -e KMS_ACCOUNT_ID=111122223333 -e KMS_REGION=us-east-1 -e KMS_SEED_PATH=init/seed.yaml local-kms - name: Log into Docker Container run: | @@ -57,12 +64,7 @@ jobs: seed_path=$(docker exec $container_id ls /init) echo "Seed path: $seed_path" - - name: Display Files - run: | - echo "Files in the container:" - docker exec localkms ls /init/ - - run: |- echo "Start: run test cases" sh ./mvnw clean test - echo "Done: run test cases" \ No newline at end of file + echo "Done: run test cases" From 6a285a8da3f08d469de68228735f89e599910348 Mon Sep 17 00:00:00 2001 From: Abhishek Roy <43261722+roy-cse@users.noreply.github.com> Date: Thu, 24 Aug 2023 18:08:02 +0530 Subject: [PATCH 051/195] Created Dockerfile.github --- .github/workflows/Dockerfile.github | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .github/workflows/Dockerfile.github diff --git a/.github/workflows/Dockerfile.github b/.github/workflows/Dockerfile.github new file mode 100644 index 00000000..456f4310 --- /dev/null +++ b/.github/workflows/Dockerfile.github @@ -0,0 +1,5 @@ +FROM nsmithuk/local-kms + +# Add a file to the image +WORKDIR /init +COPY init/seed.yaml /init From 3c25b157cd58101e1ee56b8d70774d691fed48fd Mon Sep 17 00:00:00 2001 From: Abhishek Roy <43261722+roy-cse@users.noreply.github.com> Date: Thu, 24 Aug 2023 18:09:04 +0530 Subject: [PATCH 052/195] Removed original localkms container --- .github/workflows/run_tests.yaml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/run_tests.yaml b/.github/workflows/run_tests.yaml index 80b660a9..a20ba3bf 100644 --- a/.github/workflows/run_tests.yaml +++ b/.github/workflows/run_tests.yaml @@ -25,19 +25,19 @@ jobs: ports: - 8000:8000 - localkms: - image: nsmithuk/local-kms - ports: - - 4599:8080 - volumes: - - ./init:/init - env: - AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }} - AWS_REGION: us-east-1 - KMS_ACCOUNT_ID: 111122223333 - KMS_REGION: us-east-1 - KMS_SEED_PATH: /init/seed.yaml + # localkms: + # image: nsmithuk/local-kms + # ports: + # - 4599:8080 + # volumes: + # - ./init:/init + # env: + # AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }} + # AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }} + # AWS_REGION: us-east-1 + # KMS_ACCOUNT_ID: 111122223333 + # KMS_REGION: us-east-1 + # KMS_SEED_PATH: /init/seed.yaml steps: - uses: actions/checkout@v3 From ebd6bff42eb61aeca6e5d42d22c9b182229114fd Mon Sep 17 00:00:00 2001 From: Abhishek Roy <43261722+roy-cse@users.noreply.github.com> Date: Thu, 24 Aug 2023 18:11:59 +0530 Subject: [PATCH 053/195] Delete Dockerfile.github --- .github/workflows/Dockerfile.github | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 .github/workflows/Dockerfile.github diff --git a/.github/workflows/Dockerfile.github b/.github/workflows/Dockerfile.github deleted file mode 100644 index 456f4310..00000000 --- a/.github/workflows/Dockerfile.github +++ /dev/null @@ -1,5 +0,0 @@ -FROM nsmithuk/local-kms - -# Add a file to the image -WORKDIR /init -COPY init/seed.yaml /init From 106b61d2be152d5e945cd7df6c02828687753b11 Mon Sep 17 00:00:00 2001 From: Abhishek Roy <43261722+roy-cse@users.noreply.github.com> Date: Thu, 24 Aug 2023 18:12:31 +0530 Subject: [PATCH 054/195] Create Dockerfile.github --- Dockerfile.github | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 Dockerfile.github diff --git a/Dockerfile.github b/Dockerfile.github new file mode 100644 index 00000000..8aa0bb1f --- /dev/null +++ b/Dockerfile.github @@ -0,0 +1,5 @@ +FROM nsmithuk/local-kms + +# Add a file to the image +WORKDIR /init +COPY init/seed.yaml /init From 3c252482ccb1df39394131b326556fd368991f36 Mon Sep 17 00:00:00 2001 From: Abhishek Roy <43261722+roy-cse@users.noreply.github.com> Date: Thu, 24 Aug 2023 18:16:34 +0530 Subject: [PATCH 055/195] Update run_tests.yaml --- .github/workflows/run_tests.yaml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/run_tests.yaml b/.github/workflows/run_tests.yaml index a20ba3bf..1bf01fe5 100644 --- a/.github/workflows/run_tests.yaml +++ b/.github/workflows/run_tests.yaml @@ -57,11 +57,8 @@ jobs: - name: Log into Docker Container run: | - echo "Getting container id" - container_id=$(docker ps -q -f ancestor=nsmithuk/local-kms) - echo "Container id: $container_id" echo "Checking seed path" - seed_path=$(docker exec $container_id ls /init) + seed_path=$(docker exec localkms ls /init) echo "Seed path: $seed_path" - run: |- From 0f23b15c4c80a2384d9b3827d3cc34dc2d8a84b1 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 24 Aug 2023 18:23:43 +0530 Subject: [PATCH 056/195] updated ports in workflow --- .github/workflows/run_tests.yaml | 2 +- Dockerfile.github | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/run_tests.yaml b/.github/workflows/run_tests.yaml index 1bf01fe5..acd39ede 100644 --- a/.github/workflows/run_tests.yaml +++ b/.github/workflows/run_tests.yaml @@ -53,7 +53,7 @@ jobs: echo "Building docker image" docker build -t local-kms -f Dockerfile.github . echo "Starting docker container for local-kms" - docker run -d --name localkms -e AWS_ACCESS_KEY_ID=${{ env.AWS_ACCESS_KEY_ID }} -e AWS_SECRET_ACCESS_KEY=${{ env.AWS_SECRET_ACCESS_KEY }} -e AWS_REGION=us-east-1 -e KMS_ACCOUNT_ID=111122223333 -e KMS_REGION=us-east-1 -e KMS_SEED_PATH=init/seed.yaml local-kms + docker run -d --name localkms -p 4599:8080 -e AWS_ACCESS_KEY_ID=${{ env.AWS_ACCESS_KEY_ID }} -e AWS_SECRET_ACCESS_KEY=${{ env.AWS_SECRET_ACCESS_KEY }} -e AWS_REGION=us-east-1 -e KMS_ACCOUNT_ID=111122223333 -e KMS_REGION=us-east-1 -e KMS_SEED_PATH=init/seed.yaml local-kms - name: Log into Docker Container run: | diff --git a/Dockerfile.github b/Dockerfile.github index 8aa0bb1f..613afe5e 100644 --- a/Dockerfile.github +++ b/Dockerfile.github @@ -1,5 +1,7 @@ FROM nsmithuk/local-kms +EXPOSE 8080 + # Add a file to the image WORKDIR /init COPY init/seed.yaml /init From 7f0725865b5518fb4189841110cdf353894e8d21 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 24 Aug 2023 18:33:03 +0530 Subject: [PATCH 057/195] updated workflow --- .github/workflows/run_tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run_tests.yaml b/.github/workflows/run_tests.yaml index acd39ede..bf75543f 100644 --- a/.github/workflows/run_tests.yaml +++ b/.github/workflows/run_tests.yaml @@ -53,7 +53,7 @@ jobs: echo "Building docker image" docker build -t local-kms -f Dockerfile.github . echo "Starting docker container for local-kms" - docker run -d --name localkms -p 4599:8080 -e AWS_ACCESS_KEY_ID=${{ env.AWS_ACCESS_KEY_ID }} -e AWS_SECRET_ACCESS_KEY=${{ env.AWS_SECRET_ACCESS_KEY }} -e AWS_REGION=us-east-1 -e KMS_ACCOUNT_ID=111122223333 -e KMS_REGION=us-east-1 -e KMS_SEED_PATH=init/seed.yaml local-kms + docker run -d --name localkms -p 4599:8080 -e AWS_ACCESS_KEY_ID=${{ env.AWS_ACCESS_KEY_ID }} -e AWS_SECRET_ACCESS_KEY=${{ env.AWS_SECRET_ACCESS_KEY }} -e AWS_REGION=us-east-1 -e KMS_ACCOUNT_ID=111122223333 -e KMS_REGION=us-east-1 -e KMS_SEED_PATH=seed.yaml local-kms - name: Log into Docker Container run: | From 08ed2d4324ea952e20d39793866f20255f577607 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 24 Aug 2023 18:44:00 +0530 Subject: [PATCH 058/195] added logs for debugging --- src/main/java/com/salessparrow/api/config/AwsConfig.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/salessparrow/api/config/AwsConfig.java b/src/main/java/com/salessparrow/api/config/AwsConfig.java index 9030f53e..5d446ae7 100644 --- a/src/main/java/com/salessparrow/api/config/AwsConfig.java +++ b/src/main/java/com/salessparrow/api/config/AwsConfig.java @@ -45,9 +45,12 @@ public AWSKMS kmsClient() { CoreConstants.awsRegion() ); - return AWSKMSClientBuilder.standard() + AWSKMS kms = AWSKMSClientBuilder.standard() .withEndpointConfiguration(endpointConfiguration) .build(); + + System.out.println("kms.listKeys();: ======" + kms.listKeys()); + return kms; } return AWSKMSClientBuilder.standard() From ea5c48637a29aa5675b3b43a2612f479f766a457 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 24 Aug 2023 18:51:07 +0530 Subject: [PATCH 059/195] updated log for debugging --- src/main/java/com/salessparrow/api/config/AwsConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/salessparrow/api/config/AwsConfig.java b/src/main/java/com/salessparrow/api/config/AwsConfig.java index 5d446ae7..d6edf255 100644 --- a/src/main/java/com/salessparrow/api/config/AwsConfig.java +++ b/src/main/java/com/salessparrow/api/config/AwsConfig.java @@ -49,7 +49,7 @@ public AWSKMS kmsClient() { .withEndpointConfiguration(endpointConfiguration) .build(); - System.out.println("kms.listKeys();: ======" + kms.listKeys()); + System.out.println("kms.listKeys(): ======" + kms.listKeys()); return kms; } From 0f3f7fc4217bd6e0830dab5cf99afbaf8a8d983d Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Thu, 24 Aug 2023 18:51:33 +0530 Subject: [PATCH 060/195] Added get account task list api changes --- .../controllers/AccountTaskController.java | 45 +++- .../api/dto/entities/TaskEntity.java | 22 ++ .../formatter/GetTasksListFormatterDto.java | 20 ++ .../GetAccountTasksListFactory.java | 46 ++++ .../GetAccountTasksListInterface.java | 14 + .../GetSalesforceAccountTasksList.java | 116 ++++++++ .../dto/SalesforceGetTasksListDto.java | 43 +++ .../helper/SalesforceQueryBuilder.java | 12 + .../GetAccountTasksListService.java | 38 +++ .../accountController/GetAccountListTest.java | 2 - .../GetTasksListTest.java | 117 ++++++++ .../getTasksList.scenarios.json | 252 ++++++++++++++++++ .../getTasksList.fixtures.json | 14 + 13 files changed, 725 insertions(+), 16 deletions(-) create mode 100644 src/main/java/com/salessparrow/api/dto/entities/TaskEntity.java create mode 100644 src/main/java/com/salessparrow/api/dto/formatter/GetTasksListFormatterDto.java create mode 100644 src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetAccountTasksListFactory.java create mode 100644 src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetAccountTasksListInterface.java create mode 100644 src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetSalesforceAccountTasksList.java create mode 100644 src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetTasksListDto.java create mode 100644 src/main/java/com/salessparrow/api/services/accountTask/GetAccountTasksListService.java create mode 100644 src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/GetTasksListTest.java create mode 100644 src/test/resources/data/controllers/accountTaskController/getTasksList.scenarios.json create mode 100644 src/test/resources/fixtures/controllers/accountTaskController/getTasksList.fixtures.json diff --git a/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java b/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java index 888f3ad0..eccd32a3 100644 --- a/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java +++ b/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java @@ -6,6 +6,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -13,8 +14,10 @@ import org.springframework.web.bind.annotation.RestController; import com.salessparrow.api.dto.formatter.CreateTaskFormatterDto; +import com.salessparrow.api.dto.formatter.GetTasksListFormatterDto; import com.salessparrow.api.dto.requestMapper.CreateTaskDto; import com.salessparrow.api.services.accountTask.CreateTaskService; +import com.salessparrow.api.services.accountTask.GetAccountTasksListService; import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; @@ -25,18 +28,32 @@ @Validated public class AccountTaskController { - Logger logger = LoggerFactory.getLogger(AccountTaskController.class); - @Autowired - private CreateTaskService createTaskService; - - @PostMapping("/{account_id}/tasks") - public ResponseEntity createTask( - HttpServletRequest request, - @PathVariable("account_id") String accountId, - @Valid @RequestBody CreateTaskDto task - ){ - logger.info("Create task request received"); - CreateTaskFormatterDto createTaskFormatterDto = createTaskService.createTask(request, accountId, task); - return ResponseEntity.status(HttpStatus.CREATED).body(createTaskFormatterDto); - } + Logger logger = LoggerFactory.getLogger(AccountTaskController.class); + @Autowired + private CreateTaskService createTaskService; + + @Autowired + private GetAccountTasksListService getAccountTasksListService; + + @PostMapping("/{account_id}/tasks") + public ResponseEntity createTask( + HttpServletRequest request, + @PathVariable("account_id") String accountId, + @Valid @RequestBody CreateTaskDto task + ){ + logger.info("Create task request received"); + CreateTaskFormatterDto createTaskFormatterDto = createTaskService.createTask(request, accountId, task); + return ResponseEntity.status(HttpStatus.CREATED).body(createTaskFormatterDto); + } + + @GetMapping("/{account_id}/tasks") + public ResponseEntity getTasksList( + HttpServletRequest request, + @PathVariable("account_id") String accountId + ){ + logger.info("Get tasks list request received"); + + GetTasksListFormatterDto getTasksListFormatterDto = getAccountTasksListService.getTasksList(request, accountId); + return ResponseEntity.status(HttpStatus.OK).body(getTasksListFormatterDto); + } } diff --git a/src/main/java/com/salessparrow/api/dto/entities/TaskEntity.java b/src/main/java/com/salessparrow/api/dto/entities/TaskEntity.java new file mode 100644 index 00000000..5f0318ee --- /dev/null +++ b/src/main/java/com/salessparrow/api/dto/entities/TaskEntity.java @@ -0,0 +1,22 @@ +package com.salessparrow.api.dto.entities; + +import java.util.Date; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; + +import lombok.Data; + +/** + * TaskEntity is a DTO class for the Task List. + */ +@Data +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) +public class TaskEntity { + private String id; + private String creatorName; + private String description; + private Date dueDate; + private String crmOrganizationUserName; + private Date lastModifiedTime; +} diff --git a/src/main/java/com/salessparrow/api/dto/formatter/GetTasksListFormatterDto.java b/src/main/java/com/salessparrow/api/dto/formatter/GetTasksListFormatterDto.java new file mode 100644 index 00000000..61913205 --- /dev/null +++ b/src/main/java/com/salessparrow/api/dto/formatter/GetTasksListFormatterDto.java @@ -0,0 +1,20 @@ +package com.salessparrow.api.dto.formatter; + +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.salessparrow.api.dto.entities.TaskEntity; + +import lombok.Data; + +/** + * GetTasksListFormatterDto is a DTO class for the GetTasksListFormatterDto response. + */ +@Data +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) +public class GetTasksListFormatterDto { + private List taskIds; + private Map taskMapById; +} diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetAccountTasksListFactory.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetAccountTasksListFactory.java new file mode 100644 index 00000000..4780f673 --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetAccountTasksListFactory.java @@ -0,0 +1,46 @@ +package com.salessparrow.api.lib.crmActions.getAccountTasksList; + +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.User; +import com.salessparrow.api.dto.formatter.GetTasksListFormatterDto; +import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.lib.errorLib.ErrorObject; +import com.salessparrow.api.lib.globalConstants.UserConstants; + +/** + * GetAccountTasksListFactory is a factory class for the GetAccountTasksList action for the CRM. + */ +@Component +public class GetAccountTasksListFactory { + Logger logger = LoggerFactory.getLogger(GetAccountTasksListFactory.class); + + @Autowired + private GetSalesforceAccountTasksList getSalesforceAccountTasksList; + + /** + * Get the list of tasks for a given account. + * + * @param user + * @param accountId + * + * @return GetTasksListFormatterDto + **/ + public GetTasksListFormatterDto getTasksList(User user, String accountId) { + logger.info("factory for getTasksList action"); + + switch(user.getUserKind()) { + case UserConstants.SALESFORCE_USER_KIND: + return getSalesforceAccountTasksList.getTasksList(user, accountId); + default: + throw new CustomException( + new ErrorObject( + "l_ca_gatl_gatlf_gtl_1", + "something_went_wrong", + "Invalid user kind.")); + } + } +} diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetAccountTasksListInterface.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetAccountTasksListInterface.java new file mode 100644 index 00000000..c42796f1 --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetAccountTasksListInterface.java @@ -0,0 +1,14 @@ +package com.salessparrow.api.lib.crmActions.getAccountTasksList; + +import org.springframework.stereotype.Component; + +import com.salessparrow.api.domain.User; +import com.salessparrow.api.dto.formatter.GetTasksListFormatterDto; + +/** + * GetAccountTasksListInterface is an interface for the GetAccountTasksList action for the CRM. + */ +@Component +public interface GetAccountTasksListInterface { + public GetTasksListFormatterDto getTasksList(User user, String accountId); +} diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetSalesforceAccountTasksList.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetSalesforceAccountTasksList.java new file mode 100644 index 00000000..66548549 --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetSalesforceAccountTasksList.java @@ -0,0 +1,116 @@ +package com.salessparrow.api.lib.crmActions.getAccountTasksList; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.salessparrow.api.domain.User; +import com.salessparrow.api.dto.entities.TaskEntity; +import com.salessparrow.api.dto.formatter.GetTasksListFormatterDto; +import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.lib.Util; +import com.salessparrow.api.lib.errorLib.ErrorObject; +import com.salessparrow.api.lib.globalConstants.SalesforceConstants; +import com.salessparrow.api.lib.httpLib.HttpClient; +import com.salessparrow.api.lib.salesforce.dto.CompositeRequestDto; +import com.salessparrow.api.lib.salesforce.dto.SalesforceGetTasksListDto; +import com.salessparrow.api.lib.salesforce.helper.MakeCompositeRequest; +import com.salessparrow.api.lib.salesforce.helper.SalesforceQueryBuilder; + +/** + * GetSalesforceAccountTasksList is a class for the GetAccountTasksList service for the Salesforce CRM. + */ +@Component +public class GetSalesforceAccountTasksList { + Logger logger = LoggerFactory.getLogger(GetSalesforceAccountTasksList.class); + + @Autowired + private SalesforceConstants salesforceConstants; + + @Autowired + private MakeCompositeRequest makeCompositeRequest; + + /** + * Get the list of tasks for a given account + * + * @param user + * @param accountId + * + * @return GetTasksListFormatterDto + **/ + public GetTasksListFormatterDto getTasksList(User user, String accountId) { + logger.info("Salesforce getTasksList action"); + + String salesforceUserId = user.getExternalUserId(); + + SalesforceQueryBuilder salesforceQuery = new SalesforceQueryBuilder(); + String query = salesforceQuery.getTasksQuery(accountId); + + String url = salesforceConstants.queryUrlPath() + query; + + CompositeRequestDto compositeReq = new CompositeRequestDto("GET", url, "GetTasksList"); + + List compositeRequests = new ArrayList(); + compositeRequests.add(compositeReq); + + HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, salesforceUserId); + + return parseResponse(response.getResponseBody()); + } + + /** + * Parse Response + * + * @param responseBody + * + * @return GetTasksListFormatterDto + **/ + public GetTasksListFormatterDto parseResponse(String responseBody) { + + List taskIds = new ArrayList(); + Map taskIdToEntityMap = new HashMap<>(); + + Util util = new Util(); + JsonNode rootNode = util.getJsonNode(responseBody); + + JsonNode getTasksCompositeResponse = rootNode.get("compositeResponse").get(0); + Integer getTasksStatusCode = getTasksCompositeResponse.get("httpStatusCode").asInt(); + + if (getTasksStatusCode != 200 && getTasksStatusCode != 201) { + String errorBody = getTasksCompositeResponse.get("body").asText(); + + throw new CustomException( + new ErrorObject( + "l_ca_gatl_gsatl_pr_1", + "something_went_wrong", + errorBody)); + } + + JsonNode recordsNode = rootNode.get("compositeResponse").get(0).get("body").get("records");; + + for (JsonNode recordNode : recordsNode) { + ObjectMapper mapper = new ObjectMapper(); + mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + SalesforceGetTasksListDto salesforceGetTasksListDto = mapper.convertValue(recordNode, SalesforceGetTasksListDto.class); + TaskEntity taskEntity = salesforceGetTasksListDto.taskEntity(); + + taskIds.add(taskEntity.getId()); + taskIdToEntityMap.put(taskEntity.getId(), taskEntity); + } + + GetTasksListFormatterDto getTasksListFormatterDto = new GetTasksListFormatterDto(); + getTasksListFormatterDto.setTaskMapById(taskIdToEntityMap); + getTasksListFormatterDto.setTaskIds(taskIds); + + return getTasksListFormatterDto; + } +} diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetTasksListDto.java b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetTasksListDto.java new file mode 100644 index 00000000..40dc36ab --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetTasksListDto.java @@ -0,0 +1,43 @@ +package com.salessparrow.api.lib.salesforce.dto; + +import java.util.Date; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.salessparrow.api.dto.entities.TaskEntity; + +import lombok.Data; + +@Data +@JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) +public class SalesforceGetTasksListDto { + private String id; + private String description; + private Date activityDate; + private CreatedBy createdBy; + private Owner owner; + private Date lastModifiedDate; + + @Data + @JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) + private class CreatedBy{ + private String name; + } + + @Data + @JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) + private class Owner{ + private String name; + } + + public TaskEntity taskEntity(){ + TaskEntity taskEntity = new TaskEntity(); + taskEntity.setId(this.id); + taskEntity.setCreatorName(this.createdBy.name); + taskEntity.setDescription(this.description); + taskEntity.setDueDate(this.activityDate); + taskEntity.setCrmOrganizationUserName(this.owner.name); + taskEntity.setLastModifiedTime(this.lastModifiedDate); + return taskEntity; + } +} diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java index a4cc80a1..05c8231d 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java @@ -24,6 +24,18 @@ public String getAccountsQuery(String searchTerm) { return "SELECT Id, Name FROM Account WHERE Name LIKE '%25"+searchTerm+"%25' ORDER BY LastModifiedDate DESC LIMIT 20"; } + /** + * Get the list of tasks for a given account + * + * @param accountId + * + * @return String + */ + public String getTasksQuery(String accountId) { + return "SELECT Id, Description, ActivityDate, CreatedBy.Name, Owner.Name, LastModifiedDate FROM Task WHERE WhatId='" + + accountId + "' ORDER BY LastModifiedDate DESC LIMIT 5"; + } + /** * Get the list of notes for a given account * diff --git a/src/main/java/com/salessparrow/api/services/accountTask/GetAccountTasksListService.java b/src/main/java/com/salessparrow/api/services/accountTask/GetAccountTasksListService.java new file mode 100644 index 00000000..7fa097d7 --- /dev/null +++ b/src/main/java/com/salessparrow/api/services/accountTask/GetAccountTasksListService.java @@ -0,0 +1,38 @@ +package com.salessparrow.api.services.accountTask; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.salessparrow.api.domain.User; +import com.salessparrow.api.dto.formatter.GetTasksListFormatterDto; +import com.salessparrow.api.lib.crmActions.getAccountTasksList.GetAccountTasksListFactory; + +import jakarta.servlet.http.HttpServletRequest; + +/** + * GetAccountTasksListService class is responsible for getting list of account tasks in CRM + */ +@Service +public class GetAccountTasksListService { + Logger logger = LoggerFactory.getLogger(GetAccountTasksListService.class); + + @Autowired + private GetAccountTasksListFactory getAccountTasksListFactory; + + /** + * Get list of account tasks from CRM + * + * @param request HttpServletRequest object + * @param accountId CRM account id + * + * @return GetTasksListFormatterDto object + */ + public GetTasksListFormatterDto getTasksList(HttpServletRequest request, String accountId) { + logger.info("Inside getTasksList Service"); + + User currentUser = (User) request.getAttribute("current_user"); + return getAccountTasksListFactory.getTasksList(currentUser, accountId); + } +} diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java index a472b658..1ff0a3f9 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java @@ -77,7 +77,6 @@ public void getAccountList(Scenario testScenario) throws Exception { // Load fixture data String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); FixtureData fixtureData = common.loadFixture("classpath:fixtures/controllers/accountController/getAccountList.fixtures.json", currentFunctionName); - System.out.println("fixtureData++++++ "+fixtureData); loadFixture.perform(fixtureData); // Read data from the scenario @@ -92,7 +91,6 @@ public void getAccountList(Scenario testScenario) throws Exception { // Perform the request String url = "/api/v1/accounts"; String q = objectMapper.writeValueAsString(testScenario.getInput().get("q")); - System.out.println("q++++++ "+q); ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get(url) .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/GetTasksListTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/GetTasksListTest.java new file mode 100644 index 00000000..90b8c9b9 --- /dev/null +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/GetTasksListTest.java @@ -0,0 +1,117 @@ +package com.salessparrow.api.functional.controllers.accountTaskController; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Stream; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +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.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +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; +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 com.salessparrow.api.lib.httpLib.HttpClient.HttpResponse; +import com.salessparrow.api.lib.salesforce.helper.MakeCompositeRequest; + +import jakarta.servlet.http.Cookie; + +@SpringBootTest +@AutoConfigureMockMvc +@WebAppConfiguration +@Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) +public class GetTasksListTest { + + @Autowired + private MockMvc mockMvc; + @Autowired + private Common common; + @Autowired + private LoadFixture loadFixture; + @Autowired + private Setup setup; + @Autowired + private Cleanup cleanup; + + @MockBean + private MakeCompositeRequest makeCompositeRequestMock; + + @BeforeEach + public void setUp() throws DynamobeeException { + setup.perform(); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + @ParameterizedTest + @MethodSource("testScenariosProvider") + public void getTasksList(Scenario testScenario) throws Exception { + + // Load fixture data + String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/controllers/accountTaskController/getTasksList.fixtures.json", currentFunctionName); + loadFixture.perform(fixtureData); + + // Read data from the scenario + ObjectMapper objectMapper = new ObjectMapper(); + String cookieValue = Constants.SALESFORCE_ACTIVE_USET_COOKIE_VALUE; + String accountId = (String) testScenario.getInput().get("accountId"); + + // Prepare mock responses + HttpResponse getTasksListMockResponse = new HttpResponse(); + getTasksListMockResponse.setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest"))); + when(makeCompositeRequestMock.makePostRequest(any(), any())).thenReturn(getTasksListMockResponse); + + // Perform the request + String url = "/api/v1/accounts/" + accountId + "/tasks"; + + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get(url) + .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) + .contentType(MediaType.APPLICATION_JSON)); + + // Check the response + String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); + String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); + assertEquals(expectedOutput, actualOutput); + } + + static Stream testScenariosProvider() throws IOException { + List testScenarios = loadScenarios(); + return testScenarios.stream(); + } + + private static List loadScenarios() throws IOException { + String scenariosPath = "classpath:data/controllers/accountTaskController/getTasksList.scenarios.json"; + Resource resource = new DefaultResourceLoader().getResource(scenariosPath); + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); + } +} diff --git a/src/test/resources/data/controllers/accountTaskController/getTasksList.scenarios.json b/src/test/resources/data/controllers/accountTaskController/getTasksList.scenarios.json new file mode 100644 index 00000000..627ae213 --- /dev/null +++ b/src/test/resources/data/controllers/accountTaskController/getTasksList.scenarios.json @@ -0,0 +1,252 @@ +[ + { + "description": "Should return the 5 latest Notes", + "input": { + "accountId": "0011e00000bWSxdAAG" + }, + "mocks": { + "makeCompositeRequest": { + "compositeResponse": [ + { + "body": { + "totalSize": 5, + "done": true, + "records": [ + { + "attributes": { + "type": "Task", + "url": "/services/data/v58.0/sobjects/Task/00T1e000007mGYaEAM" + }, + "Id": "00T1e000007mGYaEAM", + "Description": "Update remaining documentations", + "ActivityDate": "2023-12-01", + "CreatedBy": { + "attributes": { + "type": "User", + "url": "/services/data/v58.0/sobjects/User/0055i00000AUxQHAA1" + }, + "Name": "Name2" + }, + "Owner": { + "attributes": { + "type": "Name", + "url": "/services/data/v58.0/sobjects/User/0051e0000047G03AAE" + }, + "Name": "Name1" + }, + "LastModifiedDate": "2023-08-24T12:16:05.000+0000" + }, + { + "attributes": { + "type": "Task", + "url": "/services/data/v58.0/sobjects/Task/00T1e000007mGXXEA2" + }, + "Id": "00T1e000007mGXXEA2", + "Description": "Update remaining documentations", + "ActivityDate": "2023-12-01", + "CreatedBy": { + "attributes": { + "type": "User", + "url": "/services/data/v58.0/sobjects/User/0055i00000AUxQHAA1" + }, + "Name": "Name2" + }, + "Owner": { + "attributes": { + "type": "Name", + "url": "/services/data/v58.0/sobjects/User/0051e0000047G03AAE" + }, + "Name": "Name1" + }, + "LastModifiedDate": "2023-08-24T12:09:51.000+0000" + }, + { + "attributes": { + "type": "Task", + "url": "/services/data/v58.0/sobjects/Task/00T1e000007mF0oEAE" + }, + "Id": "00T1e000007mF0oEAE", + "Description": "Update remaining documentations", + "ActivityDate": "2023-12-01", + "CreatedBy": { + "attributes": { + "type": "User", + "url": "/services/data/v58.0/sobjects/User/0055i00000AUxQHAA1" + }, + "Name": "Name2" + }, + "Owner": { + "attributes": { + "type": "Name", + "url": "/services/data/v58.0/sobjects/User/0051e0000047G03AAE" + }, + "Name": "Name1" + }, + "LastModifiedDate": "2023-08-23T13:11:03.000+0000" + }, + { + "attributes": { + "type": "Task", + "url": "/services/data/v58.0/sobjects/Task/00T1e000007mEk9EAE" + }, + "Id": "00T1e000007mEk9EAE", + "Description": "Update remaining documentations", + "ActivityDate": "2023-12-01", + "CreatedBy": { + "attributes": { + "type": "User", + "url": "/services/data/v58.0/sobjects/User/0055i00000AUxQHAA1" + }, + "Name": "Name2" + }, + "Owner": { + "attributes": { + "type": "Name", + "url": "/services/data/v58.0/sobjects/User/0051e0000047G03AAE" + }, + "Name": "Name1" + }, + "LastModifiedDate": "2023-08-23T07:49:23.000+0000" + }, + { + "attributes": { + "type": "Task", + "url": "/services/data/v58.0/sobjects/Task/00T1e000007mEfuEAE" + }, + "Id": "00T1e000007mEfuEAE", + "Description": "Update remaining documentations", + "ActivityDate": "2023-12-01", + "CreatedBy": { + "attributes": { + "type": "User", + "url": "/services/data/v58.0/sobjects/User/0055i00000AUxQHAA1" + }, + "Name": "Name2" + }, + "Owner": { + "attributes": { + "type": "Name", + "url": "/services/data/v58.0/sobjects/User/0051e0000047G03AAE" + }, + "Name": "Name1" + }, + "LastModifiedDate": "2023-08-23T07:10:53.000+0000" + } + ] + }, + "httpHeaders": {}, + "httpStatusCode": 200, + "referenceId": "GetTasksList" + } + ] + } + }, + "output": { + "task_ids": [ + "00T1e000007mGYaEAM", + "00T1e000007mGXXEA2", + "00T1e000007mF0oEAE", + "00T1e000007mEk9EAE", + "00T1e000007mEfuEAE" + ], + "task_map_by_id": { + "00T1e000007mGXXEA2": { + "id": "00T1e000007mGXXEA2", + "creator_name": "Name2", + "description": "Update remaining documentations", + "due_date": "2023-12-01T00:00:00.000+00:00", + "crm_organization_user_name": "Name1", + "last_modified_time": "2023-08-24T12:09:51.000+00:00" + }, + "00T1e000007mEk9EAE": { + "id": "00T1e000007mEk9EAE", + "creator_name": "Name2", + "description": "Update remaining documentations", + "due_date": "2023-12-01T00:00:00.000+00:00", + "crm_organization_user_name": "Name1", + "last_modified_time": "2023-08-23T07:49:23.000+00:00" + }, + "00T1e000007mEfuEAE": { + "id": "00T1e000007mEfuEAE", + "creator_name": "Name2", + "description": "Update remaining documentations", + "due_date": "2023-12-01T00:00:00.000+00:00", + "crm_organization_user_name": "Name1", + "last_modified_time": "2023-08-23T07:10:53.000+00:00" + }, + "00T1e000007mF0oEAE": { + "id": "00T1e000007mF0oEAE", + "creator_name": "Name2", + "description": "Update remaining documentations", + "due_date": "2023-12-01T00:00:00.000+00:00", + "crm_organization_user_name": "Name1", + "last_modified_time": "2023-08-23T13:11:03.000+00:00" + }, + "00T1e000007mGYaEAM": { + "id": "00T1e000007mGYaEAM", + "creator_name": "Name2", + "description": "Update remaining documentations", + "due_date": "2023-12-01T00:00:00.000+00:00", + "crm_organization_user_name": "Name1", + "last_modified_time": "2023-08-24T12:16:05.000+00:00" + } + } + } + }, + { + "description": "should return empty response when no tasks are present", + "input": { + "accountId": "0011e00000bWSxdAAG" + }, + "mocks": { + "makeCompositeRequest": { + "compositeResponse": [ + { + "body": { + "totalSize": 0, + "done": true, + "records": [] + }, + "httpHeaders": {}, + "httpStatusCode": 200, + "referenceId": "GetTasksList" + } + ] + } + }, + "output": { + "task_ids": [], + "task_map_by_id": {} + } + }, + { + "description": "should return error response when account id is invalid", + "input": { + "accountId": "invalid" + }, + "mocks": { + "makeCompositeRequest": { + "compositeResponse": [ + { + "body": [ + { + "message": "\nLastModifiedDate FROM Task WHERE WhatId='invalid' ORDER BY LastModifiedDate\n ^\nERROR at Row:1:Column:109\ninvalid ID field: abcd", + "errorCode": "INVALID_QUERY_FILTER_OPERATOR" + } + ], + "httpHeaders": {}, + "httpStatusCode": 400, + "referenceId": "GetTasksList" + } + ] + } + }, + "output": { + "http_code": 500, + "message": "Something went wrong.", + "code": "INTERNAL_SERVER_ERROR", + "internal_error_identifier": "l_ca_gatl_gsatl_pr_1", + "param_errors": [] + } + } +] \ No newline at end of file diff --git a/src/test/resources/fixtures/controllers/accountTaskController/getTasksList.fixtures.json b/src/test/resources/fixtures/controllers/accountTaskController/getTasksList.fixtures.json new file mode 100644 index 00000000..4b0ddba6 --- /dev/null +++ b/src/test/resources/fixtures/controllers/accountTaskController/getTasksList.fixtures.json @@ -0,0 +1,14 @@ +{ + "getTasksList": { + "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 2b60df822e2f16067f622143d5708ad0eed21dd2 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 24 Aug 2023 18:56:14 +0530 Subject: [PATCH 061/195] reverted logs added for debugging --- src/main/java/com/salessparrow/api/config/AwsConfig.java | 5 +---- src/main/java/com/salessparrow/api/lib/AwsKms.java | 3 --- .../controllers/accountController/GetNoteDetailsTest.java | 6 +----- 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/salessparrow/api/config/AwsConfig.java b/src/main/java/com/salessparrow/api/config/AwsConfig.java index d6edf255..9030f53e 100644 --- a/src/main/java/com/salessparrow/api/config/AwsConfig.java +++ b/src/main/java/com/salessparrow/api/config/AwsConfig.java @@ -45,12 +45,9 @@ public AWSKMS kmsClient() { CoreConstants.awsRegion() ); - AWSKMS kms = AWSKMSClientBuilder.standard() + return AWSKMSClientBuilder.standard() .withEndpointConfiguration(endpointConfiguration) .build(); - - System.out.println("kms.listKeys(): ======" + kms.listKeys()); - return kms; } return AWSKMSClientBuilder.standard() diff --git a/src/main/java/com/salessparrow/api/lib/AwsKms.java b/src/main/java/com/salessparrow/api/lib/AwsKms.java index b80c9873..527b4bf3 100644 --- a/src/main/java/com/salessparrow/api/lib/AwsKms.java +++ b/src/main/java/com/salessparrow/api/lib/AwsKms.java @@ -46,9 +46,6 @@ public String encryptToken(String token) { .withKeyId(CoreConstants.kmsKeyId()) .withPlaintext(ByteBuffer.wrap(token.getBytes())); - System.out.println("kmsKeyId: " + CoreConstants.kmsKeyId()); - System.out.println("local kms endpoint: " + CoreConstants.localKmsEndpoint()); - EncryptResult result = null; try { result = kmsClient.encrypt(request); diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java index 3a17f691..682df833 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java @@ -82,15 +82,11 @@ public void tearDown() { @MethodSource("testScenariosProvider") public void getNoteDetails(Scenario testScenario) throws Exception{ String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - try { - FixtureData fixtureData = common.loadFixture( + FixtureData fixtureData = common.loadFixture( "classpath:fixtures/controllers/accountController/getNoteDetails.fixtures.json", currentFunctionName ); loadFixture.perform(fixtureData); - } catch(Exception e) { - System.out.println("Exception in fixtures: --- " + e); - } ObjectMapper objectMapper = new ObjectMapper(); From 2b0cc489245466a1fbe4d9916d62b159e7becc1b Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 24 Aug 2023 19:07:35 +0530 Subject: [PATCH 062/195] fixed indentation in test case --- .../controllers/accountController/GetNoteDetailsTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java index 682df833..62c65ad6 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java @@ -83,10 +83,10 @@ public void tearDown() { public void getNoteDetails(Scenario testScenario) throws Exception{ String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); FixtureData fixtureData = common.loadFixture( - "classpath:fixtures/controllers/accountController/getNoteDetails.fixtures.json", - currentFunctionName - ); - loadFixture.perform(fixtureData); + "classpath:fixtures/controllers/accountController/getNoteDetails.fixtures.json", + currentFunctionName + ); + loadFixture.perform(fixtureData); ObjectMapper objectMapper = new ObjectMapper(); From ddc1e6f26381a00013d59b2f3620512f89e83b17 Mon Sep 17 00:00:00 2001 From: Yagnik Thummar Date: Thu, 24 Aug 2023 19:13:56 +0530 Subject: [PATCH 063/195] Added Get a list of CRM Organization Users Endpoint. --- .../CrmOrganizationUserController.java | 30 +++-- .../entities/CrmOrganizationUserEntity.java | 9 ++ .../GetCrmOrganizationUsersFormatterDto.java | 17 +++ .../GetCrmOrganizationUsersDto.java | 10 ++ .../GetCrmOrganizationUsers.java | 16 +++ .../GetCrmOrganizationUsersFactory.java | 46 +++++++ .../GetSalesforceCrmOrganizationUsers.java | 114 ++++++++++++++++++ .../dto/SalesforceCrmOrganizationUserDto.java | 25 ++++ .../helper/SalesforceQueryBuilder.java | 7 ++ .../GetCrmOrganizationUsersList.java | 64 ++++++++++ ...va => GetCrmOrganizationUserListTest.java} | 10 +- .../getCrmOrganizationUserList.scenarios.json | 8 +- 12 files changed, 340 insertions(+), 16 deletions(-) create mode 100644 src/main/java/com/salessparrow/api/dto/entities/CrmOrganizationUserEntity.java create mode 100644 src/main/java/com/salessparrow/api/dto/formatter/GetCrmOrganizationUsersFormatterDto.java create mode 100644 src/main/java/com/salessparrow/api/dto/requestMapper/GetCrmOrganizationUsersDto.java create mode 100644 src/main/java/com/salessparrow/api/lib/crmActions/getCrmOrganizationUsers/GetCrmOrganizationUsers.java create mode 100644 src/main/java/com/salessparrow/api/lib/crmActions/getCrmOrganizationUsers/GetCrmOrganizationUsersFactory.java create mode 100644 src/main/java/com/salessparrow/api/lib/crmActions/getCrmOrganizationUsers/GetSalesforceCrmOrganizationUsers.java create mode 100644 src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceCrmOrganizationUserDto.java create mode 100644 src/main/java/com/salessparrow/api/services/crmOrganizationUsers/GetCrmOrganizationUsersList.java rename src/test/java/com/salessparrow/api/functional/controllers/crmOrganizationUserController/{GetCrmorganizationUsersListTest.java => GetCrmOrganizationUserListTest.java} (95%) diff --git a/src/main/java/com/salessparrow/api/controllers/CrmOrganizationUserController.java b/src/main/java/com/salessparrow/api/controllers/CrmOrganizationUserController.java index 3057b635..29abf8f4 100644 --- a/src/main/java/com/salessparrow/api/controllers/CrmOrganizationUserController.java +++ b/src/main/java/com/salessparrow/api/controllers/CrmOrganizationUserController.java @@ -5,9 +5,17 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import jakarta.validation.constraints.Positive; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; +import com.salessparrow.api.dto.formatter.GetCrmOrganizationUsersFormatterDto; +import com.salessparrow.api.dto.requestMapper.GetCrmOrganizationUsersDto; +import com.salessparrow.api.services.crmOrganizationUsers.GetCrmOrganizationUsersList; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.Valid; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; @RestController @@ -15,11 +23,19 @@ public class CrmOrganizationUserController { Logger logger = LoggerFactory.getLogger(CrmOrganizationUserController.class); - @PostMapping("") - public void createCrmOrganizationUser( - @Positive @RequestBody String crmOrganizationUserId + @Autowired + private GetCrmOrganizationUsersList getCrmOrganizationUsersList; + + @GetMapping("") + public ResponseEntity getCrmOrganizationUsers( + HttpServletRequest request, + @Valid @ModelAttribute GetCrmOrganizationUsersDto CrmOrganizationUsersDto ){ - logger.info("Create crm organization user request received"); + logger.info("Search crm organization user request received"); + + GetCrmOrganizationUsersFormatterDto getCrmOrganizationUsersFormatterDto = getCrmOrganizationUsersList.getCrmOrganizationUsers(request, CrmOrganizationUsersDto); + + return ResponseEntity.ok().body(getCrmOrganizationUsersFormatterDto); } } diff --git a/src/main/java/com/salessparrow/api/dto/entities/CrmOrganizationUserEntity.java b/src/main/java/com/salessparrow/api/dto/entities/CrmOrganizationUserEntity.java new file mode 100644 index 00000000..e9355172 --- /dev/null +++ b/src/main/java/com/salessparrow/api/dto/entities/CrmOrganizationUserEntity.java @@ -0,0 +1,9 @@ +package com.salessparrow.api.dto.entities; + +import lombok.Data; + +@Data +public class CrmOrganizationUserEntity { + private String id; + private String name; +} diff --git a/src/main/java/com/salessparrow/api/dto/formatter/GetCrmOrganizationUsersFormatterDto.java b/src/main/java/com/salessparrow/api/dto/formatter/GetCrmOrganizationUsersFormatterDto.java new file mode 100644 index 00000000..8281b132 --- /dev/null +++ b/src/main/java/com/salessparrow/api/dto/formatter/GetCrmOrganizationUsersFormatterDto.java @@ -0,0 +1,17 @@ +package com.salessparrow.api.dto.formatter; + +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.salessparrow.api.dto.entities.CrmOrganizationUserEntity; + +import lombok.Data; + +@Data +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) +public class GetCrmOrganizationUsersFormatterDto { + private List crmOrganizationUserIds; + private Map crmOrganizationUserMapById; +} diff --git a/src/main/java/com/salessparrow/api/dto/requestMapper/GetCrmOrganizationUsersDto.java b/src/main/java/com/salessparrow/api/dto/requestMapper/GetCrmOrganizationUsersDto.java new file mode 100644 index 00000000..847394c4 --- /dev/null +++ b/src/main/java/com/salessparrow/api/dto/requestMapper/GetCrmOrganizationUsersDto.java @@ -0,0 +1,10 @@ +package com.salessparrow.api.dto.requestMapper; + +import jakarta.validation.constraints.Size; +import lombok.Data; + +@Data +public class GetCrmOrganizationUsersDto { + @Size(max = 200, message = "search_term_too_long") + private String q; +} diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getCrmOrganizationUsers/GetCrmOrganizationUsers.java b/src/main/java/com/salessparrow/api/lib/crmActions/getCrmOrganizationUsers/GetCrmOrganizationUsers.java new file mode 100644 index 00000000..283236ae --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getCrmOrganizationUsers/GetCrmOrganizationUsers.java @@ -0,0 +1,16 @@ +package com.salessparrow.api.lib.crmActions.getCrmOrganizationUsers; + +import org.springframework.stereotype.Component; + +import com.salessparrow.api.domain.User; +import com.salessparrow.api.dto.formatter.GetCrmOrganizationUsersFormatterDto; + +/** + * GetCrmOrganizationUsers interface for the getCrmOrganizationUsers action. + * + */ +@Component +public interface GetCrmOrganizationUsers { + + public GetCrmOrganizationUsersFormatterDto getCrmOrganizationUsers(User user, String searchTerm); +} diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getCrmOrganizationUsers/GetCrmOrganizationUsersFactory.java b/src/main/java/com/salessparrow/api/lib/crmActions/getCrmOrganizationUsers/GetCrmOrganizationUsersFactory.java new file mode 100644 index 00000000..31bc34b6 --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getCrmOrganizationUsers/GetCrmOrganizationUsersFactory.java @@ -0,0 +1,46 @@ +package com.salessparrow.api.lib.crmActions.getCrmOrganizationUsers; + +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.User; +import com.salessparrow.api.dto.formatter.GetCrmOrganizationUsersFormatterDto; +import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.lib.errorLib.ErrorObject; +import com.salessparrow.api.lib.globalConstants.UserConstants; + +/** + * GetCrmOrganizationUsersFactory class for the getCrmOrganizationUsers action. + * + */ +@Component +public class GetCrmOrganizationUsersFactory { + + Logger logger = LoggerFactory.getLogger(GetCrmOrganizationUsersFactory.class); + + @Autowired + private GetSalesforceCrmOrganizationUsers getSalesforceCrmOrganizationUsers; + + /** + * getCrmOrganizationUsers method for the getCrmOrganizationUsers action. + * + * @param user + * @param searchTerm + * @return GetCrmOrganizationUsersFormatterDto + */ + public GetCrmOrganizationUsersFormatterDto getCrmOrganizationUsers(User user, String searchTerm){ + switch(user.getUserKind()) { + case UserConstants.SALESFORCE_USER_KIND: + logger.info("Executing salesforce get CrmOrganizationUser Service"); + return getSalesforceCrmOrganizationUsers.getCrmOrganizationUsers(user, searchTerm); + default: + throw new CustomException( + new ErrorObject( + "l_ca_gcou_gcouf_gcou_1", + "something_went_wrong", + "Invalid user kind.")); + } + } +} diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getCrmOrganizationUsers/GetSalesforceCrmOrganizationUsers.java b/src/main/java/com/salessparrow/api/lib/crmActions/getCrmOrganizationUsers/GetSalesforceCrmOrganizationUsers.java new file mode 100644 index 00000000..d14c48c8 --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getCrmOrganizationUsers/GetSalesforceCrmOrganizationUsers.java @@ -0,0 +1,114 @@ +package com.salessparrow.api.lib.crmActions.getCrmOrganizationUsers; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.salessparrow.api.domain.User; +import com.salessparrow.api.dto.entities.CrmOrganizationUserEntity; +import com.salessparrow.api.dto.formatter.GetCrmOrganizationUsersFormatterDto; +import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.lib.Util; +import com.salessparrow.api.lib.errorLib.ErrorObject; +import com.salessparrow.api.lib.globalConstants.SalesforceConstants; +import com.salessparrow.api.lib.httpLib.HttpClient; +import com.salessparrow.api.lib.salesforce.dto.CompositeRequestDto; +import com.salessparrow.api.lib.salesforce.dto.SalesforceCrmOrganizationUserDto; +import com.salessparrow.api.lib.salesforce.helper.MakeCompositeRequest; +import com.salessparrow.api.lib.salesforce.helper.SalesforceQueryBuilder; + +/** + * GetCrmOrganizationUsersFactory class for the getCrmOrganizationUsers action. + * + */ +@Component +public class GetSalesforceCrmOrganizationUsers implements GetCrmOrganizationUsers{ + + Logger logger = LoggerFactory.getLogger(GetSalesforceCrmOrganizationUsers.class); + + @Autowired + private SalesforceConstants salesforceConstants; + + @Autowired + private MakeCompositeRequest makeCompositeRequest; + + /** + * getCrmOrganizationUsers method for the getCrmOrganizationUsers action. + * + * @param user + * @param searchTerm + * + * @return GetCrmOrganizationUsersFormatterDto + */ + public GetCrmOrganizationUsersFormatterDto getCrmOrganizationUsers(User user, String searchTerm) { + String salesforceUserId = user.getExternalUserId(); + + SalesforceQueryBuilder salesforceQuery = new SalesforceQueryBuilder(); + String query = salesforceQuery.getCrmOrganizationUsersQuery(searchTerm); + + String url = salesforceConstants.queryUrlPath() + query; + + CompositeRequestDto compositeReq = new CompositeRequestDto("GET", url, "getCrmOrganizationUsers"); + + List compositeRequests = new ArrayList(); + compositeRequests.add(compositeReq); + + HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, salesforceUserId); + + return parseResponse(response.getResponseBody()); + } + + /** + * parseResponse method for the getCrmOrganizationUsers action. + * + * @param responseBody + * + * @return GetCrmOrganizationUsersFormatterDto + */ + private GetCrmOrganizationUsersFormatterDto parseResponse(String responseBody){ + List crmOrganizationUserIds = new ArrayList(); + Map crmOrganizationUserMap = new HashMap(); + + logger.info("Parsing response from salesforce"); + + Util util = new Util(); + JsonNode rootNode = util.getJsonNode(responseBody); + + JsonNode httpStatusCodeNode = rootNode.get("compositeResponse").get(0).get("httpStatusCode"); + + if (httpStatusCodeNode.asInt() != 200 && httpStatusCodeNode.asInt() != 201) { + throw new CustomException( + new ErrorObject( + "l_ca_ga_gsa_pr_1", + "bad_request", + "Error in fetching accounts from salesforce")); + } + + JsonNode recordsNode = rootNode.get("compositeResponse").get(0).get("body").get("records"); + + for (JsonNode recordNode : recordsNode) { + ObjectMapper mapper = new ObjectMapper(); + mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + SalesforceCrmOrganizationUserDto salesforceCrmOrganization = mapper.convertValue(recordNode, SalesforceCrmOrganizationUserDto.class); + CrmOrganizationUserEntity accountCrmOrganizationUser = salesforceCrmOrganization.getCrmOrganizationUserEntity(); + + crmOrganizationUserIds.add(accountCrmOrganizationUser.getId()); + crmOrganizationUserMap.put(accountCrmOrganizationUser.getId(), accountCrmOrganizationUser); + } + + GetCrmOrganizationUsersFormatterDto getCrmOrganizationUsersResponse = new GetCrmOrganizationUsersFormatterDto(); + getCrmOrganizationUsersResponse.setCrmOrganizationUserIds(crmOrganizationUserIds); + getCrmOrganizationUsersResponse.setCrmOrganizationUserMapById(crmOrganizationUserMap); + + return getCrmOrganizationUsersResponse; + } +} diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceCrmOrganizationUserDto.java b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceCrmOrganizationUserDto.java new file mode 100644 index 00000000..2494a585 --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceCrmOrganizationUserDto.java @@ -0,0 +1,25 @@ +package com.salessparrow.api.lib.salesforce.dto; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.salessparrow.api.dto.entities.CrmOrganizationUserEntity; + +import lombok.Data; + +@Data +@JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) +public class SalesforceCrmOrganizationUserDto { + private String id; + private String name; + + /** + * convert SalesforceCrmOrganizationUserDto into CrmOrganizationUserEntity + */ + public CrmOrganizationUserEntity getCrmOrganizationUserEntity() { + CrmOrganizationUserEntity crmOrganizationUserEntity = new CrmOrganizationUserEntity(); + crmOrganizationUserEntity.setId(this.id); + crmOrganizationUserEntity.setName(this.name); + + return crmOrganizationUserEntity; + } +} diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java index a4cc80a1..3bfe3c36 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java @@ -59,4 +59,11 @@ public String getNoteDetailsUrl(String noteId){ return "SELECT Id, Title, TextPreview, CreatedBy.Name, LastModifiedDate FROM ContentNote WHERE Id = '" + noteId + "'"; } + public String getCrmOrganizationUsersQuery(String searchTerm) { + if (searchTerm == "") { + return "SELECT Id, Name FROM User ORDER BY LastModifiedDate DESC LIMIT 20"; + } + return "SELECT Id, Name FROM User WHERE Name LIKE '%25"+searchTerm+"%25' ORDER BY LastModifiedDate DESC LIMIT 20"; + } + } diff --git a/src/main/java/com/salessparrow/api/services/crmOrganizationUsers/GetCrmOrganizationUsersList.java b/src/main/java/com/salessparrow/api/services/crmOrganizationUsers/GetCrmOrganizationUsersList.java new file mode 100644 index 00000000..fc248bd5 --- /dev/null +++ b/src/main/java/com/salessparrow/api/services/crmOrganizationUsers/GetCrmOrganizationUsersList.java @@ -0,0 +1,64 @@ +package com.salessparrow.api.services.crmOrganizationUsers; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.salessparrow.api.domain.User; +import com.salessparrow.api.dto.formatter.GetCrmOrganizationUsersFormatterDto; +import com.salessparrow.api.dto.requestMapper.GetCrmOrganizationUsersDto; +import com.salessparrow.api.lib.crmActions.getCrmOrganizationUsers.GetCrmOrganizationUsersFactory; + +import jakarta.servlet.http.HttpServletRequest; + +/** + * GetCrmOrganizationUsersList class for the getCrmOrganizationUsers action. + * + * + */ +@Service +public class GetCrmOrganizationUsersList { + + Logger logger = LoggerFactory.getLogger(GetCrmOrganizationUsersList.class); + + @Autowired + private GetCrmOrganizationUsersFactory getCrmOrganizationUsersFactory; + + /** + * getCrmOrganizationUsers method for the getCrmOrganizationUsers action. + * + * @param request + * @param crmOrganizationUsersDto + * + * @return GetCrmOrganizationUsersFormatterDto + */ + public GetCrmOrganizationUsersFormatterDto getCrmOrganizationUsers(HttpServletRequest request ,GetCrmOrganizationUsersDto crmOrganizationUsersDto) { + logger.info("Inside Search crm organization user service"); + User currentUser = (User) request.getAttribute("current_user"); + + String formattedSearchString = formatSearchString(crmOrganizationUsersDto.getQ()); + return getCrmOrganizationUsersFactory.getCrmOrganizationUsers(currentUser, formattedSearchString); + } + + /** + * formatSearchString method for the getCrmOrganizationUsers action. + * + * @param searchTerm + * + * @return String + */ + private String formatSearchString(String searchTerm) { + logger.info("format and sanitize search term"); + searchTerm = searchTerm.trim(); + try { + return URLEncoder.encode(searchTerm,"UTF-8"); + } catch (UnsupportedEncodingException e) { + return searchTerm; + } + } + +} diff --git a/src/test/java/com/salessparrow/api/functional/controllers/crmOrganizationUserController/GetCrmorganizationUsersListTest.java b/src/test/java/com/salessparrow/api/functional/controllers/crmOrganizationUserController/GetCrmOrganizationUserListTest.java similarity index 95% rename from src/test/java/com/salessparrow/api/functional/controllers/crmOrganizationUserController/GetCrmorganizationUsersListTest.java rename to src/test/java/com/salessparrow/api/functional/controllers/crmOrganizationUserController/GetCrmOrganizationUserListTest.java index 1b471608..e8db876c 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/crmOrganizationUserController/GetCrmorganizationUsersListTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/crmOrganizationUserController/GetCrmOrganizationUserListTest.java @@ -45,7 +45,7 @@ @AutoConfigureMockMvc @WebAppConfiguration @Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) -public class GetCrmorganizationUsersListTest { +public class GetCrmOrganizationUserListTest { @Autowired private MockMvc mockMvc; @Autowired @@ -70,9 +70,9 @@ public void tearDown() { cleanup.perform(); } - @ParameterizedTest + @ParameterizedTest @MethodSource("testScenariosProvider") - public void getAccountList(Scenario testScenario) throws Exception { + public void getCrmOrganizationUserList(Scenario testScenario) throws Exception { // Load fixture data String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); FixtureData fixtureData = common.loadFixture("classpath:fixtures/controllers/crmOrganizationUserController/getCrmOrganizationUserList.fixtures.json", currentFunctionName); @@ -81,7 +81,7 @@ public void getAccountList(Scenario testScenario) throws Exception { // Read data from the scenario ObjectMapper objectMapper = new ObjectMapper(); - String cookieValue = (String) testScenario.getInput().get("cookieValue"); + String cookieValue = (String) testScenario.getInput().get("cookie"); String q = (String) testScenario.getInput().get("q"); // Prepare mock responses @@ -90,7 +90,7 @@ public void getAccountList(Scenario testScenario) throws Exception { when(makeCompositeRequestMock.makePostRequest(any(), any())).thenReturn(getAccountMockResponse); // Perform the request - String url = "/api/v1/crm-organization-user"; + String url = "/api/v1/crm-organization-users"; ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get(url) .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) diff --git a/src/test/resources/data/controllers/crmOrganizationUserController/getCrmOrganizationUserList.scenarios.json b/src/test/resources/data/controllers/crmOrganizationUserController/getCrmOrganizationUserList.scenarios.json index 9e694170..b8f18dee 100644 --- a/src/test/resources/data/controllers/crmOrganizationUserController/getCrmOrganizationUserList.scenarios.json +++ b/src/test/resources/data/controllers/crmOrganizationUserController/getCrmOrganizationUserList.scenarios.json @@ -39,11 +39,11 @@ } }, "output": { - "account_ids": [ + "crm_organization_user_ids": [ "0051e0000047G03AAE", "0051e000004NQ6fAAG" ], - "account_map_by_id": { + "crm_organization_user_map_by_id": { "0051e0000047G03AAE": { "id": "0051e0000047G03AAE", "name": "Alpesh Modi" @@ -95,11 +95,11 @@ } }, "output": { - "account_ids": [ + "crm_organization_user_ids": [ "0051e0000047G03AAE", "0051e000004NQ6fAAG" ], - "account_map_by_id": { + "crm_organization_user_map_by_id": { "0051e0000047G03AAE": { "id": "0051e0000047G03AAE", "name": "Alpesh Modi" From 5d5b7b6c3f3f74b1d22df78a4f7c1b7cf5f3b8b8 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 24 Aug 2023 19:19:30 +0530 Subject: [PATCH 064/195] fixed indentation in test cases --- .../accountController/GetNoteDetailsTest.java | 5 +- .../getNoteDetails.scenarios.json | 174 +++++++++--------- 2 files changed, 87 insertions(+), 92 deletions(-) diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java index 62c65ad6..71bdcb7a 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java @@ -82,10 +82,7 @@ public void tearDown() { @MethodSource("testScenariosProvider") public void getNoteDetails(Scenario testScenario) throws Exception{ String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture( - "classpath:fixtures/controllers/accountController/getNoteDetails.fixtures.json", - currentFunctionName - ); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/controllers/accountController/getNoteDetails.fixtures.json", currentFunctionName); loadFixture.perform(fixtureData); ObjectMapper objectMapper = new ObjectMapper(); diff --git a/src/test/resources/data/controllers/accountController/getNoteDetails.scenarios.json b/src/test/resources/data/controllers/accountController/getNoteDetails.scenarios.json index 77f4f83c..8919d2cc 100644 --- a/src/test/resources/data/controllers/accountController/getNoteDetails.scenarios.json +++ b/src/test/resources/data/controllers/accountController/getNoteDetails.scenarios.json @@ -1,90 +1,88 @@ [ - { - "description": "Should return the 5 latest Notes", - "input": { - "accountId":"0011e00000bWSxdAAG", - "noteId":"0691e000001WY58AAG", - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" - }, - "mocks":{ - "makeCompositeRequest":{ - "compositeResponse": [ - { - "body": { - "totalSize": 1, - "done": true, - "records": [ - { - "attributes": { - "type": "ContentNote", - "url": "/services/data/v58.0/sobjects/ContentNote/0691e000001WY58AAG" - }, - "Id": "0691e000001WY58AAG", - "Title": "Test Note with composite", - "TextPreview": "Let's use plural routes and have accountId in URL as per the API Convention.\\n/v1/account/content-notes => /v1/salesforce/accounts/{accountId}/content-notes\\n/v1/composite is generic. It can be under a salesforce route.\\n/v1/composite => /v1/salesforce/co", - "CreatedBy": { - "attributes": { - "type": "User", - "url": "/services/data/v58.0/sobjects/User/0055i00000AUxQHAA1" - }, - "Name": "Ashfaq Bhojani" - }, - "LastModifiedDate": "2023-08-01T10:38:23.000+0000" - } - ] - }, - "httpHeaders": {}, - "httpStatusCode": 200, - "referenceId": "ContentDocument" - } - ] - }, - "makeWrapperRequest":"

Let's use plural routes and have accountId in URL as per the API Convention.\n/v1/account/content-notes => /v1/salesforce/accounts/{accountId}/content-notes\n/v1/composite is generic. It can be under a salesforce route.\n/v1/composite => /v1/salesforce/composite\nQuestion:TextPreview in content notes response is a truncated version of the full text in notes?She suspicion dejection saw instantly. Well deny may real one told yet saw hard dear. Bed chief house rapid right the. Set noisy one state tears which. No girl oh part must fact high my he. Simplicity in excellence melancholy as remarkably discovered. Own partiality motionless was old excellence she inquietude contrasted. Sister giving so wicket cousin of an he rather marked. Of on game part body rich. Adapted mr savings venture it or comfort affixed friends.Prepared is me marianne pleasure likewise debating. Wonder an unable except better stairs do ye admire. His and eat secure sex called esteem praise. So moreover as speedily differed branched ignorant. Tall are her knew poor now does then. Procured to contempt oh he raptures amounted occasion. One boy assure income spirit lovers set.Passage its ten led hearted removal cordial. Preference any astonished unreserved mrs. Prosperous understood middletons in conviction an uncommonly do. Supposing so be resolving breakfast am or perfectly. Is drew am hill from mr. Valley by oh twenty direct me so. Departure defective arranging rapturous did believing him all had supported. Family months lasted simple set nature vulgar him. Picture for attempt joy excited ten carried manners talking how. Suspicion neglected he resolving agreement perceived at an.Dashwood contempt on mr unlocked resolved provided of of. Stanhill wondered it it welcomed oh. Hundred no prudent he however smiling at an offence. If earnestly extremity he he propriety something admitting convinced ye. Pleasant in to although as if differed horrible. Mirth his quick its set front enjoy hoped had there. Who connection imprudence middletons too but increasing celebrated principles joy. Herself too improve gay winding ask expense are compact. New all paid few hard pure she.That know ask case sex ham dear her spot. Weddings followed the all marianne nor whatever settling. Perhaps six prudent several her had offence. Did had way law dinner square tastes. Recommend concealed yet her procuring see consulted depending. Adieu

" - }, - "output":{ - "note_detail": { - "id": "0691e000001WY58AAG", - "creator": "Ashfaq Bhojani", - "text": "\"

Let's use plural routes and have accountId in URL as per the API Convention.\\n/v1/account/content-notes => /v1/salesforce/accounts/{accountId}/content-notes\\n/v1/composite is generic. It can be under a salesforce route.\\n/v1/composite => /v1/salesforce/composite\\nQuestion:TextPreview in content notes response is a truncated version of the full text in notes?She suspicion dejection saw instantly. Well deny may real one told yet saw hard dear. Bed chief house rapid right the. Set noisy one state tears which. No girl oh part must fact high my he. Simplicity in excellence melancholy as remarkably discovered. Own partiality motionless was old excellence she inquietude contrasted. Sister giving so wicket cousin of an he rather marked. Of on game part body rich. Adapted mr savings venture it or comfort affixed friends.Prepared is me marianne pleasure likewise debating. Wonder an unable except better stairs do ye admire. His and eat secure sex called esteem praise. So moreover as speedily differed branched ignorant. Tall are her knew poor now does then. Procured to contempt oh he raptures amounted occasion. One boy assure income spirit lovers set.Passage its ten led hearted removal cordial. Preference any astonished unreserved mrs. Prosperous understood middletons in conviction an uncommonly do. Supposing so be resolving breakfast am or perfectly. Is drew am hill from mr. Valley by oh twenty direct me so. Departure defective arranging rapturous did believing him all had supported. Family months lasted simple set nature vulgar him. Picture for attempt joy excited ten carried manners talking how. Suspicion neglected he resolving agreement perceived at an.Dashwood contempt on mr unlocked resolved provided of of. Stanhill wondered it it welcomed oh. Hundred no prudent he however smiling at an offence. If earnestly extremity he he propriety something admitting convinced ye. Pleasant in to although as if differed horrible. Mirth his quick its set front enjoy hoped had there. Who connection imprudence middletons too but increasing celebrated principles joy. Herself too improve gay winding ask expense are compact. New all paid few hard pure she.That know ask case sex ham dear her spot. Weddings followed the all marianne nor whatever settling. Perhaps six prudent several her had offence. Did had way law dinner square tastes. Recommend concealed yet her procuring see consulted depending. Adieu

\"", - "last_modified_time": "2023-08-01T10:38:23.000+00:00" - } - } - }, - { - "description": "should return error response when note id is invalid", - "input": { - "account_id": "0011e00000bWSxdAAG", - "note_id": "0011e00000bWSxdAAG", - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" - }, - "mocks":{ - "makeCompositeRequest":{ - "compositeResponse": [ - { - "body": { - "totalSize": 0, - "done": true, - "records": [] - }, - "httpHeaders": {}, - "httpStatusCode": 200, - "referenceId": "Note" - } - ] - }, - "makeWrapperRequest":[ - { - "errorCode": "NOT_FOUND", - "message": "The requested resource does not exist" - } - ] - }, - "output": { - "http_code": 500, - "message": "Something went wrong.", - "code": "INTERNAL_SERVER_ERROR", - "internal_error_identifier": "l_c_gnd_gsnd_2", - "param_errors": [] - } - } + { + "description": "Should return the 5 latest Notes", + "input": { + "accountId":"0011e00000bWSxdAAG", + "noteId":"0691e000001WY58AAG", + "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + }, + "mocks":{ + "makeCompositeRequest":{ + "compositeResponse": [ + { + "body": { + "totalSize": 1, + "done": true, + "records": [ + { + "attributes": { + "type": "ContentNote", + "url": "/services/data/v58.0/sobjects/ContentNote/0691e000001WY58AAG" + }, + "Id": "0691e000001WY58AAG", + "Title": "Test Note with composite", + "TextPreview": "Let's use plural routes and have accountId in URL as per the API Convention.\\n/v1/account/content-notes => /v1/salesforce/accounts/{accountId}/content-notes\\n/v1/composite is generic. It can be under a salesforce route.\\n/v1/composite => /v1/salesforce/co", + "CreatedBy": { + "attributes": { + "type": "User", + "url": "/services/data/v58.0/sobjects/User/0055i00000AUxQHAA1" + }, + "Name": "Ashfaq Bhojani" + }, + "LastModifiedDate": "2023-08-01T10:38:23.000+0000" + } + ] + }, + "httpHeaders": {}, + "httpStatusCode": 200, + "referenceId": "ContentDocument" + } + ] + }, + "makeWrapperRequest":"

Let's use plural routes and have accountId in URL as per the API Convention.\n/v1/account/content-notes => /v1/salesforce/accounts/{accountId}/content-notes\n/v1/composite is generic. It can be under a salesforce route.\n/v1/composite => /v1/salesforce/composite\nQuestion:TextPreview in content notes response is a truncated version of the full text in notes?She suspicion dejection saw instantly. Well deny may real one told yet saw hard dear. Bed chief house rapid right the. Set noisy one state tears which. No girl oh part must fact high my he. Simplicity in excellence melancholy as remarkably discovered. Own partiality motionless was old excellence she inquietude contrasted. Sister giving so wicket cousin of an he rather marked. Of on game part body rich. Adapted mr savings venture it or comfort affixed friends.Prepared is me marianne pleasure likewise debating. Wonder an unable except better stairs do ye admire. His and eat secure sex called esteem praise. So moreover as speedily differed branched ignorant. Tall are her knew poor now does then. Procured to contempt oh he raptures amounted occasion. One boy assure income spirit lovers set.Passage its ten led hearted removal cordial. Preference any astonished unreserved mrs. Prosperous understood middletons in conviction an uncommonly do. Supposing so be resolving breakfast am or perfectly. Is drew am hill from mr. Valley by oh twenty direct me so. Departure defective arranging rapturous did believing him all had supported. Family months lasted simple set nature vulgar him. Picture for attempt joy excited ten carried manners talking how. Suspicion neglected he resolving agreement perceived at an.Dashwood contempt on mr unlocked resolved provided of of. Stanhill wondered it it welcomed oh. Hundred no prudent he however smiling at an offence. If earnestly extremity he he propriety something admitting convinced ye. Pleasant in to although as if differed horrible. Mirth his quick its set front enjoy hoped had there. Who connection imprudence middletons too but increasing celebrated principles joy. Herself too improve gay winding ask expense are compact. New all paid few hard pure she.That know ask case sex ham dear her spot. Weddings followed the all marianne nor whatever settling. Perhaps six prudent several her had offence. Did had way law dinner square tastes. Recommend concealed yet her procuring see consulted depending. Adieu

" + }, + "output":{ + "note_detail": { + "id": "0691e000001WY58AAG", + "creator": "Ashfaq Bhojani", + "text": "\"

Let's use plural routes and have accountId in URL as per the API Convention.\\n/v1/account/content-notes => /v1/salesforce/accounts/{accountId}/content-notes\\n/v1/composite is generic. It can be under a salesforce route.\\n/v1/composite => /v1/salesforce/composite\\nQuestion:TextPreview in content notes response is a truncated version of the full text in notes?She suspicion dejection saw instantly. Well deny may real one told yet saw hard dear. Bed chief house rapid right the. Set noisy one state tears which. No girl oh part must fact high my he. Simplicity in excellence melancholy as remarkably discovered. Own partiality motionless was old excellence she inquietude contrasted. Sister giving so wicket cousin of an he rather marked. Of on game part body rich. Adapted mr savings venture it or comfort affixed friends.Prepared is me marianne pleasure likewise debating. Wonder an unable except better stairs do ye admire. His and eat secure sex called esteem praise. So moreover as speedily differed branched ignorant. Tall are her knew poor now does then. Procured to contempt oh he raptures amounted occasion. One boy assure income spirit lovers set.Passage its ten led hearted removal cordial. Preference any astonished unreserved mrs. Prosperous understood middletons in conviction an uncommonly do. Supposing so be resolving breakfast am or perfectly. Is drew am hill from mr. Valley by oh twenty direct me so. Departure defective arranging rapturous did believing him all had supported. Family months lasted simple set nature vulgar him. Picture for attempt joy excited ten carried manners talking how. Suspicion neglected he resolving agreement perceived at an.Dashwood contempt on mr unlocked resolved provided of of. Stanhill wondered it it welcomed oh. Hundred no prudent he however smiling at an offence. If earnestly extremity he he propriety something admitting convinced ye. Pleasant in to although as if differed horrible. Mirth his quick its set front enjoy hoped had there. Who connection imprudence middletons too but increasing celebrated principles joy. Herself too improve gay winding ask expense are compact. New all paid few hard pure she.That know ask case sex ham dear her spot. Weddings followed the all marianne nor whatever settling. Perhaps six prudent several her had offence. Did had way law dinner square tastes. Recommend concealed yet her procuring see consulted depending. Adieu

\"", + "last_modified_time": "2023-08-01T10:38:23.000+00:00" + } + } + }, + { + "description": "should return error response when note id is invalid", + "input": { + "account_id": "0011e00000bWSxdAAG", + "note_id": "0011e00000bWSxdAAG", + "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + }, + "mocks":{ + "makeCompositeRequest":{ + "compositeResponse": [ + { + "body": { + "totalSize": 0, + "done": true, + "records": [] + }, + "httpHeaders": {}, + "httpStatusCode": 200, + "referenceId": "Note" + } + ] + }, + "makeWrapperRequest":[ + { + "errorCode": "NOT_FOUND", + "message": "The requested resource does not exist" + } + ] + }, + "output": { + "http_code": 500, + "code": "INTERNAL_SERVER_ERROR", + "param_errors": [] + } + } ] \ No newline at end of file From d68f46d57dabe8d14476e68bc3c83c8a73d60048 Mon Sep 17 00:00:00 2001 From: ajinkyac03 Date: Thu, 24 Aug 2023 19:29:29 +0530 Subject: [PATCH 065/195] Added crm action suggestions api. --- .../api/config/CoreConstants.java | 9 ++ .../controllers/SuggestionsController.java | 35 +++++++ .../entities/AddTaskSuggestionEntityDto.java | 16 ++++ .../CrmActionSuggestionsFormatterDto.java | 18 ++++ .../CrmActionsSuggestionsDto.java | 13 +++ .../api/lib/GetCrmActionSuggestions.java | 95 +++++++++++++++++++ .../lib/globalConstants/OpenAiConstants.java | 11 +++ .../api/lib/openAi/OpenAiPayloadBuilder.java | 68 +++++++++++++ .../api/lib/openAi/OpenAiRequest.java | 61 ++++++++++++ .../CrmActionsSuggestionsService.java | 23 +++++ 10 files changed, 349 insertions(+) create mode 100644 src/main/java/com/salessparrow/api/controllers/SuggestionsController.java create mode 100644 src/main/java/com/salessparrow/api/dto/entities/AddTaskSuggestionEntityDto.java create mode 100644 src/main/java/com/salessparrow/api/dto/formatter/CrmActionSuggestionsFormatterDto.java create mode 100644 src/main/java/com/salessparrow/api/dto/requestMapper/CrmActionsSuggestionsDto.java create mode 100644 src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java create mode 100644 src/main/java/com/salessparrow/api/lib/globalConstants/OpenAiConstants.java create mode 100644 src/main/java/com/salessparrow/api/lib/openAi/OpenAiPayloadBuilder.java create mode 100644 src/main/java/com/salessparrow/api/lib/openAi/OpenAiRequest.java create mode 100644 src/main/java/com/salessparrow/api/services/suggestions/CrmActionsSuggestionsService.java diff --git a/src/main/java/com/salessparrow/api/config/CoreConstants.java b/src/main/java/com/salessparrow/api/config/CoreConstants.java index b381cbe6..1d0befaa 100644 --- a/src/main/java/com/salessparrow/api/config/CoreConstants.java +++ b/src/main/java/com/salessparrow/api/config/CoreConstants.java @@ -73,6 +73,15 @@ public static String[] getWhitelistedRedirectUris() { return redirectUrisJson.split(","); } + /** + * This method returns api key for OpenAI. + * + * @return String + */ + public static String openAiApiKey() { + return System.getenv("OPENAI_API_KEY"); + } + /** * This method returns the email address that will be used to send error emails. * This email address or its domain must be verified in AWS SES. diff --git a/src/main/java/com/salessparrow/api/controllers/SuggestionsController.java b/src/main/java/com/salessparrow/api/controllers/SuggestionsController.java new file mode 100644 index 00000000..aca6a157 --- /dev/null +++ b/src/main/java/com/salessparrow/api/controllers/SuggestionsController.java @@ -0,0 +1,35 @@ +package com.salessparrow.api.controllers; + +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.salessparrow.api.dto.formatter.CrmActionSuggestionsFormatterDto; +import com.salessparrow.api.dto.requestMapper.CrmActionsSuggestionsDto; +import com.salessparrow.api.services.suggestions.CrmActionsSuggestionsService; + +import jakarta.validation.Valid; + +@RestController +@RequestMapping("/api/v1/suggestions") +@Validated +public class SuggestionsController { + + private Logger logger = org.slf4j.LoggerFactory.getLogger(SuggestionsController.class); + + @Autowired + private CrmActionsSuggestionsService crmActionsSuggestionsService; + + @PostMapping("/crm-actions") + public CrmActionSuggestionsFormatterDto getCrmActionSuggestions( + @Valid @RequestBody CrmActionsSuggestionsDto crmActionsSuggestionsDto) { + logger.info("Crm actions suggestions request received"); + + return crmActionsSuggestionsService.getSuggestions(crmActionsSuggestionsDto); + } + +} diff --git a/src/main/java/com/salessparrow/api/dto/entities/AddTaskSuggestionEntityDto.java b/src/main/java/com/salessparrow/api/dto/entities/AddTaskSuggestionEntityDto.java new file mode 100644 index 00000000..84c459d8 --- /dev/null +++ b/src/main/java/com/salessparrow/api/dto/entities/AddTaskSuggestionEntityDto.java @@ -0,0 +1,16 @@ +package com.salessparrow.api.dto.entities; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; + +import lombok.Data; + +/** + * Add Task Suggestion Entity is a DTO class for the Add Task Suggestion Entity. + */ +@Data +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) +public class AddTaskSuggestionEntityDto { + private String description; + private String dueDate; +} diff --git a/src/main/java/com/salessparrow/api/dto/formatter/CrmActionSuggestionsFormatterDto.java b/src/main/java/com/salessparrow/api/dto/formatter/CrmActionSuggestionsFormatterDto.java new file mode 100644 index 00000000..eaf968af --- /dev/null +++ b/src/main/java/com/salessparrow/api/dto/formatter/CrmActionSuggestionsFormatterDto.java @@ -0,0 +1,18 @@ +package com.salessparrow.api.dto.formatter; + +import java.util.List; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.salessparrow.api.dto.entities.AddTaskSuggestionEntityDto; + +import lombok.Data; + +/** + * CrmActionSuggestionsFormatterDto is a class for the formatter of the crm action suggestions. + */ +@Data +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) +public class CrmActionSuggestionsFormatterDto { + private List addTaskSuggestions; +} diff --git a/src/main/java/com/salessparrow/api/dto/requestMapper/CrmActionsSuggestionsDto.java b/src/main/java/com/salessparrow/api/dto/requestMapper/CrmActionsSuggestionsDto.java new file mode 100644 index 00000000..29d73476 --- /dev/null +++ b/src/main/java/com/salessparrow/api/dto/requestMapper/CrmActionsSuggestionsDto.java @@ -0,0 +1,13 @@ +package com.salessparrow.api.dto.requestMapper; + +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +/** + * CrmActionsSuggestionsDto is a dto class for the crm actions suggestions. + */ +@Data +public class CrmActionsSuggestionsDto { + @NotBlank(message = "missing_text") + private String text; +} diff --git a/src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java b/src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java new file mode 100644 index 00000000..48d518a7 --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java @@ -0,0 +1,95 @@ +package com.salessparrow.api.lib; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.salessparrow.api.dto.entities.AddTaskSuggestionEntityDto; +import com.salessparrow.api.dto.formatter.CrmActionSuggestionsFormatterDto; +import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.lib.errorLib.ErrorObject; +import com.salessparrow.api.lib.openAi.OpenAiPayloadBuilder; +import com.salessparrow.api.lib.openAi.OpenAiRequest; + +/** + * GetCrmActionSuggestions is a class for getting the crm action suggestions. + */ +@Component +public class GetCrmActionSuggestions { + @Autowired + private OpenAiRequest openAiRequest; + + @Autowired + private OpenAiPayloadBuilder openAiPayloadBuilder; + + public CrmActionSuggestionsFormatterDto getTaskSuggestions(String text) { + String escapedText = escapeForJson(text); + String payload = openAiPayloadBuilder.payloadForCrmActionsSuggestions(escapedText); + + String response = openAiRequest.makeRequest(payload).getResponseBody(); + + return parseResponse(response); + } + + private CrmActionSuggestionsFormatterDto parseResponse(String responseBody){ + CrmActionSuggestionsFormatterDto crmActionSuggestionsFormatterDto = new CrmActionSuggestionsFormatterDto(); + + try { + Util util = new Util(); + JsonNode rootNode = util.getJsonNode(responseBody); + JsonNode argumentsNode = rootNode.get("choices").get(0).get("message").get("function_call").get("arguments"); + + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + String argumentsJson = objectMapper.convertValue(argumentsNode, String.class); + + Map> arguments = objectMapper.readValue(argumentsJson, new TypeReference>>() {}); + List addTaskList = arguments.get("add_task"); + + + List formattedTaskSuggestionEntityDtos = new ArrayList<>(); + if (addTaskList != null) { + for (AddTaskSuggestionEntityDto addTask : addTaskList) { + AddTaskSuggestionEntityDto addTaskSuggestionEntityDto = new AddTaskSuggestionEntityDto(); + addTaskSuggestionEntityDto.setDescription(addTask.getDescription()); + + // Format the response check if duedate format is YYYY-MM-DD else remove duedate + String dueDate = addTask.getDueDate(); + if (dueDate != null && dueDate.length() > 0) { + Pattern pattern = Pattern.compile("\\d{4}-\\d{2}-\\d{2}"); + Matcher matcher = pattern.matcher(dueDate); + if (matcher.find()) { + addTaskSuggestionEntityDto.setDueDate(dueDate); + } + } + + formattedTaskSuggestionEntityDtos.add(addTaskSuggestionEntityDto); + } + } + + crmActionSuggestionsFormatterDto.setAddTaskSuggestions(formattedTaskSuggestionEntityDtos); + return crmActionSuggestionsFormatterDto; + } catch (Exception e) { + throw new CustomException( + new ErrorObject( + "l_c_gnl_gsnl_1", + "something_went_wrong", + e.getMessage() + ) + ); + } + } + + private String escapeForJson(String input) { + return input.replace("\"", "\\\"").replace("\n", "\\n"); + } +} diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/OpenAiConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/OpenAiConstants.java new file mode 100644 index 00000000..9837f214 --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/OpenAiConstants.java @@ -0,0 +1,11 @@ +package com.salessparrow.api.lib.globalConstants; + +import org.springframework.stereotype.Component; + +@Component +public class OpenAiConstants { + + public String chatCompletionUrl() { + return "https://api.openai.com/v1/chat/completions"; + } +} diff --git a/src/main/java/com/salessparrow/api/lib/openAi/OpenAiPayloadBuilder.java b/src/main/java/com/salessparrow/api/lib/openAi/OpenAiPayloadBuilder.java new file mode 100644 index 00000000..c2777bd8 --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/openAi/OpenAiPayloadBuilder.java @@ -0,0 +1,68 @@ +package com.salessparrow.api.lib.openAi; + +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.springframework.stereotype.Component; + +/** + * OpenAiPayloadBuilder is a class for the payload builder for the open ai. + */ +@Component +public class OpenAiPayloadBuilder { + + /** + * Payload for crm actions suggestions. + * @param text + * @return + */ + public String payloadForCrmActionsSuggestions(String text) { + + return "{\n" + + " \"model\": \"gpt-3.5-turbo-0613\",\n" + + " \"messages\": [\n" + + " {\n" + + " \"role\": \"user\",\n" + + " \"content\": \"You are an AI assistant which gives suggestion on creating task using the input message.Only use the functions you have been provided with. \\nInput message: \\n" + text + "\\n\"\n" + + " }\n" + + " ],\n" + + " \"functions\": [\n" + + " {\n" + + " \"name\": \"suggest_actions\",\n" + + " \"description\": \"This is function for suggesting actions in crm(example salesforce, freshsales) based on input message.\",\n" + + " \"parameters\": {\n" + + " \"type\": \"object\",\n" + + " \"properties\": {\n" + + " \"add_task\": {\n" + + " \"name\": \"add_task\",\n" + + " \"description\": \"Tasks using input message.\",\n" + + " \"type\": \"array\",\n" + + " \"items\": {\n" + + " \"type\": \"object\",\n" + + " \"properties\": {\n" + + " \"description\": {\n" + + " \"type\": \"string\",\n" + + " \"description\": \"Description for task to add. This is mandatory\"\n" + + " },\n" + + " \"due_date\": {\n" + + " \"type\": \"string\",\n" + + " \"description\": \"Due date for task. Must be in YYYY-MM-DD format. This is mandatory.\" \n" + + " }\n" + + " },\n" + + " \"required\": [\"description\", \"due_date\"]\n" + + " }\n" + + " }\n" + + " },\n" + + " \"required\": [\"add_task\"]\n" + + " }\n" + + " }\n" + + " ]\n" + + "}"; + } + + // get todays date in YYYY-MM-DD format + public String getTodaysDate() { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + return sdf.format(new Date()); + } +} diff --git a/src/main/java/com/salessparrow/api/lib/openAi/OpenAiRequest.java b/src/main/java/com/salessparrow/api/lib/openAi/OpenAiRequest.java new file mode 100644 index 00000000..73b42f62 --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/openAi/OpenAiRequest.java @@ -0,0 +1,61 @@ +package com.salessparrow.api.lib.openAi; + +import java.util.HashMap; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.client.WebClientResponseException; + +import com.salessparrow.api.config.CoreConstants; +import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.lib.errorLib.ErrorObject; +import com.salessparrow.api.lib.globalConstants.OpenAiConstants; +import com.salessparrow.api.lib.httpLib.HttpClient; + +/** + * OpenAiRequest is a class for making a request to the OpenAI API. + **/ +@Component +public class OpenAiRequest { + @Autowired + private OpenAiConstants openAiConstants; + + public HttpClient.HttpResponse makeRequest(Object payload) { + String httpReqUrl = openAiConstants.chatCompletionUrl(); + + Map headers = new HashMap<>(); + headers.put("Authorization", "Bearer " + CoreConstants.openAiApiKey()); + + Integer timeoutMillis = 30000; + try { + HttpClient.HttpResponse response = HttpClient.makePostRequest( + httpReqUrl, + headers, + payload, + timeoutMillis); + + return response; + } catch (WebClientResponseException e) { + if(e.getStatusCode().value() == 401) { + throw new CustomException( + new ErrorObject( + "l_o_a_oar_mr_1", + "something_went_wrong", + "Invalid OpenAI API key")); + } else if(e.getStatusCode().value() == 400) { + throw new CustomException( + new ErrorObject( + "l_o_a_oar_mr_2", + "something_went_wrong", + "Invalid request payload")); + } + + throw new CustomException( + new ErrorObject( + "l_o_a_oar_mr_3", + "something_went_wrong", + e.getMessage())); + } + } +} diff --git a/src/main/java/com/salessparrow/api/services/suggestions/CrmActionsSuggestionsService.java b/src/main/java/com/salessparrow/api/services/suggestions/CrmActionsSuggestionsService.java new file mode 100644 index 00000000..09f6e6e1 --- /dev/null +++ b/src/main/java/com/salessparrow/api/services/suggestions/CrmActionsSuggestionsService.java @@ -0,0 +1,23 @@ +package com.salessparrow.api.services.suggestions; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.salessparrow.api.dto.formatter.CrmActionSuggestionsFormatterDto; +import com.salessparrow.api.dto.requestMapper.CrmActionsSuggestionsDto; +import com.salessparrow.api.lib.GetCrmActionSuggestions; + +/** + * CrmActionsSuggestionsService is a service class for the crm actions suggestions. + */ +@Service +public class CrmActionsSuggestionsService { + @Autowired + private GetCrmActionSuggestions getCrmActionSuggestions; + + public CrmActionSuggestionsFormatterDto getSuggestions(CrmActionsSuggestionsDto crmActionsSuggestionsDto) { + String text = crmActionsSuggestionsDto.getText(); + + return getCrmActionSuggestions.getTaskSuggestions(text); + } +} From 539a7c1030394c5568df97dd0f18776a44775cfa Mon Sep 17 00:00:00 2001 From: amanbarbaria Date: Thu, 24 Aug 2023 19:30:02 +0530 Subject: [PATCH 066/195] 1. Test Cases fixed for cookie changes 2. Add Prefix in cache key generator to use env vars --- .../api/config/MemcachedConfig.java | 6 ++-- .../api/utility/CacheKeyGenerator.java | 36 +++++++++++++++++++ .../accountController/GetNoteDetailsTest.java | 4 ++- .../accountController/GetNoteListTest.java | 4 ++- .../authController/PostLogoutTest.java | 2 +- .../salessparrow/api/helper/Constants.java | 2 +- .../createNote.scenarios.json | 16 +++++---- .../getNoteDetails.scenarios.json | 6 ++-- .../getNotesList.scenarios.json | 3 -- .../authController/Logout.scenarios.json | 6 ++-- .../SalesforceConnect.scenarios.json | 16 ++++----- .../getCurrentUser.scenarios.json | 8 ++--- .../ActiveSalesforceOauthToken.json | 14 ++++---- .../ActiveSalesforceOrganization.json | 2 +- .../salesforceUser/ActiveSalesforceUser.json | 12 +++---- 15 files changed, 87 insertions(+), 50 deletions(-) create mode 100644 src/main/java/com/salessparrow/api/utility/CacheKeyGenerator.java diff --git a/src/main/java/com/salessparrow/api/config/MemcachedConfig.java b/src/main/java/com/salessparrow/api/config/MemcachedConfig.java index 1dc3738a..a4b2fc93 100644 --- a/src/main/java/com/salessparrow/api/config/MemcachedConfig.java +++ b/src/main/java/com/salessparrow/api/config/MemcachedConfig.java @@ -7,6 +7,7 @@ import com.salessparrow.api.exception.CustomException; import com.salessparrow.api.lib.errorLib.ErrorObject; import com.salessparrow.api.lib.globalConstants.CacheConstants; +import com.salessparrow.api.utility.CacheKeyGenerator; import com.salessparrow.api.utility.Memcached; import net.spy.memcached.AddrUtil; @@ -22,7 +23,6 @@ import org.springframework.cache.interceptor.CacheResolver; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.cache.interceptor.SimpleCacheErrorHandler; -import org.springframework.cache.interceptor.SimpleKeyGenerator; import org.springframework.cache.support.SimpleCacheManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -95,13 +95,13 @@ public void setMemcachedClient() { } /** - * Key Generator + * Key Generator is overriden to include a prefix that can be different for different environments. * * @return KeyGenerator */ @Override public KeyGenerator keyGenerator() { - return new SimpleKeyGenerator(); + return new CacheKeyGenerator(); } /** diff --git a/src/main/java/com/salessparrow/api/utility/CacheKeyGenerator.java b/src/main/java/com/salessparrow/api/utility/CacheKeyGenerator.java new file mode 100644 index 00000000..fd706592 --- /dev/null +++ b/src/main/java/com/salessparrow/api/utility/CacheKeyGenerator.java @@ -0,0 +1,36 @@ +package com.salessparrow.api.utility; + +import com.salessparrow.api.config.CoreConstants; +import org.springframework.cache.interceptor.KeyGenerator; +import java.lang.reflect.Method; + + +/** + * Cache Key Generator + */ +public class CacheKeyGenerator implements KeyGenerator { + /** + * Generate the key based on the method name and the parameters. Append the environment name to the key. + * + * @param target + * @param method + * @param params + * + * @return String + */ + @Override + public Object generate(Object target, Method method, Object... params) { + String prefix = CoreConstants.environment(); + StringBuilder key = new StringBuilder(); + key.append(prefix); + key.append(":"); + key.append(target.getClass().getSimpleName()); + key.append(":"); + key.append(method.getName()); + for (Object param : params) { + key.append(":"); + key.append(param.toString()); + } + return key.toString(); + }; +} diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java index 8aa54afb..87c16b9f 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java @@ -36,6 +36,8 @@ import com.salessparrow.api.helper.Scenario; import com.salessparrow.api.helper.Setup; import com.salessparrow.api.lib.globalConstants.CookieConstants; +import com.salessparrow.api.helper.Constants; + import com.salessparrow.api.lib.httpLib.HttpClient.HttpResponse; import com.salessparrow.api.lib.salesforce.helper.MakeCompositeRequest; import com.salessparrow.api.lib.salesforce.wrappers.SalesforceGetNoteContent; @@ -90,7 +92,7 @@ public void getNoteDetails(Scenario testScenario) throws Exception{ ObjectMapper objectMapper = new ObjectMapper(); - String cookieValue = (String) testScenario.getInput().get("cookie"); + String cookieValue = Constants.SALESFORCE_ACTIVE_USET_COOKIE_VALUE; String accountId = (String) testScenario.getInput().get("accountId"); String noteId = (String) testScenario.getInput().get("noteId"); diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteListTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteListTest.java index cb16b237..a7a48440 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteListTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteListTest.java @@ -38,6 +38,8 @@ import com.salessparrow.api.helper.Scenario; import com.salessparrow.api.helper.Setup; import com.salessparrow.api.lib.globalConstants.CookieConstants; +import com.salessparrow.api.helper.Constants; + import com.salessparrow.api.lib.globalConstants.SalesforceConstants; import com.salessparrow.api.lib.httpLib.HttpClient.HttpResponse; import com.salessparrow.api.lib.salesforce.dto.CompositeRequestDto; @@ -95,7 +97,7 @@ public void getNoteList(Scenario testScenario) throws Exception{ ObjectMapper objectMapper = new ObjectMapper(); - String cookieValue = (String) testScenario.getInput().get("cookie"); + String cookieValue = Constants.SALESFORCE_ACTIVE_USET_COOKIE_VALUE; String accountId = (String) testScenario.getInput().get("accountId"); List documentIds = (List) testScenario.getInput().get("documentId"); 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 a889b869..054f96cb 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 @@ -23,13 +23,13 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.dynamobee.exception.DynamobeeException; -import com.google.common.net.HttpHeaders; import com.salessparrow.api.helper.Cleanup; import com.salessparrow.api.helper.Common; 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; diff --git a/src/test/java/com/salessparrow/api/helper/Constants.java b/src/test/java/com/salessparrow/api/helper/Constants.java index 2d52bcd8..2c991d79 100644 --- a/src/test/java/com/salessparrow/api/helper/Constants.java +++ b/src/test/java/com/salessparrow/api/helper/Constants.java @@ -4,5 +4,5 @@ * Constants is a helper class for the tests. */ public class Constants { - public static final String SALESFORCE_ACTIVE_USET_COOKIE_VALUE = "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw=="; + public static final String SALESFORCE_ACTIVE_USET_COOKIE_VALUE = "1:0055i00000AUxQHAA1:SALESFORCE:app:1692878227:a2xOxjcPChK/YsKCWRuY50J3gH21/tqcGlv7sWU/aPw3/UFVFPbvWn2LLzY5B5kVPXjj1gELRqa4B4ds6uuqIw=="; } diff --git a/src/test/resources/data/controllers/accountController/createNote.scenarios.json b/src/test/resources/data/controllers/accountController/createNote.scenarios.json index 76a7eb37..f2ea26fe 100644 --- a/src/test/resources/data/controllers/accountController/createNote.scenarios.json +++ b/src/test/resources/data/controllers/accountController/createNote.scenarios.json @@ -6,7 +6,7 @@ "text": "Test note" }, "accountId": "0011e00000bWSxdAAG", - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + "cookie": "1:0055i00000AUxQHAA1:SALESFORCE:app:1692878227:a2xOxjcPChK/YsKCWRuY50J3gH21/tqcGlv7sWU/aPw3/UFVFPbvWn2LLzY5B5kVPXjj1gELRqa4B4ds6uuqIw==" }, "mocks": { "makeCompositeRequest": { @@ -49,7 +49,7 @@ "text": "" }, "accountId": "0011e00000bWSxdAAG", - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + "cookie": "1:0055i00000AUxQHAA1:SALESFORCE:app:1692878227:a2xOxjcPChK/YsKCWRuY50J3gH21/tqcGlv7sWU/aPw3/UFVFPbvWn2LLzY5B5kVPXjj1gELRqa4B4ds6uuqIw==" }, "mocks": {}, "output": { @@ -71,7 +71,7 @@ "input": { "body": {}, "accountId": "0011e00000bWSxdAAG", - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + "cookie": "1:0055i00000AUxQHAA1:SALESFORCE:app:1692878227:a2xOxjcPChK/YsKCWRuY50J3gH21/tqcGlv7sWU/aPw3/UFVFPbvWn2LLzY5B5kVPXjj1gELRqa4B4ds6uuqIw==" }, "mocks": {}, "output": { @@ -91,9 +91,11 @@ { "description": "Should fail when the cookie is invalid", "input": { - "body": {}, + "body": { + "text": "Test note" + }, "accountId": "0011e00000bWSxdAAG", - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:invalid" + "cookie": "1:0055i00000AUxQHAA1:SALESFORCE:app:1692878227:a2xOxjcPChK/YsKCWRuY50J3gH21/tqcGlv7sWU/aPw3/UFVFPbvWn2LLzY5B5kVPXjj1gELRqds6uuq==" }, "mocks": {}, "output": { @@ -111,7 +113,7 @@ "text": "Test note" }, "accountId": "invalid", - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + "cookie": "1:0055i00000AUxQHAA1:SALESFORCE:app:1692878227:a2xOxjcPChK/YsKCWRuY50J3gH21/tqcGlv7sWU/aPw3/UFVFPbvWn2LLzY5B5kVPXjj1gELRqa4B4ds6uuqIw==" }, "mocks": { "makeCompositeRequest": { @@ -160,7 +162,7 @@ "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." }, "accountId": "0011e00000bWSxdAAG", - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + "cookie": "1:0055i00000AUxQHAA1:SALESFORCE:app:1692878227:a2xOxjcPChK/YsKCWRuY50J3gH21/tqcGlv7sWU/aPw3/UFVFPbvWn2LLzY5B5kVPXjj1gELRqa4B4ds6uuqIw==" }, "mocks": { "makeCompositeRequest": { diff --git a/src/test/resources/data/controllers/accountController/getNoteDetails.scenarios.json b/src/test/resources/data/controllers/accountController/getNoteDetails.scenarios.json index 77f4f83c..ade3ef53 100644 --- a/src/test/resources/data/controllers/accountController/getNoteDetails.scenarios.json +++ b/src/test/resources/data/controllers/accountController/getNoteDetails.scenarios.json @@ -3,8 +3,7 @@ "description": "Should return the 5 latest Notes", "input": { "accountId":"0011e00000bWSxdAAG", - "noteId":"0691e000001WY58AAG", - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + "noteId":"0691e000001WY58AAG" }, "mocks":{ "makeCompositeRequest":{ @@ -54,8 +53,7 @@ "description": "should return error response when note id is invalid", "input": { "account_id": "0011e00000bWSxdAAG", - "note_id": "0011e00000bWSxdAAG", - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + "note_id": "0011e00000bWSxdAAG" }, "mocks":{ "makeCompositeRequest":{ diff --git a/src/test/resources/data/controllers/accountController/getNotesList.scenarios.json b/src/test/resources/data/controllers/accountController/getNotesList.scenarios.json index 393ed52f..05f54b4b 100644 --- a/src/test/resources/data/controllers/accountController/getNotesList.scenarios.json +++ b/src/test/resources/data/controllers/accountController/getNotesList.scenarios.json @@ -3,7 +3,6 @@ "description": "Should return the 5 latest Notes", "input": { "accountId":"0011e00000bWSxdAAG", - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==", "documentId": ["0691e000001WKXSAA4","0691e000001WSt7AAG","0691e000001WSuKAAW","0691e000001WSzFAAW","0691e000001WUBCAA4","0691e000001WWHCAA4","0691e000001WXlcAAG","0691e000001WXzPAAW","0691e000001WY0NAAW","0691e000001WY58AAG","0691e000001WaSzAAK","0691e000001Wc4fAAC","0691e000001Wc4pAAC","0691e000001Wl1GAAS","0691e000001WrxGAAS","0691e000001WrxpAAC","0691e000001WrxuAAC","0691e000001Ws2QAAS","0691e000001WsIxAAK","0691e000001WsJHAA0","0691e000001Wt2HAAS","0691e000001Wt5GAAS","0691e000001WtEXAA0","0691e000001WtRgAAK","0691e000001WtxrAAC","0691e000001Wu8pAAC","0691e000001WuIuAAK","0691e000001WuJ9AAK"] }, @@ -366,7 +365,6 @@ "description": "should return empty response when no notes are present", "input": { "account_id": "0011e00000bWSxdAAG", - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==", "document_id":[] }, "mocks":{ @@ -397,7 +395,6 @@ "description": "should return error response when account id is invalid", "input": { "account_id": "0011e00000bWSxdAAG", - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==", "document_id":[] }, "mocks":{ diff --git a/src/test/resources/data/controllers/authController/Logout.scenarios.json b/src/test/resources/data/controllers/authController/Logout.scenarios.json index fbe4272d..6b46c398 100644 --- a/src/test/resources/data/controllers/authController/Logout.scenarios.json +++ b/src/test/resources/data/controllers/authController/Logout.scenarios.json @@ -3,13 +3,13 @@ { "description": "Should logout user if valid cookie", "input": { - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + "cookie": "1:0055i00000AUxQHAA1:SALESFORCE:app:1692878227:a2xOxjcPChK/YsKCWRuY50J3gH21/tqcGlv7sWU/aPw3/UFVFPbvWn2LLzY5B5kVPXjj1gELRqa4B4ds6uuqIw==" } }, { "description": "Should return error if invalid cookie", "input": { - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:invalid" + "cookie": "1:0055i00000AUxQHAA1:SALESFORCE:app:1899000000:invalid" }, "output": { "http_code": 401, @@ -27,7 +27,7 @@ { "description": "Should return error if expired cookie", "input": { - "cookie": "1:00112233445566AAA1:SALESFORCE:1592189876:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + "cookie": "1:0055i00000AUxQHAA1:SALESFORCE:app:1592189876:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" }, "output": { "http_code": 401, diff --git a/src/test/resources/data/controllers/authController/SalesforceConnect.scenarios.json b/src/test/resources/data/controllers/authController/SalesforceConnect.scenarios.json index 53937670..2a7b8c90 100644 --- a/src/test/resources/data/controllers/authController/SalesforceConnect.scenarios.json +++ b/src/test/resources/data/controllers/authController/SalesforceConnect.scenarios.json @@ -16,14 +16,14 @@ "scope": "xyz", "id_token": "xyz", "instance_url": "xyz", - "id": "https://test.salesforce.com/id/00D2v0000012gJjEAI/00112233445566AAA14", + "id": "https://test.salesforce.com/id/000Org-id/00112233445566AAA14", "token_type": "Bearer", "issued_at": "1690520247198" }, "getIdentity": { - "sub": "https://test.salesforce.com/id/00D2v0000012gJjEAI/00112233445566AAA14", + "sub": "https://test.salesforce.com/id/000Org-id/00112233445566AAA14", "user_id": "00112233445566AAA14", - "organization_id": "00D2v0000012gJjEAI", + "organization_id": "000Org-id", "name": "Test User", "email": "test@test.com" } @@ -106,21 +106,21 @@ "scope": "testScope", "id_token": "testIdToken", "instance_url": "https://test.sandbox.my.salesforce.com", - "id": "https://test.salesforce.com/id/00D2v0000012gJjEAI/00112233445566AAA1", + "id": "https://test.salesforce.com/id/000Org-id/0055i00000AUxQHAA1", "token_type": "Bearer", "issued_at": "1690520247198" }, "getIdentity": { - "sub": "https://test.salesforce.com/id/00D2v0000012gJjEAI/00112233445566AAA1", - "user_id": "00112233445566AAA1", - "organization_id": "00D2v0000012gJjEAI", + "sub": "https://test.salesforce.com/id/000Org-id/0055i00000AUxQHAA1", + "user_id": "0055i00000AUxQHAA1", + "organization_id": "000Org-id", "name": "Test User", "email": "test@test.com" } }, "output": { "current_user": { - "id": "SALESFORCE-00112233445566AAA1", + "id": "SALESFORCE-0055i00000AUxQHAA1", "name": "Test User", "email": "test@test.com" } diff --git a/src/test/resources/data/controllers/userController/getCurrentUser.scenarios.json b/src/test/resources/data/controllers/userController/getCurrentUser.scenarios.json index 259a5ef9..16920d99 100644 --- a/src/test/resources/data/controllers/userController/getCurrentUser.scenarios.json +++ b/src/test/resources/data/controllers/userController/getCurrentUser.scenarios.json @@ -2,11 +2,11 @@ { "description": "Should return current user", "input": { - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + "cookie": "1:0055i00000AUxQHAA1:SALESFORCE:app:1692878227:a2xOxjcPChK/YsKCWRuY50J3gH21/tqcGlv7sWU/aPw3/UFVFPbvWn2LLzY5B5kVPXjj1gELRqa4B4ds6uuqIw==" }, "output": { "current_user": { - "id": "00112233445566AAA1", + "id": "0055i00000AUxQHAA1", "name": "Test User", "email": "test@test.com" } @@ -15,7 +15,7 @@ { "description": "Should return error if invalid cookie", "input": { - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:invalid" + "cookie": "1:0055i00000AUxQHAA1:SALESFORCE:app:1899000000:invalid" }, "output": { "http_code": 401, @@ -33,7 +33,7 @@ { "description": "Should return error if expired cookie", "input": { - "cookie": "1:00112233445566AAA1:SALESFORCE:1592189876:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + "cookie": "1:0055i00000AUxQHAA1:SALESFORCE:app:1592189876:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" }, "output": { "http_code": 401, diff --git a/src/test/resources/fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json b/src/test/resources/fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json index b01de72d..93912263 100644 --- a/src/test/resources/fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json +++ b/src/test/resources/fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json @@ -1,13 +1,13 @@ { - "accessToken": "AQICAHh8THF/qGARx8DUe8vJOd05vKEx5gSfpBLKTZxcuYkMbwFWjWxrd+Vi8AJcNygAUAkxAAAA0zCB0AYJKoZIhvcNAQcGoIHCMIG/AgEAMIG5BgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDOiBQbHbADXAUCKszwIBEICBi8Mxso89hUZxuO/sab9tzOLCsTWNd6XMMSruXdmxTsjnCVIuuFmO9xE/dIlfLgdEOYx8ItFQ1yY1yHK0Mf5v9ioQZsjEqBloFwt6a0Zpu4ZPds3xd5SlhYb/DUOvQr2CeIw7c4DMCbhC3D4n3PPWwFrEAxwjbyZu6EuwKSCAJX8WNB/5SZyCWbF+lHo=", - "refreshToken": "AQICAHh8THF/qGARx8DUe8vJOd05vKEx5gSfpBLKTZxcuYkMbwGt67XnwFLbkXZGUHGMAbT+AAAAuTCBtgYJKoZIhvcNAQcGoIGoMIGlAgEAMIGfBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDEP3/y2MUdnniQUOTwIBEIByVjHYvSlaSx8QoDbRN7bN2tYTnqG73wuEr0Ak1CTROx3s5ztbyDqhlXvcQSJpeoP4dzbri9JFXQzvc18Y4SuW6Fkb7flN10LuxNuQWvCd5Meo4fPTovjzyVOXt9Qoy4BYJ8eaWZ9IaxpdYjyqzg0be1/O", + "accessToken": "AQICAHh8THF/Dummy=", + "refreshToken": "AQICAHh8THF/Dummy", "updatedAt": "2023-08-17T09:53:08.331Z", - "signature": "FCGHH2fMCTciwY6zwcrBin10xO8dDKhYwp/FLavAQ8U=", - "instanceUrl": "https://truesparrowsystemspvtltd--dev.sandbox.my.salesforce.com", - "idToken": "eyJraWQiOiIyNDQiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoiRXlBLTRWX2xoQlRHVzZ4QW40ZmtJQSIsInN1YiI6Imh0dHBzOi8vdGVzdC5zYWxlc2ZvcmNlLmNvbS9pZC8wMEQxZTAwMDAwMDBOUllFQTIvMDA1NWkwMDAwMEFVeFFIQUExIiwiYXVkIjoiM01WRzlaVUdnMTBIaDIyN01MUE0zd2lMTWxtMTQ5MTJvRHFkbDRzQkFnVjNyVUw4ODBYbWdZRVh6S0RZa3VlbEhQSmF4TnRjanBYdlkwYk1qVVNaWiIsImlzcyI6Imh0dHBzOi8vdGVzdC5zYWxlc2ZvcmNlLmNvbSIsImV4cCI6MTY5MjI2NjEwNywiaWF0IjoxNjkyMjY1OTg3fQ.ulBzHKfMkd0TtGOF60dgbae4ORHHilBakkfT9iB-FciFTJPAd87Jy5uKOndISDiqNtkcPDFJaH_1Sjl16DLHcLS8vNbzQFmJtoQt0tYEWT7_sQ7xq5DYnZKOVgPUnZyHh0UC7Y3a7UbQD1IQ-sMPtNZZn_jWGL_6UOcEotlh_Gg3DxrylkBGpS82h0U9CZyKRe2yZ0SE_6-FW_xFasSXfEF_9e6x6NAzJAEULpU4iLp2t7cHtjoKwIgFsqk3gasua26y74uxdZCbFOmivyBudIDSVzmIYmr_0kVezOZ5QEZgdVjkQUhmioGUFed5wzoNeUaYPYqRjGLeDHiYjSzBiSGRPil6Oimrwwre1W0Qurnw5vwcjgae3-Jf3mbP-IlMN4XZxiEG2fjeXBIO8-sMCLJfun4-RG48A5UYukQwVSB062h-1exmZ9ugv2wetUKAEaLKDLyKx4CWgoI7hLibXDB345IfOmsFNfOKCwHVE7_s-PHlyA70-_QihrDvuADfdjFR6LesRFMis4ns96ISOyR5h0nDcXaNufR-YKeHA90QgLXSeNs21B89tCvdMulnj2noRatDQcMRESxbiV6O98vJV27Z8E1UVJdwsHXQJZAxLd4Ib5uXbZNjqC10tVFLzT9KxgTYI8KtS9TxQ4DekPfXbziS9IC3c--ImEbSeio", + "signature": "FCGHH2fMCTciwY6zwcrBin10xO8hYwp/FLavAQ8U=", + "instanceUrl": "https://salesforce.com", + "idToken": "dummy--ee", "createdAt": "2023-08-17T09:53:08.331Z", - "identityUrl": "https://test.salesforce.com/id/00D1e0000000NRYEA2/0055i00000AUxQHAA1", + "identityUrl": "https://salesforce.com/id/000Org-id/0055i00000AUxQHAA1", "issuedAt": "1692265987212", - "externalUserId": "00112233445566AAA1", + "externalUserId": "0055i00000AUxQHAA1", "status": "ACTIVE" } \ No newline at end of file diff --git a/src/test/resources/fixtures/repositories/salesforceOrganization/ActiveSalesforceOrganization.json b/src/test/resources/fixtures/repositories/salesforceOrganization/ActiveSalesforceOrganization.json index e9ed13e5..fbb2e794 100644 --- a/src/test/resources/fixtures/repositories/salesforceOrganization/ActiveSalesforceOrganization.json +++ b/src/test/resources/fixtures/repositories/salesforceOrganization/ActiveSalesforceOrganization.json @@ -1,4 +1,4 @@ { - "externalOrganizationId": "00D2v0000012gJjEAI", + "externalOrganizationId": "000Org-id", "status": "ACTIVE" } \ No newline at end of file diff --git a/src/test/resources/fixtures/repositories/salesforceUser/ActiveSalesforceUser.json b/src/test/resources/fixtures/repositories/salesforceUser/ActiveSalesforceUser.json index d9e6f056..f87411dd 100644 --- a/src/test/resources/fixtures/repositories/salesforceUser/ActiveSalesforceUser.json +++ b/src/test/resources/fixtures/repositories/salesforceUser/ActiveSalesforceUser.json @@ -1,11 +1,11 @@ { - "externalUserId": "00112233445566AAA1", - "identityUrl": "https://test.salesforce.com/id/00D2v0000012gJjEAI/00112233445566AAA1", - "externalOrganizationId": "00D2v0000012gJjEAI", + "externalUserId": "0055i00000AUxQHAA1", + "identityUrl": "https://test.salesforce.com/id/000Org-id/0055i00000AUxQHAA1", + "externalOrganizationId": "000Org-id", "name": "Test User", "email": "test@test.com", "userKind": "SALESFORCE", - "cookieToken": "RSfDRwhQvIeFwJ9AAnv1ed3YN3ob9e9R0vSgKbsaxFcHFKwuyH6DiWVpD4orMrHQ3Kftns15kq04igHvaPaZLXbzWxQUOgtMr1lYZWBBF3s=", - "encryptionSalt": "EHpifHQeXUJcz1LtEDdx2Z/yB2qoHNTGfcWZQQlxsOeHGICDip9rPMpzG+LVtUOh", + "cookieToken": "oGzc1IRNmu45Oe73KBYipqDSsgC4n5vepVt3P9+jJiX0wr39SVb0J8ontP277D3NdkHnyL0HPDFuwTSQxNz2gSUHaTMfe0oebcxl9AMUpIw=", + "encryptionSalt": "Qc8x8AZvWZBqnYJ9Xk6+CbyHmHi29DvL8vzwFZULsquHGICDip9rPMpzG+LVtUOh", "status": "ACTIVE" -} \ No newline at end of file +} From 55d5be4f5234f87142d34eeb52088fd6a0220719 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 24 Aug 2023 19:34:29 +0530 Subject: [PATCH 067/195] updated local setup docs --- LOCAL_SETUP.md | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/LOCAL_SETUP.md b/LOCAL_SETUP.md index d037c6dd..94e9420d 100644 --- a/LOCAL_SETUP.md +++ b/LOCAL_SETUP.md @@ -4,20 +4,10 @@ Before using the *Sales Sparrow* APIs, make sure your development environment meets the following prerequisites and system requirements: -### Using Docker (Recommended) +### Docker - Docker version 4.19.0 or newer -### Without Docker - -- Java 17 - - Download it from [Oracle's official website](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html). -- DynamoDB Local Setup - - Download the DynamoDB Local JAR (NoSQL Workbench) from [here](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/workbench.settingup.html). - - Install and run the NoSQL Workbench on your local machine. - - Toggle the *DDB local* option from the bottom of the left-side menu to turn it on. - - Add a local connection from the operation builder tab. - ## Getting Started To clone the project and install dependencies, follow these steps: @@ -82,6 +72,6 @@ $ touch test.secrets.json #### Run Test Cases ```sh -$ docker-compose run test +$ docker-compose up test ``` To view the test coverage, simply open the target/site/index.html file in a web browser. \ No newline at end of file From 925ba647ad7921ff83bc7d2f30b092977cfa5afc Mon Sep 17 00:00:00 2001 From: amanbarbaria Date: Thu, 24 Aug 2023 20:46:12 +0530 Subject: [PATCH 068/195] 1. Added functional test cases for SecurityConfig. 2. Added functional test cases forGlobalExceptionHandler. 3. Added functional test cases for JsonOnlyInterceptor. --- .../functional/config/SecurityConfigTest.java | 78 +++++++++++++++++++ .../exception/GlobalExceptionHandlerTest.java | 70 +++++++++++++++++ .../interceptors/JsonOnlyInterceptorTest.java | 69 ++++++++++++++++ .../globalExceptionHandler.scenarios.json | 13 ++++ .../jsonOnlyInterceptor.scenarios.json | 13 ++++ 5 files changed, 243 insertions(+) create mode 100644 src/test/java/com/salessparrow/api/functional/config/SecurityConfigTest.java create mode 100644 src/test/java/com/salessparrow/api/functional/exception/GlobalExceptionHandlerTest.java create mode 100644 src/test/java/com/salessparrow/api/functional/interceptors/JsonOnlyInterceptorTest.java create mode 100644 src/test/resources/data/exceptions/globalExceptionHandler.scenarios.json create mode 100644 src/test/resources/data/interceptors/jsonOnlyInterceptor.scenarios.json diff --git a/src/test/java/com/salessparrow/api/functional/config/SecurityConfigTest.java b/src/test/java/com/salessparrow/api/functional/config/SecurityConfigTest.java new file mode 100644 index 00000000..677d78a0 --- /dev/null +++ b/src/test/java/com/salessparrow/api/functional/config/SecurityConfigTest.java @@ -0,0 +1,78 @@ +package com.salessparrow.api.functional.config; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; +import java.io.IOException; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +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.github.dynamobee.exception.DynamobeeException; +import com.salessparrow.api.helper.Cleanup; +import com.salessparrow.api.helper.Common; +import com.salessparrow.api.helper.LoadFixture; +import com.salessparrow.api.helper.Setup; + + +@SpringBootTest +@AutoConfigureMockMvc +@WebAppConfiguration +@Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) +public class SecurityConfigTest { + @Autowired + private MockMvc mockMvc; + + @Autowired + private Setup setup; + + @Autowired + private Cleanup cleanup; + + @Autowired + private Common common; + + @BeforeEach + public void setUp() throws DynamobeeException, IOException { + setup.perform(); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + @Test + public void allRoutesShouldBeAccessibleWithoutAuthenticationAndAuthorization() throws Exception{ + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/auth/salesforce/redirect-url") + .param("redirect_uri", "http://localhost:3000") + .contentType(MediaType.APPLICATION_JSON)); + assertEquals(resultActions.andReturn().getResponse().getStatus(), 200); + } + + @Test + public void securityHeadersShouldBeSet() throws Exception{ + mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/auth/salesforce/redirect-url") + .param("redirect_uri", "http://localhost:3000") + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(header().string("X-Content-Type-Options", "nosniff")) + .andExpect(header().string("X-XSS-Protection", "1; mode=block")) + .andExpect(header().string("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate")) + .andExpect(header().string("Pragma", "no-cache")) + .andExpect(header().string("Expires", "0")) + .andExpect(header().string("X-Frame-Options", "DENY")) + .andExpect(header().string("Referrer-Policy", "same-origin")) + .andExpect(header().string("Content-Type", "application/json")); + } + +} + diff --git a/src/test/java/com/salessparrow/api/functional/exception/GlobalExceptionHandlerTest.java b/src/test/java/com/salessparrow/api/functional/exception/GlobalExceptionHandlerTest.java new file mode 100644 index 00000000..3bb72cd6 --- /dev/null +++ b/src/test/java/com/salessparrow/api/functional/exception/GlobalExceptionHandlerTest.java @@ -0,0 +1,70 @@ +package com.salessparrow.api.functional.exception; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; +import java.util.List; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +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.github.dynamobee.exception.DynamobeeException; +import com.salessparrow.api.helper.Cleanup; +import com.salessparrow.api.helper.Common; +import com.salessparrow.api.helper.LoadFixture; +import com.salessparrow.api.helper.Scenario; +import com.salessparrow.api.helper.Setup; + + +@SpringBootTest +@AutoConfigureMockMvc +@WebAppConfiguration +@Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) +public class GlobalExceptionHandlerTest { + @Autowired + private MockMvc mockMvc; + + @Autowired + private Setup setup; + + @Autowired + private Cleanup cleanup; + + @Autowired + private Common common; + + @BeforeEach + public void setUp() throws DynamobeeException, IOException { + setup.perform(); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + @Test + public void handleNoHandlerFoundException() throws Exception{ + List testDataItems = common.loadScenariosData("classpath:data/exceptions/globalExceptionHandler.scenarios.json"); + for (Scenario testDataItem : testDataItems) { + + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/unknown-route") + .contentType(MediaType.APPLICATION_JSON)); + + String contentAsString = resultActions.andReturn().getResponse().getContentAsString(); + common.compareErrors(testDataItem, contentAsString); + } + + } +} + diff --git a/src/test/java/com/salessparrow/api/functional/interceptors/JsonOnlyInterceptorTest.java b/src/test/java/com/salessparrow/api/functional/interceptors/JsonOnlyInterceptorTest.java new file mode 100644 index 00000000..39dac315 --- /dev/null +++ b/src/test/java/com/salessparrow/api/functional/interceptors/JsonOnlyInterceptorTest.java @@ -0,0 +1,69 @@ +package com.salessparrow.api.functional.interceptors; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; +import java.util.List; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +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.github.dynamobee.exception.DynamobeeException; +import com.salessparrow.api.helper.Cleanup; +import com.salessparrow.api.helper.Common; +import com.salessparrow.api.helper.LoadFixture; +import com.salessparrow.api.helper.Scenario; +import com.salessparrow.api.helper.Setup; + + +@SpringBootTest +@AutoConfigureMockMvc +@WebAppConfiguration +@Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) +public class JsonOnlyInterceptorTest { + @Autowired + private MockMvc mockMvc; + + @Autowired + private Setup setup; + + @Autowired + private Cleanup cleanup; + + @Autowired + private Common common; + + @BeforeEach + public void setUp() throws DynamobeeException, IOException { + setup.perform(); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + @Test + public void preHandle() throws Exception{ + List testDataItems = common.loadScenariosData("classpath:data/interceptors/jsonOnlyInterceptor.scenarios.json"); + for (Scenario testDataItem : testDataItems) { + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/auth/salesforce/redirect-url") + .contentType(MediaType.ALL_VALUE)); + + String contentAsString = resultActions.andReturn().getResponse().getContentAsString(); + common.compareErrors(testDataItem, contentAsString); + } + + } +} + diff --git a/src/test/resources/data/exceptions/globalExceptionHandler.scenarios.json b/src/test/resources/data/exceptions/globalExceptionHandler.scenarios.json new file mode 100644 index 00000000..02f696f3 --- /dev/null +++ b/src/test/resources/data/exceptions/globalExceptionHandler.scenarios.json @@ -0,0 +1,13 @@ +[ + { + "description": "Should return 404 error", + "input": {}, + "output": { + "http_code":404, + "message":"Resource not found. Please check if the resource identifier passed in the URL is valid and try again.", + "code":"NOT_FOUND", + "internal_error_identifier":"a_e_geh_nf_1", + "param_errors":[] + } + } +] \ No newline at end of file diff --git a/src/test/resources/data/interceptors/jsonOnlyInterceptor.scenarios.json b/src/test/resources/data/interceptors/jsonOnlyInterceptor.scenarios.json new file mode 100644 index 00000000..0dbd5bc1 --- /dev/null +++ b/src/test/resources/data/interceptors/jsonOnlyInterceptor.scenarios.json @@ -0,0 +1,13 @@ +[ + { + "description": "Should return 415 content type error", + "input": {}, + "output": { + "http_code":415, + "message":"Unsupported Media Type. Content-Type header should be application/json.", + "code":"UNSUPPORTED_MEDIA_TYPE", + "internal_error_identifier":"i_joi_ph_1", + "param_errors":[] + } + } +] \ No newline at end of file From 8e931b54a30aa9585fc898f2985e6a030cbf5107 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 24 Aug 2023 23:46:06 +0530 Subject: [PATCH 069/195] close resources to avoid resource leaks --- .../controllers/accountController/CreateNoteTest.java | 6 +++++- .../controllers/accountController/GetAccountListTest.java | 6 +++++- .../controllers/accountController/GetNoteDetailsTest.java | 8 ++++++-- .../controllers/accountController/GetNoteListTest.java | 8 ++++++-- 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/CreateNoteTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/CreateNoteTest.java index 4d877fd8..92880314 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/CreateNoteTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/CreateNoteTest.java @@ -5,6 +5,7 @@ import static org.mockito.Mockito.when; import java.io.IOException; +import java.io.InputStream; import java.util.List; import java.util.stream.Stream; @@ -118,6 +119,9 @@ private static List loadScenarios() throws IOException { String scenariosPath = "classpath:data/controllers/accountController/createNote.scenarios.json"; Resource resource = new DefaultResourceLoader().getResource(scenariosPath); ObjectMapper objectMapper = new ObjectMapper(); - return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); + + try (InputStream inputStream = resource.getInputStream()) { + return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); + } } } diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java index 1ff0a3f9..9191aaa0 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java @@ -5,6 +5,7 @@ import static org.mockito.Mockito.when; import java.io.IOException; +import java.io.InputStream; import java.util.List; import java.util.stream.Stream; @@ -117,6 +118,9 @@ private static List loadScenarios() throws IOException { String scenariosPath = "classpath:data/controllers/accountController/getAccountList.scenarios.json"; Resource resource = new DefaultResourceLoader().getResource(scenariosPath); ObjectMapper objectMapper = new ObjectMapper(); - return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); + + try (InputStream inputStream = resource.getInputStream()) { + return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); + } } } diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java index 71bdcb7a..25c547ef 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java @@ -8,6 +8,7 @@ import static org.mockito.Mockito.when; import java.io.IOException; +import java.io.InputStream; import java.util.List; import java.util.stream.Stream; @@ -124,10 +125,13 @@ static Stream testScenariosProvider() throws IOException { return testScenarios.stream(); } - public static List loadScenarios() throws IOException { + private static List loadScenarios() throws IOException { String scenariosPath = "classpath:data/controllers/accountController/getNoteDetails.scenarios.json"; Resource resource = new DefaultResourceLoader().getResource(scenariosPath); ObjectMapper objectMapper = new ObjectMapper(); - return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); + + try (InputStream inputStream = resource.getInputStream()) { + return objectMapper.readValue(inputStream, new TypeReference>() {}); + } } } diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteListTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteListTest.java index cb16b237..4d1f89e6 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteListTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteListTest.java @@ -9,6 +9,7 @@ import static org.mockito.Mockito.when; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.stream.Stream; @@ -146,10 +147,13 @@ static Stream testScenariosProvider() throws IOException { return testScenarios.stream(); } - public static List loadScenarios() throws IOException { + private static List loadScenarios() throws IOException { String scenariosPath = "classpath:data/controllers/accountController/getNotesList.scenarios.json"; Resource resource = new DefaultResourceLoader().getResource(scenariosPath); ObjectMapper objectMapper = new ObjectMapper(); - return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); + + try (InputStream inputStream = resource.getInputStream()) { + return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); + } } } From 213159dc272e29fe14bd09a05ef82ca4472c64c8 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Fri, 25 Aug 2023 00:03:27 +0530 Subject: [PATCH 070/195] close resources to avoid resource leaks --- .../salessparrow/api/helper/LoadFixture.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/salessparrow/api/helper/LoadFixture.java b/src/test/java/com/salessparrow/api/helper/LoadFixture.java index 151dfc2d..be5c24df 100644 --- a/src/test/java/com/salessparrow/api/helper/LoadFixture.java +++ b/src/test/java/com/salessparrow/api/helper/LoadFixture.java @@ -1,6 +1,7 @@ package com.salessparrow.api.helper; import java.io.IOException; +import java.io.InputStream; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.Resource; @@ -73,8 +74,10 @@ public void perform(FixtureData fixtureData) throws IOException { public SalesforceUser loadSalesForceUserFixture(String location) throws IOException { Resource resource = resourceLoader.getResource(location); ObjectMapper objectMapper = new ObjectMapper(); - return objectMapper.readValue(resource.getInputStream(), new TypeReference() { - }); + + try (InputStream inputStream = resource.getInputStream()) { + return objectMapper.readValue(resource.getInputStream(), new TypeReference() {}); + } } /** @@ -87,8 +90,10 @@ public SalesforceUser loadSalesForceUserFixture(String location) throws IOExcept public SalesforceOauthToken loadSalesForceOAuthTokenFixture(String location) throws IOException { Resource resource = resourceLoader.getResource(location); ObjectMapper objectMapper = new ObjectMapper(); - return objectMapper.readValue(resource.getInputStream(), new TypeReference() { - }); + + try (InputStream inputStream = resource.getInputStream()) { + return objectMapper.readValue(resource.getInputStream(), new TypeReference() {}); + } } /** @@ -101,7 +106,9 @@ public SalesforceOauthToken loadSalesForceOAuthTokenFixture(String location) thr public SalesforceOrganization loadSalesForceOrganizationFixture(String location) throws IOException { Resource resource = resourceLoader.getResource(location); ObjectMapper objectMapper = new ObjectMapper(); - return objectMapper.readValue(resource.getInputStream(), new TypeReference() { - }); + + try (InputStream inputStream = resource.getInputStream()) { + return objectMapper.readValue(resource.getInputStream(), new TypeReference() {}); + } } } From 58e376d9e8ccb3818697c601c3e8e11db982e22a Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Fri, 25 Aug 2023 00:07:46 +0530 Subject: [PATCH 071/195] added extra resource file to debug --- .../accountController/getNoteDetails.fixtures.json | 2 +- .../ActiveSalesforceOauthToken1.json | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 src/test/resources/fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken1.json diff --git a/src/test/resources/fixtures/controllers/accountController/getNoteDetails.fixtures.json b/src/test/resources/fixtures/controllers/accountController/getNoteDetails.fixtures.json index 0f64e59e..302fe440 100644 --- a/src/test/resources/fixtures/controllers/accountController/getNoteDetails.fixtures.json +++ b/src/test/resources/fixtures/controllers/accountController/getNoteDetails.fixtures.json @@ -7,7 +7,7 @@ ], "salesforce_oauth_tokens": [ { - "filepath": "classpath:fixtures/repositories/salesforceOauthToken/ActiveSalesforceOAuthToken.json" + "filepath": "classpath:fixtures/repositories/salesforceOauthToken/ActiveSalesforceOAuthToken1.json" } ] } diff --git a/src/test/resources/fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken1.json b/src/test/resources/fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken1.json new file mode 100644 index 00000000..b01de72d --- /dev/null +++ b/src/test/resources/fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken1.json @@ -0,0 +1,13 @@ +{ + "accessToken": "AQICAHh8THF/qGARx8DUe8vJOd05vKEx5gSfpBLKTZxcuYkMbwFWjWxrd+Vi8AJcNygAUAkxAAAA0zCB0AYJKoZIhvcNAQcGoIHCMIG/AgEAMIG5BgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDOiBQbHbADXAUCKszwIBEICBi8Mxso89hUZxuO/sab9tzOLCsTWNd6XMMSruXdmxTsjnCVIuuFmO9xE/dIlfLgdEOYx8ItFQ1yY1yHK0Mf5v9ioQZsjEqBloFwt6a0Zpu4ZPds3xd5SlhYb/DUOvQr2CeIw7c4DMCbhC3D4n3PPWwFrEAxwjbyZu6EuwKSCAJX8WNB/5SZyCWbF+lHo=", + "refreshToken": "AQICAHh8THF/qGARx8DUe8vJOd05vKEx5gSfpBLKTZxcuYkMbwGt67XnwFLbkXZGUHGMAbT+AAAAuTCBtgYJKoZIhvcNAQcGoIGoMIGlAgEAMIGfBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDEP3/y2MUdnniQUOTwIBEIByVjHYvSlaSx8QoDbRN7bN2tYTnqG73wuEr0Ak1CTROx3s5ztbyDqhlXvcQSJpeoP4dzbri9JFXQzvc18Y4SuW6Fkb7flN10LuxNuQWvCd5Meo4fPTovjzyVOXt9Qoy4BYJ8eaWZ9IaxpdYjyqzg0be1/O", + "updatedAt": "2023-08-17T09:53:08.331Z", + "signature": "FCGHH2fMCTciwY6zwcrBin10xO8dDKhYwp/FLavAQ8U=", + "instanceUrl": "https://truesparrowsystemspvtltd--dev.sandbox.my.salesforce.com", + "idToken": "eyJraWQiOiIyNDQiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoiRXlBLTRWX2xoQlRHVzZ4QW40ZmtJQSIsInN1YiI6Imh0dHBzOi8vdGVzdC5zYWxlc2ZvcmNlLmNvbS9pZC8wMEQxZTAwMDAwMDBOUllFQTIvMDA1NWkwMDAwMEFVeFFIQUExIiwiYXVkIjoiM01WRzlaVUdnMTBIaDIyN01MUE0zd2lMTWxtMTQ5MTJvRHFkbDRzQkFnVjNyVUw4ODBYbWdZRVh6S0RZa3VlbEhQSmF4TnRjanBYdlkwYk1qVVNaWiIsImlzcyI6Imh0dHBzOi8vdGVzdC5zYWxlc2ZvcmNlLmNvbSIsImV4cCI6MTY5MjI2NjEwNywiaWF0IjoxNjkyMjY1OTg3fQ.ulBzHKfMkd0TtGOF60dgbae4ORHHilBakkfT9iB-FciFTJPAd87Jy5uKOndISDiqNtkcPDFJaH_1Sjl16DLHcLS8vNbzQFmJtoQt0tYEWT7_sQ7xq5DYnZKOVgPUnZyHh0UC7Y3a7UbQD1IQ-sMPtNZZn_jWGL_6UOcEotlh_Gg3DxrylkBGpS82h0U9CZyKRe2yZ0SE_6-FW_xFasSXfEF_9e6x6NAzJAEULpU4iLp2t7cHtjoKwIgFsqk3gasua26y74uxdZCbFOmivyBudIDSVzmIYmr_0kVezOZ5QEZgdVjkQUhmioGUFed5wzoNeUaYPYqRjGLeDHiYjSzBiSGRPil6Oimrwwre1W0Qurnw5vwcjgae3-Jf3mbP-IlMN4XZxiEG2fjeXBIO8-sMCLJfun4-RG48A5UYukQwVSB062h-1exmZ9ugv2wetUKAEaLKDLyKx4CWgoI7hLibXDB345IfOmsFNfOKCwHVE7_s-PHlyA70-_QihrDvuADfdjFR6LesRFMis4ns96ISOyR5h0nDcXaNufR-YKeHA90QgLXSeNs21B89tCvdMulnj2noRatDQcMRESxbiV6O98vJV27Z8E1UVJdwsHXQJZAxLd4Ib5uXbZNjqC10tVFLzT9KxgTYI8KtS9TxQ4DekPfXbziS9IC3c--ImEbSeio", + "createdAt": "2023-08-17T09:53:08.331Z", + "identityUrl": "https://test.salesforce.com/id/00D1e0000000NRYEA2/0055i00000AUxQHAA1", + "issuedAt": "1692265987212", + "externalUserId": "00112233445566AAA1", + "status": "ACTIVE" +} \ No newline at end of file From 8e4e4b16b16319d920ee2c5b1f38af7ae8e4a5e8 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Fri, 25 Aug 2023 00:12:13 +0530 Subject: [PATCH 072/195] reverted changes --- .../accountController/getNoteDetails.fixtures.json | 2 +- .../ActiveSalesforceOauthToken1.json | 13 ------------- 2 files changed, 1 insertion(+), 14 deletions(-) delete mode 100644 src/test/resources/fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken1.json diff --git a/src/test/resources/fixtures/controllers/accountController/getNoteDetails.fixtures.json b/src/test/resources/fixtures/controllers/accountController/getNoteDetails.fixtures.json index 302fe440..0f64e59e 100644 --- a/src/test/resources/fixtures/controllers/accountController/getNoteDetails.fixtures.json +++ b/src/test/resources/fixtures/controllers/accountController/getNoteDetails.fixtures.json @@ -7,7 +7,7 @@ ], "salesforce_oauth_tokens": [ { - "filepath": "classpath:fixtures/repositories/salesforceOauthToken/ActiveSalesforceOAuthToken1.json" + "filepath": "classpath:fixtures/repositories/salesforceOauthToken/ActiveSalesforceOAuthToken.json" } ] } diff --git a/src/test/resources/fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken1.json b/src/test/resources/fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken1.json deleted file mode 100644 index b01de72d..00000000 --- a/src/test/resources/fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken1.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "accessToken": "AQICAHh8THF/qGARx8DUe8vJOd05vKEx5gSfpBLKTZxcuYkMbwFWjWxrd+Vi8AJcNygAUAkxAAAA0zCB0AYJKoZIhvcNAQcGoIHCMIG/AgEAMIG5BgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDOiBQbHbADXAUCKszwIBEICBi8Mxso89hUZxuO/sab9tzOLCsTWNd6XMMSruXdmxTsjnCVIuuFmO9xE/dIlfLgdEOYx8ItFQ1yY1yHK0Mf5v9ioQZsjEqBloFwt6a0Zpu4ZPds3xd5SlhYb/DUOvQr2CeIw7c4DMCbhC3D4n3PPWwFrEAxwjbyZu6EuwKSCAJX8WNB/5SZyCWbF+lHo=", - "refreshToken": "AQICAHh8THF/qGARx8DUe8vJOd05vKEx5gSfpBLKTZxcuYkMbwGt67XnwFLbkXZGUHGMAbT+AAAAuTCBtgYJKoZIhvcNAQcGoIGoMIGlAgEAMIGfBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDEP3/y2MUdnniQUOTwIBEIByVjHYvSlaSx8QoDbRN7bN2tYTnqG73wuEr0Ak1CTROx3s5ztbyDqhlXvcQSJpeoP4dzbri9JFXQzvc18Y4SuW6Fkb7flN10LuxNuQWvCd5Meo4fPTovjzyVOXt9Qoy4BYJ8eaWZ9IaxpdYjyqzg0be1/O", - "updatedAt": "2023-08-17T09:53:08.331Z", - "signature": "FCGHH2fMCTciwY6zwcrBin10xO8dDKhYwp/FLavAQ8U=", - "instanceUrl": "https://truesparrowsystemspvtltd--dev.sandbox.my.salesforce.com", - "idToken": "eyJraWQiOiIyNDQiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoiRXlBLTRWX2xoQlRHVzZ4QW40ZmtJQSIsInN1YiI6Imh0dHBzOi8vdGVzdC5zYWxlc2ZvcmNlLmNvbS9pZC8wMEQxZTAwMDAwMDBOUllFQTIvMDA1NWkwMDAwMEFVeFFIQUExIiwiYXVkIjoiM01WRzlaVUdnMTBIaDIyN01MUE0zd2lMTWxtMTQ5MTJvRHFkbDRzQkFnVjNyVUw4ODBYbWdZRVh6S0RZa3VlbEhQSmF4TnRjanBYdlkwYk1qVVNaWiIsImlzcyI6Imh0dHBzOi8vdGVzdC5zYWxlc2ZvcmNlLmNvbSIsImV4cCI6MTY5MjI2NjEwNywiaWF0IjoxNjkyMjY1OTg3fQ.ulBzHKfMkd0TtGOF60dgbae4ORHHilBakkfT9iB-FciFTJPAd87Jy5uKOndISDiqNtkcPDFJaH_1Sjl16DLHcLS8vNbzQFmJtoQt0tYEWT7_sQ7xq5DYnZKOVgPUnZyHh0UC7Y3a7UbQD1IQ-sMPtNZZn_jWGL_6UOcEotlh_Gg3DxrylkBGpS82h0U9CZyKRe2yZ0SE_6-FW_xFasSXfEF_9e6x6NAzJAEULpU4iLp2t7cHtjoKwIgFsqk3gasua26y74uxdZCbFOmivyBudIDSVzmIYmr_0kVezOZ5QEZgdVjkQUhmioGUFed5wzoNeUaYPYqRjGLeDHiYjSzBiSGRPil6Oimrwwre1W0Qurnw5vwcjgae3-Jf3mbP-IlMN4XZxiEG2fjeXBIO8-sMCLJfun4-RG48A5UYukQwVSB062h-1exmZ9ugv2wetUKAEaLKDLyKx4CWgoI7hLibXDB345IfOmsFNfOKCwHVE7_s-PHlyA70-_QihrDvuADfdjFR6LesRFMis4ns96ISOyR5h0nDcXaNufR-YKeHA90QgLXSeNs21B89tCvdMulnj2noRatDQcMRESxbiV6O98vJV27Z8E1UVJdwsHXQJZAxLd4Ib5uXbZNjqC10tVFLzT9KxgTYI8KtS9TxQ4DekPfXbziS9IC3c--ImEbSeio", - "createdAt": "2023-08-17T09:53:08.331Z", - "identityUrl": "https://test.salesforce.com/id/00D1e0000000NRYEA2/0055i00000AUxQHAA1", - "issuedAt": "1692265987212", - "externalUserId": "00112233445566AAA1", - "status": "ACTIVE" -} \ No newline at end of file From 9f9a96266d1c4dbc53ce55211f226951fc5d17f1 Mon Sep 17 00:00:00 2001 From: Yagnik Thummar Date: Fri, 25 Aug 2023 10:21:34 +0530 Subject: [PATCH 073/195] Code review changes: - Renaming files, Adding logs. --- .../api/controllers/AccountTaskController.java | 4 ++-- ...CreateTaskDto.java => CreateTaskInAccountDto.java} | 2 +- ...ceTask.java => CreateSalesforceTaskInAccount.java} | 11 +++++------ .../createTaskInAccount/CreateTaskInAccount.java | 4 ++-- .../CreateTaskInAccountFactory.java | 11 +++++------ .../lib/salesforce/helper/MakeCompositeRequest.java | 3 +-- .../api/services/accountTask/CreateTaskService.java | 7 +++---- 7 files changed, 19 insertions(+), 23 deletions(-) rename src/main/java/com/salessparrow/api/dto/requestMapper/{CreateTaskDto.java => CreateTaskInAccountDto.java} (95%) rename src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/{CreateSalesforceTask.java => CreateSalesforceTaskInAccount.java} (92%) diff --git a/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java b/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java index 888f3ad0..6c847a46 100644 --- a/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java +++ b/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java @@ -13,7 +13,7 @@ import org.springframework.web.bind.annotation.RestController; import com.salessparrow.api.dto.formatter.CreateTaskFormatterDto; -import com.salessparrow.api.dto.requestMapper.CreateTaskDto; +import com.salessparrow.api.dto.requestMapper.CreateTaskInAccountDto; import com.salessparrow.api.services.accountTask.CreateTaskService; import jakarta.servlet.http.HttpServletRequest; @@ -33,7 +33,7 @@ public class AccountTaskController { public ResponseEntity createTask( HttpServletRequest request, @PathVariable("account_id") String accountId, - @Valid @RequestBody CreateTaskDto task + @Valid @RequestBody CreateTaskInAccountDto task ){ logger.info("Create task request received"); CreateTaskFormatterDto createTaskFormatterDto = createTaskService.createTask(request, accountId, task); diff --git a/src/main/java/com/salessparrow/api/dto/requestMapper/CreateTaskDto.java b/src/main/java/com/salessparrow/api/dto/requestMapper/CreateTaskInAccountDto.java similarity index 95% rename from src/main/java/com/salessparrow/api/dto/requestMapper/CreateTaskDto.java rename to src/main/java/com/salessparrow/api/dto/requestMapper/CreateTaskInAccountDto.java index af8135a5..20f3d3e5 100644 --- a/src/main/java/com/salessparrow/api/dto/requestMapper/CreateTaskDto.java +++ b/src/main/java/com/salessparrow/api/dto/requestMapper/CreateTaskInAccountDto.java @@ -10,7 +10,7 @@ @Data @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) -public class CreateTaskDto { +public class CreateTaskInAccountDto { @NotBlank(message = "missing_crm_organization_user_id") private String crmOrganizationUserId; diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateSalesforceTask.java b/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateSalesforceTaskInAccount.java similarity index 92% rename from src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateSalesforceTask.java rename to src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateSalesforceTaskInAccount.java index a337b9bf..c93228f2 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateSalesforceTask.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateSalesforceTaskInAccount.java @@ -13,10 +13,9 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import com.salessparrow.api.controllers.AccountTaskController; import com.salessparrow.api.domain.User; import com.salessparrow.api.dto.formatter.CreateTaskFormatterDto; -import com.salessparrow.api.dto.requestMapper.CreateTaskDto; +import com.salessparrow.api.dto.requestMapper.CreateTaskInAccountDto; import com.salessparrow.api.exception.CustomException; import com.salessparrow.api.lib.Util; import com.salessparrow.api.lib.errorLib.ErrorObject; @@ -30,9 +29,9 @@ * CreateSalesforceTask class is responsible for creating a task in Salesforce */ @Component -public class CreateSalesforceTask implements CreateTaskInAccount{ +public class CreateSalesforceTaskInAccount implements CreateTaskInAccount{ - Logger logger = LoggerFactory.getLogger(AccountTaskController.class); + Logger logger = LoggerFactory.getLogger(CreateSalesforceTaskInAccount.class); @Autowired private SalesforceConstants salesforceConstants; @@ -49,7 +48,7 @@ public class CreateSalesforceTask implements CreateTaskInAccount{ * * @return CreateTaskFormatterDto object */ - public CreateTaskFormatterDto createTask(User User, String accountId, CreateTaskDto task) { + public CreateTaskFormatterDto createTask(User User, String accountId, CreateTaskInAccountDto task) { String salesforceUserId = User.getExternalUserId(); String taskSubject = getTaskSubjectFromDescription(task); @@ -124,7 +123,7 @@ private CreateTaskFormatterDto parseResponse(String createTaskResponse){ * * @return String task subject */ - private String getTaskSubjectFromDescription(CreateTaskDto task) { + private String getTaskSubjectFromDescription(CreateTaskInAccountDto task) { logger.info("getting task subject from description"); if (task.getDescription().length() < 60) { return task.getDescription(); diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccount.java b/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccount.java index 915cd7aa..d020aa1f 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccount.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccount.java @@ -4,12 +4,12 @@ import com.salessparrow.api.domain.User; import com.salessparrow.api.dto.formatter.CreateTaskFormatterDto; -import com.salessparrow.api.dto.requestMapper.CreateTaskDto; +import com.salessparrow.api.dto.requestMapper.CreateTaskInAccountDto; /** * CreateTask interface is interface for createTask for various CRM services */ @Component public interface CreateTaskInAccount { - public CreateTaskFormatterDto createTask(User User,String accountId, CreateTaskDto task); + public CreateTaskFormatterDto createTask(User User,String accountId, CreateTaskInAccountDto task); } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccountFactory.java b/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccountFactory.java index a7370428..2b7b4a97 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccountFactory.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccountFactory.java @@ -5,10 +5,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import com.salessparrow.api.controllers.AccountTaskController; import com.salessparrow.api.domain.User; import com.salessparrow.api.dto.formatter.CreateTaskFormatterDto; -import com.salessparrow.api.dto.requestMapper.CreateTaskDto; +import com.salessparrow.api.dto.requestMapper.CreateTaskInAccountDto; import com.salessparrow.api.exception.CustomException; import com.salessparrow.api.lib.errorLib.ErrorObject; import com.salessparrow.api.lib.globalConstants.UserConstants; @@ -19,10 +18,10 @@ @Component public class CreateTaskInAccountFactory { - Logger logger = LoggerFactory.getLogger(AccountTaskController.class); + Logger logger = LoggerFactory.getLogger(CreateTaskInAccountFactory.class); @Autowired - CreateSalesforceTask createSalesforceTask; + CreateSalesforceTaskInAccount createSalesforceTaskInAccount; /** * Create a task in CRM @@ -33,11 +32,11 @@ public class CreateTaskInAccountFactory { * * @return CreateTaskFormatterDto object */ - public CreateTaskFormatterDto createTask(User user, String accountId, CreateTaskDto task) { + public CreateTaskFormatterDto createTask(User user, String accountId, CreateTaskInAccountDto task) { switch(user.getUserKind()) { case UserConstants.SALESFORCE_USER_KIND: logger.info("calling createTask of salesforceCreateTask"); - return createSalesforceTask.createTask(user, accountId, task); + return createSalesforceTaskInAccount.createTask(user, accountId, task); default: throw new CustomException( new ErrorObject( diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/helper/MakeCompositeRequest.java b/src/main/java/com/salessparrow/api/lib/salesforce/helper/MakeCompositeRequest.java index 952a2b74..d16a2dcb 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/helper/MakeCompositeRequest.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/helper/MakeCompositeRequest.java @@ -9,7 +9,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import com.salessparrow.api.controllers.AccountTaskController; import com.salessparrow.api.lib.globalConstants.SalesforceConstants; import com.salessparrow.api.lib.httpLib.HttpClient; import com.salessparrow.api.lib.salesforce.dto.CompositeRequestDto; @@ -20,7 +19,7 @@ @Component public class MakeCompositeRequest { - Logger logger = LoggerFactory.getLogger(AccountTaskController.class); + Logger logger = LoggerFactory.getLogger(MakeCompositeRequest.class); @Autowired private SalesforceRequest salesforceOauthRequest; diff --git a/src/main/java/com/salessparrow/api/services/accountTask/CreateTaskService.java b/src/main/java/com/salessparrow/api/services/accountTask/CreateTaskService.java index 9da09c97..1d452014 100644 --- a/src/main/java/com/salessparrow/api/services/accountTask/CreateTaskService.java +++ b/src/main/java/com/salessparrow/api/services/accountTask/CreateTaskService.java @@ -5,10 +5,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import com.salessparrow.api.controllers.AccountTaskController; import com.salessparrow.api.domain.User; import com.salessparrow.api.dto.formatter.CreateTaskFormatterDto; -import com.salessparrow.api.dto.requestMapper.CreateTaskDto; +import com.salessparrow.api.dto.requestMapper.CreateTaskInAccountDto; import com.salessparrow.api.lib.crmActions.createTaskInAccount.CreateTaskInAccountFactory; import jakarta.servlet.http.HttpServletRequest; @@ -18,7 +17,7 @@ */ @Service public class CreateTaskService { - Logger logger = LoggerFactory.getLogger(AccountTaskController.class); + Logger logger = LoggerFactory.getLogger(CreateTaskService.class); @Autowired private CreateTaskInAccountFactory createTaskInAccountFactory; @@ -32,7 +31,7 @@ public class CreateTaskService { * * @return CreateTaskFormatterDto object */ - public CreateTaskFormatterDto createTask(HttpServletRequest request, String accountId, CreateTaskDto task) { + public CreateTaskFormatterDto createTask(HttpServletRequest request, String accountId, CreateTaskInAccountDto task) { logger.info("inside createTask Service"); User currentUser = (User) request.getAttribute("current_user"); return createTaskInAccountFactory.createTask(currentUser, accountId, task); From 0dcfa22521bd65eaa0028063f0c7de427fe168cc Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Fri, 25 Aug 2023 11:26:46 +0530 Subject: [PATCH 074/195] updated test case for workflow test --- .../accountController/GetNoteDetailsTest.java | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java index 25c547ef..dc9f0179 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java @@ -1,8 +1,5 @@ package com.salessparrow.api.functional.controllers.accountController; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; @@ -14,6 +11,8 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; @@ -48,26 +47,22 @@ @WebAppConfiguration @Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) public class GetNoteDetailsTest { - @Autowired - private MockMvc mockMvc; - - @Autowired - private Setup setup; @Autowired - private Cleanup cleanup; - + private MockMvc mockMvc; @Autowired private Common common; - @Autowired private LoadFixture loadFixture; - + @Autowired + private Setup setup; + @Autowired + private Cleanup cleanup; @MockBean - private MakeCompositeRequest makeCompositeRequestMock; + private SalesforceGetNoteContent salesforceGetNoteContentMock; @MockBean - private SalesforceGetNoteContent salesforceGetNoteContentMock; + private MakeCompositeRequest makeCompositeRequestMock; @BeforeEach public void setUp() throws DynamobeeException, IOException { @@ -81,7 +76,7 @@ public void tearDown() { @ParameterizedTest @MethodSource("testScenariosProvider") - public void getNoteDetails(Scenario testScenario) throws Exception{ + public void getNoteDetails(Scenario testScenario) throws Exception { String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); FixtureData fixtureData = common.loadFixture("classpath:fixtures/controllers/accountController/getNoteDetails.fixtures.json", currentFunctionName); loadFixture.perform(fixtureData); From a846f01a72001fb9c42ae45a0730e19f84d6ac8c Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Fri, 25 Aug 2023 11:31:44 +0530 Subject: [PATCH 075/195] added logs for debugging --- src/test/java/com/salessparrow/api/helper/LoadFixture.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/test/java/com/salessparrow/api/helper/LoadFixture.java b/src/test/java/com/salessparrow/api/helper/LoadFixture.java index be5c24df..81493fac 100644 --- a/src/test/java/com/salessparrow/api/helper/LoadFixture.java +++ b/src/test/java/com/salessparrow/api/helper/LoadFixture.java @@ -91,6 +91,11 @@ public SalesforceOauthToken loadSalesForceOAuthTokenFixture(String location) thr Resource resource = resourceLoader.getResource(location); ObjectMapper objectMapper = new ObjectMapper(); + System.out.println("resource file name: " + resource.getFilename()); + System.out.println("resource exists: " + resource.exists()); + System.out.println("resource isFile: " + resource.isFile()); + System.out.println("resource isOpen: " + resource.isOpen()); + System.out.println("resource isReadable: " + resource.isReadable()); try (InputStream inputStream = resource.getInputStream()) { return objectMapper.readValue(resource.getInputStream(), new TypeReference() {}); } From 54582ad762f4559a494bad9b02de622cc05af76f Mon Sep 17 00:00:00 2001 From: Yagnik Thummar Date: Fri, 25 Aug 2023 11:49:30 +0530 Subject: [PATCH 076/195] Code review changes: - Added missing testCases. --- .../controllers/AccountTaskController.java | 2 +- .../CreateSalesforceTaskInAccount.java | 2 +- .../CreateTaskInAccount.java | 2 +- .../CreateTaskInAccountFactory.java | 4 +- .../accountTask/CreateTaskService.java | 4 +- .../resources/config/ParamErrorConfig.json | 2 +- .../createTask.scenarios.json | 52 ++++++++++++++++++- 7 files changed, 59 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java b/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java index 6c847a46..c184ba60 100644 --- a/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java +++ b/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java @@ -36,7 +36,7 @@ public ResponseEntity createTask( @Valid @RequestBody CreateTaskInAccountDto task ){ logger.info("Create task request received"); - CreateTaskFormatterDto createTaskFormatterDto = createTaskService.createTask(request, accountId, task); + CreateTaskFormatterDto createTaskFormatterDto = createTaskService.createTaskInAccount(request, accountId, task); return ResponseEntity.status(HttpStatus.CREATED).body(createTaskFormatterDto); } } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateSalesforceTaskInAccount.java b/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateSalesforceTaskInAccount.java index c93228f2..9427387f 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateSalesforceTaskInAccount.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateSalesforceTaskInAccount.java @@ -48,7 +48,7 @@ public class CreateSalesforceTaskInAccount implements CreateTaskInAccount{ * * @return CreateTaskFormatterDto object */ - public CreateTaskFormatterDto createTask(User User, String accountId, CreateTaskInAccountDto task) { + public CreateTaskFormatterDto createTaskInAccount(User User, String accountId, CreateTaskInAccountDto task) { String salesforceUserId = User.getExternalUserId(); String taskSubject = getTaskSubjectFromDescription(task); diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccount.java b/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccount.java index d020aa1f..c98b4e98 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccount.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccount.java @@ -11,5 +11,5 @@ */ @Component public interface CreateTaskInAccount { - public CreateTaskFormatterDto createTask(User User,String accountId, CreateTaskInAccountDto task); + public CreateTaskFormatterDto createTaskInAccount(User User,String accountId, CreateTaskInAccountDto task); } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccountFactory.java b/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccountFactory.java index 2b7b4a97..540f6ef3 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccountFactory.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccountFactory.java @@ -32,11 +32,11 @@ public class CreateTaskInAccountFactory { * * @return CreateTaskFormatterDto object */ - public CreateTaskFormatterDto createTask(User user, String accountId, CreateTaskInAccountDto task) { + public CreateTaskFormatterDto createTaskInAccount(User user, String accountId, CreateTaskInAccountDto task) { switch(user.getUserKind()) { case UserConstants.SALESFORCE_USER_KIND: logger.info("calling createTask of salesforceCreateTask"); - return createSalesforceTaskInAccount.createTask(user, accountId, task); + return createSalesforceTaskInAccount.createTaskInAccount(user, accountId, task); default: throw new CustomException( new ErrorObject( diff --git a/src/main/java/com/salessparrow/api/services/accountTask/CreateTaskService.java b/src/main/java/com/salessparrow/api/services/accountTask/CreateTaskService.java index 1d452014..134fd8bf 100644 --- a/src/main/java/com/salessparrow/api/services/accountTask/CreateTaskService.java +++ b/src/main/java/com/salessparrow/api/services/accountTask/CreateTaskService.java @@ -31,9 +31,9 @@ public class CreateTaskService { * * @return CreateTaskFormatterDto object */ - public CreateTaskFormatterDto createTask(HttpServletRequest request, String accountId, CreateTaskInAccountDto task) { + public CreateTaskFormatterDto createTaskInAccount(HttpServletRequest request, String accountId, CreateTaskInAccountDto task) { logger.info("inside createTask Service"); User currentUser = (User) request.getAttribute("current_user"); - return createTaskInAccountFactory.createTask(currentUser, accountId, task); + return createTaskInAccountFactory.createTaskInAccount(currentUser, accountId, task); } } diff --git a/src/main/resources/config/ParamErrorConfig.json b/src/main/resources/config/ParamErrorConfig.json index 781bbd08..65c30324 100644 --- a/src/main/resources/config/ParamErrorConfig.json +++ b/src/main/resources/config/ParamErrorConfig.json @@ -17,7 +17,7 @@ "invalid_due_date":{ "parameter": "due_date", "param_error_identifier": "invalid_due_date", - "message": "Invalid due date. Please double check and try again." + "message": "Invalid or missing due date. Please double check and try again." }, "description_too_long":{ "parameter": "description", diff --git a/src/test/resources/data/controllers/accountTaskController/createTask.scenarios.json b/src/test/resources/data/controllers/accountTaskController/createTask.scenarios.json index 8b58be1d..dfa2b679 100644 --- a/src/test/resources/data/controllers/accountTaskController/createTask.scenarios.json +++ b/src/test/resources/data/controllers/accountTaskController/createTask.scenarios.json @@ -83,6 +83,56 @@ ] } }, + { + "description": "Should fail when the task due_date is not provided", + "input": { + "body": { + "crm_organization_user_id":"0011e00000bWSxdAA1", + "description":"Update remaining documentations" + }, + "accountId": "0011e00000bWSxdAAG", + "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + }, + "mocks": {}, + "output": { + "http_code": 400, + "message": "At least one parameter is invalid or missing.", + "code": "INVALID_PARAMS", + "internal_error_identifier": "b_2", + "param_errors": [ + { + "parameter": "due_date", + "param_error_identifier": "invalid_due_date", + "message": "Invalid or missing due date. Please double check and try again." + } + ] + } + }, + { + "description": "Should fail when the task crm_organization_user_id is not provided", + "input": { + "body": { + "description":"Update remaining documentations", + "due_date":"2023-12-01" + }, + "accountId": "0011e00000bWSxdAAG", + "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + }, + "mocks": {}, + "output": { + "http_code": 400, + "message": "At least one parameter is invalid or missing.", + "code": "INVALID_PARAMS", + "internal_error_identifier": "b_2", + "param_errors": [ + { + "parameter": "crm_organization_user_id", + "param_error_identifier": "missing_crm_organization_user_id", + "message": "crm_organization_user_id is required parameter. Please provide crm_organization_user_id." + } + ] + } + }, { "description": "Should fail when the task Due is not valid", "input": { @@ -104,7 +154,7 @@ { "parameter": "due_date", "param_error_identifier": "invalid_due_date", - "message": "Invalid due date. Please double check and try again." + "message": "Invalid or missing due date. Please double check and try again." } ] } From 5a02f80c752be7eb5c47ed8d0f90f0ded27d9c0d Mon Sep 17 00:00:00 2001 From: Yagnik Thummar Date: Fri, 25 Aug 2023 11:55:40 +0530 Subject: [PATCH 077/195] Added missing testCases. --- .../getCrmOrganizationUserList.scenarios.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/test/resources/data/controllers/crmOrganizationUserController/getCrmOrganizationUserList.scenarios.json b/src/test/resources/data/controllers/crmOrganizationUserController/getCrmOrganizationUserList.scenarios.json index b8f18dee..0f4a27c0 100644 --- a/src/test/resources/data/controllers/crmOrganizationUserController/getCrmOrganizationUserList.scenarios.json +++ b/src/test/resources/data/controllers/crmOrganizationUserController/getCrmOrganizationUserList.scenarios.json @@ -131,5 +131,19 @@ } ] } + }, + { + "description": "Should return error if search string is not provided", + "input": { + "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + }, + "mocks": {}, + "output": { + "http_code": 500, + "message": "Something went wrong.", + "code": "INTERNAL_SERVER_ERROR", + "internal_error_identifier": "e_geh_hre_1", + "param_errors": [] + } } ] \ No newline at end of file From 9680085785478763f8d7bddf323b4b901660ab21 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Fri, 25 Aug 2023 12:03:32 +0530 Subject: [PATCH 078/195] updated file name in resource loading for test cases --- .../controllers/accountController/getNoteDetails.fixtures.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/resources/fixtures/controllers/accountController/getNoteDetails.fixtures.json b/src/test/resources/fixtures/controllers/accountController/getNoteDetails.fixtures.json index 0f64e59e..795a75d8 100644 --- a/src/test/resources/fixtures/controllers/accountController/getNoteDetails.fixtures.json +++ b/src/test/resources/fixtures/controllers/accountController/getNoteDetails.fixtures.json @@ -7,7 +7,7 @@ ], "salesforce_oauth_tokens": [ { - "filepath": "classpath:fixtures/repositories/salesforceOauthToken/ActiveSalesforceOAuthToken.json" + "filepath": "classpath:fixtures/repositories/salesforceOauthToken/ActiveSalesforceAuthToken.json" } ] } From 315c2ca3e6a979aa169676198861227caacc02cf Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Fri, 25 Aug 2023 12:08:58 +0530 Subject: [PATCH 079/195] file name fix added in fixtures --- .../controllers/accountController/getNoteDetails.fixtures.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/resources/fixtures/controllers/accountController/getNoteDetails.fixtures.json b/src/test/resources/fixtures/controllers/accountController/getNoteDetails.fixtures.json index 795a75d8..c9d6c0e7 100644 --- a/src/test/resources/fixtures/controllers/accountController/getNoteDetails.fixtures.json +++ b/src/test/resources/fixtures/controllers/accountController/getNoteDetails.fixtures.json @@ -7,7 +7,7 @@ ], "salesforce_oauth_tokens": [ { - "filepath": "classpath:fixtures/repositories/salesforceOauthToken/ActiveSalesforceAuthToken.json" + "filepath": "classpath:fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" } ] } From a276ac1076e54ac6ac1cf731718d4b88105af731 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Fri, 25 Aug 2023 12:26:10 +0530 Subject: [PATCH 080/195] added milestone branch in run test workflow --- .github/workflows/run_tests.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/run_tests.yaml b/.github/workflows/run_tests.yaml index bf75543f..af144a07 100644 --- a/.github/workflows/run_tests.yaml +++ b/.github/workflows/run_tests.yaml @@ -4,6 +4,7 @@ on: pull_request: branches: - master + - milestone/* env: ENVIRONMENT: test From cd79dcf3806ff26b5847a8d13012f79a14068dea Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Fri, 25 Aug 2023 12:43:55 +0530 Subject: [PATCH 081/195] removed unnecessary commented code and logs added for debugging --- .github/workflows/run_tests.yaml | 14 -------------- .../com/salessparrow/api/helper/LoadFixture.java | 5 ----- 2 files changed, 19 deletions(-) diff --git a/.github/workflows/run_tests.yaml b/.github/workflows/run_tests.yaml index af144a07..8bd87a47 100644 --- a/.github/workflows/run_tests.yaml +++ b/.github/workflows/run_tests.yaml @@ -25,20 +25,6 @@ jobs: image: amazon/dynamodb-local:latest ports: - 8000:8000 - - # localkms: - # image: nsmithuk/local-kms - # ports: - # - 4599:8080 - # volumes: - # - ./init:/init - # env: - # AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }} - # AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }} - # AWS_REGION: us-east-1 - # KMS_ACCOUNT_ID: 111122223333 - # KMS_REGION: us-east-1 - # KMS_SEED_PATH: /init/seed.yaml steps: - uses: actions/checkout@v3 diff --git a/src/test/java/com/salessparrow/api/helper/LoadFixture.java b/src/test/java/com/salessparrow/api/helper/LoadFixture.java index 81493fac..be5c24df 100644 --- a/src/test/java/com/salessparrow/api/helper/LoadFixture.java +++ b/src/test/java/com/salessparrow/api/helper/LoadFixture.java @@ -91,11 +91,6 @@ public SalesforceOauthToken loadSalesForceOAuthTokenFixture(String location) thr Resource resource = resourceLoader.getResource(location); ObjectMapper objectMapper = new ObjectMapper(); - System.out.println("resource file name: " + resource.getFilename()); - System.out.println("resource exists: " + resource.exists()); - System.out.println("resource isFile: " + resource.isFile()); - System.out.println("resource isOpen: " + resource.isOpen()); - System.out.println("resource isReadable: " + resource.isReadable()); try (InputStream inputStream = resource.getInputStream()) { return objectMapper.readValue(resource.getInputStream(), new TypeReference() {}); } From 6345f347ddf1b0b8c7aae0fef63f4e76ceb9b4fd Mon Sep 17 00:00:00 2001 From: ajinkyac03 Date: Fri, 25 Aug 2023 12:46:03 +0530 Subject: [PATCH 082/195] Functional test cases updated. --- .../PostCrmActionsSuggestionsTest.java | 102 ++++++++++++++++ .../crmActionsSuggestions.scenarios.json | 110 ++++++++++++++++++ .../postCrmActionsSuggestions.fixtures.json | 9 ++ 3 files changed, 221 insertions(+) create mode 100644 src/test/java/com/salessparrow/api/functional/controllers/suggestionsController/PostCrmActionsSuggestionsTest.java create mode 100644 src/test/resources/data/controllers/suggestionsController/crmActionsSuggestions.scenarios.json create mode 100644 src/test/resources/fixtures/controllers/suggestionsController/postCrmActionsSuggestions.fixtures.json diff --git a/src/test/java/com/salessparrow/api/functional/controllers/suggestionsController/PostCrmActionsSuggestionsTest.java b/src/test/java/com/salessparrow/api/functional/controllers/suggestionsController/PostCrmActionsSuggestionsTest.java new file mode 100644 index 00000000..8c866170 --- /dev/null +++ b/src/test/java/com/salessparrow/api/functional/controllers/suggestionsController/PostCrmActionsSuggestionsTest.java @@ -0,0 +1,102 @@ +package com.salessparrow.api.functional.controllers.suggestionsController; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.util.List; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +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.github.dynamobee.exception.DynamobeeException; +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 com.salessparrow.api.lib.httpLib.HttpClient.HttpResponse; +import com.salessparrow.api.lib.openAi.OpenAiRequest; + +import jakarta.servlet.http.Cookie; + +@SpringBootTest +@AutoConfigureMockMvc +@WebAppConfiguration +@Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) +public class PostCrmActionsSuggestionsTest { + @Autowired + private MockMvc mockMvc; + + @Autowired + private Setup setup; + + @Autowired + private Cleanup cleanup; + + @Autowired + private Common common; + + @Autowired + private LoadFixture loadFixture; + + @MockBean + private OpenAiRequest openAiRequestMock; + + @BeforeEach + public void setUp() throws DynamobeeException, IOException { + setup.perform(); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + @Test + public void testPostCrmActionsSuggestions() throws Exception { + String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/controllers/suggestionsController/postCrmActionsSuggestions.fixtures.json", + currentFunctionName); + loadFixture.perform(fixtureData); + + List testDataItems = common.loadScenariosData("classpath:data/controllers/suggestionsController/crmActionsSuggestions.scenarios.json"); + for (Scenario testDataItem : testDataItems) { + ObjectMapper objectMapper = new ObjectMapper(); + HttpResponse getAccountMockResponse = new HttpResponse(); + getAccountMockResponse.setResponseBody(objectMapper.writeValueAsString(testDataItem.getMocks().get("makeRequest"))); + when(openAiRequestMock.makeRequest(any())).thenReturn(getAccountMockResponse); + + String expectedOutput = objectMapper.writeValueAsString(testDataItem.getOutput()); + String cookieValue = Constants.SALESFORCE_ACTIVE_USET_COOKIE_VALUE; + + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.post("/api/v1/suggestions/crm-actions") + .content(objectMapper.writeValueAsString(testDataItem.getInput())) + .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) { + assertEquals(expectedOutput, actualOutput); + } else { + common.compareErrors(testDataItem, actualOutput); + } + } + } +} diff --git a/src/test/resources/data/controllers/suggestionsController/crmActionsSuggestions.scenarios.json b/src/test/resources/data/controllers/suggestionsController/crmActionsSuggestions.scenarios.json new file mode 100644 index 00000000..43b4fb95 --- /dev/null +++ b/src/test/resources/data/controllers/suggestionsController/crmActionsSuggestions.scenarios.json @@ -0,0 +1,110 @@ +[ + { + "description": "Should return correct suggestions for a given text", + "input": { + "text": "We reviewed the tasks that the team has completed since the last meeting and discussed additional projects.\n\nHere are the main topics we discussed:\n\nJoe updated us on the calendar for editorial, advertorial and social media content.\n" + }, + "mocks":{ + "makeRequest":{ + "id": "chatcmpl-0000", + "object": "chat.completion", + "created": 1692945329, + "model": "gpt-3.5-turbo-0613", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": null, + "function_call": { + "name": "suggest_actions", + "arguments": "{\n \"add_task\": [\n {\n \"description\": \"Review calendar for editorial, advertorial, and social media content\",\n \"due_date\": \"2023-08-30\"\n }\n ]\n}" + } + }, + "finish_reason": "function_call" + } + ], + "usage": { + "prompt_tokens": 168, + "completion_tokens": 52, + "total_tokens": 220 + } + } + }, + "output": { + "add_task_suggestions": [ + { + "description": "Review calendar for editorial, advertorial, and social media content", + "due_date": "2023-08-30" + } + ] + } + }, + { + "description": "Should remove due_date from the response if it is not in correct format", + "input": { + "text": "We reviewed the tasks that the team has completed since the last meeting and discussed additional projects.\n\nHere are the main topics we discussed:\n\nJoe updated us on the calendar for editorial, advertorial and social media content.\n" + }, + "mocks":{ + "makeRequest":{ + "id": "chatcmpl-0000", + "object": "chat.completion", + "created": 1692945329, + "model": "gpt-3.5-turbo-0613", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": null, + "function_call": { + "name": "suggest_actions", + "arguments": "{\n \"add_task\": [\n {\n \"description\": \"Review calendar for editorial, advertorial, and social media content\",\n \"due_date\": \"next week\"\n }\n ]\n}" + } + }, + "finish_reason": "function_call" + } + ], + "usage": { + "prompt_tokens": 168, + "completion_tokens": 52, + "total_tokens": 220 + } + } + }, + "output": { + "add_task_suggestions": [ + { + "description": "Review calendar for editorial, advertorial, and social media content", + "due_date": null + } + ] + } + }, + { + "description": "Should return error if no text is not provided", + "input": {}, + "mocks": {}, + "output": { + "http_code": 400, + "code": "INVALID_PARAMS", + "param_errors": [ + "missing_text" + ] + } + }, + { + "description": "Should return error if text is empty", + "input": { + "text": "" + }, + "mocks": {}, + "output": { + "http_code": 400, + "code": "INVALID_PARAMS", + "param_errors": [ + "missing_text" + ] + } + } +] \ No newline at end of file diff --git a/src/test/resources/fixtures/controllers/suggestionsController/postCrmActionsSuggestions.fixtures.json b/src/test/resources/fixtures/controllers/suggestionsController/postCrmActionsSuggestions.fixtures.json new file mode 100644 index 00000000..1aaed891 --- /dev/null +++ b/src/test/resources/fixtures/controllers/suggestionsController/postCrmActionsSuggestions.fixtures.json @@ -0,0 +1,9 @@ +{ + "testPostCrmActionsSuggestions": { + "salesforce_users": [ + { + "filepath": "classpath:fixtures/repositories/salesforceUser/ActiveSalesforceUser.json" + } + ] + } +} \ No newline at end of file From c75e849d6c95793becbffbc14ae570dae0e3ef2d Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Fri, 25 Aug 2023 12:52:28 +0530 Subject: [PATCH 083/195] Added due date format method --- .../api/dto/entities/TaskEntity.java | 2 +- .../java/com/salessparrow/api/lib/Util.java | 18 ++++++++++++++++++ .../dto/SalesforceGetTasksListDto.java | 8 +++++++- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/salessparrow/api/dto/entities/TaskEntity.java b/src/main/java/com/salessparrow/api/dto/entities/TaskEntity.java index 5f0318ee..958d4cd3 100644 --- a/src/main/java/com/salessparrow/api/dto/entities/TaskEntity.java +++ b/src/main/java/com/salessparrow/api/dto/entities/TaskEntity.java @@ -16,7 +16,7 @@ public class TaskEntity { private String id; private String creatorName; private String description; - private Date dueDate; + private String dueDate; private String crmOrganizationUserName; private Date lastModifiedTime; } diff --git a/src/main/java/com/salessparrow/api/lib/Util.java b/src/main/java/com/salessparrow/api/lib/Util.java index 65c341fe..9c51cff3 100644 --- a/src/main/java/com/salessparrow/api/lib/Util.java +++ b/src/main/java/com/salessparrow/api/lib/Util.java @@ -1,5 +1,8 @@ package com.salessparrow.api.lib; +import java.text.SimpleDateFormat; +import java.util.Date; + import org.springframework.stereotype.Component; import com.fasterxml.jackson.databind.JsonNode; @@ -61,4 +64,19 @@ public static String generateHeaderLogString(HttpServletRequest request) { return headerBuilder.toString(); } + + /** + * Get date format from datetime + * + * @param date + * + * @return String + */ + public String getDateFormatFromDatetime(Date date) { + if (date != null) { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + return dateFormat.format(date); + } + return null; + } } diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetTasksListDto.java b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetTasksListDto.java index 40dc36ab..66a9071a 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetTasksListDto.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetTasksListDto.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.databind.annotation.JsonNaming; import com.salessparrow.api.dto.entities.TaskEntity; +import com.salessparrow.api.lib.Util; import lombok.Data; @@ -31,13 +32,18 @@ private class Owner{ } public TaskEntity taskEntity(){ + Util util = new Util(); + TaskEntity taskEntity = new TaskEntity(); taskEntity.setId(this.id); taskEntity.setCreatorName(this.createdBy.name); taskEntity.setDescription(this.description); - taskEntity.setDueDate(this.activityDate); taskEntity.setCrmOrganizationUserName(this.owner.name); taskEntity.setLastModifiedTime(this.lastModifiedDate); + + String dueDate = util.getDateFormatFromDatetime(this.activityDate); + + taskEntity.setDueDate(dueDate); return taskEntity; } } From 5bef3f68bb1e735f09c54e02f11f711845241412 Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Fri, 25 Aug 2023 12:57:43 +0530 Subject: [PATCH 084/195] Renamed methods to getAccountTasks from getTasks --- .../api/controllers/AccountTaskController.java | 2 +- .../getAccountTasksList/GetAccountTasksListFactory.java | 6 +++--- .../GetSalesforceAccountTasksList.java | 8 ++++---- .../api/lib/salesforce/helper/SalesforceQueryBuilder.java | 2 +- .../services/accountTask/GetAccountTasksListService.java | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java b/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java index eccd32a3..11211e52 100644 --- a/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java +++ b/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java @@ -53,7 +53,7 @@ public ResponseEntity getTasksList( ){ logger.info("Get tasks list request received"); - GetTasksListFormatterDto getTasksListFormatterDto = getAccountTasksListService.getTasksList(request, accountId); + GetTasksListFormatterDto getTasksListFormatterDto = getAccountTasksListService.getAccountTasksList(request, accountId); return ResponseEntity.status(HttpStatus.OK).body(getTasksListFormatterDto); } } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetAccountTasksListFactory.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetAccountTasksListFactory.java index 4780f673..a18185f8 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetAccountTasksListFactory.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetAccountTasksListFactory.java @@ -29,12 +29,12 @@ public class GetAccountTasksListFactory { * * @return GetTasksListFormatterDto **/ - public GetTasksListFormatterDto getTasksList(User user, String accountId) { - logger.info("factory for getTasksList action"); + public GetTasksListFormatterDto getAccountTasksList(User user, String accountId) { + logger.info("factory for getAccountTasksList action"); switch(user.getUserKind()) { case UserConstants.SALESFORCE_USER_KIND: - return getSalesforceAccountTasksList.getTasksList(user, accountId); + return getSalesforceAccountTasksList.getAccountTasksList(user, accountId); default: throw new CustomException( new ErrorObject( diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetSalesforceAccountTasksList.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetSalesforceAccountTasksList.java index 66548549..19c105b7 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetSalesforceAccountTasksList.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetSalesforceAccountTasksList.java @@ -40,20 +40,20 @@ public class GetSalesforceAccountTasksList { private MakeCompositeRequest makeCompositeRequest; /** - * Get the list of tasks for a given account + * Get the list of tasks for a given account in salesforce * * @param user * @param accountId * * @return GetTasksListFormatterDto **/ - public GetTasksListFormatterDto getTasksList(User user, String accountId) { - logger.info("Salesforce getTasksList action"); + public GetTasksListFormatterDto getAccountTasksList(User user, String accountId) { + logger.info("Salesforce getAccountTasksList action called"); String salesforceUserId = user.getExternalUserId(); SalesforceQueryBuilder salesforceQuery = new SalesforceQueryBuilder(); - String query = salesforceQuery.getTasksQuery(accountId); + String query = salesforceQuery.getAccountTasksQuery(accountId); String url = salesforceConstants.queryUrlPath() + query; diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java index 05c8231d..a3477ac7 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java @@ -31,7 +31,7 @@ public String getAccountsQuery(String searchTerm) { * * @return String */ - public String getTasksQuery(String accountId) { + public String getAccountTasksQuery(String accountId) { return "SELECT Id, Description, ActivityDate, CreatedBy.Name, Owner.Name, LastModifiedDate FROM Task WHERE WhatId='" + accountId + "' ORDER BY LastModifiedDate DESC LIMIT 5"; } diff --git a/src/main/java/com/salessparrow/api/services/accountTask/GetAccountTasksListService.java b/src/main/java/com/salessparrow/api/services/accountTask/GetAccountTasksListService.java index 7fa097d7..cc4b2254 100644 --- a/src/main/java/com/salessparrow/api/services/accountTask/GetAccountTasksListService.java +++ b/src/main/java/com/salessparrow/api/services/accountTask/GetAccountTasksListService.java @@ -29,10 +29,10 @@ public class GetAccountTasksListService { * * @return GetTasksListFormatterDto object */ - public GetTasksListFormatterDto getTasksList(HttpServletRequest request, String accountId) { - logger.info("Inside getTasksList Service"); + public GetTasksListFormatterDto getAccountTasksList(HttpServletRequest request, String accountId) { + logger.info("getAccountTasksList Service called"); User currentUser = (User) request.getAttribute("current_user"); - return getAccountTasksListFactory.getTasksList(currentUser, accountId); + return getAccountTasksListFactory.getAccountTasksList(currentUser, accountId); } } From ff32b10edd272fd953652c9da7d90341182533b9 Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Fri, 25 Aug 2023 13:08:39 +0530 Subject: [PATCH 085/195] Renamed getTasksList Test methods to GetAccountTasksList --- ...TasksListTest.java => GetAccountTasksListTest.java} | 8 ++++---- ...enarios.json => getAccountTasksList.scenarios.json} | 10 +++++----- ...fixtures.json => getAccountTasksList.fixtures.json} | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) rename src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/{GetTasksListTest.java => GetAccountTasksListTest.java} (94%) rename src/test/resources/data/controllers/accountTaskController/{getTasksList.scenarios.json => getAccountTasksList.scenarios.json} (96%) rename src/test/resources/fixtures/controllers/accountTaskController/{getTasksList.fixtures.json => getAccountTasksList.fixtures.json} (92%) diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/GetTasksListTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/GetAccountTasksListTest.java similarity index 94% rename from src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/GetTasksListTest.java rename to src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/GetAccountTasksListTest.java index 90b8c9b9..8287ca5b 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/GetTasksListTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/GetAccountTasksListTest.java @@ -45,7 +45,7 @@ @AutoConfigureMockMvc @WebAppConfiguration @Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) -public class GetTasksListTest { +public class GetAccountTasksListTest { @Autowired private MockMvc mockMvc; @@ -73,11 +73,11 @@ public void tearDown() { @ParameterizedTest @MethodSource("testScenariosProvider") - public void getTasksList(Scenario testScenario) throws Exception { + public void getAccountTasksList(Scenario testScenario) throws Exception { // Load fixture data String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/controllers/accountTaskController/getTasksList.fixtures.json", currentFunctionName); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/controllers/accountTaskController/getAccountTasksList.fixtures.json", currentFunctionName); loadFixture.perform(fixtureData); // Read data from the scenario @@ -109,7 +109,7 @@ static Stream testScenariosProvider() throws IOException { } private static List loadScenarios() throws IOException { - String scenariosPath = "classpath:data/controllers/accountTaskController/getTasksList.scenarios.json"; + String scenariosPath = "classpath:data/controllers/accountTaskController/getAccountTasksList.scenarios.json"; Resource resource = new DefaultResourceLoader().getResource(scenariosPath); ObjectMapper objectMapper = new ObjectMapper(); return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); diff --git a/src/test/resources/data/controllers/accountTaskController/getTasksList.scenarios.json b/src/test/resources/data/controllers/accountTaskController/getAccountTasksList.scenarios.json similarity index 96% rename from src/test/resources/data/controllers/accountTaskController/getTasksList.scenarios.json rename to src/test/resources/data/controllers/accountTaskController/getAccountTasksList.scenarios.json index 627ae213..2a4a24fe 100644 --- a/src/test/resources/data/controllers/accountTaskController/getTasksList.scenarios.json +++ b/src/test/resources/data/controllers/accountTaskController/getAccountTasksList.scenarios.json @@ -154,7 +154,7 @@ "id": "00T1e000007mGXXEA2", "creator_name": "Name2", "description": "Update remaining documentations", - "due_date": "2023-12-01T00:00:00.000+00:00", + "due_date": "2023-12-01", "crm_organization_user_name": "Name1", "last_modified_time": "2023-08-24T12:09:51.000+00:00" }, @@ -162,7 +162,7 @@ "id": "00T1e000007mEk9EAE", "creator_name": "Name2", "description": "Update remaining documentations", - "due_date": "2023-12-01T00:00:00.000+00:00", + "due_date": "2023-12-01", "crm_organization_user_name": "Name1", "last_modified_time": "2023-08-23T07:49:23.000+00:00" }, @@ -170,7 +170,7 @@ "id": "00T1e000007mEfuEAE", "creator_name": "Name2", "description": "Update remaining documentations", - "due_date": "2023-12-01T00:00:00.000+00:00", + "due_date": "2023-12-01", "crm_organization_user_name": "Name1", "last_modified_time": "2023-08-23T07:10:53.000+00:00" }, @@ -178,7 +178,7 @@ "id": "00T1e000007mF0oEAE", "creator_name": "Name2", "description": "Update remaining documentations", - "due_date": "2023-12-01T00:00:00.000+00:00", + "due_date": "2023-12-01", "crm_organization_user_name": "Name1", "last_modified_time": "2023-08-23T13:11:03.000+00:00" }, @@ -186,7 +186,7 @@ "id": "00T1e000007mGYaEAM", "creator_name": "Name2", "description": "Update remaining documentations", - "due_date": "2023-12-01T00:00:00.000+00:00", + "due_date": "2023-12-01", "crm_organization_user_name": "Name1", "last_modified_time": "2023-08-24T12:16:05.000+00:00" } diff --git a/src/test/resources/fixtures/controllers/accountTaskController/getTasksList.fixtures.json b/src/test/resources/fixtures/controllers/accountTaskController/getAccountTasksList.fixtures.json similarity index 92% rename from src/test/resources/fixtures/controllers/accountTaskController/getTasksList.fixtures.json rename to src/test/resources/fixtures/controllers/accountTaskController/getAccountTasksList.fixtures.json index 4b0ddba6..07052f62 100644 --- a/src/test/resources/fixtures/controllers/accountTaskController/getTasksList.fixtures.json +++ b/src/test/resources/fixtures/controllers/accountTaskController/getAccountTasksList.fixtures.json @@ -1,5 +1,5 @@ { - "getTasksList": { + "getAccountTasksList": { "salesforce_users": [ { "filepath": "classpath:fixtures/repositories/salesforceUser/ActiveSalesforceUser.json" From 84e7d4a43fc7fb498d7cda9407030653659bd387 Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Fri, 25 Aug 2023 13:17:13 +0530 Subject: [PATCH 086/195] Renamed deleteAcountNote to deleteAccountNote --- .../com/salessparrow/api/controllers/AccountNoteController.java | 2 +- .../api/services/accountNotes/DeleteAccountNoteService.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/salessparrow/api/controllers/AccountNoteController.java b/src/main/java/com/salessparrow/api/controllers/AccountNoteController.java index 6c1a0eff..16d32670 100644 --- a/src/main/java/com/salessparrow/api/controllers/AccountNoteController.java +++ b/src/main/java/com/salessparrow/api/controllers/AccountNoteController.java @@ -89,7 +89,7 @@ public ResponseEntity deleteNote( ) { logger.info("Delete Note request received"); - deleteAccountNoteService.deleteAcountNote(request, accountId, noteId); + deleteAccountNoteService.deleteAccountNote(request, accountId, noteId); return ResponseEntity.noContent().build(); } diff --git a/src/main/java/com/salessparrow/api/services/accountNotes/DeleteAccountNoteService.java b/src/main/java/com/salessparrow/api/services/accountNotes/DeleteAccountNoteService.java index 7246b832..3ed5ea2f 100644 --- a/src/main/java/com/salessparrow/api/services/accountNotes/DeleteAccountNoteService.java +++ b/src/main/java/com/salessparrow/api/services/accountNotes/DeleteAccountNoteService.java @@ -27,7 +27,7 @@ public class DeleteAccountNoteService { * * @return void */ - public void deleteAcountNote(HttpServletRequest request, String accountId, String noteId) { + public void deleteAccountNote(HttpServletRequest request, String accountId, String noteId) { logger.info("Delete Account Note Service called"); User currentUser = (User) request.getAttribute("current_user"); From a0ebcfb707555528a2fa2c01368779440b914b6d Mon Sep 17 00:00:00 2001 From: amanbarbaria Date: Fri, 25 Aug 2023 14:07:46 +0530 Subject: [PATCH 087/195] 1. Resolved review comments 2. Resolved merge conflicts with branch milestone/v0.2.0 --- ENVIRONMENT_VARS.md | 5 ++++ LOCAL_SETUP.md | 3 +- sample.secrets.json | 3 +- .../api/config/SecurityConfig.java | 3 +- .../lib/globalConstants/SecretConstants.java | 4 +++ .../accountController/CreateNoteTest.java | 3 +- .../accountController/GetAccountListTest.java | 2 +- .../accountController/GetNoteDetailsTest.java | 2 +- .../accountController/GetNoteListTest.java | 2 +- .../salessparrow/api/helper/Constants.java | 2 +- .../createNote.scenarios.json | 30 ++++--------------- 11 files changed, 26 insertions(+), 33 deletions(-) diff --git a/ENVIRONMENT_VARS.md b/ENVIRONMENT_VARS.md index 26125cbc..c7d7e05f 100644 --- a/ENVIRONMENT_VARS.md +++ b/ENVIRONMENT_VARS.md @@ -76,3 +76,8 @@ This document provides descriptions for the environment variables used in the co - **Description:** Logging level for the application. - **Example Value:** `debug` + +## COOKIE_DOMAIN + +- **Description:** Domain for the API cookies. +- **Example Value:** `localhost` \ No newline at end of file diff --git a/LOCAL_SETUP.md b/LOCAL_SETUP.md index 94e9420d..65758490 100644 --- a/LOCAL_SETUP.md +++ b/LOCAL_SETUP.md @@ -65,7 +65,8 @@ $ touch test.secrets.json "DYNAMO_DB_URL": "http://dynamodb:8000", "LOCAL_KMS_ENDPOINT": "http://localkms:8080", "ERROR_MAIL_FROM": "", - "ERROR_MAIL_TO": "" + "ERROR_MAIL_TO": "", + "COOKIE_DOMAIN":"" } ``` diff --git a/sample.secrets.json b/sample.secrets.json index 1f784c95..46be9a5e 100644 --- a/sample.secrets.json +++ b/sample.secrets.json @@ -12,5 +12,6 @@ "LOG_LEVEL": "", "DYNAMO_DB_URL": "", "ERROR_MAIL_FROM": "", - "ERROR_MAIL_TO": "" + "ERROR_MAIL_TO": "", + "COOKIE_DOMAIN": "" } \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/config/SecurityConfig.java b/src/main/java/com/salessparrow/api/config/SecurityConfig.java index 4d6737d9..02e7dfc7 100644 --- a/src/main/java/com/salessparrow/api/config/SecurityConfig.java +++ b/src/main/java/com/salessparrow/api/config/SecurityConfig.java @@ -71,7 +71,8 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti // Enable for production and staging - if (!CoreConstants.isDevEnvironment() && !CoreConstants.isTestEnvironment()) { + if (!CoreConstants.isDevEnvironment() && !CoreConstants.isTestEnvironment() && + !CoreConstants.isLocalTestEnvironment()) { // All requests must be secure http.requiresChannel(channel -> channel.anyRequest().requiresSecure()); } diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java index fb1b2403..b38b6269 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java @@ -82,6 +82,10 @@ private static String getSecretId() { /* Secrets start */ + public static String cookieDomain() { + return getSecret("COOKIE_DOMAIN"); + } + public static String awsRegion() { return getSecret("AWS_IAM_REGION"); } diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/CreateNoteTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/CreateNoteTest.java index 92880314..cc11ccfc 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/CreateNoteTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/CreateNoteTest.java @@ -31,6 +31,7 @@ import com.github.dynamobee.exception.DynamobeeException; 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; @@ -82,7 +83,7 @@ public void createNote(Scenario testScenario) throws Exception { // Read data from the scenario ObjectMapper objectMapper = new ObjectMapper(); - String cookieValue = (String) testScenario.getInput().get("cookie"); + String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; String accountId = (String) testScenario.getInput().get("accountId"); // Prepare mock responses diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java index 9191aaa0..ee9d86ac 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java @@ -82,7 +82,7 @@ public void getAccountList(Scenario testScenario) throws Exception { // Read data from the scenario ObjectMapper objectMapper = new ObjectMapper(); - String cookieValue = Constants.SALESFORCE_ACTIVE_USET_COOKIE_VALUE; + String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; // Prepare mock responses HttpResponse getAccountMockResponse = new HttpResponse(); diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java index b2b54b1e..e11d4c8f 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java @@ -85,7 +85,7 @@ public void getNoteDetails(Scenario testScenario) throws Exception { ObjectMapper objectMapper = new ObjectMapper(); - String cookieValue = Constants.SALESFORCE_ACTIVE_USET_COOKIE_VALUE; + String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; String accountId = (String) testScenario.getInput().get("accountId"); String noteId = (String) testScenario.getInput().get("noteId"); diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteListTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteListTest.java index 56cc2760..f4d29f47 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteListTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteListTest.java @@ -98,7 +98,7 @@ public void getNoteList(Scenario testScenario) throws Exception{ ObjectMapper objectMapper = new ObjectMapper(); - String cookieValue = Constants.SALESFORCE_ACTIVE_USET_COOKIE_VALUE; + String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; String accountId = (String) testScenario.getInput().get("accountId"); List documentIds = (List) testScenario.getInput().get("documentId"); diff --git a/src/test/java/com/salessparrow/api/helper/Constants.java b/src/test/java/com/salessparrow/api/helper/Constants.java index 2c991d79..41822d84 100644 --- a/src/test/java/com/salessparrow/api/helper/Constants.java +++ b/src/test/java/com/salessparrow/api/helper/Constants.java @@ -4,5 +4,5 @@ * Constants is a helper class for the tests. */ public class Constants { - public static final String SALESFORCE_ACTIVE_USET_COOKIE_VALUE = "1:0055i00000AUxQHAA1:SALESFORCE:app:1692878227:a2xOxjcPChK/YsKCWRuY50J3gH21/tqcGlv7sWU/aPw3/UFVFPbvWn2LLzY5B5kVPXjj1gELRqa4B4ds6uuqIw=="; + public static final String SALESFORCE_ACTIVE_USER_COOKIE_VALUE = "1:0055i00000AUxQHAA1:SALESFORCE:app:1692878227:a2xOxjcPChK/YsKCWRuY50J3gH21/tqcGlv7sWU/aPw3/UFVFPbvWn2LLzY5B5kVPXjj1gELRqa4B4ds6uuqIw=="; } diff --git a/src/test/resources/data/controllers/accountController/createNote.scenarios.json b/src/test/resources/data/controllers/accountController/createNote.scenarios.json index ad1e94d9..66bbd7d5 100644 --- a/src/test/resources/data/controllers/accountController/createNote.scenarios.json +++ b/src/test/resources/data/controllers/accountController/createNote.scenarios.json @@ -5,8 +5,7 @@ "body": { "text": "Test note" }, - "accountId": "0011e00000bWSxdAAG", - "cookie": "1:0055i00000AUxQHAA1:SALESFORCE:app:1692878227:a2xOxjcPChK/YsKCWRuY50J3gH21/tqcGlv7sWU/aPw3/UFVFPbvWn2LLzY5B5kVPXjj1gELRqa4B4ds6uuqIw==" + "accountId": "0011e00000bWSxdAAG" }, "mocks": { "makeCompositeRequest": { @@ -48,8 +47,7 @@ "body": { "text": "" }, - "accountId": "0011e00000bWSxdAAG", - "cookie": "1:0055i00000AUxQHAA1:SALESFORCE:app:1692878227:a2xOxjcPChK/YsKCWRuY50J3gH21/tqcGlv7sWU/aPw3/UFVFPbvWn2LLzY5B5kVPXjj1gELRqa4B4ds6uuqIw==" + "accountId": "0011e00000bWSxdAAG" }, "mocks": {}, "output": { @@ -64,8 +62,7 @@ "description": "Should fail when the note text is not provided", "input": { "body": {}, - "accountId": "0011e00000bWSxdAAG", - "cookie": "1:0055i00000AUxQHAA1:SALESFORCE:app:1692878227:a2xOxjcPChK/YsKCWRuY50J3gH21/tqcGlv7sWU/aPw3/UFVFPbvWn2LLzY5B5kVPXjj1gELRqa4B4ds6uuqIw==" + "accountId": "0011e00000bWSxdAAG" }, "mocks": {}, "output": { @@ -76,29 +73,13 @@ ] } }, - { - "description": "Should fail when the cookie is invalid", - "input": { - "body": { - "text": "Test note" - }, - "accountId": "0011e00000bWSxdAAG", - "cookie": "1:0055i00000AUxQHAA1:SALESFORCE:app:1692878227:a2xOxjcPChK/YsKCWRuY50J3gH21/tqcGlv7sWU/aPw3/UFVFPbvWn2LLzY5B5kVPXjj1gELRqds6uuq==" - }, - "mocks": {}, - "output": { - "http_code": 401, - "code": "UNAUTHORIZED" - } - }, { "description": "Should fail when the account id invalid", "input": { "body": { "text": "Test note" }, - "accountId": "invalid", - "cookie": "1:0055i00000AUxQHAA1:SALESFORCE:app:1692878227:a2xOxjcPChK/YsKCWRuY50J3gH21/tqcGlv7sWU/aPw3/UFVFPbvWn2LLzY5B5kVPXjj1gELRqa4B4ds6uuqIw==" + "accountId": "invalid" }, "mocks": { "makeCompositeRequest": { @@ -143,8 +124,7 @@ "body": { "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." }, - "accountId": "0011e00000bWSxdAAG", - "cookie": "1:0055i00000AUxQHAA1:SALESFORCE:app:1692878227:a2xOxjcPChK/YsKCWRuY50J3gH21/tqcGlv7sWU/aPw3/UFVFPbvWn2LLzY5B5kVPXjj1gELRqa4B4ds6uuqIw==" + "accountId": "0011e00000bWSxdAAG" }, "mocks": { "makeCompositeRequest": { From d9a6c8e157e62dacc6caae9abba9eeffd20e9e58 Mon Sep 17 00:00:00 2001 From: Yagnik Thummar Date: Fri, 25 Aug 2023 14:33:42 +0530 Subject: [PATCH 088/195] Code review changes. --- .../CrmOrganizationUserController.java | 2 +- .../accounts/GetAccountListService.java | 21 +++++++++++-- .../GetCrmOrganizationUsersList.java | 21 +++++++++++-- .../resources/config/ParamErrorConfig.json | 5 +++ .../GetCrmOrganizationUserListTest.java | 9 ++++-- .../getCrmOrganizationUserList.scenarios.json | 31 +++---------------- 6 files changed, 56 insertions(+), 33 deletions(-) diff --git a/src/main/java/com/salessparrow/api/controllers/CrmOrganizationUserController.java b/src/main/java/com/salessparrow/api/controllers/CrmOrganizationUserController.java index 29abf8f4..918628f3 100644 --- a/src/main/java/com/salessparrow/api/controllers/CrmOrganizationUserController.java +++ b/src/main/java/com/salessparrow/api/controllers/CrmOrganizationUserController.java @@ -31,7 +31,7 @@ public ResponseEntity getCrmOrganizationUse HttpServletRequest request, @Valid @ModelAttribute GetCrmOrganizationUsersDto CrmOrganizationUsersDto ){ - logger.info("Search crm organization user request received"); + logger.info("Get list of crm organization users request received"); GetCrmOrganizationUsersFormatterDto getCrmOrganizationUsersFormatterDto = getCrmOrganizationUsersList.getCrmOrganizationUsers(request, CrmOrganizationUsersDto); diff --git a/src/main/java/com/salessparrow/api/services/accounts/GetAccountListService.java b/src/main/java/com/salessparrow/api/services/accounts/GetAccountListService.java index 02744131..a4182771 100644 --- a/src/main/java/com/salessparrow/api/services/accounts/GetAccountListService.java +++ b/src/main/java/com/salessparrow/api/services/accounts/GetAccountListService.java @@ -2,6 +2,8 @@ import java.io.UnsupportedEncodingException; import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -9,7 +11,9 @@ import com.salessparrow.api.domain.User; import com.salessparrow.api.dto.formatter.GetAccountsFormatterDto; import com.salessparrow.api.dto.requestMapper.GetAccountsDto; +import com.salessparrow.api.exception.CustomException; import com.salessparrow.api.lib.crmActions.getAccounts.GetAccountsFactory; +import com.salessparrow.api.lib.errorLib.ParamErrorObject; import jakarta.servlet.http.HttpServletRequest; @@ -31,7 +35,10 @@ public class GetAccountListService { public GetAccountsFormatterDto getAccounts(HttpServletRequest request, GetAccountsDto getAccountsDto) { User currentUser = (User) request.getAttribute("current_user"); - String formattedSearchString = formatSearchString(getAccountsDto.getQ()); + String formattedSearchString = ""; + if(getAccountsDto.getQ() != null){ + formattedSearchString = formatSearchString(getAccountsDto.getQ()); + } return getAccountsFactory.getAccounts(currentUser, formattedSearchString); } @@ -40,7 +47,17 @@ private String formatSearchString(String q) { try { return URLEncoder.encode(q, "UTF-8"); } catch (UnsupportedEncodingException e) { - return q; + + List paramError = new ArrayList<>(); + paramError.add("invalid_search_term"); + + throw new CustomException( + new ParamErrorObject( + "s_a_gals_fss", + e.getMessage(), + paramError + ) + ); } } } diff --git a/src/main/java/com/salessparrow/api/services/crmOrganizationUsers/GetCrmOrganizationUsersList.java b/src/main/java/com/salessparrow/api/services/crmOrganizationUsers/GetCrmOrganizationUsersList.java index fc248bd5..8d663ff7 100644 --- a/src/main/java/com/salessparrow/api/services/crmOrganizationUsers/GetCrmOrganizationUsersList.java +++ b/src/main/java/com/salessparrow/api/services/crmOrganizationUsers/GetCrmOrganizationUsersList.java @@ -2,6 +2,8 @@ import java.io.UnsupportedEncodingException; import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -11,7 +13,9 @@ import com.salessparrow.api.domain.User; import com.salessparrow.api.dto.formatter.GetCrmOrganizationUsersFormatterDto; import com.salessparrow.api.dto.requestMapper.GetCrmOrganizationUsersDto; +import com.salessparrow.api.exception.CustomException; import com.salessparrow.api.lib.crmActions.getCrmOrganizationUsers.GetCrmOrganizationUsersFactory; +import com.salessparrow.api.lib.errorLib.ParamErrorObject; import jakarta.servlet.http.HttpServletRequest; @@ -39,8 +43,11 @@ public class GetCrmOrganizationUsersList { public GetCrmOrganizationUsersFormatterDto getCrmOrganizationUsers(HttpServletRequest request ,GetCrmOrganizationUsersDto crmOrganizationUsersDto) { logger.info("Inside Search crm organization user service"); User currentUser = (User) request.getAttribute("current_user"); + String formattedSearchString = ""; + if(crmOrganizationUsersDto.getQ() != null){ + formattedSearchString = formatSearchString(crmOrganizationUsersDto.getQ()); + } - String formattedSearchString = formatSearchString(crmOrganizationUsersDto.getQ()); return getCrmOrganizationUsersFactory.getCrmOrganizationUsers(currentUser, formattedSearchString); } @@ -57,7 +64,17 @@ private String formatSearchString(String searchTerm) { try { return URLEncoder.encode(searchTerm,"UTF-8"); } catch (UnsupportedEncodingException e) { - return searchTerm; + + List paramError = new ArrayList<>(); + paramError.add("invalid_search_term"); + + throw new CustomException( + new ParamErrorObject( + "s_cou_gcoul_fss", + e.getMessage(), + paramError + ) + ); } } diff --git a/src/main/resources/config/ParamErrorConfig.json b/src/main/resources/config/ParamErrorConfig.json index 0b724abb..34551034 100644 --- a/src/main/resources/config/ParamErrorConfig.json +++ b/src/main/resources/config/ParamErrorConfig.json @@ -13,5 +13,10 @@ "parameter": "q", "param_error_identifier": "search_term_too_long", "message": "Search term too long. Please shorten and try again." + }, + "invalid_search_term":{ + "parameter": "q", + "param_error_identifier": "invalid_search_term", + "message": "Invalid search term. Please try again." } } \ No newline at end of file diff --git a/src/test/java/com/salessparrow/api/functional/controllers/crmOrganizationUserController/GetCrmOrganizationUserListTest.java b/src/test/java/com/salessparrow/api/functional/controllers/crmOrganizationUserController/GetCrmOrganizationUserListTest.java index e8db876c..5d59e89e 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/crmOrganizationUserController/GetCrmOrganizationUserListTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/crmOrganizationUserController/GetCrmOrganizationUserListTest.java @@ -31,6 +31,7 @@ import com.github.dynamobee.exception.DynamobeeException; 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; @@ -81,7 +82,7 @@ public void getCrmOrganizationUserList(Scenario testScenario) throws Exception { // Read data from the scenario ObjectMapper objectMapper = new ObjectMapper(); - String cookieValue = (String) testScenario.getInput().get("cookie"); + String cookieValue = Constants.SALESFORCE_ACTIVE_USET_COOKIE_VALUE; String q = (String) testScenario.getInput().get("q"); // Prepare mock responses @@ -105,7 +106,11 @@ public void getCrmOrganizationUserList(Scenario testScenario) throws Exception { JsonNode expectedOutputJson = objectMapper.readTree(expectedOutput); JsonNode actualOutputJson = objectMapper.readTree(actualOutput); - assertEquals(expectedOutputJson, actualOutputJson); + if(resultActions.andReturn().getResponse().getStatus() == 200) { + assertEquals(expectedOutputJson, actualOutputJson); + } else { + common.compareErrors(testScenario, actualOutput); + } } static Stream testScenariosProvider() throws IOException { diff --git a/src/test/resources/data/controllers/crmOrganizationUserController/getCrmOrganizationUserList.scenarios.json b/src/test/resources/data/controllers/crmOrganizationUserController/getCrmOrganizationUserList.scenarios.json index 0f4a27c0..b94d553a 100644 --- a/src/test/resources/data/controllers/crmOrganizationUserController/getCrmOrganizationUserList.scenarios.json +++ b/src/test/resources/data/controllers/crmOrganizationUserController/getCrmOrganizationUserList.scenarios.json @@ -2,8 +2,7 @@ { "description": "Should return the list of crm Users", "input": { - "q": "a", - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + "q": "a" }, "mocks": { "makeCompositeRequest": { @@ -58,8 +57,7 @@ { "description": "Should return the list of crm users sorted by modified date on empty search string", "input": { - "q": "", - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + "q": "" }, "mocks": { "makeCompositeRequest": { @@ -114,9 +112,8 @@ { "description": "Should return error if search string length > 200", "input": { - "q": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" - }, + "q": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz" + }, "mocks": {}, "output": { "http_code": 400, @@ -124,26 +121,8 @@ "code": "INVALID_PARAMS", "internal_error_identifier": "b_2", "param_errors": [ - { - "parameter": "q", - "param_error_identifier": "search_term_too_long", - "message": "Search term too long. Please shorten and try again." - } + "search_term_too_long" ] } - }, - { - "description": "Should return error if search string is not provided", - "input": { - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" - }, - "mocks": {}, - "output": { - "http_code": 500, - "message": "Something went wrong.", - "code": "INTERNAL_SERVER_ERROR", - "internal_error_identifier": "e_geh_hre_1", - "param_errors": [] - } } ] \ No newline at end of file From cdaef8dffb811a696d242e6fb457da08e88d3ecd Mon Sep 17 00:00:00 2001 From: Yagnik Thummar Date: Fri, 25 Aug 2023 14:43:20 +0530 Subject: [PATCH 089/195] Removed cookie values form scenario files. --- .../accountTaskController/CreateTaskTest.java | 10 ++- .../createTask.scenarios.json | 76 ++++--------------- 2 files changed, 22 insertions(+), 64 deletions(-) diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/CreateTaskTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/CreateTaskTest.java index 8cf6e7b1..339f9f4c 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/CreateTaskTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/CreateTaskTest.java @@ -30,6 +30,7 @@ import com.github.dynamobee.exception.DynamobeeException; 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; @@ -81,7 +82,7 @@ public void createTask(Scenario testScenario) throws Exception { // Read data from the scenario ObjectMapper objectMapper = new ObjectMapper(); - String cookieValue = (String) testScenario.getInput().get("cookie"); + String cookieValue = Constants.SALESFORCE_ACTIVE_USET_COOKIE_VALUE; String accountId = (String) testScenario.getInput().get("accountId"); // Prepare mock responses @@ -101,7 +102,12 @@ public void createTask(Scenario testScenario) throws Exception { // Check the response String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); - assertEquals(expectedOutput, actualOutput); + + if(resultActions.andReturn().getResponse().getStatus() == 201) { + assertEquals(expectedOutput, actualOutput); + } else { + common.compareErrors(testScenario, actualOutput); + } } static Stream testScenariosProvider() throws IOException { diff --git a/src/test/resources/data/controllers/accountTaskController/createTask.scenarios.json b/src/test/resources/data/controllers/accountTaskController/createTask.scenarios.json index dfa2b679..af6b7e26 100644 --- a/src/test/resources/data/controllers/accountTaskController/createTask.scenarios.json +++ b/src/test/resources/data/controllers/accountTaskController/createTask.scenarios.json @@ -7,8 +7,7 @@ "description":"Update remaining documentations", "due_date":"2023-12-01" }, - "accountId": "0011e00000bWSxdAAG", - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + "accountId": "0011e00000bWSxdAAG" }, "mocks": { "makeCompositeRequest": { @@ -40,8 +39,7 @@ "description":"", "due_date":"2023-12-01" }, - "accountId": "0011e00000bWSxdAAG", - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + "accountId": "0011e00000bWSxdAAG" }, "mocks": {}, "output": { @@ -50,11 +48,7 @@ "code": "INVALID_PARAMS", "internal_error_identifier": "b_2", "param_errors": [ - { - "parameter": "description", - "param_error_identifier": "missing_description", - "message": "description is required parameter. Please provide description." - } + "missing_description" ] } }, @@ -65,8 +59,7 @@ "crm_organization_user_id":"0011e00000bWSxdAA1", "due_date":"2023-12-01" }, - "accountId": "0011e00000bWSxdAAG", - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + "accountId": "0011e00000bWSxdAAG" }, "mocks": {}, "output": { @@ -75,11 +68,7 @@ "code": "INVALID_PARAMS", "internal_error_identifier": "b_2", "param_errors": [ - { - "parameter": "description", - "param_error_identifier": "missing_description", - "message": "description is required parameter. Please provide description." - } + "missing_description" ] } }, @@ -90,8 +79,7 @@ "crm_organization_user_id":"0011e00000bWSxdAA1", "description":"Update remaining documentations" }, - "accountId": "0011e00000bWSxdAAG", - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + "accountId": "0011e00000bWSxdAAG" }, "mocks": {}, "output": { @@ -100,11 +88,7 @@ "code": "INVALID_PARAMS", "internal_error_identifier": "b_2", "param_errors": [ - { - "parameter": "due_date", - "param_error_identifier": "invalid_due_date", - "message": "Invalid or missing due date. Please double check and try again." - } + "invalid_due_date" ] } }, @@ -115,8 +99,7 @@ "description":"Update remaining documentations", "due_date":"2023-12-01" }, - "accountId": "0011e00000bWSxdAAG", - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + "accountId": "0011e00000bWSxdAAG" }, "mocks": {}, "output": { @@ -125,11 +108,7 @@ "code": "INVALID_PARAMS", "internal_error_identifier": "b_2", "param_errors": [ - { - "parameter": "crm_organization_user_id", - "param_error_identifier": "missing_crm_organization_user_id", - "message": "crm_organization_user_id is required parameter. Please provide crm_organization_user_id." - } + "missing_crm_organization_user_id" ] } }, @@ -141,8 +120,7 @@ "description":"Update remaining documentations", "due_date":"2023-120-01" }, - "accountId": "0011e00000bWSxdAAG", - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + "accountId": "0011e00000bWSxdAAG" }, "mocks": {}, "output": { @@ -151,11 +129,7 @@ "code": "INVALID_PARAMS", "internal_error_identifier": "b_2", "param_errors": [ - { - "parameter": "due_date", - "param_error_identifier": "invalid_due_date", - "message": "Invalid or missing due date. Please double check and try again." - } + "invalid_due_date" ] } }, @@ -167,8 +141,7 @@ "description":"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc, quis gravida magna mi a libero. Fusce vulputate eleifend sapien. Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Nullam accumsan lorem in dui. Cras ultricies mi eu turpis hendrerit fringilla. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; In ac dui quis mi consectetuer lacinia. Nam pretium turpis et arcu. Duis arcu tortor, suscipit eget, imperdiet nec, imperdiet iaculis, ipsum. Sed aliquam ultrices mauris. Integer ante arcu, accumsan a, consectetuer eget, posuere ut, mauris. Praesent adipiscing. Phasellus ullamcorper ipsum rutrum nunc. Nunc nonummy metus. Vestibulum volutpat pretium libero. Cras id dui. Aenean ut eros et nisl sagittis vestibulum. Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Sed lectus. Donec mollis hendrerit risus. Phasellus nec sem in justo pellentesque facilisis. Etiam imperdiet imperdiet orci. Nunc nec neque. Phasellus leo dolor, tempus non, auctor et, hendrerit quis, nisi. Curabitur ligula sapien, tincidunt non, euismod vitae, posuere imperdiet, leo. Maecenas malesuada. Praesent congue erat at massa. Sed cursus turpis vitae tortor. Donec posuere vulputate arcu. Phasellus accumsan cursus velit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed aliquam, nisi quis porttitor congue, elit erat euismod orci, ac placerat dolor lectus quis orci. Phasellus consectetuer vestibulum elit. Aenean tellus metus, bibendum sed, posuere ac, mattis non, nunc. Vestibulum fringilla pede sit amet augue. In turpis. Pellentesque posuere. Praesent turpis. Aenean posuere, tortor sed cursus feugiat, nunc augue blandit nunc, eu sollicitudin urna dolor sagittis lacus. Donec elit libero, sodales nec, volutpat a, suscipit non, turpis. Nullam sagittis. Suspendisse pulvinar, augue ac venenatis condimentum, sem libero volutpat nibh, nec pellentesque velit pede quis nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Fusce id purus. Ut varius tincidunt libero. Phasellus dolor. Maecenas vestibulum mollis diam. Pellentesque ut neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. In dui magna, posuere eget, vestibulum et, tempor auctor, justo. In ac felis quis tortor malesuada pretium. Pellentesque auctor neque nec urna. Proin sapien ipsum, porta a, auctor quis, euismod ut, mi. Aenean viverra rhoncus pede. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Ut non enim eleifend felis pretium feugiat. Vivamus quis mi. Phasellus a est. Phasellus magna. In hac habitasse platea dictumst. Curabitur at lacus ac velit ornare lobortis. Curabitur a felis in nunc fringilla tristique. Morbi mattis ullamcorper velit. Phasellus gravida semper nisi. Nullam vel sem. Pellentesque libero tortor, tincidunt et, tincidunt eget, semper nec, quam. Sed hendrerit. Morbi ac felis. Nunc egestas, augue at pellentesque laoreet, felis eros vehicula leo, at malesuada velit leo quis pede. Donec interdum, metus et hendrerit aliquet, dolor diam sagittis ligula, eget egestas libero turpis vel mi. Nunc nulla. Fusce risus nisl, viverra et, tempor et, pretium in, sapien. Donec venenatis vulputate lorem. Morbi nec metus. Phasellus blandit leo ut odio. Maecenas ullamcorper, dui et placerat feugiat, eros pede varius nisi, condimentum viverra felis nunc et lorem. Sed magna purus, fermentum eu, tincidunt eu, varius ut, felis. In auctor lobortis lacus. Quisque libero metus, condimentum nec, tempor a, commodo mollis, magna. Vestibulum ullamcorper mauris at ligula. Fusce fermentum. Nullam cursus lacinia erat. Praesent blandit laoreet nibh. Fusce convallis metus id felis luctus adipiscing. Pellentesque egestas, neque sit amet convallis pulvinar, justo nulla eleifend augue, ac auctor orci leo non est. Quisque id mi. Ut tincidunt tincidunt erat. Etiam feugiat lorem non metus. Vestibulum dapibus nunc ac augue. Curabitur vestibulum aliquam leo. Praesent egestas neque eu enim. In hac habitasse platea dictumst. Fusce a quam. Etiam ut purus mattis mauris sodales aliquam. Curabitur nisi. Quisque malesuada placerat nisl. Nam ipsum risus, rutrum vitae, vestibulum eu, molestie vel, lacus. Sed augue ipsum, egestas nec, vestibulum et, malesuada adipiscing, dui. Vestibulum facilisis, purus nec pulvinar iaculis, ligula mi congue nunc, vitae euismod ligula urna in dolor. Mauris sollicitudin fermentum libero. Praesent nonummy mi in odio. Nunc interdum lacus sit amet orci. Vestibulum rutrum, mi nec elementum vehicula, eros quam gravida nisl, id fringilla neque ante vel mi. Morbi mollis tellus ac sapien. Phasellus volutpat, metus eget egestas mollis, lacus lacus blandit dui, id egestas quam mauris ut lacus. Fusce vel dui. Sed in libero ut nibh placerat accumsan. Proin faucibus arcu quis ante. In consectetuer turpis ut velit. Nulla sit amet est. Praesent metus tellus, elementum eu, semper a, adipiscing nec, purus. Cras risus ipsum, faucibus ut, ullamcorper id, varius ac, leo. Suspendisse feugiat. Suspendisse enim turpis, dictum sed, iaculis a, condimentum nec, nisi. Praesent nec nisl a purus blandit viverra. Praesent ac massa at ligula laoreet iaculis. Nulla neque dolor, sagittis eget, iaculis quis, molestie non, velit. Mauris turpis nunc, blandit et, volutpat molestie, porta ut, ligula. Fusce pharetra convallis urna. Quisque ut nisi. Donec mi odio, faucibus at, scelerisque quis, convallis in, nisi. Suspendisse non nisl sit amet velit hendrerit rutrum. Ut leo. Ut a nisl id ante tempus hendrerit. Proin pretium, leo ac pellentesque mollis, felis nunc ultrices eros, sed gravida augue augue mollis justo. Suspendisse eu ligula. Nulla facilisi. Donec id justo. Praesent porttitor, nulla vitae posuere iaculis, arcu nisl dignissim dolor, a pretium mi sem ut ipsum. Curabitur suscipit suscipit tellus. Praesent vestibulum dapibus nibh. Etiam iaculis nunc ac metus. Ut id nisl quis enim dignissim sagittis. Etiam sollicitudin, ipsum eu pulvinar rutrum, tellus ipsum laoreet sapien, quis venenatis ante odio sit amet eros. Proin magna. Duis vel nibh at velit scelerisque suscipit. Curabitur turpis. Vestibulum suscipit nulla quis orci. Fusce ac felis sit amet ligula pharetra condimentum. Maecenas egestas arcu quis ligula mattis placerat. Duis lobortis massa imperdiet quam. Suspendisse potenti. Pellentesque commodo eros a enim. Vestibulum turpis sem, aliquet eget, lobortis pellentesque, rutrum eu, nisl. Sed libero. Aliquam erat volutpat. Etiam vitae tortor. Morbi vestibulum volutpat enim. Aliquam eu nunc. Nunc sed turpis. Sed mollis, eros et ultrices tempus, mauris ipsum aliquam libero, non adipiscing dolor urna a orci. Nulla porta dolor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Pellentesque dapibus hendrerit tortor. Praesent egestas tristique nibh. Sed a libero. Cras varius. Donec vitae orci sed dolor rutrum auctor. Fusce egestas elit eget lorem. Suspendisse nisl elit, rhoncus eget, elementum ac, condimentum eget, diam. Nam at tortor in tellus interdum sagittis. Aliquam lobortis. Donec orci lectus, aliquam ut, faucibus non, euismod id, nulla. Curabitur blandit mollis lacus. Nam adipiscing. Vestibulum eu odio. Vivamus laoreet. Nullam tincidunt adipiscing enim. Phasellus tempus. Proin viverra, ligula sit amet ultrices semper, ligula arcu tristique sapien, a accumsan nisi mauris ac eros. Fusce neque. Suspendisse faucibus, nunc et pellentesque egestas, lacus ante convallis tellus, vitae iaculis lacus elit id tortor. Vivamus aliquet elit ac nisl. Fusce fermentum odio nec arcu. Vivamus euismod mauris. In ut quam vitae odio lacinia tincidunt. Praesent ut ligula non mi varius sagittis. Cras sagittis. Praesent ac sem eget est egestas volutpat. Vivamus consectetuer hendrerit lacus. Cras non dolor. Vivamus in erat ut urna cursus vestibulum. Fusce commodo aliquam arcu. Nam commodo suscipit quam. Quisque id odio. Praesent venenatis metus at tortor pulvinar varius. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc, quis gravida magna mi a libero. Fusce vulputate eleifend sapien. Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Nullam accumsan lorem in dui. Cras ultricies mi eu turpis hendrerit fringilla. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; In ac dui quis mi consectetuer lacinia. Nam pretium turpis et arcu. Duis arcu tortor, suscipit eget, imperdiet nec, imperdiet iaculis, ipsum. Sed aliquam ultrices mauris. Integer ante arcu, accumsan a, consectetuer eget, posuere ut, mauris. Praesent adipiscing. Phasellus ullamcorper ipsum rutrum nunc. Nunc nonummy metus. Vestibulum volutpat pretium libero. Cras id dui. Aenean ut eros et nisl sagittis vestibulum. Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Sed lectus. Donec mollis hendrerit risus. Phasellus nec sem in justo pellentesque facilisis. Etiam imperdiet imperdiet orci. Nunc nec neque. Phasellus leo dolor, tempus non, auctor et, hendrerit quis, nisi. Curabitur ligula sapien, tincidunt non, euismod vitae, posuere imperdiet, leo. Maecenas malesuada. Praesent congue erat at massa. Sed cursus turpis vitae tortor. Donec posuere vulputate arcu. Phasellus accumsan cursus velit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed aliquam, nisi quis porttitor congue, elit erat euismod orci, ac placerat dolor lectus quis orci. Phasellus consectetuer vestibulum elit. Aenean tellus metus, bibendum sed, posuere ac, mattis non, nunc. Vestibulum fringilla pede sit amet augue. In turpis. Pellentesque posuere. Praesent turpis. Aenean posuere, tortor sed cursus feugiat, nunc augue blandit nunc, eu sollicitudin urna dolor sagittis lacus. Donec elit libero, sodales nec, volutpat a, suscipit non, turpis. Nullam sagittis. Suspendisse pulvinar, augue ac venenatis condimentum, sem libero volutpat nibh, nec pellentesque velit pede quis nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Fusce id purus. Ut varius tincidunt libero. Phasellus dolor. Maecenas vestibulum mollis diam. Pellentesque ut neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. In dui magna, posuere eget, vestibulum et, tempor auctor, justo. In ac felis quis tortor malesuada pretium. Pellentesque auctor neque nec urna. Proin sapien ipsum, porta a, auctor quis, euismod ut, mi. Aenean viverra rhoncus pede. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Ut non enim eleifend felis pretium feugiat. Vivamus quis mi. Phasellus a est. Phasellus magna. In hac habitasse platea dictumst. Curabitur at lacus ac velit ornare lobortis. Curabitur a felis in nunc fringilla tristique. Morbi mattis ullamcorper velit. Phasellus gravida semper nisi. Nullam vel sem. Pellentesque libero tortor, tincidunt et, tincidunt eget, semper nec, quam. Sed hendrerit. Morbi ac felis. Nunc egestas, augue at pellentesque laoreet, felis eros vehicula leo, at malesuada velit leo quis pede. Donec interdum, metus et hendrerit aliquet, dolor diam sagittis ligula, eget egestas libero turpis vel mi. Nunc nulla. Fusce risus nisl, viverra et, tempor et, pretium in, sapien. Donec venenatis vulputate lorem. Morbi nec metus. Phasellus blandit leo ut odio. Maecenas ullamcorper, dui et placerat feugiat, eros pede varius nisi, condimentum viverra felis nunc et lorem. Sed magna purus, fermentum eu, tincidunt eu, varius ut, felis. In auctor lobortis lacus. Quisque libero metus, condimentum nec, tempor a, commodo mollis, magna. Vestibulum ullamcorper mauris at ligula. Fusce fermentum. Nullam cursus lacinia erat. Praesent blandit laoreet nibh. Fusce convallis metus id felis luctus adipiscing. Pellentesque egestas, neque sit amet convallis pulvinar, justo nulla eleifend augue, ac auctor orci leo non est. Quisque id mi. Ut tincidunt tincidunt erat. Etiam feugiat lorem non metus. Vestibulum dapibus nunc ac augue. Curabitur vestibulum aliquam leo. Praesent egestas neque eu enim. In hac habitasse platea dictumst. Fusce a quam. Etiam ut purus mattis mauris sodales aliquam. Curabitur nisi. Quisque malesuada placerat nisl. Nam ipsum risus, rutrum vitae, vestibulum eu, molestie vel, lacus. Sed augue ipsum, egestas nec, vestibulum et, malesuada adipiscing, dui. Vestibulum facilisis, purus nec pulvinar iaculis, ligula mi congue nunc, vitae euismod ligula urna in dolor. Mauris sollicitudin fermentum libero. Praesent nonummy mi in odio. Nunc interdum lacus sit amet orci. Vestibulum rutrum, mi nec elementum vehicula, eros quam gravida nisl, id fringilla neque ante vel mi. Morbi mollis tellus ac sapien. Phasellus volutpat, metus eget egestas mollis, lacus lacus blandit dui, id egestas quam mauris ut lacus. Fusce vel dui. Sed in libero ut nibh placerat accumsan. Proin faucibus arcu quis ante. In consectetuer turpis ut velit. Nulla sit amet est. Praesent metus tellus, elementum eu, semper a, adipiscing nec, purus. Cras risus ipsum, faucibus ut, ullamcorper id, varius ac, leo. Suspendisse feugiat. Suspendisse enim turpis, dictum sed, iaculis a, condimentum nec, nisi. Praesent nec nisl a purus blandit viverra. Praesent ac massa at ligula laoreet iaculis. Nulla neque dolor, sagittis eget, iaculis quis, molestie non, velit. Mauris turpis nunc, blandit et, volutpat molestie, porta ut, ligula. Fusce pharetra convallis urna. Quisque ut nisi. Donec mi odio, faucibus at, scelerisque quis, convallis in, nisi. Suspendisse non nisl sit amet velit hendrerit rutrum. Ut leo. Ut a nisl id ante tempus hendrerit. Proin pretium, leo ac pellentesque mollis, felis nunc ultrices eros, sed gravida augue augue mollis justo. Suspendisse eu ligula. Nulla facilisi. Donec id justo. Praesent porttitor, nulla vitae posuere iaculis, arcu nisl dignissim dolor, a pretium mi sem ut ipsum. Curabitur suscipit suscipit tellus. Praesent vestibulum dapibus nibh. Etiam iaculis nunc ac metus. Ut id nisl quis enim dignissim sagittis. Etiam sollicitudin, ipsum eu pulvinar rutrum, tellus ipsum laoreet sapien, quis venenatis ante odio sit amet eros. Proin magna. Duis vel nibh at velit scelerisque suscipit. Curabitur turpis. Vestibulum suscipit nulla quis orci. Fusce ac felis sit amet ligula pharetra condimentum. Maecenas egestas arcu quis ligula mattis placerat. Duis lobortis massa imperdiet quam. Suspendisse potenti. Pellentesque commodo eros a enim. Vestibulum turpis sem, aliquet eget, lobortis pellentesque, rutrum eu, nisl. Sed libero. Aliquam erat volutpat. Etiam vitae tortor. Morbi vestibulum volutpat enim. Aliquam eu nunc. Nunc sed turpis. Sed mollis, eros et ultrices tempus, mauris ipsum aliquam libero, non adipiscing dolor urna a orci. Nulla porta dolor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Pellentesque dapibus hendrerit tortor. Praesent egestas tristique nibh. Sed a libero. Cras varius. Donec vitae orci sed dolor rutrum auctor. Fusce egestas elit eget lorem. Suspendisse nisl elit, rhoncus eget, elementum ac, condimentum eget, diam. Nam at tortor in tellus interdum sagittis. Aliquam lobortis. Donec orci lectus, aliquam ut, faucibus non, euismod id, nulla. Curabitur blandit mollis lacus. Nam adipiscing. Vestibulum eu odio. Vivamus laoreet. Nullam tincidunt adipiscing enim. Phasellus tempus. Proin viverra, ligula sit amet ultrices semper, ligula arcu tristique sapien, a accumsan nisi mauris ac eros. Fusce neque. Suspendisse faucibus, nunc et pellentesque egestas, lacus ante convallis tellus, vitae iaculis lacus elit id tortor. Vivamus aliquet elit ac nisl. Fusce fermentum odio nec arcu. Vivamus euismod mauris. In ut quam vitae odio lacinia tincidunt. Praesent ut ligula non mi varius sagittis. Cras sagittis. Praesent ac sem eget est egestas volutpat. Vivamus consectetuer hendrerit lacus. Cras non dolor. Vivamus in erat ut urna cursus vestibulum. Fusce commodo aliquam arcu. Nam commodo suscipit quam. Quisque id odio. Praesent venenatis metus at tortor pulvinar varius. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc, quis gravida magna mi a libero. Fusce vulputate eleifend sapien. Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Nullam accumsan lorem in dui. Cras ultricies mi eu turpis hendrerit fringilla. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; In ac dui quis mi consectetuer lacinia. Nam pretium turpis et arcu. Duis arcu tortor, suscipit eget, imperdiet nec, imperdiet iaculis, ipsum. Sed aliquam ultrices mauris. Integer ante arcu, accumsan a, consectetuer eget, posuere ut, mauris. Praesent adipiscing. Phasellus ullamcorper ipsum rutrum nunc. Nunc nonummy metus. Vestibulum volutpat pretium libero. Cras id dui. Aenean ut eros et nisl sagittis vestibulum. Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Sed lectus. Donec mollis hendrerit risus. Phasellus nec sem in justo pellentesque facilisis. Etiam imperdiet imperdiet orci. Nunc nec neque. Phasellus leo dolor, tempus non, auctor et, hendrerit quis, nisi. Curabitur ligula sapien, tincidunt non, euismod vitae, posuere imperdiet, leo. Maecenas malesuada. Praesent congue erat at massa. Sed cursus turpis vitae tortor. Donec posuere vulputate arcu. Phasellus accumsan cursus velit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed aliquam, nisi quis porttitor congue, elit erat euismod orci, ac placerat dolor lectus quis orci. Phasellus consectetuer vestibulum elit. Aenean tellus metus, bibendum sed, posuere ac, mattis non, nunc. Vestibulum fringilla pede sit amet augue. In turpis. Pellentesque posuere. Praesent turpis. Aenean posuere, tortor sed cursus feugiat, nunc augue blandit nunc, eu sollicitudin urna dolor sagittis lacus. Donec elit libero, sodales nec, volutpat a, suscipit non, turpis. Nullam sagittis. Suspendisse pulvinar, augue ac venenatis condimentum, sem libero volutpat nibh, nec pellentesque velit pede quis nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Fusce id purus. Ut varius tincidunt libero. Phasellus dolor. Maecenas vestibulum mollis diam. Pellentesque ut neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. In dui magna, posuere eget, vestibulum et, tempor auctor, justo. In ac felis quis tortor malesuada pretium. Pellentesque auctor neque nec urna. Proin sapien ipsum, porta a, auctor quis, euismod ut, mi. Aenean viverra rhoncus pede. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Ut non enim eleifend felis pretium feugiat. Vivamus quis mi. Phasellus a est. Phasellus magna. In hac habitasse platea dictumst. Curabitur at lacus ac velit ornare lobortis. Curabitur a felis in nunc fringilla tristique. Morbi mattis ullamcorper velit. Phasellus gravida semper nisi. Nullam vel sem. Pellentesque libero tortor, tincidunt et, tincidunt eget, semper nec, quam. Sed hendrerit. Morbi ac felis. Nunc egestas, augue at pellentesque laoreet, felis eros vehicula leo, at malesuada velit leo quis pede. Donec interdum, metus et hendrerit aliquet, dolor diam sagittis ligula, eget egestas libero turpis vel mi. Nunc nulla. Fusce risus nisl, viverra et, tempor et, pretium in, sapien. Donec venenatis vulputate lorem. Morbi nec metus. Phasellus blandit leo ut odio. Maecenas ullamcorper, dui et placerat feugiat, eros pede varius nisi, condimentum viverra felis nunc et lorem. Sed magna purus, fermentum eu, tincidunt eu, varius ut, felis. In auctor lobortis lacus. Quisque libero metus, condimentum nec, tempor a, commodo mollis, magna. Vestibulum ullamcorper mauris at ligula. Fusce fermentum. Nullam cursus lacinia erat. Praesent blandit laoreet nibh. Fusce convallis metus id felis luctus adipiscing. Pellentesque egestas, neque sit amet convallis pulvinar, justo nulla eleifend augue, ac auctor orci leo non est. Quisque id mi. Ut tincidunt tincidunt erat. Etiam feugiat lorem non metus. Vestibulum dapibus nunc ac augue. Curabitur vestibulum aliquam leo. Praesent egestas neque eu enim. In hac habitasse platea dictumst. Fusce a quam. Etiam ut purus mattis mauris sodales aliquam. Curabitur nisi. Quisque malesuada placerat nisl. Nam ipsum risus, rutrum vitae, vestibulum eu, molestie vel, lacus. Sed augue ipsum, egestas nec, vestibulum et, malesuada adipiscing, dui. Vestibulum facilisis, purus nec pulvinar iaculis, ligula mi congue nunc, vitae euismod ligula urna in dolor. Mauris sollicitudin fermentum libero. Praesent nonummy mi in odio. Nunc interdum lacus sit amet orci. Vestibulum rutrum, mi nec elementum vehicula, eros quam gravida nisl, id fringilla neque ante vel mi. Morbi mollis tellus ac sapien. Phasellus volutpat, metus eget egestas mollis, lacus lacus blandit dui, id egestas quam mauris ut lacus. Fusce vel dui. Sed in libero ut nibh placerat accumsan. Proin faucibus arcu quis ante. In consectetuer turpis ut velit. Nulla sit amet est. Praesent metus tellus, elementum eu, semper a, adipiscing nec, purus. Cras risus ipsum, faucibus ut, ullamcorper id, varius ac, leo. Suspendisse feugiat. Suspendisse enim turpis, dictum sed, iaculis a, condimentum nec, nisi. Praesent nec nisl a purus blandit viverra. Praesent ac massa at ligula laoreet iaculis. Nulla neque dolor, sagittis eget, iaculis quis, molestie non, velit. Mauris turpis nunc, blandit et, volutpat molestie, porta ut, ligula. Fusce pharetra convallis urna. Quisque ut nisi. Donec mi odio, faucibus at, scelerisque quis, convallis in, nisi. Suspendisse non nisl sit amet velit hendrerit rutrum. Ut leo. Ut a nisl id ante tempus hendrerit. Proin pretium, leo ac pellentesque mollis, felis nunc ultrices eros, sed gravida augue augue mollis justo. Suspendisse eu ligula. Nulla facilisi. Donec id justo. Praesent porttitor, nulla vitae posuere iaculis, arcu nisl dignissim dolor, a pretium mi sem ut ipsum. Curabitur suscipit suscipit tellus. Praesent vestibulum dapibus nibh. Etiam iaculis nunc ac metus. Ut id nisl quis enim dignissim sagittis. Etiam sollicitudin, ipsum eu pulvinar rutrum, tellus ipsum laoreet sapien, quis venenatis ante odio sit amet eros. Proin magna. Duis vel nibh at velit scelerisque suscipit. Curabitur turpis. Vestibulum suscipit nulla quis orci. Fusce ac felis sit amet ligula pharetra condimentum. Maecenas egestas arcu quis ligula mattis placerat. Duis lobortis massa imperdiet quam. Suspendisse potenti. Pellentesque commodo eros a enim. Vestibulum turpis sem, aliquet eget, lobortis pellentesque, rutrum eu, nisl. Sed libero. Aliquam erat volutpat. Etiam vitae tortor. Morbi vestibulum volutpat enim. Aliquam eu nunc. Nunc sed turpis. Sed mollis, eros et ultrices tempus, mauris ipsum aliquam libero, non adipiscing dolor urna a orci. Nulla porta dolor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Pellentesque dapibus hendrerit tortor. Praesent egestas tristique nibh. Sed a libero. Cras varius. Donec vitae orci sed dolor rutrum auctor. Fusce egestas elit eget lorem. Suspendisse nisl elit, rhoncus eget, elementum ac, condimentum eget, diam. Nam at tortor in tellus interdum sagittis. Aliquam lobortis. Donec orci lectus, aliquam ut, faucibus non, euismod id, nulla. Curabitur blandit mollis lacus. Nam adipiscing. Vestibulum eu odio. Vivamus laoreet. Nullam tincidunt adipiscing enim. Phasellus tempus. Proin viverra, ligula sit amet ultrices semper, ligula arcu tristique sapien, a accumsan nisi mauris ac eros. Fusce neque. Suspendisse faucibus, nunc et pellentesque egestas, lacus ante convallis tellus, vitae iaculis lacus elit id tortor. Vivamus aliquet elit ac nisl. Fusce fermentum odio nec arcu. Vivamus euismod mauris. In ut quam vitae odio lacinia tincidunt. Praesent ut ligula non mi varius sagittis. Cras sagittis. Praesent ac sem eget est egestas volutpat. Vivamus consectetuer hendrerit lacus. Cras non dolor. Vivamus in erat ut urna cursus vestibulum. Fusce commodo aliquam arcu. Nam commodo suscipit quam. Quisque id odio. Praesent venenatis metus at tortor pulvinar varius. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc, quis gravida magna mi a libero. Fusce vulputate eleifend sapien. Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Nullam accumsan lorem in dui. Cras ultricies mi eu turpis hendrerit fringilla. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; In ac dui quis mi consectetuer lacinia. Nam pretium turpis et arcu. Duis arcu tortor, suscipit eget, imperdiet nec, imperdiet iaculis, ipsum. Sed aliquam ultrices mauris. Integer ante arcu, accumsan a, consectetuer eget, posuere ut, mauris. Praesent adipiscing. Phasellus ullamcorper ipsum rutrum nunc. Nunc nonummy metus. Vestibulum volutpat pretium libero. Cras id dui. Aenean ut eros et nisl sagittis vestibulum. Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Sed lectus. Donec mollis hendrerit risus. Phasellus nec sem in justo pellentesque facilisis. Etiam imperdiet imperdiet orci. Nunc nec neque. Phasellus leo dolor, tempus non, auctor et, hendrerit quis, nisi. Curabitur ligula sapien, tincidunt non, euismod vitae, posuere imperdiet, leo. Maecenas malesuada. Praesent congue erat at massa. Sed cursus turpis vitae tortor. Donec posuere vulputate arcu. Phasellus accumsan cursus velit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed aliquam, nisi quis porttitor congue, elit erat euismod orci, ac placerat dolor lectus quis orci. Phasellus consectetuer vestibulum elit. Aenean tellus metus, bibendum sed, posuere ac, mattis non, nunc. Vestibulum fringilla pede sit amet augue. In turpis. Pellentesque posuere. Praesent turpis. Aenean posuere, tortor sed cursus feugiat, nunc augue blandit nunc, eu sollicitudin urna dolor sagittis lacus. Donec elit libero, sodales nec, volutpat a, suscipit non, turpis. Nullam sagittis. Suspendisse pulvinar, augue ac venenatis condimentum, sem libero volutpat nibh, nec pellentesque velit pede quis nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Fusce id purus. Ut varius tincidunt libero. Phasellus dolor. Maecenas vestibulum mollis diam. Pellentesque ut neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. In dui magna, posuere eget, vestibulum et, tempor auctor, justo. In ac felis quis tortor malesuada pretium. Pellentesque auctor neque nec urna. Proin sapien ipsum, porta a, auctor quis, euismod ut, mi. Aenean viverra rhoncus pede. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Ut non enim eleifend felis pretium feugiat. Vivamus quis mi. Phasellus a est. Phasellus magna. In hac habitasse platea dictumst. Curabitur at lacus ac velit ornare lobortis. Curabitur a felis in nunc fringilla tristique. Morbi mattis ullamcorper velit. Phasellus gravida semper nisi. Nullam vel sem. Pellentesque libero tortor, tincidunt et, tincidunt eget, semper nec, quam. Sed hendrerit. Morbi ac felis. Nunc egestas, augue at pellentesque laoreet, felis eros vehicula leo, at malesuada velit leo quis pede. Donec interdum, metus et hendrerit aliquet, dolor diam sagittis ligula, eget egestas libero turpis vel mi. Nunc nulla. Fusce risus nisl, viverra et, tempor et, pretium in, sapien. Donec venenatis vulputate lorem. Morbi nec metus. Phasellus blandit leo ut odio. Maecenas ullamcorper, dui et placerat feugiat, eros pede varius nisi, condimentum viverra felis nunc et lorem. Sed magna purus, fermentum eu, tincidunt eu,", "due_date":"2023-12-01" }, - "accountId": "0011e00000bWSxdAAG", - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + "accountId": "0011e00000bWSxdAAG" }, "mocks": {}, "output": { @@ -177,30 +150,10 @@ "code": "INVALID_PARAMS", "internal_error_identifier": "b_2", "param_errors": [ - { - "parameter": "description", - "param_error_identifier": "description_too_long", - "message": "Description too long. Please shorten and try again." - } + "description_too_long" ] } }, - { - "description": "Should fail when the cookie is invalid", - "input": { - "body": {}, - "accountId": "0011e00000bWSxdAAG", - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:invalid" - }, - "mocks": {}, - "output": { - "http_code": 401, - "message": "Unauthorized API request. Please check your API key.", - "code": "UNAUTHORIZED", - "internal_error_identifier": "l_ulca_vct_2", - "param_errors": [] - } - }, { "description": "Should fail when the account id invalid", "input": { @@ -209,8 +162,7 @@ "description":"Update remaining documentations", "due_date":"2023-12-01" }, - "accountId": "invalid", - "cookie": "1:00112233445566AAA1:SALESFORCE:1899000000:IbFOqqub193hajGqMDwrF41iUiKl8KJKWpmPl7oqX4eesrydP9cSx483f86OFK+dtSNAukoy+Tr7pRYsD3yVNw==" + "accountId": "invalid" }, "mocks": { "makeCompositeRequest": { From 7ab67077e5570edf57fac778b5b75848f413d70e Mon Sep 17 00:00:00 2001 From: amanbarbaria Date: Fri, 25 Aug 2023 14:44:42 +0530 Subject: [PATCH 090/195] Temp commit to test git workflow --- .../salessparrow/api/lib/globalConstants/SecretConstants.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java index b38b6269..a596760e 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java @@ -29,7 +29,7 @@ public class SecretConstants { */ // public static SecretsManagerClientBuilder secretsManagerClientBuilder = SecretsManagerClient.builder() // .credentialsProvider(InstanceProfileCredentialsProvider.builder().build()); - + public static SecretsManagerClientBuilder secretsManagerClientBuilder = SecretsManagerClient.builder(); /** @@ -52,6 +52,7 @@ public static String getSecret(String key) { cache.close(); } + System.out.println("================================secretJson: " + secretJson); ObjectMapper objectMapper = new ObjectMapper(); String specificValue = ""; try { From 6d785bd61c731df07952a5b5700a8864e2def653 Mon Sep 17 00:00:00 2001 From: amanbarbaria Date: Fri, 25 Aug 2023 14:49:51 +0530 Subject: [PATCH 091/195] Removed commented code and unused imports --- .../salessparrow/api/lib/globalConstants/SecretConstants.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java index a596760e..f5f74e59 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java @@ -13,7 +13,6 @@ import com.salessparrow.api.exception.CustomException; import com.salessparrow.api.lib.errorLib.ErrorObject; -import software.amazon.awssdk.auth.credentials.InstanceProfileCredentialsProvider; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClientBuilder; @@ -27,9 +26,6 @@ public class SecretConstants { /** * This is the builder that is going to be used to access the secrets manager. */ - // public static SecretsManagerClientBuilder secretsManagerClientBuilder = SecretsManagerClient.builder() - // .credentialsProvider(InstanceProfileCredentialsProvider.builder().build()); - public static SecretsManagerClientBuilder secretsManagerClientBuilder = SecretsManagerClient.builder(); /** From f4feb226ceec5197f34709d893a7c06c143cb386 Mon Sep 17 00:00:00 2001 From: amanbarbaria Date: Fri, 25 Aug 2023 14:55:49 +0530 Subject: [PATCH 092/195] remove temp test commit --- .../salessparrow/api/lib/globalConstants/SecretConstants.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java index f5f74e59..5317f640 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java @@ -48,7 +48,6 @@ public static String getSecret(String key) { cache.close(); } - System.out.println("================================secretJson: " + secretJson); ObjectMapper objectMapper = new ObjectMapper(); String specificValue = ""; try { From bd769a6b7b27ef2eb0308f7d69abe24255b72595 Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Fri, 25 Aug 2023 15:53:27 +0530 Subject: [PATCH 093/195] Updated SALESFORCE_ACTIVE_USER_COOKIE_VALUE name --- .../accountNoteController/DeleteAccountNoteTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountNoteController/DeleteAccountNoteTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountNoteController/DeleteAccountNoteTest.java index 3bbee4c1..8eb798d1 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountNoteController/DeleteAccountNoteTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountNoteController/DeleteAccountNoteTest.java @@ -82,7 +82,7 @@ public void deleteAccountNote(Scenario testScenario) throws Exception { // Read data from the scenario ObjectMapper objectMapper = new ObjectMapper(); - String cookieValue = Constants.SALESFORCE_ACTIVE_USET_COOKIE_VALUE; + String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; String accountId = (String) testScenario.getInput().get("accountId"); String noteId = (String) testScenario.getInput().get("noteId"); From 7e527fc8b0f869e062bb301896aac4ff7cbdab9f Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Fri, 25 Aug 2023 15:54:14 +0530 Subject: [PATCH 094/195] Updated SALESFORCE_ACTIVE_USER_COOKIE_VALUE name --- .../accountTaskController/GetAccountTasksListTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/GetAccountTasksListTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/GetAccountTasksListTest.java index 8287ca5b..0193f7e3 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/GetAccountTasksListTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/GetAccountTasksListTest.java @@ -82,7 +82,7 @@ public void getAccountTasksList(Scenario testScenario) throws Exception { // Read data from the scenario ObjectMapper objectMapper = new ObjectMapper(); - String cookieValue = Constants.SALESFORCE_ACTIVE_USET_COOKIE_VALUE; + String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; String accountId = (String) testScenario.getInput().get("accountId"); // Prepare mock responses From 60e4b87d08cf1cc4c37c28656df3fe1c86b470f5 Mon Sep 17 00:00:00 2001 From: Yagnik Thummar Date: Fri, 25 Aug 2023 16:02:34 +0530 Subject: [PATCH 095/195] Updated cookie value in test files. --- .../controllers/accountTaskController/CreateTaskTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/CreateTaskTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/CreateTaskTest.java index 339f9f4c..a4b64459 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/CreateTaskTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/CreateTaskTest.java @@ -82,7 +82,7 @@ public void createTask(Scenario testScenario) throws Exception { // Read data from the scenario ObjectMapper objectMapper = new ObjectMapper(); - String cookieValue = Constants.SALESFORCE_ACTIVE_USET_COOKIE_VALUE; + String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; String accountId = (String) testScenario.getInput().get("accountId"); // Prepare mock responses From 4fdf01077523ceed674d2dc40d3d312671aa1528 Mon Sep 17 00:00:00 2001 From: Yagnik Thummar Date: Fri, 25 Aug 2023 16:47:51 +0530 Subject: [PATCH 096/195] Updated Cookie value for testCases. --- .../GetCrmOrganizationUserListTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/salessparrow/api/functional/controllers/crmOrganizationUserController/GetCrmOrganizationUserListTest.java b/src/test/java/com/salessparrow/api/functional/controllers/crmOrganizationUserController/GetCrmOrganizationUserListTest.java index 5d59e89e..1ef99b81 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/crmOrganizationUserController/GetCrmOrganizationUserListTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/crmOrganizationUserController/GetCrmOrganizationUserListTest.java @@ -82,7 +82,7 @@ public void getCrmOrganizationUserList(Scenario testScenario) throws Exception { // Read data from the scenario ObjectMapper objectMapper = new ObjectMapper(); - String cookieValue = Constants.SALESFORCE_ACTIVE_USET_COOKIE_VALUE; + String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; String q = (String) testScenario.getInput().get("q"); // Prepare mock responses From 16f2e20c5f40a54059e064b440753eb93dcb4f52 Mon Sep 17 00:00:00 2001 From: amanbarbaria Date: Fri, 25 Aug 2023 16:59:50 +0530 Subject: [PATCH 097/195] Cache Docker Dependencies --- Dockerfile.local | 18 ++++++++++++++---- docker-compose.yml | 2 ++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Dockerfile.local b/Dockerfile.local index a87cfc83..1d9ad1e9 100644 --- a/Dockerfile.local +++ b/Dockerfile.local @@ -1,9 +1,19 @@ -FROM openjdk:17-jdk-alpine +# Use the openjdk 17 with alpine as a base image +FROM openjdk:17-jdk-alpine as builder +# Create and set the working directory inside the container RUN mkdir -p /app WORKDIR /app -COPY . /app +# Install bash for Alpine and other necessary tools +RUN apk add --no-cache bash maven -EXPOSE 8080 -RUN apk add --no-cache bash \ No newline at end of file +# Copy the pom.xml and download dependencies +COPY ./pom.xml ./pom.xml +RUN mvn dependency:go-offline + +# Copy the rest of the application +COPY ./ ./ + +# Expose the port 8080 for the application +EXPOSE 8080 \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 9f8347c3..ef4a3d10 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,6 +10,7 @@ services: - localdev volumes: - './:/app' + - '~/.m2:/root/.m2' environment: - ENVIRONMENT=development - AWS_ACCESS_KEY_ID=local @@ -31,6 +32,7 @@ services: - localdev volumes: - './:/app' + - '~/.m2:/root/.m2' environment: - ENVIRONMENT=local-test - AWS_ACCESS_KEY_ID=local From f31d0fe514416d926ea4ec09ebb6f027ac2027a7 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Fri, 25 Aug 2023 17:43:59 +0530 Subject: [PATCH 098/195] added release process md --- README.md | 9 +++-- RELEASE_PROCESS.md | 96 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 RELEASE_PROCESS.md diff --git a/README.md b/README.md index 6083592f..883254c4 100644 --- a/README.md +++ b/README.md @@ -3,13 +3,16 @@ This repository contains salessparrow apis. ## Local Setup -Please follow the steps in [LOCAL_SETUP](LOCAL_SETUP.md) to setup the project locally. +Follow the steps in [LOCAL_SETUP](LOCAL_SETUP.md) to setup the project locally. ## Environment Variables -Please refer to [ENVIRONMENT_VARS](ENVIRONMENT_VARS.md) for detailed descriptions for the environment variables. +Refer to [ENVIRONMENT_VARS](ENVIRONMENT_VARS.md) for detailed descriptions for the environment variables. ## Project Structure -Please refer to [PROJECT_STRUCTURE](PROJECT_STRUCTURE.md) for details on the project structure. +Refer to [PROJECT_STRUCTURE](PROJECT_STRUCTURE.md) for details on the project structure. + +## Release Process +Refer to [RELEASE_PROCESS](RELEASE_PROCESS.md) to ensure smooth and consistent software releases. This process outlines the steps to prepare, package, and distribute new versions of our software. ## License diff --git a/RELEASE_PROCESS.md b/RELEASE_PROCESS.md new file mode 100644 index 00000000..b7cc7189 --- /dev/null +++ b/RELEASE_PROCESS.md @@ -0,0 +1,96 @@ +# SalesSparrow APIs Release Process + +## Introduction + +**Objective:** Ensure that our open source backend repository is consistently and effectively updated, with full transparency to our community. Our agile approach, combined with a unique milestone branch system and continuous integration, strives to deliver high-quality updates in a structured manner. + +--- + +## **1. Pre-Release Planning** + +### **1.1 Sprint Planning** + +- At the beginning of each sprint, prioritize the GitHub issues to be addressed. +- Label issues with milestones corresponding to the anticipated release version (e.g., `v1.2.0`). +- Whenever a bug is discovered or a new feature needs to be implemented, an issue is created on GitHub. +- Issues are tagged appropriately (e.g., `bug`, `enhancement`, `documentation`) and are assigned to the relevant team members. + +### **1.2 Continuous Integration (CI)** + +- Ensure that any code pushed to the main branch passes through a CI pipeline, which includes lint checks, unit tests, integration tests, and other relevant checks. +- For each issue team members work on, they create a new branch from the `milestone` branch created for that milestone. e.g. `milestone/v1.2.0` +--- + +## **2. Release Candidate (RC)** + +### **2.1 Branching** + +- Create a release branch off the main branch named `release/vX.Y.Z` (where `X.Y.Z` is the release version) or use the `milestone` branch approach based on project conventions. +- Developers raise PRs against this branch (or the `milestone` branch if using that approach). PR titles and descriptions should be detailed, linking back to the original issue. + +### **2.2 Version Update** + +- Update the version in the project configuration or metadata files. + +### **2.3 Testing** + +- PRs will automatically trigger the CI workflow, ensuring that the combined changes from the entire milestone don't introduce any issues when integrated. +- Ensure that the release candidate is thoroughly tested. This may include: + - Regression Testing + - Performance Testing + - Security Scanning + - User Acceptance Testing (UAT) for significant features or changes + +### **2.4 Documentation** + +- Update the `CHANGELOG.md` or equivalent file with the details of the changes, enhancements, fixes, and any potential breaking changes. +- Ensure that all new features, enhancements, or changes are documented appropriately. + +--- + +## **3. Release** + +### **3.1 Merging** + +- Once the release candidate is deemed stable, merge the `release/vX.Y.Z` branch (or the `milestone` branch) into the `main` branch. +- Create a tagged commit on the main branch with the version number. + +### **3.2 GitHub Release** + +- On the GitHub repository, navigate to the "Releases" tab. +- Draft a new release, inputting the tag version, release title, and the notes from the `CHANGELOG.md`. +- Publish the release. This action will notify watchers and those who have starred the repository. + +### **3.3 Announcements** + +- Announce the new release on any relevant communication channels, such as the project's mailing list, Twitter, Discord, or other community platforms. + +--- + +## **4. Post-Release** + +### **4.1 Monitoring** + +- Monitor any feedback or issues reported by users related to the new release. + +### **4.2 Hotfixes** + +- If any critical issues or bugs are reported, prioritize and address them immediately. +- For significant bugs, create a hotfix branch off the main branch, apply the fix, and then merge it back into the main branch. +- Tag a new minor release version (e.g., `v1.2.1`) and follow the release steps as mentioned above. + +### **4.3 Sprint Retrospective** + +- At the end of the sprint or after the release, review the process and any feedback. +- Identify areas of improvement or optimization for the next release cycle. + +--- + +## **5. Best Practices** + +- **Transparency:** Ensure all decisions, issues, and discussions related to the release are public and transparent. +- **Communication:** Keep the community informed about release dates, anticipated changes, and any delays. +- **Documentation:** All features and changes should be well-documented to assist users and contributors. +- **Feedback Loop:** Encourage users to report bugs, issues, or provide feedback about the release. + +--- \ No newline at end of file From d1f1b20ae2f3568a15ff343c0c2ab84054d28116 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Fri, 25 Aug 2023 18:55:51 +0530 Subject: [PATCH 099/195] moved docs specific to repo to repo-docs --- README.md | 13 +++++++------ CODE_OF_CONDUCT.md => repo-docs/CODE_OF_CONDUCT.md | 0 CONTRIBUTING.md => repo-docs/CONTRIBUTING.md | 0 .../ENVIRONMENT_VARS.md | 0 LOCAL_SETUP.md => repo-docs/LOCAL_SETUP.md | 0 .../PROJECT_STRUCTURE.md | 3 +++ RELEASE_PROCESS.md => repo-docs/RELEASE_PROCESS.md | 0 7 files changed, 10 insertions(+), 6 deletions(-) rename CODE_OF_CONDUCT.md => repo-docs/CODE_OF_CONDUCT.md (100%) rename CONTRIBUTING.md => repo-docs/CONTRIBUTING.md (100%) rename ENVIRONMENT_VARS.md => repo-docs/ENVIRONMENT_VARS.md (100%) rename LOCAL_SETUP.md => repo-docs/LOCAL_SETUP.md (100%) rename PROJECT_STRUCTURE.md => repo-docs/PROJECT_STRUCTURE.md (95%) rename RELEASE_PROCESS.md => repo-docs/RELEASE_PROCESS.md (100%) diff --git a/README.md b/README.md index 883254c4..564c204d 100644 --- a/README.md +++ b/README.md @@ -3,23 +3,24 @@ This repository contains salessparrow apis. ## Local Setup -Follow the steps in [LOCAL_SETUP](LOCAL_SETUP.md) to setup the project locally. +Follow the steps in [LOCAL_SETUP](repo-docs/LOCAL_SETUP.md) to setup the project locally. ## Environment Variables -Refer to [ENVIRONMENT_VARS](ENVIRONMENT_VARS.md) for detailed descriptions for the environment variables. +Refer to [ENVIRONMENT_VARS](repo-docs/ENVIRONMENT_VARS.md) for detailed descriptions for the environment variables. ## Project Structure -Refer to [PROJECT_STRUCTURE](PROJECT_STRUCTURE.md) for details on the project structure. +Refer to [PROJECT_STRUCTURE](repo-docs/PROJECT_STRUCTURE.md) for details on the project structure. + ## Release Process -Refer to [RELEASE_PROCESS](RELEASE_PROCESS.md) to ensure smooth and consistent software releases. This process outlines the steps to prepare, package, and distribute new versions of our software. +Refer to [RELEASE_PROCESS](repo-docs/RELEASE_PROCESS.md) to ensure smooth and consistent software releases. This process outlines the steps to prepare, package, and distribute new versions of our software. ## License This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. ## Contributing -Contributions to the project are welcome! Please see our guidelines on how to [CONTRIBUTE](CONTRIBUTING.md). +Contributions to the project are welcome! Please see our guidelines on how to [CONTRIBUTE](repo-docs/CONTRIBUTING.md). ## Code of Conduct -This project has a code of conduct that outlines expected behavior for contributors and users. Please read the [CODE_OF_CONDUCT](CODE_OF_CONDUCT.md) file before getting involved. \ No newline at end of file +This project has a code of conduct that outlines expected behavior for contributors and users. Please read the [CODE_OF_CONDUCT](repo-docs/CODE_OF_CONDUCT.md) file before getting involved. \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/repo-docs/CODE_OF_CONDUCT.md similarity index 100% rename from CODE_OF_CONDUCT.md rename to repo-docs/CODE_OF_CONDUCT.md diff --git a/CONTRIBUTING.md b/repo-docs/CONTRIBUTING.md similarity index 100% rename from CONTRIBUTING.md rename to repo-docs/CONTRIBUTING.md diff --git a/ENVIRONMENT_VARS.md b/repo-docs/ENVIRONMENT_VARS.md similarity index 100% rename from ENVIRONMENT_VARS.md rename to repo-docs/ENVIRONMENT_VARS.md diff --git a/LOCAL_SETUP.md b/repo-docs/LOCAL_SETUP.md similarity index 100% rename from LOCAL_SETUP.md rename to repo-docs/LOCAL_SETUP.md diff --git a/PROJECT_STRUCTURE.md b/repo-docs/PROJECT_STRUCTURE.md similarity index 95% rename from PROJECT_STRUCTURE.md rename to repo-docs/PROJECT_STRUCTURE.md index 71eb05d4..1523242f 100644 --- a/PROJECT_STRUCTURE.md +++ b/repo-docs/PROJECT_STRUCTURE.md @@ -29,6 +29,9 @@ This is a Markdown file that usually contains important information about your p This directory serves as a submodule linked to [ai-salesparrow-docs](https://github.com/TrueSparrowSystems/AI-SalesSparrow-docs) repository that holds comprehensive documentation for the project. Instead of duplicating documentation within the main repository, this submodule approach allows you to maintain documentation separately, ensuring consistency and easier management. +### repo-docs/ +This directory contains documentation that serves as a reference for various aspects of the project. This directory is intended to store informative documents that provide insights, explanations, and guidelines related to the project. + ## src/ Directory: ``` diff --git a/RELEASE_PROCESS.md b/repo-docs/RELEASE_PROCESS.md similarity index 100% rename from RELEASE_PROCESS.md rename to repo-docs/RELEASE_PROCESS.md From 3cabb590c6fb9ba1f9cc16bf3ab1483c6b29f8a9 Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Fri, 25 Aug 2023 19:01:36 +0530 Subject: [PATCH 100/195] Moved assertCustomEquals to common method --- .../accountNoteController/DeleteAccountNoteTest.java | 12 +----------- .../java/com/salessparrow/api/helper/Common.java | 10 ++++++++++ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountNoteController/DeleteAccountNoteTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountNoteController/DeleteAccountNoteTest.java index 8eb798d1..51f0833e 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountNoteController/DeleteAccountNoteTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountNoteController/DeleteAccountNoteTest.java @@ -101,7 +101,7 @@ public void deleteAccountNote(Scenario testScenario) throws Exception { // Check the response String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); - assertCustomEquals(expectedOutput, actualOutput); + common.assertCustomEquals(expectedOutput, actualOutput); } static Stream testScenariosProvider() throws IOException { @@ -115,14 +115,4 @@ private static List loadScenarios() throws IOException { ObjectMapper objectMapper = new ObjectMapper(); return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); } - - // Custom assertion method that treats and <> as the same - public static void assertCustomEquals(String expected, String actual) { - - if (expected.equals("{}")) { - expected = ""; - } - - assertEquals(expected, actual); - } } diff --git a/src/test/java/com/salessparrow/api/helper/Common.java b/src/test/java/com/salessparrow/api/helper/Common.java index ed8a65ff..45ff3eda 100644 --- a/src/test/java/com/salessparrow/api/helper/Common.java +++ b/src/test/java/com/salessparrow/api/helper/Common.java @@ -78,4 +78,14 @@ public void compareErrors(Scenario testDataItem, String contentAsString) throws } } } + + // Custom assertion method that treats {} and "" as the same + public void assertCustomEquals(String expected, String actual) { + + if (expected.equals("{}")) { + expected = ""; + } + + assertEquals(expected, actual); + } } From 0a6ada79684e2e8b555af63edbd5c21c33b34aa9 Mon Sep 17 00:00:00 2001 From: amanbarbaria Date: Fri, 25 Aug 2023 19:01:38 +0530 Subject: [PATCH 101/195] 1. Added unit test cases for UserConstants file 2. Added unit test cases for SalesforceConstants file --- .../lib/globalConstants/UserConstants.java | 5 ++ .../SalesforceConstantsTest.java | 78 +++++++++++++++++++ .../globalConstants/UserConstantsTest.java | 24 ++++++ 3 files changed, 107 insertions(+) create mode 100644 src/test/java/com/salessparrow/api/unit/globalConstants/SalesforceConstantsTest.java create mode 100644 src/test/java/com/salessparrow/api/unit/globalConstants/UserConstantsTest.java diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/UserConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/UserConstants.java index 773e26f4..e6d4cb08 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/UserConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/UserConstants.java @@ -5,4 +5,9 @@ */ public class UserConstants { public static final String SALESFORCE_USER_KIND = "SALESFORCE"; + + // Private constructor to prevent instantiation + private UserConstants() { + throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); + } } diff --git a/src/test/java/com/salessparrow/api/unit/globalConstants/SalesforceConstantsTest.java b/src/test/java/com/salessparrow/api/unit/globalConstants/SalesforceConstantsTest.java new file mode 100644 index 00000000..2dbd72a6 --- /dev/null +++ b/src/test/java/com/salessparrow/api/unit/globalConstants/SalesforceConstantsTest.java @@ -0,0 +1,78 @@ +package com.salessparrow.api.unit.globalConstants; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; +import com.salessparrow.api.lib.globalConstants.SalesforceConstants; + +public class SalesforceConstantsTest { + + @Test + void testCompositeUrlPath() { + assertEquals("/services/data/v58.0/composite", new SalesforceConstants().compositeUrlPath()); + } + + @Test + void testQueryUrlPath() { + assertEquals("/services/data/v58.0/query/?q=", new SalesforceConstants().queryUrlPath()); + } + + @Test + void testSObjectsPath() { + assertEquals("/services/data/v58.0/sobjects", new SalesforceConstants().sObjectsPath()); + } + + @Test + void testSalesforceCompositeUrl() { + assertEquals("https://test.salesforce.com/services/data/v58.0/composite", new SalesforceConstants().salesforceCompositeUrl("https://test.salesforce.com")); + } + + @Test + void testOauth2AuthorizeUrl() { + assertEquals("https://test.salesforce.com/services/oauth2/authorize", new SalesforceConstants().oauth2AuthorizeUrl()); + } + + @Test + void testOauth2Url() { + assertEquals("https://test.salesforce.com/services/oauth2/token", new SalesforceConstants().oauth2Url()); + } + + @Test + void testSalesforceCreateNoteUrl() { + assertEquals("/services/data/v58.0/sobjects/ContentNote", new SalesforceConstants().salesforceCreateNoteUrl()); + } + + @Test + void testSalesforceAttachNoteUrl() { + assertEquals("/services/data/v58.0/sobjects/ContentDocumentLink", new SalesforceConstants().salesforceAttachNoteUrl()); + } + + @Test + void testIdentityUrl() { + assertEquals("/services/oauth2/userinfo", new SalesforceConstants().identityUrl()); + } + + @Test + void testAuthorizationCodeGrantType() { + assertEquals("authorization_code", new SalesforceConstants().authorizationCodeGrantType()); + } + + @Test + void testRefreshTokenGrantType() { + assertEquals("refresh_token", new SalesforceConstants().refreshTokenGrantType()); + } + + @Test + void testTimeoutMillis() { + assertEquals(10000, new SalesforceConstants().timeoutMillis()); + } + + @Test + void testSalesforceNotesContentUrl() { + assertEquals("https://test.salesforce.com/services/data/v58.0/sobjects/ContentNote/123/Content", new SalesforceConstants().salesforceNotesContentUrl("https://test.salesforce.com", "123")); + } + + @Test + void testSalesforceCreateTaskUrl() { + assertEquals("/services/data/v58.0/sobjects/Task", new SalesforceConstants().salesforceCreateTaskUrl()); + } +} diff --git a/src/test/java/com/salessparrow/api/unit/globalConstants/UserConstantsTest.java b/src/test/java/com/salessparrow/api/unit/globalConstants/UserConstantsTest.java new file mode 100644 index 00000000..6b7f19a3 --- /dev/null +++ b/src/test/java/com/salessparrow/api/unit/globalConstants/UserConstantsTest.java @@ -0,0 +1,24 @@ +package com.salessparrow.api.unit.globalConstants; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.Test; +import com.salessparrow.api.lib.globalConstants.UserConstants; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +public class UserConstantsTest { + @Test + void testGetName() { + assertEquals("SALESFORCE", UserConstants.SALESFORCE_USER_KIND); + } + + @Test + void testPrivateConstructor() throws NoSuchMethodException, IllegalAccessException, InstantiationException { + Constructor constructor = UserConstants.class.getDeclaredConstructor(); + constructor.setAccessible(true); + assertThrows(InvocationTargetException.class, constructor::newInstance); + } + +} From 245acb33cd4f9e4a434d5fa7b73ae4882d4346c5 Mon Sep 17 00:00:00 2001 From: amanbarbaria Date: Fri, 25 Aug 2023 19:11:39 +0530 Subject: [PATCH 102/195] Clear cache on every test case start --- src/test/java/com/salessparrow/api/helper/Setup.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/salessparrow/api/helper/Setup.java b/src/test/java/com/salessparrow/api/helper/Setup.java index c7df5374..a8b474a6 100644 --- a/src/test/java/com/salessparrow/api/helper/Setup.java +++ b/src/test/java/com/salessparrow/api/helper/Setup.java @@ -1,5 +1,6 @@ package com.salessparrow.api.helper; +import org.springframework.cache.CacheManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -8,6 +9,7 @@ import com.github.dynamobee.Dynamobee; import com.github.dynamobee.exception.DynamobeeException; +import com.salessparrow.api.lib.globalConstants.CacheConstants; /** * This class is used to create the setup. @@ -24,6 +26,9 @@ public class Setup { @Autowired private Dynamobee dynamobee; + @Autowired + private CacheManager cacheManager; + /** * Create the setup. * - Flush the cache @@ -44,7 +49,9 @@ public void perform() throws DynamobeeException { */ private void flushCache(){ logger.info("Setup: Flushing cache"); - } + cacheManager.getCacheNames().stream().forEach(cacheName -> { + cacheManager.getCache(cacheName).clear(); + }); } /** * Drop dynamodb tables. From 283903f825214112a727deaf5cf1cbc7e2924fd9 Mon Sep 17 00:00:00 2001 From: Yagnik Thummar Date: Fri, 25 Aug 2023 20:28:28 +0530 Subject: [PATCH 103/195] Code review changes: - sanitize params on soql queries. --- .../java/com/salessparrow/api/lib/Util.java | 34 +++++++++++++++++++ .../helper/SalesforceQueryBuilder.java | 24 ++++++++++++- .../accounts/GetAccountListService.java | 23 +------------ .../GetCrmOrganizationUsersList.java | 23 +------------ .../salessparrow/api/unit/lib/UtilTest.java | 32 +++++++++++++++++ 5 files changed, 91 insertions(+), 45 deletions(-) create mode 100644 src/test/java/com/salessparrow/api/unit/lib/UtilTest.java diff --git a/src/main/java/com/salessparrow/api/lib/Util.java b/src/main/java/com/salessparrow/api/lib/Util.java index 65c341fe..0139c418 100644 --- a/src/main/java/com/salessparrow/api/lib/Util.java +++ b/src/main/java/com/salessparrow/api/lib/Util.java @@ -1,5 +1,8 @@ package com.salessparrow.api.lib; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; + import org.springframework.stereotype.Component; import com.fasterxml.jackson.databind.JsonNode; @@ -61,4 +64,35 @@ public static String generateHeaderLogString(HttpServletRequest request) { return headerBuilder.toString(); } + + /** + * Escape special characters in a string for use in a regular expression. + * + * @param input + * + * @return String + */ + public static String escapeSpecialChars(String input) { + String[] specialChars = {"\\", "%", "'", "\"", "_"}; + + for (String specialChar : specialChars) { + input = input.replace(specialChar, "\\" + specialChar); + } + + return input; + } + + public static String urlEncoder(String input){ + try { + return URLEncoder.encode(input, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new CustomException( + new ErrorObject( + "u_u_ue_1", + "something_went_wrong", + e.getMessage() + ) + ); + } + } } diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java index 3bfe3c36..d8c7627f 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java @@ -4,11 +4,22 @@ import org.springframework.stereotype.Component; +import com.salessparrow.api.lib.Util; + /** * SalesforceQueries is a class for building the Salesforce queries. */ @Component public class SalesforceQueryBuilder { + public String formatStringForSoqlQueries(String input){ + // escaping special characters of SOQL queries Like ( ', ", \, %, _) + input = Util.escapeSpecialChars(input); + + // encoding the input to UrlEncoder + input = Util.urlEncoder(input); + + return input; + } /** * Get the list of accounts for a given searchTerm @@ -21,6 +32,8 @@ public String getAccountsQuery(String searchTerm) { if (searchTerm == "") { return "SELECT Id, Name FROM Account ORDER BY LastModifiedDate DESC LIMIT 20"; } + searchTerm = formatStringForSoqlQueries(searchTerm); + return "SELECT Id, Name FROM Account WHERE Name LIKE '%25"+searchTerm+"%25' ORDER BY LastModifiedDate DESC LIMIT 20"; } @@ -31,6 +44,8 @@ public String getAccountsQuery(String searchTerm) { * @return String */ public String getContentDocumentIdUrl(String accountId) { + accountId = Util.urlEncoder(accountId); + return "SELECT ContentDocumentId FROM ContentDocumentLink WHERE LinkedEntityId = '" + accountId + "'"; } @@ -44,11 +59,14 @@ public String getContentDocumentIdUrl(String accountId) { public String getNoteListIdUrl(List documentIds) { StringBuilder queryBuilder = new StringBuilder( "SELECT Id, Title, TextPreview, CreatedBy.Name, LastModifiedDate FROM ContentNote WHERE Id IN ("); + for (int i = 0; i < documentIds.size(); i++) { if (i > 0) { queryBuilder.append(", "); } - queryBuilder.append("'").append(documentIds.get(i)).append("'"); + + String documentId = Util.urlEncoder(documentIds.get(i)); + queryBuilder.append("'").append(documentId).append("'"); } queryBuilder.append(") ORDER BY LastModifiedDate DESC LIMIT 5"); @@ -56,6 +74,8 @@ public String getNoteListIdUrl(List documentIds) { } public String getNoteDetailsUrl(String noteId){ + noteId = Util.urlEncoder(noteId); + return "SELECT Id, Title, TextPreview, CreatedBy.Name, LastModifiedDate FROM ContentNote WHERE Id = '" + noteId + "'"; } @@ -63,6 +83,8 @@ public String getCrmOrganizationUsersQuery(String searchTerm) { if (searchTerm == "") { return "SELECT Id, Name FROM User ORDER BY LastModifiedDate DESC LIMIT 20"; } + searchTerm = formatStringForSoqlQueries(searchTerm); + return "SELECT Id, Name FROM User WHERE Name LIKE '%25"+searchTerm+"%25' ORDER BY LastModifiedDate DESC LIMIT 20"; } diff --git a/src/main/java/com/salessparrow/api/services/accounts/GetAccountListService.java b/src/main/java/com/salessparrow/api/services/accounts/GetAccountListService.java index a4182771..dcf775df 100644 --- a/src/main/java/com/salessparrow/api/services/accounts/GetAccountListService.java +++ b/src/main/java/com/salessparrow/api/services/accounts/GetAccountListService.java @@ -1,19 +1,12 @@ package com.salessparrow.api.services.accounts; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.List; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.salessparrow.api.domain.User; import com.salessparrow.api.dto.formatter.GetAccountsFormatterDto; import com.salessparrow.api.dto.requestMapper.GetAccountsDto; -import com.salessparrow.api.exception.CustomException; import com.salessparrow.api.lib.crmActions.getAccounts.GetAccountsFactory; -import com.salessparrow.api.lib.errorLib.ParamErrorObject; import jakarta.servlet.http.HttpServletRequest; @@ -44,20 +37,6 @@ public GetAccountsFormatterDto getAccounts(HttpServletRequest request, GetAccoun private String formatSearchString(String q) { q = q.trim(); - try { - return URLEncoder.encode(q, "UTF-8"); - } catch (UnsupportedEncodingException e) { - - List paramError = new ArrayList<>(); - paramError.add("invalid_search_term"); - - throw new CustomException( - new ParamErrorObject( - "s_a_gals_fss", - e.getMessage(), - paramError - ) - ); - } + return q; } } diff --git a/src/main/java/com/salessparrow/api/services/crmOrganizationUsers/GetCrmOrganizationUsersList.java b/src/main/java/com/salessparrow/api/services/crmOrganizationUsers/GetCrmOrganizationUsersList.java index 8d663ff7..a873f2d5 100644 --- a/src/main/java/com/salessparrow/api/services/crmOrganizationUsers/GetCrmOrganizationUsersList.java +++ b/src/main/java/com/salessparrow/api/services/crmOrganizationUsers/GetCrmOrganizationUsersList.java @@ -1,10 +1,5 @@ package com.salessparrow.api.services.crmOrganizationUsers; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.List; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -13,10 +8,7 @@ import com.salessparrow.api.domain.User; import com.salessparrow.api.dto.formatter.GetCrmOrganizationUsersFormatterDto; import com.salessparrow.api.dto.requestMapper.GetCrmOrganizationUsersDto; -import com.salessparrow.api.exception.CustomException; import com.salessparrow.api.lib.crmActions.getCrmOrganizationUsers.GetCrmOrganizationUsersFactory; -import com.salessparrow.api.lib.errorLib.ParamErrorObject; - import jakarta.servlet.http.HttpServletRequest; /** @@ -61,21 +53,8 @@ public GetCrmOrganizationUsersFormatterDto getCrmOrganizationUsers(HttpServletRe private String formatSearchString(String searchTerm) { logger.info("format and sanitize search term"); searchTerm = searchTerm.trim(); - try { - return URLEncoder.encode(searchTerm,"UTF-8"); - } catch (UnsupportedEncodingException e) { - List paramError = new ArrayList<>(); - paramError.add("invalid_search_term"); - - throw new CustomException( - new ParamErrorObject( - "s_cou_gcoul_fss", - e.getMessage(), - paramError - ) - ); - } + return searchTerm; } } diff --git a/src/test/java/com/salessparrow/api/unit/lib/UtilTest.java b/src/test/java/com/salessparrow/api/unit/lib/UtilTest.java new file mode 100644 index 00000000..4af3f629 --- /dev/null +++ b/src/test/java/com/salessparrow/api/unit/lib/UtilTest.java @@ -0,0 +1,32 @@ +package com.salessparrow.api.unit.lib; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +import com.salessparrow.api.lib.Util; + +public class UtilTest { + + @Test + public void testEscapeSpecialChars() { + String[] inputStrings = {"\\a","%a","_a","'a","\"a"}; + String[] expectedOutputs = {"\\\\a","\\%a","\\_a","\\'a","\\\"a"}; + + for(int i = 0; i < inputStrings.length; i++) { + String result = Util.escapeSpecialChars(inputStrings[i]); + assertEquals(expectedOutputs[i], result); + } + } + + @Test + public void testUrlEncoder() { + String[] inputStrings = {"\\\\a","\\%a","\\_a","\\'a","\\\"a","a+b","a b"}; + String[] expectedOutputs = {"%5C%5Ca","%5C%25a","%5C_a","%5C%27a","%5C%22a","a%2Bb","a+b"}; + + for(int i = 0; i < inputStrings.length; i++) { + String result = Util.urlEncoder(inputStrings[i]); + assertEquals(expectedOutputs[i], result); + } + } +} From aa4a5f3353d89575202e43c066afaf656b973902 Mon Sep 17 00:00:00 2001 From: VRDighe Date: Fri, 25 Aug 2023 20:48:14 +0530 Subject: [PATCH 104/195] Added get accounts feed API --- .../api/controllers/AccountController.java | 61 ++++--- .../AccountContactAssociationsEntity.java | 14 ++ .../api/dto/entities/AccountEntity.java | 8 + .../api/dto/entities/ContactEntity.java | 16 ++ .../dto/entities/NextPagePayloadEntity.java | 12 ++ .../formatter/GetAccountsFormatterDto.java | 4 + .../PaginationIdentifierFormatterDto.java | 8 + .../dto/requestMapper/GetAccountsFeedDto.java | 15 ++ .../GetAccountListResponseDto.java | 18 ++ .../GetAccountsFeedResponseDto.java | 24 +++ .../java/com/salessparrow/api/lib/Util.java | 68 +++++-- .../crmActions/getAccounts/GetAccounts.java | 2 +- .../getAccounts/GetAccountsFactory.java | 14 +- .../getAccounts/GetSalesforceAccounts.java | 67 +++++-- .../lib/globalConstants/AccountConstants.java | 7 + .../salesforce/dto/SalesforceAccountDto.java | 56 +++++- .../helper/SalesforceQueryBuilder.java | 26 ++- .../accounts/GetAccountListService.java | 30 ++- .../accounts/GetAccountsFeedService.java | 116 ++++++++++++ .../resources/config/ParamErrorConfig.json | 5 + .../accountController/GetAccountListTest.java | 25 +-- .../GetAccountsFeedTest.java | 165 +++++++++++++++++ .../salessparrow/api/unit/lib/UtilTest.java | 91 ++++++++++ .../getAccountList.scenarios.json | 36 ++-- .../getAccountsFeed.scenarios.json | 171 ++++++++++++++++++ .../getAccountsFeed.fixtures.json | 14 ++ 26 files changed, 976 insertions(+), 97 deletions(-) create mode 100644 src/main/java/com/salessparrow/api/dto/entities/AccountContactAssociationsEntity.java create mode 100644 src/main/java/com/salessparrow/api/dto/entities/ContactEntity.java create mode 100644 src/main/java/com/salessparrow/api/dto/entities/NextPagePayloadEntity.java create mode 100644 src/main/java/com/salessparrow/api/dto/formatter/PaginationIdentifierFormatterDto.java create mode 100644 src/main/java/com/salessparrow/api/dto/requestMapper/GetAccountsFeedDto.java create mode 100644 src/main/java/com/salessparrow/api/dto/responseMapper/GetAccountListResponseDto.java create mode 100644 src/main/java/com/salessparrow/api/dto/responseMapper/GetAccountsFeedResponseDto.java create mode 100644 src/main/java/com/salessparrow/api/lib/globalConstants/AccountConstants.java create mode 100644 src/main/java/com/salessparrow/api/services/accounts/GetAccountsFeedService.java create mode 100644 src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountsFeedTest.java create mode 100644 src/test/java/com/salessparrow/api/unit/lib/UtilTest.java create mode 100644 src/test/resources/data/controllers/accountController/getAccountsFeed.scenarios.json create mode 100644 src/test/resources/fixtures/controllers/accountController/getAccountsFeed.fixtures.json diff --git a/src/main/java/com/salessparrow/api/controllers/AccountController.java b/src/main/java/com/salessparrow/api/controllers/AccountController.java index 44058227..412bf2c2 100644 --- a/src/main/java/com/salessparrow/api/controllers/AccountController.java +++ b/src/main/java/com/salessparrow/api/controllers/AccountController.java @@ -13,13 +13,16 @@ import org.springframework.web.bind.annotation.RestController; import com.salessparrow.api.dto.formatter.CreateNoteFormatterDto; -import com.salessparrow.api.dto.formatter.GetAccountsFormatterDto; import com.salessparrow.api.dto.formatter.GetNoteDetailsFormatterDto; import com.salessparrow.api.dto.formatter.GetNotesListFormatterDto; import com.salessparrow.api.dto.requestMapper.GetAccountsDto; +import com.salessparrow.api.dto.requestMapper.GetAccountsFeedDto; import com.salessparrow.api.dto.requestMapper.NoteDto; +import com.salessparrow.api.dto.responseMapper.GetAccountListResponseDto; +import com.salessparrow.api.dto.responseMapper.GetAccountsFeedResponseDto; import com.salessparrow.api.services.accounts.CreateNoteService; import com.salessparrow.api.services.accounts.GetAccountListService; +import com.salessparrow.api.services.accounts.GetAccountsFeedService; import com.salessparrow.api.services.accounts.GetNoteDetailsService; import com.salessparrow.api.services.accounts.GetNotesListService; @@ -36,6 +39,9 @@ public class AccountController { @Autowired private GetAccountListService getAccountListService; + @Autowired + private GetAccountsFeedService getAccountsFeedService; + @Autowired private GetNotesListService getNotesListService; @@ -45,45 +51,56 @@ public class AccountController { @Autowired private CreateNoteService createNoteService; - @PostMapping("/{account_id}/notes") - public ResponseEntity addNoteToAccount( - HttpServletRequest request, - @PathVariable("account_id") String accountId, - @Valid @RequestBody NoteDto note - ) { - CreateNoteFormatterDto createNoteFormatterDto = createNoteService.createNote(request, accountId, note); + @GetMapping("") + public ResponseEntity getAccounts( + HttpServletRequest request, + @Valid @ModelAttribute GetAccountsDto getAccountsDto) { + logger.info("Request received"); - return ResponseEntity.ok().body(createNoteFormatterDto); + GetAccountListResponseDto getAccountsResponse = getAccountListService.getAccounts(request, getAccountsDto); + + return ResponseEntity.ok().body(getAccountsResponse); } - @GetMapping("") - public ResponseEntity getAccounts( - HttpServletRequest request, - @Valid @ModelAttribute GetAccountsDto getAccountsDto) { + @GetMapping("/feed") + public ResponseEntity getFeed( + HttpServletRequest request, + @Valid @ModelAttribute GetAccountsFeedDto getAccountsFeedDto) { logger.info("Request received"); - GetAccountsFormatterDto getAccountsResponse = getAccountListService.getAccounts(request, getAccountsDto); + GetAccountsFeedResponseDto getAccountsFeedResponse = getAccountsFeedService.getAccountsFeed(request, + getAccountsFeedDto); - return ResponseEntity.ok().body(getAccountsResponse); + return ResponseEntity.ok().body(getAccountsFeedResponse); + } + + @PostMapping("/{account_id}/notes") + public ResponseEntity addNoteToAccount( + HttpServletRequest request, + @PathVariable("account_id") String accountId, + @Valid @RequestBody NoteDto note) { + CreateNoteFormatterDto createNoteFormatterDto = createNoteService.createNote(request, accountId, note); + + return ResponseEntity.ok().body(createNoteFormatterDto); } @GetMapping("/{account_id}/notes") - public ResponseEntity getNotesList(HttpServletRequest request,@PathVariable("account_id") String accountId) { + public ResponseEntity getNotesList(HttpServletRequest request, + @PathVariable("account_id") String accountId) { GetNotesListFormatterDto getNotesListResponse = getNotesListService.getNotesList(request, accountId); return ResponseEntity.ok().body(getNotesListResponse); } - + @GetMapping("/{account_id}/notes/{note_id}") public ResponseEntity getNoteFromAccount( - HttpServletRequest request, - @PathVariable("account_id") String accountId, - @PathVariable("note_id") String noteId - ) { + HttpServletRequest request, + @PathVariable("account_id") String accountId, + @PathVariable("note_id") String noteId) { GetNoteDetailsFormatterDto getNoteDetailsResponse = getNoteDetailsService.getNoteDetails(request, noteId); - + return ResponseEntity.ok().body(getNoteDetailsResponse); } } diff --git a/src/main/java/com/salessparrow/api/dto/entities/AccountContactAssociationsEntity.java b/src/main/java/com/salessparrow/api/dto/entities/AccountContactAssociationsEntity.java new file mode 100644 index 00000000..fcd8748b --- /dev/null +++ b/src/main/java/com/salessparrow/api/dto/entities/AccountContactAssociationsEntity.java @@ -0,0 +1,14 @@ +package com.salessparrow.api.dto.entities; + +import java.util.List; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; + +import lombok.Data; + +@Data +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) +public class AccountContactAssociationsEntity { + private List contactIds; +} diff --git a/src/main/java/com/salessparrow/api/dto/entities/AccountEntity.java b/src/main/java/com/salessparrow/api/dto/entities/AccountEntity.java index 49b615f9..0c1d335a 100644 --- a/src/main/java/com/salessparrow/api/dto/entities/AccountEntity.java +++ b/src/main/java/com/salessparrow/api/dto/entities/AccountEntity.java @@ -1,9 +1,17 @@ package com.salessparrow.api.dto.entities; +import java.util.Map; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; + import lombok.Data; @Data +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) public class AccountEntity { private String id; private String name; + private Map additionalFields; + private String accountContactAssociationsId; } \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/dto/entities/ContactEntity.java b/src/main/java/com/salessparrow/api/dto/entities/ContactEntity.java new file mode 100644 index 00000000..02671352 --- /dev/null +++ b/src/main/java/com/salessparrow/api/dto/entities/ContactEntity.java @@ -0,0 +1,16 @@ +package com.salessparrow.api.dto.entities; + +import java.util.Map; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; + +import lombok.Data; + +@Data +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) +public class ContactEntity { + private String id; + private String name; + private Map additionalFields; +} diff --git a/src/main/java/com/salessparrow/api/dto/entities/NextPagePayloadEntity.java b/src/main/java/com/salessparrow/api/dto/entities/NextPagePayloadEntity.java new file mode 100644 index 00000000..8ccaa68e --- /dev/null +++ b/src/main/java/com/salessparrow/api/dto/entities/NextPagePayloadEntity.java @@ -0,0 +1,12 @@ +package com.salessparrow.api.dto.entities; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; + +import lombok.Data; + +@Data +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) +public class NextPagePayloadEntity { + private String paginationIdentifier; +} diff --git a/src/main/java/com/salessparrow/api/dto/formatter/GetAccountsFormatterDto.java b/src/main/java/com/salessparrow/api/dto/formatter/GetAccountsFormatterDto.java index 7a0db924..5389772d 100644 --- a/src/main/java/com/salessparrow/api/dto/formatter/GetAccountsFormatterDto.java +++ b/src/main/java/com/salessparrow/api/dto/formatter/GetAccountsFormatterDto.java @@ -7,11 +7,15 @@ import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.salessparrow.api.dto.entities.AccountContactAssociationsEntity; import com.salessparrow.api.dto.entities.AccountEntity; +import com.salessparrow.api.dto.entities.ContactEntity; @Data @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) public class GetAccountsFormatterDto { private List accountIds; private Map accountMapById; + private Map contactMapById; + private Map accountContactAssociationsMapById; } \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/dto/formatter/PaginationIdentifierFormatterDto.java b/src/main/java/com/salessparrow/api/dto/formatter/PaginationIdentifierFormatterDto.java new file mode 100644 index 00000000..7e7b1edd --- /dev/null +++ b/src/main/java/com/salessparrow/api/dto/formatter/PaginationIdentifierFormatterDto.java @@ -0,0 +1,8 @@ +package com.salessparrow.api.dto.formatter; + +import lombok.Data; + +@Data +public class PaginationIdentifierFormatterDto { + private Integer pageNumber; +} diff --git a/src/main/java/com/salessparrow/api/dto/requestMapper/GetAccountsFeedDto.java b/src/main/java/com/salessparrow/api/dto/requestMapper/GetAccountsFeedDto.java new file mode 100644 index 00000000..8348f4de --- /dev/null +++ b/src/main/java/com/salessparrow/api/dto/requestMapper/GetAccountsFeedDto.java @@ -0,0 +1,15 @@ +package com.salessparrow.api.dto.requestMapper; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies.LowerCamelCaseStrategy; +import com.fasterxml.jackson.databind.annotation.JsonNaming; + +import jakarta.validation.constraints.Pattern; +import lombok.Data; + +@Data +@JsonNaming(LowerCamelCaseStrategy.class) +public class GetAccountsFeedDto { + + @Pattern(regexp = "^[A-Za-z0-9+/]*={0,2}$", message = "invalid_pagination_identifier") + private String pagination_identifier; +} diff --git a/src/main/java/com/salessparrow/api/dto/responseMapper/GetAccountListResponseDto.java b/src/main/java/com/salessparrow/api/dto/responseMapper/GetAccountListResponseDto.java new file mode 100644 index 00000000..c2c07ccc --- /dev/null +++ b/src/main/java/com/salessparrow/api/dto/responseMapper/GetAccountListResponseDto.java @@ -0,0 +1,18 @@ +package com.salessparrow.api.dto.responseMapper; + +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.salessparrow.api.dto.entities.AccountEntity; + +import lombok.Data; + +@Data +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) +public class GetAccountListResponseDto { + + private List accountIds; + private Map accountMapById; +} diff --git a/src/main/java/com/salessparrow/api/dto/responseMapper/GetAccountsFeedResponseDto.java b/src/main/java/com/salessparrow/api/dto/responseMapper/GetAccountsFeedResponseDto.java new file mode 100644 index 00000000..3b6de1b3 --- /dev/null +++ b/src/main/java/com/salessparrow/api/dto/responseMapper/GetAccountsFeedResponseDto.java @@ -0,0 +1,24 @@ +package com.salessparrow.api.dto.responseMapper; + +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.salessparrow.api.dto.entities.AccountContactAssociationsEntity; +import com.salessparrow.api.dto.entities.AccountEntity; +import com.salessparrow.api.dto.entities.ContactEntity; +import com.salessparrow.api.dto.entities.NextPagePayloadEntity; + +import lombok.Data; + +@Data +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) +public class GetAccountsFeedResponseDto { + + private List accountIds; + private Map accountMapById; + private Map contactMapById; + private Map accountContactAssociationsMapById; + private NextPagePayloadEntity nextPagePayload; +} diff --git a/src/main/java/com/salessparrow/api/lib/Util.java b/src/main/java/com/salessparrow/api/lib/Util.java index 65c341fe..8dcebfb9 100644 --- a/src/main/java/com/salessparrow/api/lib/Util.java +++ b/src/main/java/com/salessparrow/api/lib/Util.java @@ -38,20 +38,21 @@ public JsonNode getJsonNode(String jsonString) { return jsonNode; } -/** - * Retrieves a string representation of all request headers. For security, - * the value of the "authorization, cookie, password" header is obfuscated. - * - * @param request - The HTTP request containing the headers to be logged. - * @return String - A string representation of the headers in the format "{headerName:headerValue, ...}". - */ + /** + * Retrieves a string representation of all request headers. For security, + * the value of the "authorization, cookie, password" header is obfuscated. + * + * @param request - The HTTP request containing the headers to be logged. + * @return String - A string representation of the headers in the format + * "{headerName:headerValue, ...}". + */ public static String generateHeaderLogString(HttpServletRequest request) { StringBuilder headerBuilder = new StringBuilder("{"); request.getHeaderNames().asIterator().forEachRemaining(headerName -> { // Add any other secret headers here that you don't want logged. - if (headerName.equals("authorization") || - headerName.equals("cookie") || - headerName.equals("password")) { + if (headerName.equals("authorization") || + headerName.equals("cookie") || + headerName.equals("password")) { headerBuilder.append(headerName).append(":**********, "); } else { headerBuilder.append(headerName).append(":").append(request.getHeader(headerName)).append(", "); @@ -59,6 +60,51 @@ public static String generateHeaderLogString(HttpServletRequest request) { }); headerBuilder.append("}"); - return headerBuilder.toString(); + return headerBuilder.toString(); + } + + /** + * Encode plain text to base64 + * + * @param plainText - String to be encoded + * @return String - Encoded string + */ + public String base64Encode(String plainText) { + String encodedText = null; + + try { + encodedText = java.util.Base64.getEncoder().encodeToString(plainText.getBytes()); + } catch (Exception e) { + throw new CustomException( + new ErrorObject( + "l_u_b64e_1", + "something_went_wrong", + e.getMessage())); + } + + return encodedText; + } + + /** + * Decode base64 encoded text + * + * @param encodedText - String to be decoded + * @return String - Decoded string + */ + public String base64Decode(String encodedText) { + String decodedText = null; + + try { + byte[] decodedBytes = java.util.Base64.getDecoder().decode(encodedText); + decodedText = new String(decodedBytes); + } catch (Exception e) { + throw new CustomException( + new ErrorObject( + "l_u_b64d_1", + "something_went_wrong", + e.getMessage())); + } + + return decodedText; } } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetAccounts.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetAccounts.java index b6a44704..37b95593 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetAccounts.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetAccounts.java @@ -11,5 +11,5 @@ @Component public interface GetAccounts { - public GetAccountsFormatterDto getAccounts(User user, String searchTerm); + public GetAccountsFormatterDto getAccounts(User user, String searchTerm, String viewKind, int offset); } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetAccountsFactory.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetAccountsFactory.java index 4c29d58f..80018026 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetAccountsFactory.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetAccountsFactory.java @@ -25,17 +25,17 @@ public class GetAccountsFactory { * * @return GetAccountsFormatterDto **/ - public GetAccountsFormatterDto getAccounts(User user, String searchTerm) { + public GetAccountsFormatterDto getAccounts(User user, String searchTerm, String viewKind, int offset) { - switch(user.getUserKind()) { + switch (user.getUserKind()) { case UserConstants.SALESFORCE_USER_KIND: - return getSalesforceAccounts.getAccounts(user, searchTerm); + return getSalesforceAccounts.getAccounts(user, searchTerm, viewKind, offset); default: throw new CustomException( - new ErrorObject( - "l_ca_ga_gaf_ga_1", - "something_went_wrong", - "Invalid user kind.")); + new ErrorObject( + "l_ca_ga_gaf_ga_1", + "something_went_wrong", + "Invalid user kind.")); } } } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java index 73529e6e..6b68682d 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java @@ -5,6 +5,8 @@ import java.util.List; import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -12,11 +14,15 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.salessparrow.api.domain.User; +import com.salessparrow.api.dto.entities.AccountContactAssociationsEntity; import com.salessparrow.api.dto.entities.AccountEntity; +import com.salessparrow.api.dto.entities.ContactEntity; import com.salessparrow.api.dto.formatter.GetAccountsFormatterDto; import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.lib.UserLoginCookieAuth; import com.salessparrow.api.lib.Util; import com.salessparrow.api.lib.errorLib.ErrorObject; +import com.salessparrow.api.lib.globalConstants.AccountConstants; import com.salessparrow.api.lib.globalConstants.SalesforceConstants; import com.salessparrow.api.lib.httpLib.HttpClient; import com.salessparrow.api.lib.salesforce.dto.CompositeRequestDto; @@ -25,16 +31,19 @@ import com.salessparrow.api.lib.salesforce.helper.SalesforceQueryBuilder; /** - * GetSalesforceAccounts is a class for the GetAccounts service for the Salesforce CRM. + * GetSalesforceAccounts is a class for the GetAccounts service for the + * Salesforce CRM. **/ @Component -public class GetSalesforceAccounts implements GetAccounts{ +public class GetSalesforceAccounts implements GetAccounts { @Autowired private SalesforceConstants salesforceConstants; @Autowired private MakeCompositeRequest makeCompositeRequest; + Logger logger = LoggerFactory.getLogger(UserLoginCookieAuth.class); + /** * Get the list of accounts for a given search term * @@ -42,12 +51,26 @@ public class GetSalesforceAccounts implements GetAccounts{ * @param searchTerm * * @return GetAccountsFormatterDto - **/ - public GetAccountsFormatterDto getAccounts(User user, String searchTerm) { + **/ + public GetAccountsFormatterDto getAccounts(User user, String searchTerm, String viewKind, int offset) { String salesforceUserId = user.getExternalUserId(); SalesforceQueryBuilder salesforceQuery = new SalesforceQueryBuilder(); - String query = salesforceQuery.getAccountsQuery(searchTerm); + String query = null; + + if (viewKind.equals(AccountConstants.FEED_VIEW_KIND)) { + logger.info("View kind is feed"); + query = salesforceQuery.getAccountFeedQuery(AccountConstants.PAGINATION_LIMIT, offset); + } else if (viewKind.equals(AccountConstants.BASIC_VIEW_KIND)) { + logger.info("View kind is basic"); + query = salesforceQuery.getAccountsQuery(searchTerm); + } else { + throw new CustomException( + new ErrorObject( + "l_ca_ga_gsa_ga_1", + "something_went_wrong", + "Invalid view kind.")); + } String url = salesforceConstants.queryUrlPath() + query; @@ -67,23 +90,25 @@ public GetAccountsFormatterDto getAccounts(User user, String searchTerm) { * @param responseBody * * @return GetAccountsFormatterDto - **/ + **/ public GetAccountsFormatterDto parseResponse(String responseBody) { - + List accountIds = new ArrayList(); Map accountIdToEntityMap = new HashMap<>(); + Map contactMapById = new HashMap<>(); + Map accountContactAssociationsMapById = new HashMap<>(); Util util = new Util(); JsonNode rootNode = util.getJsonNode(responseBody); JsonNode httpStatusCodeNode = rootNode.get("compositeResponse").get(0).get("httpStatusCode"); - + if (httpStatusCodeNode.asInt() != 200 && httpStatusCodeNode.asInt() != 201) { throw new CustomException( - new ErrorObject( - "l_ca_ga_gsa_pr_1", - "bad_request", - "Error in fetching accounts from salesforce")); + new ErrorObject( + "l_ca_ga_gsa_pr_1", + "bad_request", + "Error in fetching accounts from salesforce")); } JsonNode recordsNode = rootNode.get("compositeResponse").get(0).get("body").get("records"); @@ -92,15 +117,31 @@ public GetAccountsFormatterDto parseResponse(String responseBody) { ObjectMapper mapper = new ObjectMapper(); mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); SalesforceAccountDto salesforceAccount = mapper.convertValue(recordNode, SalesforceAccountDto.class); - AccountEntity accountEntity = salesforceAccount.getAccountEntity(); + AccountEntity accountEntity = salesforceAccount.getAccountEntity(); accountIds.add(accountEntity.getId()); accountIdToEntityMap.put(accountEntity.getId(), accountEntity); + + if (salesforceAccount.getContacts() != null) { + List contactIds = new ArrayList(); + + for (SalesforceAccountDto.Contact contact : salesforceAccount.getContacts().getRecords()) { + ContactEntity contactEntity = contact.getContactEntity(); + contactMapById.put(contactEntity.getId(), contactEntity); + contactIds.add(contactEntity.getId()); + } + + AccountContactAssociationsEntity accountContactAssociationsEntity = new AccountContactAssociationsEntity(); + accountContactAssociationsEntity.setContactIds(contactIds); + accountContactAssociationsMapById.put(accountEntity.getId(), accountContactAssociationsEntity); + } } GetAccountsFormatterDto getAccountsResponse = new GetAccountsFormatterDto(); getAccountsResponse.setAccountMapById(accountIdToEntityMap); getAccountsResponse.setAccountIds(accountIds); + getAccountsResponse.setContactMapById(contactMapById); + getAccountsResponse.setAccountContactAssociationsMapById(accountContactAssociationsMapById); return getAccountsResponse; } diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/AccountConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/AccountConstants.java new file mode 100644 index 00000000..056c0cf4 --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/AccountConstants.java @@ -0,0 +1,7 @@ +package com.salessparrow.api.lib.globalConstants; + +public class AccountConstants { + public static final String BASIC_VIEW_KIND = "BASIC"; + public static final String FEED_VIEW_KIND = "FEED"; + public static final int PAGINATION_LIMIT = 10; +} diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceAccountDto.java b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceAccountDto.java index 647e8b73..e2eea17c 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceAccountDto.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceAccountDto.java @@ -1,8 +1,16 @@ package com.salessparrow.api.lib.salesforce.dto; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.google.common.base.CaseFormat; import com.salessparrow.api.dto.entities.AccountEntity; +import com.salessparrow.api.dto.entities.ContactEntity; import lombok.Data; @@ -11,12 +19,56 @@ public class SalesforceAccountDto { private String id; private String name; + private Map additionalFields = new HashMap<>(); + private ContactsWrapper Contacts; public AccountEntity getAccountEntity() { AccountEntity accountEntity = new AccountEntity(); accountEntity.setId(this.id); accountEntity.setName(this.name); - + accountEntity.setAdditionalFields(this.additionalFields); + accountEntity.setAccountContactAssociationsId(this.id); return accountEntity; } -} + + @JsonAnySetter + public void setAdditionalField(String fieldName, Object value) { + fieldName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, + fieldName); + if (!fieldName.equals("attributes") && !fieldName.equals("Contacts")) { + additionalFields.put(fieldName, value); + } + } + + @Data + public static class ContactsWrapper { + private List records = new ArrayList<>(); + } + + @Data + @JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) + public static class Contact { + private String id; + private String name; + private Map additionalFields = new HashMap<>(); + + public ContactEntity getContactEntity() { + ContactEntity contactEntity = new ContactEntity(); + contactEntity.setId(this.id); + contactEntity.setName(this.name); + contactEntity.setAdditionalFields(this.additionalFields); + return contactEntity; + } + + @JsonAnySetter + public void setAdditionalField(String fieldName, Object value) { + fieldName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, + fieldName); + if (!fieldName.equals("attributes")) { + additionalFields.put(fieldName, value); + } + } + + } + +} \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java index a4cc80a1..5031af33 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java @@ -9,7 +9,7 @@ */ @Component public class SalesforceQueryBuilder { - + /** * Get the list of accounts for a given searchTerm * @@ -20,8 +20,23 @@ public class SalesforceQueryBuilder { public String getAccountsQuery(String searchTerm) { if (searchTerm == "") { return "SELECT Id, Name FROM Account ORDER BY LastModifiedDate DESC LIMIT 20"; - } - return "SELECT Id, Name FROM Account WHERE Name LIKE '%25"+searchTerm+"%25' ORDER BY LastModifiedDate DESC LIMIT 20"; + } + return "SELECT Id, Name FROM Account WHERE Name LIKE '%25" + searchTerm + + "%25' ORDER BY LastModifiedDate DESC LIMIT 20"; + } + + /** + * Get the accounts feed for a given limit and offset + * + * @param limit int + * @param offset int + * @return String + */ + public String getAccountFeedQuery(int limit, int offset) { + + return String.format( + "SELECT Id, Name, Website, (SELECT Id, Name, Title, Email, Phone FROM Contacts) FROM Account ORDER BY LastModifiedDate ASC LIMIT %d OFFSET %d", + limit, offset); } /** @@ -55,8 +70,9 @@ public String getNoteListIdUrl(List documentIds) { return queryBuilder.toString(); } - public String getNoteDetailsUrl(String noteId){ - return "SELECT Id, Title, TextPreview, CreatedBy.Name, LastModifiedDate FROM ContentNote WHERE Id = '" + noteId + "'"; + public String getNoteDetailsUrl(String noteId) { + return "SELECT Id, Title, TextPreview, CreatedBy.Name, LastModifiedDate FROM ContentNote WHERE Id = '" + noteId + + "'"; } } diff --git a/src/main/java/com/salessparrow/api/services/accounts/GetAccountListService.java b/src/main/java/com/salessparrow/api/services/accounts/GetAccountListService.java index 02744131..a368f126 100644 --- a/src/main/java/com/salessparrow/api/services/accounts/GetAccountListService.java +++ b/src/main/java/com/salessparrow/api/services/accounts/GetAccountListService.java @@ -9,30 +9,40 @@ import com.salessparrow.api.domain.User; import com.salessparrow.api.dto.formatter.GetAccountsFormatterDto; import com.salessparrow.api.dto.requestMapper.GetAccountsDto; +import com.salessparrow.api.dto.responseMapper.GetAccountListResponseDto; import com.salessparrow.api.lib.crmActions.getAccounts.GetAccountsFactory; +import com.salessparrow.api.lib.globalConstants.AccountConstants; import jakarta.servlet.http.HttpServletRequest; /** - * GetAccountListService is a service class for the GetAccounts action for the CRM. + * GetAccountListService is a service class for the GetAccounts action for the + * CRM. */ @Service public class GetAccountListService { @Autowired private GetAccountsFactory getAccountsFactory; - + /** - * Get the list of accounts for a given search term - * @param request - * @param getAccountsDto - * - * @return GetAccountsFormatterDto - **/ - public GetAccountsFormatterDto getAccounts(HttpServletRequest request, GetAccountsDto getAccountsDto) { + * Get the list of accounts for a given search term + * + * @param request + * @param getAccountsDto + * + * @return GetAccountsFormatterDto + **/ + public GetAccountListResponseDto getAccounts(HttpServletRequest request, GetAccountsDto getAccountsDto) { User currentUser = (User) request.getAttribute("current_user"); String formattedSearchString = formatSearchString(getAccountsDto.getQ()); - return getAccountsFactory.getAccounts(currentUser, formattedSearchString); + GetAccountsFormatterDto getAccountsFormatterDto = getAccountsFactory.getAccounts(currentUser, formattedSearchString, + AccountConstants.BASIC_VIEW_KIND, 0); + + GetAccountListResponseDto getAccountListResponseDto = new GetAccountListResponseDto(); + getAccountListResponseDto.setAccountIds(getAccountsFormatterDto.getAccountIds()); + getAccountListResponseDto.setAccountMapById(getAccountsFormatterDto.getAccountMapById()); + return getAccountListResponseDto; } private String formatSearchString(String q) { diff --git a/src/main/java/com/salessparrow/api/services/accounts/GetAccountsFeedService.java b/src/main/java/com/salessparrow/api/services/accounts/GetAccountsFeedService.java new file mode 100644 index 00000000..84f44a1c --- /dev/null +++ b/src/main/java/com/salessparrow/api/services/accounts/GetAccountsFeedService.java @@ -0,0 +1,116 @@ +package com.salessparrow.api.services.accounts; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.salessparrow.api.domain.User; +import com.salessparrow.api.dto.entities.NextPagePayloadEntity; +import com.salessparrow.api.dto.formatter.GetAccountsFormatterDto; +import com.salessparrow.api.dto.formatter.PaginationIdentifierFormatterDto; +import com.salessparrow.api.dto.requestMapper.GetAccountsFeedDto; +import com.salessparrow.api.dto.responseMapper.GetAccountsFeedResponseDto; +import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.lib.UserLoginCookieAuth; +import com.salessparrow.api.lib.Util; +import com.salessparrow.api.lib.crmActions.getAccounts.GetAccountsFactory; +import com.salessparrow.api.lib.errorLib.ErrorObject; +import com.salessparrow.api.lib.globalConstants.AccountConstants; + +import jakarta.servlet.http.HttpServletRequest; + +/** + * GetAccountsFeedService is a service class for the GetAccountsFeed action for + * the CRM. + */ +@Service +public class GetAccountsFeedService { + @Autowired + private GetAccountsFactory getAccountsFactory; + + @Autowired + private Util util; + + Logger logger = LoggerFactory.getLogger(UserLoginCookieAuth.class); + + int offset; + int pageNumber = 1; + String searchTerm = null; + ObjectMapper mapper = new ObjectMapper(); + + /** + * Get accounts feed method + * + * @param request HttpServletRequest + * @param getAccountsFeedDto GetAccountsFeedDto + * @return GetAccountsFeedResponseDto + */ + public GetAccountsFeedResponseDto getAccountsFeed(HttpServletRequest request, + GetAccountsFeedDto getAccountsFeedDto) { + logger.info("Getting accounts feed"); + + User currentUser = (User) request.getAttribute("current_user"); + offset = 0; + + if (getAccountsFeedDto.getPagination_identifier() != null) { + logger.info("Pagination identifier found"); + String decodedPaginationIdentifier = util.base64Decode(getAccountsFeedDto.getPagination_identifier()); + PaginationIdentifierFormatterDto paginationIdentifierObj = null; + try { + paginationIdentifierObj = mapper.readValue(decodedPaginationIdentifier, PaginationIdentifierFormatterDto.class); + } catch (Exception e) { + throw new CustomException( + new ErrorObject( + "s_a_gafs_gaf_1", + "something_went_wrong", + e.getMessage())); + } + pageNumber = paginationIdentifierObj.getPageNumber(); + offset = (pageNumber - 1) * AccountConstants.PAGINATION_LIMIT; + } + + return prepareResponse(getAccountsFactory.getAccounts(currentUser, searchTerm, + AccountConstants.FEED_VIEW_KIND, offset)); + } + + /** + * Preparing response + * + * @param accountsFactoryRes GetAccountsFormatterDto + * @return GetAccountsFeedResponseDto + */ + private GetAccountsFeedResponseDto prepareResponse(GetAccountsFormatterDto accountsFactoryRes) { + logger.info("Preparing response"); + GetAccountsFeedResponseDto accountsFeedResponse = new GetAccountsFeedResponseDto(); + + accountsFeedResponse.setAccountIds(accountsFactoryRes.getAccountIds()); + accountsFeedResponse.setAccountMapById(accountsFactoryRes.getAccountMapById()); + accountsFeedResponse.setContactMapById(accountsFactoryRes.getContactMapById()); + accountsFeedResponse.setAccountContactAssociationsMapById( + accountsFactoryRes.getAccountContactAssociationsMapById()); + + NextPagePayloadEntity nextPagePayload = new NextPagePayloadEntity(); + + logger.info("Preparing pagination identifier"); + PaginationIdentifierFormatterDto paginationIdentifier = new PaginationIdentifierFormatterDto(); + paginationIdentifier.setPageNumber(pageNumber + 1); + + try { + String paginationJson = mapper.writeValueAsString(paginationIdentifier); + nextPagePayload.setPaginationIdentifier(util.base64Encode(paginationJson)); + } catch (Exception e) { + throw new CustomException( + new ErrorObject( + "s_a_gafs_gaf_pr_1", + "something_went_wrong", + e.getMessage())); + + } + + accountsFeedResponse.setNextPagePayload(nextPagePayload); + return accountsFeedResponse; + } + +} diff --git a/src/main/resources/config/ParamErrorConfig.json b/src/main/resources/config/ParamErrorConfig.json index 0b724abb..a2f5a07a 100644 --- a/src/main/resources/config/ParamErrorConfig.json +++ b/src/main/resources/config/ParamErrorConfig.json @@ -13,5 +13,10 @@ "parameter": "q", "param_error_identifier": "search_term_too_long", "message": "Search term too long. Please shorten and try again." + }, + "invalid_pagination_identifier":{ + "parameter": "pagination_identifier", + "param_error_identifier": "invalid_pagination_identifier", + "message": "Invalid pagination identifier. Please double check and try again." } } \ No newline at end of file diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java index a472b658..730376a7 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java @@ -74,10 +74,11 @@ public void tearDown() { @ParameterizedTest @MethodSource("testScenariosProvider") public void getAccountList(Scenario testScenario) throws Exception { - // Load fixture data - String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/controllers/accountController/getAccountList.fixtures.json", currentFunctionName); - System.out.println("fixtureData++++++ "+fixtureData); + // Load fixture data + String currentFunctionName = new Object() { + }.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture( + "classpath:fixtures/controllers/accountController/getAccountList.fixtures.json", currentFunctionName); loadFixture.perform(fixtureData); // Read data from the scenario @@ -86,19 +87,18 @@ public void getAccountList(Scenario testScenario) throws Exception { // Prepare mock responses HttpResponse getAccountMockResponse = new HttpResponse(); - getAccountMockResponse.setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest"))); + getAccountMockResponse + .setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest"))); when(makeCompositeRequestMock.makePostRequest(any(), any())).thenReturn(getAccountMockResponse); - + // Perform the request String url = "/api/v1/accounts"; String q = objectMapper.writeValueAsString(testScenario.getInput().get("q")); - System.out.println("q++++++ "+q); ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get(url) - .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) - .param("q", q) - .contentType(MediaType.APPLICATION_JSON)); - + .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) + .param("q", q) + .contentType(MediaType.APPLICATION_JSON)); // Check the response String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); @@ -119,6 +119,7 @@ private static List loadScenarios() throws IOException { String scenariosPath = "classpath:data/controllers/accountController/getAccountList.scenarios.json"; Resource resource = new DefaultResourceLoader().getResource(scenariosPath); ObjectMapper objectMapper = new ObjectMapper(); - return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); + return objectMapper.readValue(resource.getInputStream(), new TypeReference>() { + }); } } diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountsFeedTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountsFeedTest.java new file mode 100644 index 00000000..f50884fb --- /dev/null +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountsFeedTest.java @@ -0,0 +1,165 @@ +package com.salessparrow.api.functional.controllers.accountController; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Stream; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +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.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +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.JsonParser; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.dynamobee.exception.DynamobeeException; +import com.salessparrow.api.dto.formatter.PaginationIdentifierFormatterDto; +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 com.salessparrow.api.lib.httpLib.HttpClient; +import com.salessparrow.api.lib.httpLib.HttpClient.HttpResponse; +import com.salessparrow.api.lib.salesforce.helper.MakeCompositeRequest; +import com.salessparrow.api.lib.salesforce.helper.SalesforceRequestInterface; + +import jakarta.servlet.http.Cookie; + +@SpringBootTest +@AutoConfigureMockMvc +@WebAppConfiguration +@Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) +public class GetAccountsFeedTest { + @Autowired + private MockMvc mockMvc; + @Autowired + private Common common; + @Autowired + private LoadFixture loadFixture; + @Autowired + private Setup setup; + @Autowired + private Cleanup cleanup; + + @MockBean + private MakeCompositeRequest makeCompositeRequestMock; + + @MockBean + private SalesforceRequestInterface salesforceRequestInterfaceMock; + + @BeforeEach + public void setUp() throws DynamobeeException { + setup.perform(); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + @ParameterizedTest + @MethodSource("testScenariosProvider") + public void getAccountsFeed(Scenario testScenario) throws Exception { + System.out.println("Description: " + testScenario.getDescription()); + // Load fixture data + String currentFunctionName = new Object() { + }.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture( + "classpath:fixtures/controllers/accountController/getAccountsFeed.fixtures.json", currentFunctionName); + loadFixture.perform(fixtureData); + + // Read data from the scenario + ObjectMapper objectMapper = new ObjectMapper(); + String cookieValue = Constants.SALESFORCE_ACTIVE_USET_COOKIE_VALUE; + + // Prepare makeCompositeRequestMock responses + if (testScenario.getMocks() != null && testScenario.getMocks().containsKey("makeCompositeRequest")) { + HttpResponse getAccountMockResponse = new HttpResponse(); + getAccountMockResponse + .setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest"))); + when(makeCompositeRequestMock.makePostRequest(any(), any())).thenReturn(getAccountMockResponse); + } + if (testScenario.getMocks() != null && testScenario.getMocks().containsKey("writeValueAsString")) { + ObjectMapper mapper = mock(ObjectMapper.class); + + String errorMessage = testScenario.getMocks().get("writeValueAsString").toString(); + when(mapper.writeValueAsString(any())) + .thenThrow(new RuntimeException(errorMessage)); + } + + if (testScenario.getMocks() != null && testScenario.getMocks().containsKey("readValue")) { + ObjectMapper mapper = mock(ObjectMapper.class); + + System.out.println("in base64Encode"); + String errorMessage = testScenario.getMocks().get("readValue").toString(); + when(mapper.readValue(any(JsonParser.class), eq(PaginationIdentifierFormatterDto.class))) + .thenThrow(new RuntimeException(errorMessage)); + } + + // Prepare salesforceRequestInterfaceMock responses + if (testScenario.getMocks() != null && testScenario.getMocks().containsKey("SalesforceRequestInterfaceError")) { + String errorMessage = testScenario.getMocks().get("SalesforceRequestInterfaceError").toString(); + + when(salesforceRequestInterfaceMock.execute(any(), any())) + .thenThrow(new RuntimeException(errorMessage)); + } + + // Perform the request + String url = "/api/v1/accounts/feed"; + String paginationIdentifier = testScenario.getInput().get("pagination_identifier").toString(); + + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get(url) + .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) + .param("pagination_identifier", paginationIdentifier) + .contentType(MediaType.APPLICATION_JSON)); + + // Check the response + String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); + String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); + + JsonNode expectedOutputJson = objectMapper.readTree(expectedOutput); + JsonNode actualOutputJson = objectMapper.readTree(actualOutput); + + if (resultActions.andReturn().getResponse().getStatus() == 200) { + assertEquals(expectedOutputJson, actualOutputJson); + } else { + common.compareErrors(testScenario, actualOutput); + } + } + + static Stream testScenariosProvider() throws IOException { + List testScenarios = loadScenarios(); + return testScenarios.stream(); + } + + private static List loadScenarios() throws IOException { + String scenariosPath = "classpath:data/controllers/accountController/getAccountsFeed.scenarios.json"; + Resource resource = new DefaultResourceLoader().getResource(scenariosPath); + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.readValue(resource.getInputStream(), new TypeReference>() { + }); + } +} diff --git a/src/test/java/com/salessparrow/api/unit/lib/UtilTest.java b/src/test/java/com/salessparrow/api/unit/lib/UtilTest.java new file mode 100644 index 00000000..8f963006 --- /dev/null +++ b/src/test/java/com/salessparrow/api/unit/lib/UtilTest.java @@ -0,0 +1,91 @@ +package com.salessparrow.api.unit.lib; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.lib.Util; + +public class UtilTest { + + @Mock + private ObjectMapper objectMapper; + + @InjectMocks + private Util util; + + @BeforeEach + public void setup() { + MockitoAnnotations.openMocks(this); + } + + @Test + public void testEncode() { + String plainText = "Hello, World!"; + String encodedText = util.base64Encode(plainText); + assertEquals("SGVsbG8sIFdvcmxkIQ==", encodedText); + } + + @Test + public void testEncodeEmptyString() { + String plainText = ""; + String encodedText = util.base64Encode(plainText); + assertEquals("", encodedText); + } + + @Test + public void testEncodeNullString() { + String plainText = null; + assertThrows(CustomException.class, () -> util.base64Encode(plainText)); + } + + @Test + public void testDecode() { + String encodedText = "SGVsbG8sIFdvcmxkIQ=="; + String decodedText = util.base64Decode(encodedText); + assertEquals("Hello, World!", decodedText); + } + + @Test + public void testDecodeEmptyString() { + String encodedText = ""; + String decodedText = util.base64Decode(encodedText); + assertEquals("", decodedText); + } + + @Test + public void testDecodeNullString() { + String encodedText = null; + assertThrows(CustomException.class, () -> util.base64Decode(encodedText)); + } + + @Test + public void testDecodeInvalidString() { + String encodedText = "SGVsbG8sIFdvcmxkIQ="; + assertThrows(CustomException.class, () -> util.base64Decode(encodedText)); + } + + @Test + public void testGetJsonNode_ValidJson() throws Exception { + String jsonString = "{\"key\": \"value\"}"; + + JsonNode resultJsonNode = util.getJsonNode(jsonString); + + assertEquals("value", resultJsonNode.get("key").asText()); + } + + @Test + public void testGetJsonNode_InvalidJson() throws Exception { + String invalidJsonString = "invalid json"; + + assertThrows(CustomException.class, () -> util.getJsonNode(invalidJsonString)); + } +} diff --git a/src/test/resources/data/controllers/accountController/getAccountList.scenarios.json b/src/test/resources/data/controllers/accountController/getAccountList.scenarios.json index 8ee16ae0..faa29b64 100644 --- a/src/test/resources/data/controllers/accountController/getAccountList.scenarios.json +++ b/src/test/resources/data/controllers/accountController/getAccountList.scenarios.json @@ -39,17 +39,21 @@ }, "output": { "account_ids": [ - "0011e00000dWhY5AAK", - "0011e00000bQwsKAAS" + "0011e00000dWhY5AAK", + "0011e00000bQwsKAAS" ], "account_map_by_id": { - "0011e00000dWhY5AAK": { - "id": "0011e00000dWhY5AAK", - "name": "Test 1" - }, "0011e00000bQwsKAAS": { "id": "0011e00000bQwsKAAS", - "name": "Test 2" + "name": "Test 2", + "additional_fields": {}, + "account_contact_associations_id": "0011e00000bQwsKAAS" + }, + "0011e00000dWhY5AAK": { + "id": "0011e00000dWhY5AAK", + "name": "Test 1", + "additional_fields": {}, + "account_contact_associations_id": "0011e00000dWhY5AAK" } } } @@ -94,17 +98,21 @@ }, "output": { "account_ids": [ - "0011e00000dWhY5AAK", - "0011e00000bQwsKAAS" + "0011e00000dWhY5AAK", + "0011e00000bQwsKAAS" ], "account_map_by_id": { - "0011e00000dWhY5AAK": { - "id": "0011e00000dWhY5AAK", - "name": "Test 1" - }, "0011e00000bQwsKAAS": { "id": "0011e00000bQwsKAAS", - "name": "Test 2" + "name": "Test 2", + "additional_fields": {}, + "account_contact_associations_id": "0011e00000bQwsKAAS" + }, + "0011e00000dWhY5AAK": { + "id": "0011e00000dWhY5AAK", + "name": "Test 1", + "additional_fields": {}, + "account_contact_associations_id": "0011e00000dWhY5AAK" } } } diff --git a/src/test/resources/data/controllers/accountController/getAccountsFeed.scenarios.json b/src/test/resources/data/controllers/accountController/getAccountsFeed.scenarios.json new file mode 100644 index 00000000..b73fbe0e --- /dev/null +++ b/src/test/resources/data/controllers/accountController/getAccountsFeed.scenarios.json @@ -0,0 +1,171 @@ +[ + { + "description": "Should return the accounts feed data sorted by lastmodifieddate", + "input": { + "pagination_identifier": "eyJwYWdlTnVtYmVyIjozfQ==" + }, + "mocks": { + "makeCompositeRequest": { + "compositeResponse": [ + { + "body": { + "totalSize": 2, + "done": true, + "records": [ + { + "attributes": { + "type": "Account", + "url": "/services/data/v58.0/sobjects/Account/0011e00000bAd2wAAC" + }, + "Id": "0011e00000dWhY5AAK", + "Name": "thenaIntegration", + "Website": "www.xyz.com", + "Contacts": null + }, + { + "attributes": { + "type": "Account", + "url": "/services/data/v58.0/sobjects/Account/0011e00000asaDXAAY" + }, + "Id": "0011e00000bQwsKAAS", + "Name": "Woomie", + "Website": "www.abc.com", + "Contacts": { + "totalSize": 2, + "done": true, + "records": [ + { + "attributes": { + "type": "Contact", + "url": "/services/data/v58.0/sobjects/Contact/0031e00000MFIHdAAP" + }, + "Id": "0031e00000MFIHdAAP", + "Name": "Sample user1", + "Title": "Sample title1" + }, + { + "attributes": { + "type": "Contact", + "url": "/services/data/v58.0/sobjects/Contact/0031e00000MFJcBAAX" + }, + "Id": "0031e00000MFJcBAAX", + "Name": "Sample user2", + "Title": "Sample title2" + } + ] + } + } + ] + }, + "httpHeaders": {}, + "httpStatusCode": 200, + "referenceId": "getAccounts" + } + ] + } + }, + "output": { + "account_ids": [ + "0011e00000dWhY5AAK", + "0011e00000bQwsKAAS" + ], + "account_map_by_id": { + "0011e00000bQwsKAAS": { + "id": "0011e00000bQwsKAAS", + "name": "Woomie", + "additional_fields": { + "website": "www.abc.com" + }, + "account_contact_associations_id": "0011e00000bQwsKAAS" + }, + "0011e00000dWhY5AAK": { + "id": "0011e00000dWhY5AAK", + "name": "thenaIntegration", + "additional_fields": { + "website": "www.xyz.com" + }, + "account_contact_associations_id": "0011e00000dWhY5AAK" + } + }, + "contact_map_by_id": { + "0031e00000MFJcBAAX": { + "id": "0031e00000MFJcBAAX", + "name": "Sample user2", + "additional_fields": { + "title": "Sample title2" + } + }, + "0031e00000MFIHdAAP": { + "id": "0031e00000MFIHdAAP", + "name": "Sample user1", + "additional_fields": { + "title": "Sample title1" + } + } + }, + "account_contact_associations_map_by_id": { + "0011e00000bQwsKAAS": { + "contact_ids": [ + "0031e00000MFIHdAAP", + "0031e00000MFJcBAAX" + ] + } + }, + "next_page_payload": { + "pagination_identifier": "eyJwYWdlTnVtYmVyIjo0fQ==" + } + } + }, + { + "description": "Should return the pagination_identifier validation error", + "input": { + "pagination_identifier": "SGVsbG8sIFdvcm*xkIQ=" + }, + "output": { + "http_code": 400, + "code": "INVALID_PARAMS", + "param_errors": [ + "invalid_pagination_identifier" + ] + } + }, + { + "description": "Should return the error from salesforce", + "input": { + "pagination_identifier": "eyJwYWdlTnVtYmVyIjozfQ==" + }, + "mocks": { + "SalesforceRequestInterfaceError": "Something went wrong" + }, + "output": { + "http_code": 500, + "code": "INTERNAL_SERVER_ERROR" + } + }, + { + "description": "Should return the error while parsing pagination_identifier", + "input": { + "pagination_identifier": "eyJwYWdlTnVtYmVyIjozfQ==" + }, + "mocks": { + "writeValueAsString": "something went wrong" + }, + "output": { + "http_code": 500, + "code": "INTERNAL_SERVER_ERROR" + } + }, + { + "description": "Should return the error while encoding paginationJson", + "input": { + "pagination_identifier": "eyJwYWdlTnVtYmVyIjozfQ==" + }, + "mocks": { + "readValue": "something went wrong" + }, + "output": { + "http_code": 500, + "code": "INTERNAL_SERVER_ERROR" + } + } +] \ No newline at end of file diff --git a/src/test/resources/fixtures/controllers/accountController/getAccountsFeed.fixtures.json b/src/test/resources/fixtures/controllers/accountController/getAccountsFeed.fixtures.json new file mode 100644 index 00000000..783268cc --- /dev/null +++ b/src/test/resources/fixtures/controllers/accountController/getAccountsFeed.fixtures.json @@ -0,0 +1,14 @@ +{ + "getAccountsFeed": { + "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 d88a8134adf37003bd4c6cfe2ead4b7d70752ede Mon Sep 17 00:00:00 2001 From: VRDighe Date: Fri, 25 Aug 2023 20:52:51 +0530 Subject: [PATCH 105/195] Added get accounts feed API --- .../api/config/SecurityConfig.java | 136 ++++++++++-------- .../GetAccountsFeedTest.java | 2 +- 2 files changed, 74 insertions(+), 64 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..e6541f66 100644 --- a/src/main/java/com/salessparrow/api/config/SecurityConfig.java +++ b/src/main/java/com/salessparrow/api/config/SecurityConfig.java @@ -8,75 +8,85 @@ import org.springframework.security.web.header.writers.XXssProtectionHeaderWriter; import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter.ReferrerPolicy; - @Configuration @EnableWebSecurity public class SecurityConfig { - + @Bean - public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { - http - // disable authorization for all routes - .authorizeHttpRequests(authorizeRequests ->authorizeRequests.anyRequest().permitAll()) - // Disable authentication for all routes - .httpBasic(httpBasic -> httpBasic.disable()) - // Disable form login - .formLogin(formLogin -> formLogin.disable()) - // Remove csrf in app routes - .csrf((csrf) -> csrf.ignoringRequestMatchers("/api/v1/**")) - - /** - * Cache-Control header - applied by default in spring security - * The Cache-Control header is the most important header to set as it effectively disables caching on the client side. - * - * Pragma header - applied by default in spring security - * The Pragma directive is an older directive meant for HTTP/1.0 clients where - * the Cache-Control header wasn't defined. - * - * Expires header - applied by default in spring security - * The Expires header is another older way to prevent caching, especially in HTTP/1.0. - * - * X-Content-Type-Options header - applied by default in spring security - * The X-Content-Type-Options header is a security feature that prevents pages from loading when they detect - * incorrect MIME types. - * By setting the value to "nosniff", you're instructing the browser not to override the provided Content-Type - * - * HSTS header - * The Strict-Transport-Security header is a security feature implemented by web browsers - * to ensure that websites are only accessed using HTTPS. - * - * X-Frame-Options header - * The X-Frame-Options header is a security feature that prevents your web page from being put in a frame. - * - * X-XSS-Protection header - applied by default in spring security - * The X-XSS-Protection header is a security feature that prevents pages from loading when they detect - * reflected cross-site scripting (XSS) attacks. - * - * It is not needed for rest api's as they are not rendered in the browser. But it is no harm and is a - * good practice to have it.The value "1; mode=block" instructs the browser to block the response if it - * detects an attack. - * - * Referrer-Policy header - * The Referrer-Policy header is a security feature that prevents pages from leaking information about the user's - * browsing behavior.The value "same-origin" instructs the browser to send the referrer header only when the request - * is originating from the same origin as the target resource. - */ - .headers(headers -> headers - .frameOptions(frameOptions -> frameOptions.deny()) - .httpStrictTransportSecurity(hsts -> hsts.includeSubDomains(true).preload(true).maxAgeInSeconds(31536000)) - .xssProtection(xss -> xss.headerValue(XXssProtectionHeaderWriter.HeaderValue.ENABLED_MODE_BLOCK)) - .referrerPolicy(referrer -> referrer.policy(ReferrerPolicy.SAME_ORIGIN)) - ); + http + // disable authorization for all routes + .authorizeHttpRequests(authorizeRequests -> authorizeRequests.anyRequest().permitAll()) + // Disable authentication for all routes + .httpBasic(httpBasic -> httpBasic.disable()) + // Disable form login + .formLogin(formLogin -> formLogin.disable()) + // Remove csrf in app routes + .csrf((csrf) -> csrf.ignoringRequestMatchers("/api/v1/**")) + /** + * Cache-Control header - applied by default in spring security + * The Cache-Control header is the most important header to set as it + * effectively disables caching on the client side. + * + * Pragma header - applied by default in spring security + * The Pragma directive is an older directive meant for HTTP/1.0 clients where + * the Cache-Control header wasn't defined. + * + * Expires header - applied by default in spring security + * The Expires header is another older way to prevent caching, especially in + * HTTP/1.0. + * + * X-Content-Type-Options header - applied by default in spring security + * The X-Content-Type-Options header is a security feature that prevents pages + * from loading when they detect + * incorrect MIME types. + * By setting the value to "nosniff", you're instructing the browser not to + * override the provided Content-Type + * + * HSTS header + * The Strict-Transport-Security header is a security feature implemented by web + * browsers + * to ensure that websites are only accessed using HTTPS. + * + * X-Frame-Options header + * The X-Frame-Options header is a security feature that prevents your web page + * from being put in a frame. + * + * X-XSS-Protection header - applied by default in spring security + * The X-XSS-Protection header is a security feature that prevents pages from + * loading when they detect + * reflected cross-site scripting (XSS) attacks. + * + * It is not needed for rest api's as they are not rendered in the browser. But + * it is no harm and is a + * good practice to have it.The value "1; mode=block" instructs the browser to + * block the response if it + * detects an attack. + * + * Referrer-Policy header + * The Referrer-Policy header is a security feature that prevents pages from + * leaking information about the user's + * browsing behavior.The value "same-origin" instructs the browser to send the + * referrer header only when the request + * is originating from the same origin as the target resource. + */ + .headers(headers -> headers + .frameOptions(frameOptions -> frameOptions.deny()) + .httpStrictTransportSecurity( + hsts -> hsts.includeSubDomains(true).preload(true).maxAgeInSeconds(31536000)) + .xssProtection( + xss -> xss.headerValue(XXssProtectionHeaderWriter.HeaderValue.ENABLED_MODE_BLOCK)) + .referrerPolicy(referrer -> referrer.policy(ReferrerPolicy.SAME_ORIGIN))); - // Enable for production and staging - if (!CoreConstants.isDevEnvironment() && !CoreConstants.isTestEnvironment() && - !CoreConstants.isLocalTestEnvironment()) { - // All requests must be secure - http.requiresChannel(channel -> channel.anyRequest().requiresSecure()); - } + // Enable for production and staging + if (!CoreConstants.isDevEnvironment() && !CoreConstants.isTestEnvironment() && + !CoreConstants.isLocalTestEnvironment()) { + // All requests must be secure + http.requiresChannel(channel -> channel.anyRequest().requiresSecure()); + } - return http.build(); - } + return http.build(); + } } diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountsFeedTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountsFeedTest.java index f50884fb..a14a83bc 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountsFeedTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountsFeedTest.java @@ -93,7 +93,7 @@ public void getAccountsFeed(Scenario testScenario) throws Exception { // Read data from the scenario ObjectMapper objectMapper = new ObjectMapper(); - String cookieValue = Constants.SALESFORCE_ACTIVE_USET_COOKIE_VALUE; + String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; // Prepare makeCompositeRequestMock responses if (testScenario.getMocks() != null && testScenario.getMocks().containsKey("makeCompositeRequest")) { From 63b1fd2a0160bcc9dacedf943d323e101a6b5f21 Mon Sep 17 00:00:00 2001 From: amanbarbaria Date: Fri, 25 Aug 2023 23:03:05 +0530 Subject: [PATCH 106/195] Added unit test cases Added another config for test logs --- .../api/domain/SalesforceOrganization.java | 3 +- src/main/resources/logback-test.xml | 25 ++++ .../api/functional/SalesSparrowApiTest.java | 20 +++ .../com/salessparrow/api/helper/Setup.java | 1 - .../SalesforceOauthTokenRepositoryTest.java | 117 +++++++++++++++++ .../SalesforceOrganizationRepositoryTest.java | 119 ++++++++++++++++++ .../SalesforceUserRepositoryTest.java | 117 +++++++++++++++++ .../salesforceOauthTokenRepository.json | 9 ++ .../salesforceOrganizationRepository.json | 9 ++ .../salesforceUserRepository.json | 9 ++ 10 files changed, 427 insertions(+), 2 deletions(-) create mode 100644 src/main/resources/logback-test.xml create mode 100644 src/test/java/com/salessparrow/api/functional/SalesSparrowApiTest.java create mode 100644 src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java create mode 100644 src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java create mode 100644 src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java create mode 100644 src/test/resources/fixtures/unit/repositories/salesforceOauthTokenRepository.json create mode 100644 src/test/resources/fixtures/unit/repositories/salesforceOrganizationRepository.json create mode 100644 src/test/resources/fixtures/unit/repositories/salesforceUserRepository.json diff --git a/src/main/java/com/salessparrow/api/domain/SalesforceOrganization.java b/src/main/java/com/salessparrow/api/domain/SalesforceOrganization.java index 97209234..f0de80ff 100644 --- a/src/main/java/com/salessparrow/api/domain/SalesforceOrganization.java +++ b/src/main/java/com/salessparrow/api/domain/SalesforceOrganization.java @@ -1,5 +1,6 @@ package com.salessparrow.api.domain; +import java.io.Serializable; import java.util.Date; import java.util.HashMap; import java.util.Map; @@ -18,7 +19,7 @@ @Data @NoArgsConstructor @DynamoDBTable(tableName = "salesforce_organizations") -public class SalesforceOrganization { +public class SalesforceOrganization implements Serializable { public enum Status { ACTIVE(1), diff --git a/src/main/resources/logback-test.xml b/src/main/resources/logback-test.xml new file mode 100644 index 00000000..b8647966 --- /dev/null +++ b/src/main/resources/logback-test.xml @@ -0,0 +1,25 @@ + + + + + + + + %d{yyyy-MM-dd HH:mm:ss} %highlight(%-5level) [%X{trackingId}] %logger{36} - %highlight(%msg%n) + + + + + + + + + + + + + + + + + diff --git a/src/test/java/com/salessparrow/api/functional/SalesSparrowApiTest.java b/src/test/java/com/salessparrow/api/functional/SalesSparrowApiTest.java new file mode 100644 index 00000000..82b7dea1 --- /dev/null +++ b/src/test/java/com/salessparrow/api/functional/SalesSparrowApiTest.java @@ -0,0 +1,20 @@ +package com.salessparrow.api.functional; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest +public class SalesSparrowApiTest { + + @Autowired + private ApplicationContext ctx; + + @Test + public void contextLoads() { + assertThat(ctx).isNotNull(); + } +} diff --git a/src/test/java/com/salessparrow/api/helper/Setup.java b/src/test/java/com/salessparrow/api/helper/Setup.java index a8b474a6..c5d4049b 100644 --- a/src/test/java/com/salessparrow/api/helper/Setup.java +++ b/src/test/java/com/salessparrow/api/helper/Setup.java @@ -9,7 +9,6 @@ import com.github.dynamobee.Dynamobee; import com.github.dynamobee.exception.DynamobeeException; -import com.salessparrow.api.lib.globalConstants.CacheConstants; /** * This class is used to create the setup. diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java new file mode 100644 index 00000000..e66f1252 --- /dev/null +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java @@ -0,0 +1,117 @@ +package com.salessparrow.api.unit.repositories; + +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.boot.test.mock.mockito.MockBean; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.when; + +import java.io.IOException; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; +import com.github.dynamobee.exception.DynamobeeException; +import com.salessparrow.api.domain.SalesforceOauthToken; +import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.helper.Cleanup; +import com.salessparrow.api.helper.Common; +import com.salessparrow.api.helper.FixtureData; +import com.salessparrow.api.helper.LoadFixture; +import com.salessparrow.api.helper.Setup; +import com.salessparrow.api.lib.errorLib.ErrorObject; +import com.salessparrow.api.repositories.SalesforceOauthTokenRepository; + +@SpringBootTest +@Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) +public class SalesforceOauthTokenRepositoryTest { + + @Autowired + private Setup setup; + + @Autowired + private Cleanup cleanup; + + @Autowired + private Common common; + + @Autowired + private LoadFixture loadFixture; + + @BeforeEach + public void setUp() throws DynamobeeException, IOException { + setup.perform(); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + @MockBean + private DynamoDBMapper dynamoDBMapper; + + @Autowired + private SalesforceOauthTokenRepository salesforceOauthTokenRepository; + + @Test + public void testSaveSalesforceOauthToken() { + //Valid Save Db Query + SalesforceOauthToken salesforceOauthTokenValid = new SalesforceOauthToken(); + salesforceOauthTokenValid.setExternalUserId("externalUserId-1"); + SalesforceOauthToken salesforceOauthTokenResp = salesforceOauthTokenRepository.saveSalesforceOauthToken(salesforceOauthTokenValid); + assertEquals(salesforceOauthTokenValid.getExternalUserId(), salesforceOauthTokenResp.getExternalUserId()); + + // Invalid Save Db Query without partition key + SalesforceOauthToken salesforceOauthTokenInvalid = new SalesforceOauthToken(); + salesforceOauthTokenInvalid.setExternalUserId("externalUserId-2"); + + // Mock the behavior to throw an exception when save is called + doThrow(new CustomException(new ErrorObject("test:r_sotr_tssfot_1", "something_went_wrong", "mock db save error"))) + .when(dynamoDBMapper) + .save(salesforceOauthTokenInvalid); + + // Test if CustomException is thrown with the expected error code + CustomException thrownException = assertThrows( + CustomException.class, + () -> salesforceOauthTokenRepository.saveSalesforceOauthToken(salesforceOauthTokenInvalid) + ); + // Validate the error identifier to be a 500 error + assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); + } + + @Test + public void testGetSalesforceOauthTokenByExternalUserId() throws Exception{{ + + String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/unit/repositories/salesforceOauthTokenRepository.json", currentFunctionName); + loadFixture.perform(fixtureData); + + //Valid Get Db Query + SalesforceOauthToken salesforceOauthTokenResp = salesforceOauthTokenRepository.getSalesforceOauthTokenByExternalUserId("0055i00000AUxQHAA1"); + assertEquals("0055i00000AUxQHAA1", salesforceOauthTokenResp.getExternalUserId()); + + String testExternalUserId = "externalUserId-3"; + + // Mock the behavior to throw an exception when load is called + when(dynamoDBMapper.load(SalesforceOauthToken.class, testExternalUserId)).thenThrow( + new CustomException(new ErrorObject("test:r_sotr_gsotbsfui_1", + "something_went_wrong","mock db query error"))); + + // Mock Invalid Get Db Query + // Test if CustomException is thrown with the expected error code + CustomException thrownException = assertThrows( + CustomException.class, + () -> salesforceOauthTokenRepository.getSalesforceOauthTokenByExternalUserId(testExternalUserId) + ); + // Validate the error identifier to be a 500 error + assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); + } + } +} diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java new file mode 100644 index 00000000..c321ba56 --- /dev/null +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java @@ -0,0 +1,119 @@ +package com.salessparrow.api.unit.repositories; + +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.boot.test.mock.mockito.MockBean; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.when; + +import java.io.IOException; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; +import com.github.dynamobee.exception.DynamobeeException; +import com.salessparrow.api.domain.SalesforceOrganization; +import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.helper.Cleanup; +import com.salessparrow.api.helper.Common; +import com.salessparrow.api.helper.FixtureData; +import com.salessparrow.api.helper.LoadFixture; +import com.salessparrow.api.helper.Setup; +import com.salessparrow.api.lib.errorLib.ErrorObject; +import com.salessparrow.api.repositories.SalesforceOrganizationRepository; + +@SpringBootTest +@Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) +public class SalesforceOrganizationRepositoryTest { + + @Autowired + private Setup setup; + + @Autowired + private Cleanup cleanup; + + @Autowired + private Common common; + + @Autowired + private LoadFixture loadFixture; + + @BeforeEach + public void setUp() throws DynamobeeException, IOException { + setup.perform(); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + @MockBean + private DynamoDBMapper dynamoDBMapper; + + @Autowired + private SalesforceOrganizationRepository salesforceOrganizationRepository; + + @Test + public void testSaveSalesforceOrganization() { + //Valid Save Db Query + SalesforceOrganization salesforceOrganizationValid = new SalesforceOrganization(); + salesforceOrganizationValid.setExternalOrganizationId("externalUserId-1"); + SalesforceOrganization salesforceOrganizationResp = salesforceOrganizationRepository.saveSalesforceOrganization(salesforceOrganizationValid); + assertEquals(salesforceOrganizationValid.getExternalOrganizationId(), salesforceOrganizationResp.getExternalOrganizationId()); + + // Invalid Save Db Query without partition key + SalesforceOrganization salesforceOrganizationInvalid = new SalesforceOrganization(); + salesforceOrganizationInvalid.setExternalOrganizationId("externalUserId-2"); + + // Mock the behavior to throw an exception when save is called + doThrow(new CustomException(new ErrorObject("test:r_sor_tssfo_1", "something_went_wrong", "mock db save error"))) + .when(dynamoDBMapper) + .save(salesforceOrganizationInvalid); + + // Test if CustomException is thrown with the expected error code + CustomException thrownException = assertThrows( + CustomException.class, + () -> salesforceOrganizationRepository.saveSalesforceOrganization(salesforceOrganizationInvalid) + ); + // Validate the error identifier to be a 500 error + assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); + } + + @Test + public void testGetSalesforceOrganizationByExternalOrganizationId() throws Exception{{ + + // String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); + // FixtureData fixtureData = common.loadFixture("classpath:fixtures/unit/repositories/salesforceOrganizationRepository.json", currentFunctionName); + // loadFixture.perform(fixtureData); + + // //Valid Get Db Query + // SalesforceOrganization salesforceOrganizationResp = salesforceOrganizationRepository.getSalesforceOrganizationByExternalOrganizationId("000Org-id"); + // System.out.println("salesfo===========: " + salesforceOrganizationResp); + + // assertEquals("000Org-id", salesforceOrganizationResp.getExternalOrganizationId()); + + String testExternalOrganizationId = "externalUserId-2"; + + // Mock the behavior to throw an exception when load is called + when(dynamoDBMapper.load(SalesforceOrganization.class, testExternalOrganizationId)).thenThrow( + new CustomException(new ErrorObject("test:r_sor_gsotbsfui_1", + "something_went_wrong","mock db query error"))); + + // Mock Invalid Get Db Query + // Test if CustomException is thrown with the expected error code + CustomException thrownException = assertThrows( + CustomException.class, + () -> salesforceOrganizationRepository.getSalesforceOrganizationByExternalOrganizationId(testExternalOrganizationId) + ); + // Validate the error identifier to be a 500 error + assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); + } + } +} diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java new file mode 100644 index 00000000..cfc61449 --- /dev/null +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java @@ -0,0 +1,117 @@ +package com.salessparrow.api.unit.repositories; + +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.boot.test.mock.mockito.MockBean; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.when; + +import java.io.IOException; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; +import com.github.dynamobee.exception.DynamobeeException; +import com.salessparrow.api.domain.SalesforceUser; +import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.helper.Cleanup; +import com.salessparrow.api.helper.Common; +import com.salessparrow.api.helper.FixtureData; +import com.salessparrow.api.helper.LoadFixture; +import com.salessparrow.api.helper.Setup; +import com.salessparrow.api.lib.errorLib.ErrorObject; +import com.salessparrow.api.repositories.SalesforceUserRepository; + +@SpringBootTest +@Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) +public class SalesforceUserRepositoryTest { + + @Autowired + private Setup setup; + + @Autowired + private Cleanup cleanup; + + @Autowired + private Common common; + + @Autowired + private LoadFixture loadFixture; + + @BeforeEach + public void setUp() throws DynamobeeException, IOException { + setup.perform(); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + @MockBean + private DynamoDBMapper dynamoDBMapper; + + @Autowired + private SalesforceUserRepository salesforceUserRepository; + + @Test + public void testSaveSalesforceUser() { + //Valid Save Db Query + SalesforceUser salesforceUserValid = new SalesforceUser(); + salesforceUserValid.setExternalUserId("externalUserId-test1"); + SalesforceUser salesforceUserResp = salesforceUserRepository.saveSalesforceUser(salesforceUserValid); + assertEquals(salesforceUserValid.getExternalUserId(), salesforceUserResp.getExternalUserId()); + + // Invalid Save Db Query without partition key + SalesforceUser salesforceUserInvalid = new SalesforceUser(); + salesforceUserInvalid.setExternalUserId("externalUserId-test2"); + + // Mock the behavior to throw an exception when save is called + doThrow(new CustomException(new ErrorObject("test:r_sotr_tssfu_1", "something_went_wrong", "mock db save error"))) + .when(dynamoDBMapper) + .save(salesforceUserInvalid); + + // Test if CustomException is thrown with the expected error code + CustomException thrownException = assertThrows( + CustomException.class, + () -> salesforceUserRepository.saveSalesforceUser(salesforceUserInvalid) + ); + // Validate the error identifier to be a 500 error + assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); + } + + @Test + public void testGetSalesforceUserByExternalUserId() throws Exception{{ + + String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/unit/repositories/salesforceUserRepository.json", currentFunctionName); + loadFixture.perform(fixtureData); + + //Valid Get Db Query + SalesforceUser salesforceUserResp = salesforceUserRepository.getSalesforceUserByExternalUserId("0055i00000AUxQHAA1"); + assertEquals("0055i00000AUxQHAA1", salesforceUserResp.getExternalUserId()); + + String testExternalUserId = "externalUserId-test3"; + + // Mock the behavior to throw an exception when load is called + when(dynamoDBMapper.load(SalesforceUser.class, testExternalUserId)).thenThrow( + new CustomException(new ErrorObject("test:r_sur_gsotbsfui_1", + "something_went_wrong","mock db query error"))); + + // Mock Invalid Get Db Query + // Test if CustomException is thrown with the expected error code + CustomException thrownException = assertThrows( + CustomException.class, + () -> salesforceUserRepository.getSalesforceUserByExternalUserId(testExternalUserId) + ); + // Validate the error identifier to be a 500 error + assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); + } + } +} diff --git a/src/test/resources/fixtures/unit/repositories/salesforceOauthTokenRepository.json b/src/test/resources/fixtures/unit/repositories/salesforceOauthTokenRepository.json new file mode 100644 index 00000000..719f6bdc --- /dev/null +++ b/src/test/resources/fixtures/unit/repositories/salesforceOauthTokenRepository.json @@ -0,0 +1,9 @@ +{ + "testGetSalesforceOauthTokenByExternalUserId": { + "salesforce_oauth_tokens": [ + { + "filepath": "classpath:fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" + } + ] + } +} \ No newline at end of file diff --git a/src/test/resources/fixtures/unit/repositories/salesforceOrganizationRepository.json b/src/test/resources/fixtures/unit/repositories/salesforceOrganizationRepository.json new file mode 100644 index 00000000..afaf8013 --- /dev/null +++ b/src/test/resources/fixtures/unit/repositories/salesforceOrganizationRepository.json @@ -0,0 +1,9 @@ +{ + "testGetSalesforceOrganizationByExternalOrganizationId": { + "salesforce_organizations": [ + { + "filepath": "classpath:fixtures/repositories/salesforceOrganization/ActiveSalesforceOrganization.json" + } + ] + } +} \ No newline at end of file diff --git a/src/test/resources/fixtures/unit/repositories/salesforceUserRepository.json b/src/test/resources/fixtures/unit/repositories/salesforceUserRepository.json new file mode 100644 index 00000000..89b32d99 --- /dev/null +++ b/src/test/resources/fixtures/unit/repositories/salesforceUserRepository.json @@ -0,0 +1,9 @@ +{ + "testGetSalesforceUserByExternalUserId": { + "salesforce_users": [ + { + "filepath": "classpath:fixtures/repositories/salesforceUser/ActiveSalesforceUser.json" + } + ] + } +} \ No newline at end of file From f0bdb0df8bbc95086e1a7292180dc7867ac70c6c Mon Sep 17 00:00:00 2001 From: Yagnik Thummar Date: Mon, 28 Aug 2023 09:40:07 +0530 Subject: [PATCH 107/195] urlEncoder changes. --- src/main/java/com/salessparrow/api/lib/Util.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/salessparrow/api/lib/Util.java b/src/main/java/com/salessparrow/api/lib/Util.java index 0139c418..d7274dab 100644 --- a/src/main/java/com/salessparrow/api/lib/Util.java +++ b/src/main/java/com/salessparrow/api/lib/Util.java @@ -83,6 +83,8 @@ public static String escapeSpecialChars(String input) { } public static String urlEncoder(String input){ + if(input == null || input == "") + return input; try { return URLEncoder.encode(input, "UTF-8"); } catch (UnsupportedEncodingException e) { From 27a42e9780b865a0a8dbc5aa69a0f41bfbc4ccc8 Mon Sep 17 00:00:00 2001 From: ajinkyac03 Date: Mon, 28 Aug 2023 09:57:33 +0530 Subject: [PATCH 108/195] Added unit test cases for OpenAiRequest wrapper. --- .../api/config/CoreConstants.java | 2 +- .../lib/globalConstants/SecretConstants.java | 4 + .../PostCrmActionsSuggestionsTest.java | 2 +- .../unit/lib/openAi/OpenAiRequestTest.java | 80 +++++++++++++++++++ .../lib/openAi/openAiRequest.scenarios.json | 68 ++++++++++++++++ .../openAi/openAiRequestError.scenarios.json | 56 +++++++++++++ 6 files changed, 210 insertions(+), 2 deletions(-) create mode 100644 src/test/java/com/salessparrow/api/unit/lib/openAi/OpenAiRequestTest.java create mode 100644 src/test/resources/data/lib/openAi/openAiRequest.scenarios.json create mode 100644 src/test/resources/data/lib/openAi/openAiRequestError.scenarios.json diff --git a/src/main/java/com/salessparrow/api/config/CoreConstants.java b/src/main/java/com/salessparrow/api/config/CoreConstants.java index 8b8576da..37b2f81c 100644 --- a/src/main/java/com/salessparrow/api/config/CoreConstants.java +++ b/src/main/java/com/salessparrow/api/config/CoreConstants.java @@ -88,7 +88,7 @@ public static String[] getWhitelistedRedirectUris() { * @return String */ public static String openAiApiKey() { - return System.getenv("OPENAI_API_KEY"); + return SecretConstants.openAiApiKey(); } /** diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java index 5317f640..3ec93ed2 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java @@ -122,6 +122,10 @@ public static String salesforceWhitelistedRedirectUris() { return getSecret("SALESFORCE_WHITELISTED_REDIRECT_URIS"); } + public static String openAiApiKey() { + return getSecret("OPENAI_API_KEY"); + } + public static String errorEmailFrom() { return getSecret("ERROR_EMAIL_FROM"); } diff --git a/src/test/java/com/salessparrow/api/functional/controllers/suggestionsController/PostCrmActionsSuggestionsTest.java b/src/test/java/com/salessparrow/api/functional/controllers/suggestionsController/PostCrmActionsSuggestionsTest.java index 8c866170..f808062b 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/suggestionsController/PostCrmActionsSuggestionsTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/suggestionsController/PostCrmActionsSuggestionsTest.java @@ -84,7 +84,7 @@ public void testPostCrmActionsSuggestions() throws Exception { when(openAiRequestMock.makeRequest(any())).thenReturn(getAccountMockResponse); String expectedOutput = objectMapper.writeValueAsString(testDataItem.getOutput()); - String cookieValue = Constants.SALESFORCE_ACTIVE_USET_COOKIE_VALUE; + String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.post("/api/v1/suggestions/crm-actions") .content(objectMapper.writeValueAsString(testDataItem.getInput())) diff --git a/src/test/java/com/salessparrow/api/unit/lib/openAi/OpenAiRequestTest.java b/src/test/java/com/salessparrow/api/unit/lib/openAi/OpenAiRequestTest.java new file mode 100644 index 00000000..0b7a1b23 --- /dev/null +++ b/src/test/java/com/salessparrow/api/unit/lib/openAi/OpenAiRequestTest.java @@ -0,0 +1,80 @@ +package com.salessparrow.api.unit.lib.openAi; + +import static org.junit.jupiter.api.Assertions.assertEquals; +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 java.io.IOException; +import java.util.List; + +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 org.springframework.web.reactive.function.client.WebClientResponseException; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.helper.Common; +import com.salessparrow.api.helper.Scenario; +import com.salessparrow.api.lib.httpLib.HttpClient; +import com.salessparrow.api.lib.httpLib.HttpClient.HttpResponse; +import com.salessparrow.api.lib.openAi.OpenAiRequest; + +@SpringBootTest +@Import({Common.class, OpenAiRequest.class}) +public class OpenAiRequestTest { + @Autowired + private OpenAiRequest openAiRequest; + + @Autowired + private Common common; + + @MockBean + private HttpClient httpClientMock; + + @Test + void testOpenAiRequest() throws IOException { + List testDataItems = common.loadScenariosData("classpath:data/lib/openAi/openAiRequest.scenarios.json"); + MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); + + for (Scenario testDataItem : testDataItems) { + ObjectMapper objectMapper = new ObjectMapper(); + + HttpResponse openAiMocksResponse = new HttpResponse(); + openAiMocksResponse.setResponseBody(objectMapper.writeValueAsString(testDataItem.getMocks().get("makeRequest"))); + httpClientMockedStatic.when(() -> HttpClient.makePostRequest(anyString(), anyMap(), any(), anyInt())) + .thenReturn(openAiMocksResponse); + + HttpResponse actualResponse = openAiRequest.makeRequest(testDataItem.getInput().get("payload")); + String expectedOutput = objectMapper.writeValueAsString(testDataItem.getOutput()); + + assertEquals(actualResponse.getResponseBody(), expectedOutput); + } + httpClientMockedStatic.close(); + } + + @Test + void testOpenAiRequestError() throws IOException { + List testDataItems = common.loadScenariosData("classpath:data/lib/openAi/openAiRequestError.scenarios.json"); + MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); + + for (Scenario testDataItem : testDataItems) { + int statusCode = (int) testDataItem.getInput().get("statusCode"); + httpClientMockedStatic.when(() -> HttpClient.makePostRequest(anyString(), anyMap(), any(), anyInt())) + .thenThrow( new WebClientResponseException("error", statusCode, "error", null, null, null)); + try { + openAiRequest.makeRequest(testDataItem.getInput().get("payload")); + } catch (CustomException e) { + String expectedApiErrorIdentifier = (String) testDataItem.getOutput().get("apiErrorIdentifier"); + + assertEquals(e.getErrorObject().getApiErrorIdentifier(), expectedApiErrorIdentifier); + } + } + httpClientMockedStatic.close(); + } +} diff --git a/src/test/resources/data/lib/openAi/openAiRequest.scenarios.json b/src/test/resources/data/lib/openAi/openAiRequest.scenarios.json new file mode 100644 index 00000000..42a9b43b --- /dev/null +++ b/src/test/resources/data/lib/openAi/openAiRequest.scenarios.json @@ -0,0 +1,68 @@ +[ + { + "description": "Should return correct result", + "input": { + "payload": { + "model": "model", + "messages": [ + { + "role": "user", + "content": "hello" + } + ] + } + }, + "mocks":{ + "makeRequest":{ + "id": "chatcmpl-0000", + "object": "chat.completion", + "created": 1692945329, + "model": "gpt-3.5-turbo-0613", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": null, + "function_call": { + "name": "suggest_actions", + "arguments": "{\n \"add_task\": [\n {\n \"description\": \"Review calendar for editorial, advertorial, and social media content\",\n \"due_date\": \"2023-08-30\"\n }\n ]\n}" + } + }, + "finish_reason": "function_call" + } + ], + "usage": { + "prompt_tokens": 168, + "completion_tokens": 52, + "total_tokens": 220 + } + } + }, + "output": { + "id": "chatcmpl-0000", + "object": "chat.completion", + "created": 1692945329, + "model": "gpt-3.5-turbo-0613", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": null, + "function_call": { + "name": "suggest_actions", + "arguments": "{\n \"add_task\": [\n {\n \"description\": \"Review calendar for editorial, advertorial, and social media content\",\n \"due_date\": \"2023-08-30\"\n }\n ]\n}" + } + }, + "finish_reason": "function_call" + } + ], + "usage": { + "prompt_tokens": 168, + "completion_tokens": 52, + "total_tokens": 220 + } + } + } +] \ No newline at end of file diff --git a/src/test/resources/data/lib/openAi/openAiRequestError.scenarios.json b/src/test/resources/data/lib/openAi/openAiRequestError.scenarios.json new file mode 100644 index 00000000..04c48b25 --- /dev/null +++ b/src/test/resources/data/lib/openAi/openAiRequestError.scenarios.json @@ -0,0 +1,56 @@ +[ + { + "description": "Test 401 response", + "input": { + "payload": { + "model": "model", + "messages": [ + { + "role": "user", + "content": "hello" + } + ] + }, + "statusCode": 401 + }, + "output": { + "apiErrorIdentifier": "something_went_wrong" + } + }, + { + "description": "Test 400 response", + "input": { + "payload": { + "model": "model", + "messages": [ + { + "role": "user", + "content": "hello" + } + ] + }, + "statusCode": 400 + }, + "output": { + "apiErrorIdentifier": "something_went_wrong" + } + }, + { + "description": "Test 500 response", + "input": { + "payload": { + "model": "model", + "messages": [ + { + "role": "user", + "content": "hello" + } + ] + }, + "statusCode": 500 + }, + "output": { + "apiErrorIdentifier": "something_went_wrong" + } + } +] \ No newline at end of file From 33e39671b6ccd1bb225e88586205e4b683c9fac8 Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Mon, 28 Aug 2023 10:17:06 +0530 Subject: [PATCH 109/195] Updated delete note error to params error --- .../DeleteSalesforceAccountNote.java | 13 ++++++++----- src/main/resources/config/ParamErrorConfig.json | 5 +++++ .../deleteAccountNote.scenarios.json | 14 ++++++++++---- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteSalesforceAccountNote.java b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteSalesforceAccountNote.java index 5509fb4d..605c7cf1 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteSalesforceAccountNote.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteSalesforceAccountNote.java @@ -1,6 +1,7 @@ package com.salessparrow.api.lib.crmActions.deleteAccountNote; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import org.slf4j.Logger; @@ -11,7 +12,7 @@ import com.salessparrow.api.domain.User; import com.salessparrow.api.exception.CustomException; import com.salessparrow.api.lib.Util; -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; import com.salessparrow.api.lib.salesforce.dto.CompositeRequestDto; @@ -74,10 +75,12 @@ public void parseResponse(String responseBody) { String errorBody = deleteNoteCompositeResponse.get("body").asText(); throw new CustomException( - new ErrorObject( - "l_ca_dan_dasn_pr_1", - "internal_server_error", - errorBody)); + new ParamErrorObject( + "l_ca_dan_dasn_pr_1", + errorBody, + Arrays.asList("invalid_note_id") + ) + ); } } } \ No newline at end of file diff --git a/src/main/resources/config/ParamErrorConfig.json b/src/main/resources/config/ParamErrorConfig.json index df5ec465..f807d89c 100644 --- a/src/main/resources/config/ParamErrorConfig.json +++ b/src/main/resources/config/ParamErrorConfig.json @@ -28,5 +28,10 @@ "parameter": "description", "param_error_identifier": "description_too_long", "message": "Description too long. Please shorten and try again." + }, + "invalid_note_id": { + "parameter": "note_id", + "param_error_identifier": "invalid_note_id", + "message": "The note id you sent is incorrect. Please double check and try again." } } \ No newline at end of file diff --git a/src/test/resources/data/controllers/accountNoteController/deleteAccountNote.scenarios.json b/src/test/resources/data/controllers/accountNoteController/deleteAccountNote.scenarios.json index 1fb5d853..f9a6f2d1 100644 --- a/src/test/resources/data/controllers/accountNoteController/deleteAccountNote.scenarios.json +++ b/src/test/resources/data/controllers/accountNoteController/deleteAccountNote.scenarios.json @@ -43,11 +43,17 @@ } }, "output": { - "http_code": 500, - "message": "Something went wrong.", - "code": "INTERNAL_SERVER_ERROR", + "http_code": 400, + "message": "At least one parameter is invalid or missing.", + "code": "INVALID_PARAMS", "internal_error_identifier": "l_ca_dan_dasn_pr_1", - "param_errors": [] + "param_errors": [ + { + "parameter": "note_id", + "param_error_identifier": "invalid_note_id", + "message": "The note id you sent is incorrect. Please double check and try again." + } + ] } } ] \ No newline at end of file From c1c4aa31ca61755e0e3557e127ec8656bfcc7d30 Mon Sep 17 00:00:00 2001 From: ajinkyac03 Date: Mon, 28 Aug 2023 10:23:46 +0530 Subject: [PATCH 110/195] Added timeout in constants. --- .../api/lib/globalConstants/OpenAiConstants.java | 4 ++++ .../api/lib/openAi/OpenAiPayloadBuilder.java | 9 ++++++--- .../com/salessparrow/api/lib/openAi/OpenAiRequest.java | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/OpenAiConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/OpenAiConstants.java index 9837f214..f07f41ca 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/OpenAiConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/OpenAiConstants.java @@ -8,4 +8,8 @@ public class OpenAiConstants { public String chatCompletionUrl() { return "https://api.openai.com/v1/chat/completions"; } + + public Integer timeoutMillis() { + return 20000; + } } diff --git a/src/main/java/com/salessparrow/api/lib/openAi/OpenAiPayloadBuilder.java b/src/main/java/com/salessparrow/api/lib/openAi/OpenAiPayloadBuilder.java index c2777bd8..a5fd0408 100644 --- a/src/main/java/com/salessparrow/api/lib/openAi/OpenAiPayloadBuilder.java +++ b/src/main/java/com/salessparrow/api/lib/openAi/OpenAiPayloadBuilder.java @@ -23,7 +23,7 @@ public String payloadForCrmActionsSuggestions(String text) { " \"messages\": [\n" + " {\n" + " \"role\": \"user\",\n" + - " \"content\": \"You are an AI assistant which gives suggestion on creating task using the input message.Only use the functions you have been provided with. \\nInput message: \\n" + text + "\\n\"\n" + + " \"content\": \"You are an AI assistant which gives suggestion on creating task in crm using the input message.Only use the functions you have been provided with. \\nInput message: \\n" + text + "\\n\"\n" + " }\n" + " ],\n" + " \"functions\": [\n" + @@ -46,7 +46,7 @@ public String payloadForCrmActionsSuggestions(String text) { " },\n" + " \"due_date\": {\n" + " \"type\": \"string\",\n" + - " \"description\": \"Due date for task. Must be in YYYY-MM-DD format. This is mandatory.\" \n" + + " \"description\": \"Due date for task in YYYY-MM-DD format. Today's date is " + getTodaysDate() + ". This is mandatory\"\n" + " }\n" + " },\n" + " \"required\": [\"description\", \"due_date\"]\n" + @@ -60,7 +60,10 @@ public String payloadForCrmActionsSuggestions(String text) { "}"; } - // get todays date in YYYY-MM-DD format + /** + * Todays date in yyyy-MM-dd format. + * @return + */ public String getTodaysDate() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); return sdf.format(new Date()); diff --git a/src/main/java/com/salessparrow/api/lib/openAi/OpenAiRequest.java b/src/main/java/com/salessparrow/api/lib/openAi/OpenAiRequest.java index 73b42f62..84b8d64c 100644 --- a/src/main/java/com/salessparrow/api/lib/openAi/OpenAiRequest.java +++ b/src/main/java/com/salessparrow/api/lib/openAi/OpenAiRequest.java @@ -27,7 +27,7 @@ public HttpClient.HttpResponse makeRequest(Object payload) { Map headers = new HashMap<>(); headers.put("Authorization", "Bearer " + CoreConstants.openAiApiKey()); - Integer timeoutMillis = 30000; + Integer timeoutMillis = openAiConstants.timeoutMillis(); try { HttpClient.HttpResponse response = HttpClient.makePostRequest( httpReqUrl, From 7d014be121b45bf0ba122096c1d66eb133e46305 Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Mon, 28 Aug 2023 10:24:53 +0530 Subject: [PATCH 111/195] Updated get accounts task list error to params error --- .../GetSalesforceAccountTasksList.java | 13 ++++++++----- src/main/resources/config/ParamErrorConfig.json | 5 +++++ .../getAccountTasksList.scenarios.json | 14 ++++++++++---- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetSalesforceAccountTasksList.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetSalesforceAccountTasksList.java index 19c105b7..5f7a7a31 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetSalesforceAccountTasksList.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetSalesforceAccountTasksList.java @@ -1,6 +1,7 @@ package com.salessparrow.api.lib.crmActions.getAccountTasksList; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -18,7 +19,7 @@ import com.salessparrow.api.dto.formatter.GetTasksListFormatterDto; import com.salessparrow.api.exception.CustomException; import com.salessparrow.api.lib.Util; -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; import com.salessparrow.api.lib.salesforce.dto.CompositeRequestDto; @@ -89,10 +90,12 @@ public GetTasksListFormatterDto parseResponse(String responseBody) { String errorBody = getTasksCompositeResponse.get("body").asText(); throw new CustomException( - new ErrorObject( - "l_ca_gatl_gsatl_pr_1", - "something_went_wrong", - errorBody)); + new ParamErrorObject( + "l_ca_gatl_gsatl_pr_1", + errorBody, + Arrays.asList("invalid_account_id") + ) + ); } JsonNode recordsNode = rootNode.get("compositeResponse").get(0).get("body").get("records");; diff --git a/src/main/resources/config/ParamErrorConfig.json b/src/main/resources/config/ParamErrorConfig.json index df5ec465..e891df4b 100644 --- a/src/main/resources/config/ParamErrorConfig.json +++ b/src/main/resources/config/ParamErrorConfig.json @@ -28,5 +28,10 @@ "parameter": "description", "param_error_identifier": "description_too_long", "message": "Description too long. Please shorten and try again." + }, + "invalid_account_id": { + "parameter": "account_id", + "param_error_identifier": "invalid_account_id", + "message": "The account id you sent is incorrect. Please double check and try again." } } \ No newline at end of file diff --git a/src/test/resources/data/controllers/accountTaskController/getAccountTasksList.scenarios.json b/src/test/resources/data/controllers/accountTaskController/getAccountTasksList.scenarios.json index 2a4a24fe..0d1e6afc 100644 --- a/src/test/resources/data/controllers/accountTaskController/getAccountTasksList.scenarios.json +++ b/src/test/resources/data/controllers/accountTaskController/getAccountTasksList.scenarios.json @@ -242,11 +242,17 @@ } }, "output": { - "http_code": 500, - "message": "Something went wrong.", - "code": "INTERNAL_SERVER_ERROR", + "http_code": 400, + "message": "At least one parameter is invalid or missing.", + "code": "INVALID_PARAMS", "internal_error_identifier": "l_ca_gatl_gsatl_pr_1", - "param_errors": [] + "param_errors": [ + { + "parameter": "account_id", + "param_error_identifier": "invalid_account_id", + "message": "The account id you sent is incorrect. Please double check and try again." + } + ] } } ] \ No newline at end of file From 0fb5ebe640b21c28938f505969a03954340d94a7 Mon Sep 17 00:00:00 2001 From: ajinkyac03 Date: Mon, 28 Aug 2023 10:33:07 +0530 Subject: [PATCH 112/195] Added comments and loggers. --- sample.secrets.json | 3 ++- .../salessparrow/api/lib/GetCrmActionSuggestions.java | 11 +++++++++++ .../salessparrow/api/lib/openAi/OpenAiRequest.java | 5 +++++ .../suggestions/CrmActionsSuggestionsService.java | 5 +++++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/sample.secrets.json b/sample.secrets.json index 46be9a5e..f3be477d 100644 --- a/sample.secrets.json +++ b/sample.secrets.json @@ -13,5 +13,6 @@ "DYNAMO_DB_URL": "", "ERROR_MAIL_FROM": "", "ERROR_MAIL_TO": "", - "COOKIE_DOMAIN": "" + "COOKIE_DOMAIN": "", + "OPENAI_API_KEY": "" } \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java b/src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java index 48d518a7..9bcc1831 100644 --- a/src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java +++ b/src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java @@ -6,6 +6,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -13,6 +14,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.salessparrow.api.controllers.SuggestionsController; import com.salessparrow.api.dto.entities.AddTaskSuggestionEntityDto; import com.salessparrow.api.dto.formatter.CrmActionSuggestionsFormatterDto; import com.salessparrow.api.exception.CustomException; @@ -30,8 +32,12 @@ public class GetCrmActionSuggestions { @Autowired private OpenAiPayloadBuilder openAiPayloadBuilder; + + private Logger logger = org.slf4j.LoggerFactory.getLogger(SuggestionsController.class); public CrmActionSuggestionsFormatterDto getTaskSuggestions(String text) { + logger.info("Crm actions suggestions lib called"); + String escapedText = escapeForJson(text); String payload = openAiPayloadBuilder.payloadForCrmActionsSuggestions(escapedText); @@ -89,6 +95,11 @@ private CrmActionSuggestionsFormatterDto parseResponse(String responseBody){ } } + /** + * Escape the input string for json. + * @param input + * @return + */ private String escapeForJson(String input) { return input.replace("\"", "\\\"").replace("\n", "\\n"); } diff --git a/src/main/java/com/salessparrow/api/lib/openAi/OpenAiRequest.java b/src/main/java/com/salessparrow/api/lib/openAi/OpenAiRequest.java index 84b8d64c..6c3e256c 100644 --- a/src/main/java/com/salessparrow/api/lib/openAi/OpenAiRequest.java +++ b/src/main/java/com/salessparrow/api/lib/openAi/OpenAiRequest.java @@ -3,11 +3,13 @@ import java.util.HashMap; import java.util.Map; +import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.client.WebClientResponseException; import com.salessparrow.api.config.CoreConstants; +import com.salessparrow.api.controllers.SuggestionsController; import com.salessparrow.api.exception.CustomException; import com.salessparrow.api.lib.errorLib.ErrorObject; import com.salessparrow.api.lib.globalConstants.OpenAiConstants; @@ -20,6 +22,8 @@ public class OpenAiRequest { @Autowired private OpenAiConstants openAiConstants; + + private Logger logger = org.slf4j.LoggerFactory.getLogger(SuggestionsController.class); public HttpClient.HttpResponse makeRequest(Object payload) { String httpReqUrl = openAiConstants.chatCompletionUrl(); @@ -29,6 +33,7 @@ public HttpClient.HttpResponse makeRequest(Object payload) { Integer timeoutMillis = openAiConstants.timeoutMillis(); try { + logger.info("Making request to OpenAI API"); HttpClient.HttpResponse response = HttpClient.makePostRequest( httpReqUrl, headers, diff --git a/src/main/java/com/salessparrow/api/services/suggestions/CrmActionsSuggestionsService.java b/src/main/java/com/salessparrow/api/services/suggestions/CrmActionsSuggestionsService.java index 09f6e6e1..d377c4be 100644 --- a/src/main/java/com/salessparrow/api/services/suggestions/CrmActionsSuggestionsService.java +++ b/src/main/java/com/salessparrow/api/services/suggestions/CrmActionsSuggestionsService.java @@ -1,8 +1,10 @@ package com.salessparrow.api.services.suggestions; +import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import com.salessparrow.api.controllers.SuggestionsController; import com.salessparrow.api.dto.formatter.CrmActionSuggestionsFormatterDto; import com.salessparrow.api.dto.requestMapper.CrmActionsSuggestionsDto; import com.salessparrow.api.lib.GetCrmActionSuggestions; @@ -14,8 +16,11 @@ public class CrmActionsSuggestionsService { @Autowired private GetCrmActionSuggestions getCrmActionSuggestions; + + private Logger logger = org.slf4j.LoggerFactory.getLogger(SuggestionsController.class); public CrmActionSuggestionsFormatterDto getSuggestions(CrmActionsSuggestionsDto crmActionsSuggestionsDto) { + logger.info("Crm actions service called"); String text = crmActionsSuggestionsDto.getText(); return getCrmActionSuggestions.getTaskSuggestions(text); From 8a5ddd090382f2a65b7498ba065497ca05f911da Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Mon, 28 Aug 2023 11:26:10 +0530 Subject: [PATCH 113/195] added changelog documentation --- repo-docs/CHANGELOG.md | 58 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 repo-docs/CHANGELOG.md diff --git a/repo-docs/CHANGELOG.md b/repo-docs/CHANGELOG.md new file mode 100644 index 00000000..4b1c9dd9 --- /dev/null +++ b/repo-docs/CHANGELOG.md @@ -0,0 +1,58 @@ +# SalesSparrow APIs + +## 0.2.0 + +### New Features and Enhancements: + +- API - Disconnect Salesforce Endpoint [#9](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/9) +- API - Get Recommended Actions from Text Endpoint [#13](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/13) +- API - Delete Note Endpoint [#28](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/28) +- API - Create Event for an Account [#30](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/30) +- API - Get a list of Tasks in an account [#33](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/33) +- API - Create Task in an Account Endpoint [#34](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/34) +- API - Get a list of CRM Organization Users Endpoint [#35](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/35) +- Load Secrets from AWS during app initialization [#39](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/39) +- API - Get Accounts Feed Endpoint [#45](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/45) +- Enhance Code Security with Spring Boot [#53](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/53) +- API - Delete Task in an Account Endpoint [#59](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/59) +- Add CHANGELOG.md [#62](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/62) +- Add RELEASE_PROCESS.md [#63](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/63) + +### Bug Fixes: + +- Bug: DynamoDB Upsert Behavior Updates All Fields Instead of Specific Ones [#41](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/41) +- Fix: Updated status enum values [#27](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/pull/27) + +### Miscellaneous: + +- Various code optimizations, refactoring, and improvements for better performance and maintainability. + +--- + +## 0.1.0 + +### Features: + +- Salesforce Connected App Setup [#1](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/1) +- API - Get Salesforce OAuth URL Endpoint [#2](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/2) +- Initial Project Setup [#3](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/3) +- Sequence Diagram - Salesforce OAuth Flow [#4](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/4) +- API - Post Salesforce Connect Endpoint [#5](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/5) +- Initial Setup - Add Support for DynamoDB [#6](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/6) +- API - Get Current User Endpoint [#7](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/7) +- API - User Logout Endpoint [#8](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/8) +- Initial Documentation [#10](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/10) +- API - Implement Salesforce Composite API [#11](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/11) +- API - Get Content Notes of an Account Endpoint [#12](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/12) +- API - Search Accounts Endpoint [#15](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/15) +- API - Create Note Endpoint [#16](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/16) +- API - Get Note By Id Endpoint [#17](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/17) + +--- + +Please feel free to provide feedback, report issues, and contribute to the SalesSparrow project! + +Thank you for using SalesSparrow. + + + From 6bf10adabaabaa66e0ee05e7c462801f32ebe0f4 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Mon, 28 Aug 2023 11:34:28 +0530 Subject: [PATCH 114/195] updated readme for changelog --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 564c204d..ceca2573 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,8 @@ Refer to [ENVIRONMENT_VARS](repo-docs/ENVIRONMENT_VARS.md) for detailed descript ## Project Structure Refer to [PROJECT_STRUCTURE](repo-docs/PROJECT_STRUCTURE.md) for details on the project structure. +## Changelog +Stay up-to-date with the latest changes and improvements in our API by referring to our [CHANGELOG](repo-docs/CHANGELOG.md). ## Release Process Refer to [RELEASE_PROCESS](repo-docs/RELEASE_PROCESS.md) to ensure smooth and consistent software releases. This process outlines the steps to prepare, package, and distribute new versions of our software. From 2ab5958b0e90965c26efc552d8d63d5aa6fe1dd5 Mon Sep 17 00:00:00 2001 From: VRDighe Date: Mon, 28 Aug 2023 12:14:13 +0530 Subject: [PATCH 115/195] Added upsert fix and unit test cases for salesforce oauth token repository --- .../java/com/salessparrow/api/lib/Util.java | 37 +++- .../SalesforceOauthTokenRepository.java | 4 +- .../SalesforceUserRepository.java | 6 +- .../api/services/salesforce/AuthService.java | 63 ++++-- .../salessparrow/api/helper/LoadFixture.java | 7 + .../SalesforceOauthTokenRepositoryTest.java | 190 ++++++++++++++++++ ...esforceOauthTokenRepository.scenarios.json | 41 ++++ ...alesforceOauthTokenRepository.fixture.json | 16 ++ 8 files changed, 328 insertions(+), 36 deletions(-) create mode 100644 src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java create mode 100644 src/test/resources/data/repositories/salesforceOauthTokenRepository.scenarios.json create mode 100644 src/test/resources/fixtures/repositories/salesforceOauthTokenRepository.fixture.json diff --git a/src/main/java/com/salessparrow/api/lib/Util.java b/src/main/java/com/salessparrow/api/lib/Util.java index 65c341fe..986205b1 100644 --- a/src/main/java/com/salessparrow/api/lib/Util.java +++ b/src/main/java/com/salessparrow/api/lib/Util.java @@ -1,5 +1,9 @@ package com.salessparrow.api.lib; +import java.time.Instant; +import java.time.ZoneOffset; +import java.util.Date; + import org.springframework.stereotype.Component; import com.fasterxml.jackson.databind.JsonNode; @@ -38,20 +42,21 @@ public JsonNode getJsonNode(String jsonString) { return jsonNode; } -/** - * Retrieves a string representation of all request headers. For security, - * the value of the "authorization, cookie, password" header is obfuscated. - * - * @param request - The HTTP request containing the headers to be logged. - * @return String - A string representation of the headers in the format "{headerName:headerValue, ...}". - */ + /** + * Retrieves a string representation of all request headers. For security, + * the value of the "authorization, cookie, password" header is obfuscated. + * + * @param request - The HTTP request containing the headers to be logged. + * @return String - A string representation of the headers in the format + * "{headerName:headerValue, ...}". + */ public static String generateHeaderLogString(HttpServletRequest request) { StringBuilder headerBuilder = new StringBuilder("{"); request.getHeaderNames().asIterator().forEachRemaining(headerName -> { // Add any other secret headers here that you don't want logged. - if (headerName.equals("authorization") || - headerName.equals("cookie") || - headerName.equals("password")) { + if (headerName.equals("authorization") || + headerName.equals("cookie") || + headerName.equals("password")) { headerBuilder.append(headerName).append(":**********, "); } else { headerBuilder.append(headerName).append(":").append(request.getHeader(headerName)).append(", "); @@ -59,6 +64,16 @@ public static String generateHeaderLogString(HttpServletRequest request) { }); headerBuilder.append("}"); - return headerBuilder.toString(); + return headerBuilder.toString(); + } + + /** + * Get current time in Date format + * + * @return Date + */ + public Date getCurrentTimeInDateFormat() { + Instant currentTimestamp = Instant.now(); + return Date.from(currentTimestamp.atOffset(ZoneOffset.UTC).toInstant()); } } diff --git a/src/main/java/com/salessparrow/api/repositories/SalesforceOauthTokenRepository.java b/src/main/java/com/salessparrow/api/repositories/SalesforceOauthTokenRepository.java index addf09c9..6e18ceed 100644 --- a/src/main/java/com/salessparrow/api/repositories/SalesforceOauthTokenRepository.java +++ b/src/main/java/com/salessparrow/api/repositories/SalesforceOauthTokenRepository.java @@ -1,7 +1,7 @@ package com.salessparrow.api.repositories; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.annotation.CachePut; +import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Repository; @@ -27,7 +27,7 @@ public class SalesforceOauthTokenRepository { * * @return SalesforceOauthToken */ - @CachePut(value = CacheConstants.SS_SALESFORCE_OAUTH_TOKEN_CACHE, key = "#salesforceOauthToken.externalUserId") + @CacheEvict(value = CacheConstants.SS_SALESFORCE_OAUTH_TOKEN_CACHE, key = "#salesforceOauthToken.externalUserId") public SalesforceOauthToken saveSalesforceOauthToken(SalesforceOauthToken salesforceOauthToken) { try { dynamoDBMapper.save(salesforceOauthToken); diff --git a/src/main/java/com/salessparrow/api/repositories/SalesforceUserRepository.java b/src/main/java/com/salessparrow/api/repositories/SalesforceUserRepository.java index 35c583e9..2d23636a 100644 --- a/src/main/java/com/salessparrow/api/repositories/SalesforceUserRepository.java +++ b/src/main/java/com/salessparrow/api/repositories/SalesforceUserRepository.java @@ -1,7 +1,7 @@ package com.salessparrow.api.repositories; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.annotation.CachePut; +import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Repository; @@ -27,7 +27,7 @@ public class SalesforceUserRepository { * * @return SalesforceUser */ - @CachePut(value=CacheConstants.SS_SALESFORCE_USER_CACHE, key="#salesforceUser.externalUserId") + @CacheEvict(value = CacheConstants.SS_SALESFORCE_USER_CACHE, key = "#salesforceUser.externalUserId") public SalesforceUser saveSalesforceUser(SalesforceUser salesforceUser) { try { dynamoDBMapper.save(salesforceUser); @@ -49,7 +49,7 @@ public SalesforceUser saveSalesforceUser(SalesforceUser salesforceUser) { * * @return SalesforceUser */ - @Cacheable(value=CacheConstants.SS_SALESFORCE_USER_CACHE, key="#externalUserId") + @Cacheable(value = CacheConstants.SS_SALESFORCE_USER_CACHE, key = "#externalUserId") public SalesforceUser getSalesforceUserByExternalUserId(String externalUserId) { try { return dynamoDBMapper.load(SalesforceUser.class, externalUserId); 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 67e7ab29..7fd547fd 100644 --- a/src/main/java/com/salessparrow/api/services/salesforce/AuthService.java +++ b/src/main/java/com/salessparrow/api/services/salesforce/AuthService.java @@ -80,14 +80,15 @@ public class AuthService { * @return AuthServiceDto */ public AuthServiceDto connectToSalesforce(SalesforceConnectDto params) { - 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, this will be updated based on + // conditions in further processing code = params.getCode(); redirectUri = params.getRedirect_uri(); fetchOauthTokensFromSalesforce(); - validateAndUpsertSalesforceOrganization(); + validateAndSaveSalesforceOrganization(); upsertSalesforceOAuthTokens(); @@ -122,11 +123,11 @@ private void fetchOauthTokensFromSalesforce() { } /** - * Validate and upsert Salesforce Organization in DB. + * Validate and save Salesforce Organization in DB. * * @return void */ - private void validateAndUpsertSalesforceOrganization() { + private void validateAndSaveSalesforceOrganization() { logger.info("Validating Salesforce Organization"); String salesforceOrganizationId = this.tokensData.getSalesforceOrganizationId(); @@ -145,13 +146,14 @@ private void validateAndUpsertSalesforceOrganization() { "forbidden_api_request", "Salesforce Organization is not active.")); } + return; } - logger.info("Upserting Salesforce Organization in DB"); + logger.info("Creating Salesforce Organization in DB"); SalesforceOrganization salesforceOrganization = new SalesforceOrganization(); salesforceOrganization.setExternalOrganizationId(salesforceOrganizationId); salesforceOrganization.setStatus(SalesforceOrganization.Status.ACTIVE); - + salesforceOrganization.setCreatedAt(util.getCurrentTimeInDateFormat()); salesforceOrganizationRepository .saveSalesforceOrganization(salesforceOrganization); } @@ -173,20 +175,40 @@ private void upsertSalesforceOAuthTokens() { String encryptedRefreshToken = awsKms.encryptToken(this.tokensData.getRefreshToken()); String salesforceUserId = this.tokensData.getSalesforceUserId(); - SalesforceOauthToken salesforceOauthToken = new SalesforceOauthToken(); - // Todo: use salesforceconnect res entity object - salesforceOauthToken.setExternalUserId(salesforceUserId); - salesforceOauthToken.setIdentityUrl(this.tokensData.getId()); - salesforceOauthToken.setAccessToken(encryptedAccessToken); - salesforceOauthToken.setRefreshToken(encryptedRefreshToken); - salesforceOauthToken.setSignature(this.tokensData.getSignature()); - salesforceOauthToken.setIdToken(this.tokensData.getIdToken()); - salesforceOauthToken.setInstanceUrl(this.tokensData.getInstanceUrl()); - salesforceOauthToken.setStatus(SalesforceOauthToken.Status.ACTIVE); - salesforceOauthToken.setIssuedAt(Long.parseLong(this.tokensData.getIssuedAt())); - - this.salesforceOauthToken = salesforceOauthTokenRepository - .saveSalesforceOauthToken(salesforceOauthToken); + SalesforceOauthToken existingSalesforceOauthToken = salesforceOauthTokenRepository + .getSalesforceOauthTokenByExternalUserId(salesforceUserId); + + if (existingSalesforceOauthToken != null) { + logger.info("Salesforce OAuth Token already exists"); + + SalesforceOauthToken salesforceOauthToken = new SalesforceOauthToken(); + salesforceOauthToken.setExternalUserId(salesforceUserId); + salesforceOauthToken.setAccessToken(encryptedAccessToken); + salesforceOauthToken.setRefreshToken(encryptedRefreshToken); + salesforceOauthToken.setSignature(this.tokensData.getSignature()); + salesforceOauthToken.setIdToken(this.tokensData.getIdToken()); + salesforceOauthToken.setIssuedAt(Long.parseLong(this.tokensData.getIssuedAt())); + + this.salesforceOauthToken = salesforceOauthTokenRepository + .saveSalesforceOauthToken(salesforceOauthToken); + } else { + logger.info("Salesforce OAuth Token does not exists. Creating new one."); + SalesforceOauthToken salesforceOauthToken = new SalesforceOauthToken(); + salesforceOauthToken.setExternalUserId(salesforceUserId); + salesforceOauthToken.setIdentityUrl(this.tokensData.getId()); + salesforceOauthToken.setAccessToken(encryptedAccessToken); + salesforceOauthToken.setRefreshToken(encryptedRefreshToken); + salesforceOauthToken.setSignature(this.tokensData.getSignature()); + salesforceOauthToken.setIdToken(this.tokensData.getIdToken()); + salesforceOauthToken.setInstanceUrl(this.tokensData.getInstanceUrl()); + salesforceOauthToken.setStatus(SalesforceOauthToken.Status.ACTIVE); + salesforceOauthToken.setIssuedAt(Long.parseLong(this.tokensData.getIssuedAt())); + salesforceOauthToken.setCreatedAt(util.getCurrentTimeInDateFormat()); + + this.salesforceOauthToken = salesforceOauthTokenRepository + .saveSalesforceOauthToken(salesforceOauthToken); + } + } /** @@ -250,6 +272,7 @@ private void createSalesforceUser() { salesforceUser.setCookieToken(encryptedCookieToken); salesforceUser.setEncryptionSalt(encryptedSalt); salesforceUser.setStatus(SalesforceUser.Status.ACTIVE); + salesforceUser.setCreatedAt(util.getCurrentTimeInDateFormat()); this.salesforceUser = salesforceUserRepository.saveSalesforceUser(salesforceUser); this.decryptedSalt = decryptedSalt; diff --git a/src/test/java/com/salessparrow/api/helper/LoadFixture.java b/src/test/java/com/salessparrow/api/helper/LoadFixture.java index 151dfc2d..56e107b0 100644 --- a/src/test/java/com/salessparrow/api/helper/LoadFixture.java +++ b/src/test/java/com/salessparrow/api/helper/LoadFixture.java @@ -11,6 +11,7 @@ import com.salessparrow.api.domain.SalesforceOauthToken; import com.salessparrow.api.domain.SalesforceOrganization; import com.salessparrow.api.domain.SalesforceUser; +import com.salessparrow.api.lib.Util; import com.salessparrow.api.repositories.SalesforceOauthTokenRepository; import com.salessparrow.api.repositories.SalesforceOrganizationRepository; import com.salessparrow.api.repositories.SalesforceUserRepository; @@ -31,6 +32,9 @@ public class LoadFixture { @Autowired private SalesforceOrganizationRepository salesforceOrganizationRepository; + @Autowired + private Util util; + /** * Load the fixture data. * @@ -43,6 +47,7 @@ public void perform(FixtureData fixtureData) throws IOException { if (fixtureData.getSalesforce_users() != null) { for (FilePathData filePathData : fixtureData.getSalesforce_users()) { SalesforceUser salesforceUser = loadSalesForceUserFixture(filePathData.getFilepath()); + salesforceUser.setCreatedAt(util.getCurrentTimeInDateFormat()); salesforceUserRepository.saveSalesforceUser(salesforceUser); } } @@ -50,6 +55,7 @@ public void perform(FixtureData fixtureData) throws IOException { if (fixtureData.getSalesforce_oauth_tokens() != null) { for (FilePathData filePathData : fixtureData.getSalesforce_oauth_tokens()) { SalesforceOauthToken salesforceOauth = loadSalesForceOAuthTokenFixture(filePathData.getFilepath()); + salesforceOauth.setCreatedAt(util.getCurrentTimeInDateFormat()); salesforceOauthTokenRepository.saveSalesforceOauthToken(salesforceOauth); } } @@ -57,6 +63,7 @@ public void perform(FixtureData fixtureData) throws IOException { if (fixtureData.getSalesforce_organizations() != null) { for (FilePathData filePathData : fixtureData.getSalesforce_organizations()) { SalesforceOrganization salesforceOrganization = loadSalesForceOrganizationFixture(filePathData.getFilepath()); + salesforceOrganization.setCreatedAt(util.getCurrentTimeInDateFormat()); salesforceOrganizationRepository.saveSalesforceOrganization(salesforceOrganization); } } diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java new file mode 100644 index 00000000..7658ea5e --- /dev/null +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java @@ -0,0 +1,190 @@ +package com.salessparrow.api.unit.repositories; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +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; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +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 com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.dynamobee.exception.DynamobeeException; +import com.salessparrow.api.domain.SalesforceOauthToken; +import com.salessparrow.api.helper.Cleanup; +import com.salessparrow.api.helper.Common; +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.Util; +import com.salessparrow.api.repositories.SalesforceOauthTokenRepository; + +@SpringBootTest +@Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) +public class SalesforceOauthTokenRepositoryTest { + @Autowired + private ResourceLoader resourceLoader; + + @Autowired + private Setup setup; + + @Autowired + private Cleanup cleanup; + + @Autowired + private Common common; + + @Autowired + private LoadFixture loadFixture; + + @Autowired + private SalesforceOauthTokenRepository sfOauthTokenRepository; + + @Autowired + private Util util; + + @BeforeEach + public void setUp() throws DynamobeeException, IOException { + setup.perform(); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + @Test + public void testInsert() throws Exception { + String currentFunctionName = new Object() { + }.getClass().getEnclosingMethod().getName(); + + List testDataItems = loadTestData(currentFunctionName); + + for (Scenario testDataItem : testDataItems) { + System.out.println("Test description: " + testDataItem.getDescription()); + + ObjectMapper objectMapper = new ObjectMapper(); + SalesforceOauthToken salesforceOauthToken = objectMapper.readValue( + objectMapper.writeValueAsString(testDataItem.getInput()), + new TypeReference() { + }); + salesforceOauthToken.setCreatedAt(util.getCurrentTimeInDateFormat()); + + SalesforceOauthToken insertedSalesforceOauthToken = sfOauthTokenRepository + .saveSalesforceOauthToken(salesforceOauthToken); + + assertNotNull(insertedSalesforceOauthToken); + assertNotNull(insertedSalesforceOauthToken.getExternalUserId()); + assertNotNull(insertedSalesforceOauthToken.getCreatedAt()); + assertNotNull(insertedSalesforceOauthToken.getUpdatedAt()); + } + } + + @Test + public void testUpdate() throws Exception { + String currentFunctionName = new Object() { + }.getClass().getEnclosingMethod().getName(); + + FixtureData fixtureData = common.loadFixture( + "classpath:fixtures/repositories/salesforceOauthTokenRepository.fixture.json", + currentFunctionName); + loadFixture.perform(fixtureData); + + List testDataItems = loadTestData(currentFunctionName); + + for (Scenario testDataItem : testDataItems) { + System.out.println("Test description: " + testDataItem.getDescription()); + + ObjectMapper objectMapper = new ObjectMapper(); + SalesforceOauthToken salesforceOauthToken = objectMapper.readValue( + objectMapper.writeValueAsString(testDataItem.getInput()), + new TypeReference() { + }); + + SalesforceOauthToken existingSalesforceOauthToken = sfOauthTokenRepository + .getSalesforceOauthTokenByExternalUserId(salesforceOauthToken.getExternalUserId()); + + System.out.println("existingSalesforceOauthToken: " + existingSalesforceOauthToken); + + sfOauthTokenRepository + .saveSalesforceOauthToken(salesforceOauthToken); + + SalesforceOauthToken updatedSalesforceOauthToken = sfOauthTokenRepository + .getSalesforceOauthTokenByExternalUserId(salesforceOauthToken.getExternalUserId()); + + System.out.println("updatedSalesforceOauthToken: " + updatedSalesforceOauthToken); + + assertNotNull(updatedSalesforceOauthToken); + assertNotNull(updatedSalesforceOauthToken.getUpdatedAt()); + assertEquals(updatedSalesforceOauthToken.getCreatedAt(), existingSalesforceOauthToken.getCreatedAt()); + assertEquals(updatedSalesforceOauthToken.getInstanceUrl(), existingSalesforceOauthToken.getInstanceUrl()); + assertEquals(updatedSalesforceOauthToken.getAccessToken(), salesforceOauthToken.getAccessToken()); + assertEquals(updatedSalesforceOauthToken.getRefreshToken(), salesforceOauthToken.getRefreshToken()); + } + } + + @Test + public void testUpdateWithNullAttributes() throws Exception { + String currentFunctionName = new Object() { + }.getClass().getEnclosingMethod().getName(); + + FixtureData fixtureData = common.loadFixture( + "classpath:fixtures/repositories/salesforceOauthTokenRepository.fixture.json", + currentFunctionName); + loadFixture.perform(fixtureData); + + System.out.println("Test description: " + "Update with null attributes"); + + List testDataItems = loadTestData(currentFunctionName); + + System.out.println("Test description: " + "After Update with null attributes"); + + for (Scenario testDataItem : testDataItems) { + System.out.println("Test description: " + testDataItem.getDescription()); + + ObjectMapper objectMapper = new ObjectMapper(); + SalesforceOauthToken salesforceOauthToken = objectMapper.readValue( + objectMapper.writeValueAsString(testDataItem.getInput()), + new TypeReference() { + }); + + SalesforceOauthToken existingSalesforceOauthToken = sfOauthTokenRepository + .getSalesforceOauthTokenByExternalUserId(salesforceOauthToken.getExternalUserId()); + + System.out.println("existingSalesforceOauthToken: " + existingSalesforceOauthToken); + + sfOauthTokenRepository + .saveSalesforceOauthToken(salesforceOauthToken); + + SalesforceOauthToken updatedSalesforceOauthToken = sfOauthTokenRepository + .getSalesforceOauthTokenByExternalUserId(salesforceOauthToken.getExternalUserId()); + System.out.println("updatedSalesforceOauthToken: " + updatedSalesforceOauthToken); + + assertEquals(updatedSalesforceOauthToken.getAccessToken(), salesforceOauthToken.getAccessToken()); + assertEquals(updatedSalesforceOauthToken.getIdToken(), existingSalesforceOauthToken.getIdToken()); + } + } + + public List loadTestData(String key) throws IOException { + String scenariosPath = "classpath:data/repositories/salesforceOauthTokenRepository.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/resources/data/repositories/salesforceOauthTokenRepository.scenarios.json b/src/test/resources/data/repositories/salesforceOauthTokenRepository.scenarios.json new file mode 100644 index 00000000..b9675a1a --- /dev/null +++ b/src/test/resources/data/repositories/salesforceOauthTokenRepository.scenarios.json @@ -0,0 +1,41 @@ +{ + "testInsert": [ + { + "description": "Insert New Item", + "input": { + "accessToken": "sampleAccessToken", + "refreshToken": "sampleRefreshToken", + "signature": "as/FLavAQ8U=", + "instanceUrl": "https://truesparrowsystemspvtltd--dev.sandbox.my.salesforce.com", + "idToken": "eyJraWQiOiI", + "identityUrl": "https://test.salesforce.com/id/00D1e0000000NRYEA2/0055i00000AUxQHAA1", + "issuedAt": "1692265987212", + "externalUserId": "00112233445566AAA1", + "status": "ACTIVE" + }, + "output": {} + } + ], + "testUpdate": [ + { + "description": "Update Existing Item", + "input": { + "externalUserId": "00112233445566AAA1", + "accessToken": "updatedAccessToken", + "refreshToken": "updatedRefreshToken" + }, + "output": {} + } + ], + "testUpdateWithNullAttributes": [ + { + "description": "Skip Null Attributes During Update", + "input": { + "externalUserId": "00112233445566AAA1", + "accessToken": "newAccessToken", + "idToken": null + }, + "output": {} + } + ] +} \ No newline at end of file diff --git a/src/test/resources/fixtures/repositories/salesforceOauthTokenRepository.fixture.json b/src/test/resources/fixtures/repositories/salesforceOauthTokenRepository.fixture.json new file mode 100644 index 00000000..61d68ec6 --- /dev/null +++ b/src/test/resources/fixtures/repositories/salesforceOauthTokenRepository.fixture.json @@ -0,0 +1,16 @@ +{ + "testUpdate": { + "salesforce_oauth_tokens": [ + { + "filepath": "classpath:fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" + } + ] + }, + "testUpdateWithNullAttributes": { + "salesforce_oauth_tokens": [ + { + "filepath": "classpath:fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" + } + ] + } +} \ No newline at end of file From 849aba7ce9faaf70d70e0d654ac4e793adf8b70b Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Mon, 28 Aug 2023 13:00:18 +0530 Subject: [PATCH 116/195] added note text too long validation --- .../api/dto/requestMapper/NoteDto.java | 3 +++ src/main/resources/config/ParamErrorConfig.json | 13 +++++++++---- .../accountController/createNote.scenarios.json | 17 +++++++++++++++++ 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/salessparrow/api/dto/requestMapper/NoteDto.java b/src/main/java/com/salessparrow/api/dto/requestMapper/NoteDto.java index e2a3646c..0f3bb161 100644 --- a/src/main/java/com/salessparrow/api/dto/requestMapper/NoteDto.java +++ b/src/main/java/com/salessparrow/api/dto/requestMapper/NoteDto.java @@ -1,11 +1,14 @@ package com.salessparrow.api.dto.requestMapper; +import org.hibernate.validator.constraints.Length; + import jakarta.validation.constraints.NotBlank; import lombok.Data; @Data public class NoteDto { @NotBlank(message = "missing_text") + @Length(max = 12000, message = "text_too_long") private String text; } diff --git a/src/main/resources/config/ParamErrorConfig.json b/src/main/resources/config/ParamErrorConfig.json index df5ec465..0529986a 100644 --- a/src/main/resources/config/ParamErrorConfig.json +++ b/src/main/resources/config/ParamErrorConfig.json @@ -9,24 +9,29 @@ "param_error_identifier": "invalid_email", "message": "The email address you entered is incorrect. Please double check and try again." }, - "invalid_redirect_uri":{ + "invalid_redirect_uri": { "parameter": "redirect_uri", "param_error_identifier": "invalid_redirect_uri", "message": "Invalid redirect URI. Please double check and try again." }, - "search_term_too_long":{ + "search_term_too_long": { "parameter": "q", "param_error_identifier": "search_term_too_long", "message": "Search term too long. Please shorten and try again." }, - "invalid_due_date":{ + "invalid_due_date": { "parameter": "due_date", "param_error_identifier": "invalid_due_date", "message": "Invalid or missing due date. Please double check and try again." }, - "description_too_long":{ + "description_too_long": { "parameter": "description", "param_error_identifier": "description_too_long", "message": "Description too long. Please shorten and try again." + }, + "text_too_long": { + "parameter": "text", + "param_error_identifier": "text_too_long", + "message": "Text too long. Please shorten and try again." } } \ No newline at end of file diff --git a/src/test/resources/data/controllers/accountController/createNote.scenarios.json b/src/test/resources/data/controllers/accountController/createNote.scenarios.json index 66bbd7d5..5ee878d4 100644 --- a/src/test/resources/data/controllers/accountController/createNote.scenarios.json +++ b/src/test/resources/data/controllers/accountController/createNote.scenarios.json @@ -160,5 +160,22 @@ "http_code": 500, "code": "INTERNAL_SERVER_ERROR" } + }, + { + "description": "Should fail when the note text is too long", + "input": { + "body": { + "text": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc, quis gravida magna mi a libero. Fusce vulputate eleifend sapien. Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Nullam accumsan lorem in dui. Cras ultricies mi eu turpis hendrerit fringilla. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; In ac dui quis mi consectetuer lacinia. Nam pretium turpis et arcu. Duis arcu tortor, suscipit eget, imperdiet nec, imperdiet iaculis, ipsum. Sed aliquam ultrices mauris. Integer ante arcu, accumsan a, consectetuer eget, posuere ut, mauris. Praesent adipiscing. Phasellus ullamcorper ipsum rutrum nunc. Nunc nonummy metus. Vestibulum volutpat pretium libero. Cras id dui. Aenean ut eros et nisl sagittis vestibulum. Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Sed lectus. Donec mollis hendrerit risus. Phasellus nec sem in justo pellentesque facilisis. Etiam imperdiet imperdiet orci. Nunc nec neque. Phasellus leo dolor, tempus non, auctor et, hendrerit quis, nisi. Curabitur ligula sapien, tincidunt non, euismod vitae, posuere imperdiet, leo. Maecenas malesuada. Praesent congue erat at massa. Sed cursus turpis vitae tortor. Donec posuere vulputate arcu. Phasellus accumsan cursus velit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed aliquam, nisi quis porttitor congue, elit erat euismod orci, ac placerat dolor lectus quis orci. Phasellus consectetuer vestibulum elit. Aenean tellus metus, bibendum sed, posuere ac, mattis non, nunc. Vestibulum fringilla pede sit amet augue. In turpis. Pellentesque posuere. Praesent turpis. Aenean posuere, tortor sed cursus feugiat, nunc augue blandit nunc, eu sollicitudin urna dolor sagittis lacus. Donec elit libero, sodales nec, volutpat a, suscipit non, turpis. Nullam sagittis. Suspendisse pulvinar, augue ac venenatis condimentum, sem libero volutpat nibh, nec pellentesque velit pede quis nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Fusce id purus. Ut varius tincidunt libero. Phasellus dolor. Maecenas vestibulum mollis diam. Pellentesque ut neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. In dui magna, posuere eget, vestibulum et, tempor auctor, justo. In ac felis quis tortor malesuada pretium. Pellentesque auctor neque nec urna. Proin sapien ipsum, porta a, auctor quis, euismod ut, mi. Aenean viverra rhoncus pede. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Ut non enim eleifend felis pretium feugiat. Vivamus quis mi. Phasellus a est. Phasellus magna. In hac habitasse platea dictumst. Curabitur at lacus ac velit ornare lobortis. Curabitur a felis in nunc fringilla tristique. Morbi mattis ullamcorper velit. Phasellus gravida semper nisi. Nullam vel sem. Pellentesque libero tortor, tincidunt et, tincidunt eget, semper nec, quam. Sed hendrerit. Morbi ac felis. Nunc egestas, augue at pellentesque laoreet, felis eros vehicula leo, at malesuada velit leo quis pede. Donec interdum, metus et hendrerit aliquet, dolor diam sagittis ligula, eget egestas libero turpis vel mi. Nunc nulla. Fusce risus nisl, viverra et, tempor et, pretium in, sapien. Donec venenatis vulputate lorem. Morbi nec metus. Phasellus blandit leo ut odio. Maecenas ullamcorper, dui et placerat feugiat, eros pede varius nisi, condimentum viverra felis nunc et lorem. Sed magna purus, fermentum eu, tincidunt eu, varius ut, felis. In auctor lobortis lacus. Quisque libero metus, condimentum nec, tempor a, commodo mollis, magna. Vestibulum ullamcorper mauris at ligula. Fusce fermentum. Nullam cursus lacinia erat. Praesent blandit laoreet nibh. Fusce convallis metus id felis luctus adipiscing. Pellentesque egestas, neque sit amet convallis pulvinar, justo nulla eleifend augue, ac auctor orci leo non est. Quisque id mi. Ut tincidunt tincidunt erat. Etiam feugiat lorem non metus. Vestibulum dapibus nunc ac augue. Curabitur vestibulum aliquam leo. Praesent egestas neque eu enim. In hac habitasse platea dictumst. Fusce a quam. Etiam ut purus mattis mauris sodales aliquam. Curabitur nisi. Quisque malesuada placerat nisl. Nam ipsum risus, rutrum vitae, vestibulum eu, molestie vel, lacus. Sed augue ipsum, egestas nec, vestibulum et, malesuada adipiscing, dui. Vestibulum facilisis, purus nec pulvinar iaculis, ligula mi congue nunc, vitae euismod ligula urna in dolor. Mauris sollicitudin fermentum libero. Praesent nonummy mi in odio. Nunc interdum lacus sit amet orci. Vestibulum rutrum, mi nec elementum vehicula, eros quam gravida nisl, id fringilla neque ante vel mi. Morbi mollis tellus ac sapien. Phasellus volutpat, metus eget egestas mollis, lacus lacus blandit dui, id egestas quam mauris ut lacus. Fusce vel dui. Sed in libero ut nibh placerat accumsan. Proin faucibus arcu quis ante. In consectetuer turpis ut velit. Nulla sit amet est. Praesent metus tellus, elementum eu, semper a, adipiscing nec, purus. Cras risus ipsum, faucibus ut, ullamcorper id, varius ac, leo. Suspendisse feugiat. Suspendisse enim turpis, dictum sed, iaculis a, condimentum nec, nisi. Praesent nec nisl a purus blandit viverra. Praesent ac massa at ligula laoreet iaculis. Nulla neque dolor, sagittis eget, iaculis quis, molestie non, velit. Mauris turpis nunc, blandit et, volutpat molestie, porta ut, ligula. Fusce pharetra convallis urna. Quisque ut nisi. Donec mi odio, faucibus at, scelerisque quis, convallis in, nisi. Suspendisse non nisl sit amet velit hendrerit rutrum. Ut leo. Ut a nisl id ante tempus hendrerit. Proin pretium, leo ac pellentesque mollis, felis nunc ultrices eros, sed gravida augue augue mollis justo. Suspendisse eu ligula. Nulla facilisi. Donec id justo. Praesent porttitor, nulla vitae posuere iaculis, arcu nisl dignissim dolor, a pretium mi sem ut ipsum. Curabitur suscipit suscipit tellus. Praesent vestibulum dapibus nibh. Etiam iaculis nunc ac metus. Ut id nisl quis enim dignissim sagittis. Etiam sollicitudin, ipsum eu pulvinar rutrum, tellus ipsum laoreet sapien, quis venenatis ante odio sit amet eros. Proin magna. Duis vel nibh at velit scelerisque suscipit. Curabitur turpis. Vestibulum suscipit nulla quis orci. Fusce ac felis sit amet ligula pharetra condimentum. Maecenas egestas arcu quis ligula mattis placerat. Duis lobortis massa imperdiet quam. Suspendisse potenti. Pellentesque commodo eros a enim. Vestibulum turpis sem, aliquet eget, lobortis pellentesque, rutrum eu, nisl. Sed libero. Aliquam erat volutpat. Etiam vitae tortor. Morbi vestibulum volutpat enim. Aliquam eu nunc. Nunc sed turpis. Sed mollis, eros et ultrices tempus, mauris ipsum aliquam libero, non adipiscing dolor urna a orci. Nulla porta dolor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Pellentesque dapibus hendrerit tortor. Praesent egestas tristique nibh. Sed a libero. Cras varius. Donec vitae orci sed dolor rutrum auctor. Fusce egestas elit eget lorem. Suspendisse nisl elit, rhoncus eget, elementum ac, condimentum eget, diam. Nam at tortor in tellus interdum sagittis. Aliquam lobortis. Donec orci lectus, aliquam ut, faucibus non, euismod id, nulla. Curabitur blandit mollis lacus. Nam adipiscing. Vestibulum eu odio. Vivamus laoreet. Nullam tincidunt adipiscing enim. Phasellus tempus. Proin viverra, ligula sit amet ultrices semper, ligula arcu tristique sapien, a accumsan nisi mauris ac eros. Fusce neque. Suspendisse faucibus, nunc et pellentesque egestas, lacus ante convallis tellus, vitae iaculis lacus elit id tortor. Vivamus aliquet elit ac nisl. Fusce fermentum odio nec arcu. Vivamus euismod mauris. In ut quam vitae odio lacinia tincidunt. Praesent ut ligula non mi varius sagittis. Cras sagittis. Praesent ac sem eget est egestas volutpat. Vivamus consectetuer hendrerit lacus. Cras non dolor. Vivamus in erat ut urna cursus vestibulum. Fusce commodo aliquam arcu. Nam commodo suscipit quam. Quisque id odio. Praesent venenatis metus at tortor pulvinar varius. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc, quis gravida magna mi a libero. Fusce vulputate eleifend sapien. Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Nullam accumsan lorem in dui. Cras ultricies mi eu turpis hendrerit fringilla. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; In ac dui quis mi consectetuer lacinia. Nam pretium turpis et arcu. Duis arcu tortor, suscipit eget, imperdiet nec, imperdiet iaculis, ipsum. Sed aliquam ultrices mauris. Integer ante arcu, accumsan a, consectetuer eget, posuere ut, mauris. Praesent adipiscing. Phasellus ullamcorper ipsum rutrum nunc. Nunc nonummy metus. Vestibulum volutpat pretium libero. Cras id dui. Aenean ut eros et nisl sagittis vestibulum. Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Sed lectus. Donec mollis hendrerit risus. Phasellus nec sem in justo pellentesque facilisis. Etiam imperdiet imperdiet orci. Nunc nec neque. Phasellus leo dolor, tempus non, auctor et, hendrerit quis, nisi. Curabitur ligula sapien, tincidunt non, euismod vitae, posuere imperdiet, leo. Maecenas malesuada. Praesent congue erat at massa. Sed cursus turpis vitae tortor. Donec posuere vulputate arcu. Phasellus accumsan cursus velit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed aliquam, nisi quis porttitor" + }, + "accountId": "0011e00000bWSxdAAG" + }, + "mocks": {}, + "output": { + "http_code": 400, + "code": "INVALID_PARAMS", + "param_errors": [ + "text_too_long" + ] + } } ] \ No newline at end of file From 649c18fea85249e28d75fb9137b56205292aed74 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Mon, 28 Aug 2023 13:04:23 +0530 Subject: [PATCH 117/195] updated changelog: removed task that is not present in release --- repo-docs/CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/repo-docs/CHANGELOG.md b/repo-docs/CHANGELOG.md index 4b1c9dd9..65969f66 100644 --- a/repo-docs/CHANGELOG.md +++ b/repo-docs/CHANGELOG.md @@ -7,7 +7,6 @@ - API - Disconnect Salesforce Endpoint [#9](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/9) - API - Get Recommended Actions from Text Endpoint [#13](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/13) - API - Delete Note Endpoint [#28](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/28) -- API - Create Event for an Account [#30](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/30) - API - Get a list of Tasks in an account [#33](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/33) - API - Create Task in an Account Endpoint [#34](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/34) - API - Get a list of CRM Organization Users Endpoint [#35](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/35) From 61a61a60f044e45744f95fd00a492190901e851d Mon Sep 17 00:00:00 2001 From: Yagnik Thummar Date: Mon, 28 Aug 2023 13:12:51 +0530 Subject: [PATCH 118/195] Added TestCases for delete account task. --- .../resources/config/ParamErrorConfig.json | 5 + .../DeleteAccountTaskTest.java | 125 ++++++++++++++++++ .../deleteAccountTask.scenarios.json | 55 ++++++++ .../deleteAccountTask.fixtures.json | 14 ++ 4 files changed, 199 insertions(+) create mode 100644 src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/DeleteAccountTaskTest.java create mode 100644 src/test/resources/data/controllers/accountTaskController/deleteAccountTask.scenarios.json create mode 100644 src/test/resources/fixtures/controllers/accountTaskController/deleteAccountTask.fixtures.json diff --git a/src/main/resources/config/ParamErrorConfig.json b/src/main/resources/config/ParamErrorConfig.json index df5ec465..54461310 100644 --- a/src/main/resources/config/ParamErrorConfig.json +++ b/src/main/resources/config/ParamErrorConfig.json @@ -28,5 +28,10 @@ "parameter": "description", "param_error_identifier": "description_too_long", "message": "Description too long. Please shorten and try again." + }, + "invalid_task_id":{ + "parameter": "task_id", + "param_error_identifier": "invalid_task_id", + "message": "Invalid task ID. Please double check and try again." } } \ No newline at end of file diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/DeleteAccountTaskTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/DeleteAccountTaskTest.java new file mode 100644 index 00000000..0515270a --- /dev/null +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/DeleteAccountTaskTest.java @@ -0,0 +1,125 @@ +package com.salessparrow.api.functional.controllers.accountTaskController; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.util.List; +import java.util.stream.Stream; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +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.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +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; +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 com.salessparrow.api.lib.httpLib.HttpClient.HttpResponse; +import com.salessparrow.api.lib.salesforce.helper.MakeCompositeRequest; + +import jakarta.servlet.http.Cookie; + +@SpringBootTest +@AutoConfigureMockMvc +@WebAppConfiguration +@Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) +public class DeleteAccountTaskTest { + + @Autowired + private MockMvc mockMvc; + @Autowired + private Common common; + @Autowired + private LoadFixture loadFixture; + @Autowired + private Setup setup; + @Autowired + private Cleanup cleanup; + + @MockBean + private MakeCompositeRequest makeCompositeRequestMock; + + @BeforeEach + public void setUp() throws DynamobeeException { + setup.perform(); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + @ParameterizedTest + @MethodSource("testScenariosProvider") + public void deleteAccountTask(Scenario testScenario) throws Exception { + + // Load fixture data + String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/controllers/accountTaskController/deleteAccountTask.fixtures.json", currentFunctionName); + loadFixture.perform(fixtureData); + + // Read data from the scenario + ObjectMapper objectMapper = new ObjectMapper(); + String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; + String accountId = (String) testScenario.getInput().get("accountId"); + String taskId = (String) testScenario.getInput().get("taskId"); + + // Prepare mock responses + HttpResponse createNoteMockResponse = new HttpResponse(); + createNoteMockResponse.setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest"))); + when(makeCompositeRequestMock.makePostRequest(any(), any())).thenReturn(createNoteMockResponse); + + // Perform the request + String requestBody = objectMapper.writeValueAsString(testScenario.getInput().get("body")); + String url = "/api/v1/accounts/" + accountId + "/tasks" + taskId; + + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.delete(url) + .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) + .content(requestBody) + .contentType(MediaType.APPLICATION_JSON)); + + // Check the response + String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); + String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); + + if(resultActions.andReturn().getResponse().getStatus() == 204) { + assertEquals(expectedOutput, actualOutput); + } else { + common.compareErrors(testScenario, actualOutput); + } + } + + static Stream testScenariosProvider() throws IOException { + List testScenarios = loadScenarios(); + return testScenarios.stream(); + } + + private static List loadScenarios() throws IOException { + String scenariosPath = "classpath:data/controllers/accountTaskController/deleteAccountTask.scenarios.json"; + Resource resource = new DefaultResourceLoader().getResource(scenariosPath); + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); + } +} diff --git a/src/test/resources/data/controllers/accountTaskController/deleteAccountTask.scenarios.json b/src/test/resources/data/controllers/accountTaskController/deleteAccountTask.scenarios.json new file mode 100644 index 00000000..33f9fbac --- /dev/null +++ b/src/test/resources/data/controllers/accountTaskController/deleteAccountTask.scenarios.json @@ -0,0 +1,55 @@ +[ + { + "description": "Should successfully delete the task for given task id", + "input": { + "accountId": "0011e00000bWSxdAAG", + "taskId":"0691e000001X1yTAAS" + }, + "mocks": { + "makeCompositeRequest": { + "compositeResponse": [ + { + "body": null, + "httpHeaders": {}, + "httpStatusCode": 204, + "referenceId": "DeleteTask" + } + ] + } + }, + "output": {} + }, + { + "description": "should return error response when task id is invalid", + "input": { + "accountId": "0011e00000bWSxdAAG", + "taskId":"invalidTaskId" + }, + "mocks": { + "makeCompositeRequest": { + "compositeResponse": [ + { + "body": [ + { + "errorCode": "NOT_FOUND", + "message": "Provided external ID field does not exist or is not accessible: INVALID_TASK_ID" + } + ], + "httpHeaders": {}, + "httpStatusCode": 404, + "referenceId": "DeleteTask" + } + ] + } + }, + "output": { + "http_code": 400, + "message": "At least one parameter is invalid or missing.", + "code": "INVALID_PARAMS", + "internal_error_identifier": "l_ca_dan_dasn_pr_1", + "param_errors": [ + "invalid_task_id" + ] + } + } + ] \ No newline at end of file diff --git a/src/test/resources/fixtures/controllers/accountTaskController/deleteAccountTask.fixtures.json b/src/test/resources/fixtures/controllers/accountTaskController/deleteAccountTask.fixtures.json new file mode 100644 index 00000000..9de4d059 --- /dev/null +++ b/src/test/resources/fixtures/controllers/accountTaskController/deleteAccountTask.fixtures.json @@ -0,0 +1,14 @@ +{ + "deleteAccountTask": { + "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 3a7a888150a8ce225cf8a88de2fc88aa8325e293 Mon Sep 17 00:00:00 2001 From: ajinkyac03 Date: Mon, 28 Aug 2023 13:37:54 +0530 Subject: [PATCH 119/195] Added validation for input text. --- .../requestMapper/CrmActionsSuggestionsDto.java | 3 +++ .../api/lib/GetCrmActionSuggestions.java | 10 ++++++++++ .../salessparrow/api/lib/openAi/OpenAiRequest.java | 5 +++++ .../crmActionsSuggestions.scenarios.json | 14 ++++++++++++++ 4 files changed, 32 insertions(+) diff --git a/src/main/java/com/salessparrow/api/dto/requestMapper/CrmActionsSuggestionsDto.java b/src/main/java/com/salessparrow/api/dto/requestMapper/CrmActionsSuggestionsDto.java index 29d73476..8de0553b 100644 --- a/src/main/java/com/salessparrow/api/dto/requestMapper/CrmActionsSuggestionsDto.java +++ b/src/main/java/com/salessparrow/api/dto/requestMapper/CrmActionsSuggestionsDto.java @@ -1,5 +1,7 @@ package com.salessparrow.api.dto.requestMapper; +import org.hibernate.validator.constraints.Length; + import jakarta.validation.constraints.NotBlank; import lombok.Data; @@ -9,5 +11,6 @@ @Data public class CrmActionsSuggestionsDto { @NotBlank(message = "missing_text") + @Length(max = 12000, message = "text_too_long") private String text; } diff --git a/src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java b/src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java index 9bcc1831..7339758d 100644 --- a/src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java +++ b/src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java @@ -35,6 +35,11 @@ public class GetCrmActionSuggestions { private Logger logger = org.slf4j.LoggerFactory.getLogger(SuggestionsController.class); + /** + * Get the crm action suggestions. + * @param text + * @return + */ public CrmActionSuggestionsFormatterDto getTaskSuggestions(String text) { logger.info("Crm actions suggestions lib called"); @@ -46,6 +51,11 @@ public CrmActionSuggestionsFormatterDto getTaskSuggestions(String text) { return parseResponse(response); } + /** + * Parse the response from openai. + * @param responseBody + * @return + */ private CrmActionSuggestionsFormatterDto parseResponse(String responseBody){ CrmActionSuggestionsFormatterDto crmActionSuggestionsFormatterDto = new CrmActionSuggestionsFormatterDto(); diff --git a/src/main/java/com/salessparrow/api/lib/openAi/OpenAiRequest.java b/src/main/java/com/salessparrow/api/lib/openAi/OpenAiRequest.java index 6c3e256c..757cd635 100644 --- a/src/main/java/com/salessparrow/api/lib/openAi/OpenAiRequest.java +++ b/src/main/java/com/salessparrow/api/lib/openAi/OpenAiRequest.java @@ -25,6 +25,11 @@ public class OpenAiRequest { private Logger logger = org.slf4j.LoggerFactory.getLogger(SuggestionsController.class); + /** + * Make a request to the OpenAI API. + * @param payload + * @return + */ public HttpClient.HttpResponse makeRequest(Object payload) { String httpReqUrl = openAiConstants.chatCompletionUrl(); diff --git a/src/test/resources/data/controllers/suggestionsController/crmActionsSuggestions.scenarios.json b/src/test/resources/data/controllers/suggestionsController/crmActionsSuggestions.scenarios.json index 43b4fb95..0709eb81 100644 --- a/src/test/resources/data/controllers/suggestionsController/crmActionsSuggestions.scenarios.json +++ b/src/test/resources/data/controllers/suggestionsController/crmActionsSuggestions.scenarios.json @@ -93,6 +93,20 @@ ] } }, + { + "description": "Should return error if text length is greater than 12000", + "input": { + "text": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc, quis gravida magna mi a libero. Fusce vulputate eleifend sapien. Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Nullam accumsan lorem in dui. Cras ultricies mi eu turpis hendrerit fringilla. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; In ac dui quis mi consectetuer lacinia. Nam pretium turpis et arcu. Duis arcu tortor, suscipit eget, imperdiet nec, imperdiet iaculis, ipsum. Sed aliquam ultrices mauris. Integer ante arcu, accumsan a, consectetuer eget, posuere ut, mauris. Praesent adipiscing. Phasellus ullamcorper ipsum rutrum nunc. Nunc nonummy metus. Vestibulum volutpat pretium libero. Cras id dui. Aenean ut eros et nisl sagittis vestibulum. Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Sed lectus. Donec mollis hendrerit risus. Phasellus nec sem in justo pellentesque facilisis. Etiam imperdiet imperdiet orci. Nunc nec neque. Phasellus leo dolor, tempus non, auctor et, hendrerit quis, nisi. Curabitur ligula sapien, tincidunt non, euismod vitae, posuere imperdiet, leo. Maecenas malesuada. Praesent congue erat at massa. Sed cursus turpis vitae tortor. Donec posuere vulputate arcu. Phasellus accumsan cursus velit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed aliquam, nisi quis porttitor congue, elit erat euismod orci, ac placerat dolor lectus quis orci. Phasellus consectetuer vestibulum elit. Aenean tellus metus, bibendum sed, posuere ac, mattis non, nunc. Vestibulum fringilla pede sit amet augue. In turpis. Pellentesque posuere. Praesent turpis. Aenean posuere, tortor sed cursus feugiat, nunc augue blandit nunc, eu sollicitudin urna dolor sagittis lacus. Donec elit libero, sodales nec, volutpat a, suscipit non, turpis. Nullam sagittis. Suspendisse pulvinar, augue ac venenatis condimentum, sem libero volutpat nibh, nec pellentesque velit pede quis nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Fusce id purus. Ut varius tincidunt libero. Phasellus dolor. Maecenas vestibulum mollis diam. Pellentesque ut neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. In dui magna, posuere eget, vestibulum et, tempor auctor, justo. In ac felis quis tortor malesuada pretium. Pellentesque auctor neque nec urna. Proin sapien ipsum, porta a, auctor quis, euismod ut, mi. Aenean viverra rhoncus pede. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Ut non enim eleifend felis pretium feugiat. Vivamus quis mi. Phasellus a est. Phasellus magna. In hac habitasse platea dictumst. Curabitur at lacus ac velit ornare lobortis. Curabitur a felis in nunc fringilla tristique. Morbi mattis ullamcorper velit. Phasellus gravida semper nisi. Nullam vel sem. Pellentesque libero tortor, tincidunt et, tincidunt eget, semper nec, quam. Sed hendrerit. Morbi ac felis. Nunc egestas, augue at pellentesque laoreet, felis eros vehicula leo, at malesuada velit leo quis pede. Donec interdum, metus et hendrerit aliquet, dolor diam sagittis ligula, eget egestas libero turpis vel mi. Nunc nulla. Fusce risus nisl, viverra et, tempor et, pretium in, sapien. Donec venenatis vulputate lorem. Morbi nec metus. Phasellus blandit leo ut odio. Maecenas ullamcorper, dui et placerat feugiat, eros pede varius nisi, condimentum viverra felis nunc et lorem. Sed magna purus, fermentum eu, tincidunt eu, varius ut, felis. In auctor lobortis lacus. Quisque libero metus, condimentum nec, tempor a, commodo mollis, magna. Vestibulum ullamcorper mauris at ligula. Fusce fermentum. Nullam cursus lacinia erat. Praesent blandit laoreet nibh. Fusce convallis metus id felis luctus adipiscing. Pellentesque egestas, neque sit amet convallis pulvinar, justo nulla eleifend augue, ac auctor orci leo non est. Quisque id mi. Ut tincidunt tincidunt erat. Etiam feugiat lorem non metus. Vestibulum dapibus nunc ac augue. Curabitur vestibulum aliquam leo. Praesent egestas neque eu enim. In hac habitasse platea dictumst. Fusce a quam. Etiam ut purus mattis mauris sodales aliquam. Curabitur nisi. Quisque malesuada placerat nisl. Nam ipsum risus, rutrum vitae, vestibulum eu, molestie vel, lacus. Sed augue ipsum, egestas nec, vestibulum et, malesuada adipiscing, dui. Vestibulum facilisis, purus nec pulvinar iaculis, ligula mi congue nunc, vitae euismod ligula urna in dolor. Mauris sollicitudin fermentum libero. Praesent nonummy mi in odio. Nunc interdum lacus sit amet orci. Vestibulum rutrum, mi nec elementum vehicula, eros quam gravida nisl, id fringilla neque ante vel mi. Morbi mollis tellus ac sapien. Phasellus volutpat, metus eget egestas mollis, lacus lacus blandit dui, id egestas quam mauris ut lacus. Fusce vel dui. Sed in libero ut nibh placerat accumsan. Proin faucibus arcu quis ante. In consectetuer turpis ut velit. Nulla sit amet est. Praesent metus tellus, elementum eu, semper a, adipiscing nec, purus. Cras risus ipsum, faucibus ut, ullamcorper id, varius ac, leo. Suspendisse feugiat. Suspendisse enim turpis, dictum sed, iaculis a, condimentum nec, nisi. Praesent nec nisl a purus blandit viverra. Praesent ac massa at ligula laoreet iaculis. Nulla neque dolor, sagittis eget, iaculis quis, molestie non, velit. Mauris turpis nunc, blandit et, volutpat molestie, porta ut, ligula. Fusce pharetra convallis urna. Quisque ut nisi. Donec mi odio, faucibus at, scelerisque quis, convallis in, nisi. Suspendisse non nisl sit amet velit hendrerit rutrum. Ut leo. Ut a nisl id ante tempus hendrerit. Proin pretium, leo ac pellentesque mollis, felis nunc ultrices eros, sed gravida augue augue mollis justo. Suspendisse eu ligula. Nulla facilisi. Donec id justo. Praesent porttitor, nulla vitae posuere iaculis, arcu nisl dignissim dolor, a pretium mi sem ut ipsum. Curabitur suscipit suscipit tellus. Praesent vestibulum dapibus nibh. Etiam iaculis nunc ac metus. Ut id nisl quis enim dignissim sagittis. Etiam sollicitudin, ipsum eu pulvinar rutrum, tellus ipsum laoreet sapien, quis venenatis ante odio sit amet eros. Proin magna. Duis vel nibh at velit scelerisque suscipit. Curabitur turpis. Vestibulum suscipit nulla quis orci. Fusce ac felis sit amet ligula pharetra condimentum. Maecenas egestas arcu quis ligula mattis placerat. Duis lobortis massa imperdiet quam. Suspendisse potenti. Pellentesque commodo eros a enim. Vestibulum turpis sem, aliquet eget, lobortis pellentesque, rutrum eu, nisl. Sed libero. Aliquam erat volutpat. Etiam vitae tortor. Morbi vestibulum volutpat enim. Aliquam eu nunc. Nunc sed turpis. Sed mollis, eros et ultrices tempus, mauris ipsum aliquam libero, non adipiscing dolor urna a orci. Nulla porta dolor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Pellentesque dapibus hendrerit tortor. Praesent egestas tristique nibh. Sed a libero. Cras varius. Donec vitae orci sed dolor rutrum auctor. Fusce egestas elit eget lorem. Suspendisse nisl elit, rhoncus eget, elementum ac, condimentum eget, diam. Nam at tortor in tellus interdum sagittis. Aliquam lobortis. Donec orci lectus, aliquam ut, faucibus non, euismod id, nulla. Curabitur blandit mollis lacus. Nam adipiscing. Vestibulum eu odio. Vivamus laoreet. Nullam tincidunt adipiscing enim. Phasellus tempus. Proin viverra, ligula sit amet ultrices semper, ligula arcu tristique sapien, a accumsan nisi mauris ac eros. Fusce neque. Suspendisse faucibus, nunc et pellentesque egestas, lacus ante convallis tellus, vitae iaculis lacus elit id tortor. Vivamus aliquet elit ac nisl. Fusce fermentum odio nec arcu. Vivamus euismod mauris. In ut quam vitae odio lacinia tincidunt. Praesent ut ligula non mi varius sagittis. Cras sagittis. Praesent ac sem eget est egestas volutpat. Vivamus consectetuer hendrerit lacus. Cras non dolor. Vivamus in erat ut urna cursus vestibulum. Fusce commodo aliquam arcu. Nam commodo suscipit quam. Quisque id odio. Praesent venenatis metus at tortor pulvinar varius. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc, quis gravida magna mi a libero. Fusce vulputate eleifend sapien. Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Nullam accumsan lorem in dui. Cras ultricies mi eu turpis hendrerit fringilla. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; In ac dui quis mi consectetuer lacinia. Nam pretium turpis et arcu. Duis arcu tortor, suscipit eget, imperdiet nec, imperdiet iaculis, ipsum. Sed aliquam ultrices mauris. Integer ante arcu, accumsan a, consectetuer eget, posuere ut, mauris. Praesent adipiscing. Phasellus ullamcorper ipsum rutrum nunc. Nunc nonummy metus. Vestibulum volutpat pretium libero. Cras id dui. Aenean ut eros et nisl sagittis vestibulum. Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Sed lectus. Donec mollis hendrerit risus. Phasellus nec sem in justo pellentesque facilisis. Etiam imperdiet imperdiet orci. Nunc nec neque. Phasellus leo dolor, tempus non, auctor et, hendrerit quis, nisi. Curabitur ligula sapien, tincidunt non, euismod vitae, posuere imperdiet, leo. Maecenas malesuada. Praesent congue erat at massa. Sed cursus turpis vitae tortor. Donec posuere vulputate arcu. Phasellus accumsan cursus velit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed aliquam, nisi quis porttitor" + }, + "mocks": {}, + "output": { + "http_code": 400, + "code": "INVALID_PARAMS", + "param_errors": [ + "text_too_long" + ] + } + }, { "description": "Should return error if text is empty", "input": { From 8305fa459bf2a8fdd0f6e0c4cb13e3c16c3d855a Mon Sep 17 00:00:00 2001 From: Yagnik Thummar Date: Mon, 28 Aug 2023 15:52:58 +0530 Subject: [PATCH 120/195] Added delete account task api. --- .../controllers/AccountTaskController.java | 21 ++++++ .../deleteAccountTask/DeleteAccountTask.java | 10 +++ .../DeleteAccountTaskFactory.java | 36 ++++++++++ .../DeleteSalesforceAccountTask.java | 70 +++++++++++++++++++ .../globalConstants/SalesforceConstants.java | 4 ++ .../accountTask/DeleteTaskService.java | 28 ++++++++ .../DeleteAccountTaskTest.java | 5 +- 7 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteAccountTask.java create mode 100644 src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteAccountTaskFactory.java create mode 100644 src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteSalesforceAccountTask.java create mode 100644 src/main/java/com/salessparrow/api/services/accountTask/DeleteTaskService.java diff --git a/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java b/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java index c184ba60..36f6612e 100644 --- a/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java +++ b/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java @@ -6,6 +6,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -15,6 +16,7 @@ import com.salessparrow.api.dto.formatter.CreateTaskFormatterDto; import com.salessparrow.api.dto.requestMapper.CreateTaskInAccountDto; import com.salessparrow.api.services.accountTask.CreateTaskService; +import com.salessparrow.api.services.accountTask.DeleteTaskService; import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; @@ -26,8 +28,12 @@ public class AccountTaskController { Logger logger = LoggerFactory.getLogger(AccountTaskController.class); + @Autowired private CreateTaskService createTaskService; + + @Autowired + private DeleteTaskService deleteTaskService; @PostMapping("/{account_id}/tasks") public ResponseEntity createTask( @@ -36,7 +42,22 @@ public ResponseEntity createTask( @Valid @RequestBody CreateTaskInAccountDto task ){ logger.info("Create task request received"); + CreateTaskFormatterDto createTaskFormatterDto = createTaskService.createTaskInAccount(request, accountId, task); + return ResponseEntity.status(HttpStatus.CREATED).body(createTaskFormatterDto); } + + @DeleteMapping("/{account_id}/tasks/{task_id}") + public ResponseEntity deleteTask( + HttpServletRequest request, + @PathVariable("account_id") String accountId, + @PathVariable("task_id") String taskId + ){ + logger.info("Delete task request received"); + + deleteTaskService.deleteAccountTask(request, accountId, taskId); + + return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); + } } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteAccountTask.java b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteAccountTask.java new file mode 100644 index 00000000..eb78b271 --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteAccountTask.java @@ -0,0 +1,10 @@ +package com.salessparrow.api.lib.crmActions.deleteAccountTask; + +import org.springframework.stereotype.Component; + +import com.salessparrow.api.domain.User; + +@Component +public interface DeleteAccountTask { + public void deleteAccountTask(User user, String accountId, String taskId); +} diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteAccountTaskFactory.java b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteAccountTaskFactory.java new file mode 100644 index 00000000..0a82281a --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteAccountTaskFactory.java @@ -0,0 +1,36 @@ +package com.salessparrow.api.lib.crmActions.deleteAccountTask; + +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.User; +import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.lib.errorLib.ErrorObject; +import com.salessparrow.api.lib.globalConstants.UserConstants; + +@Component +public class DeleteAccountTaskFactory { + + Logger logger = LoggerFactory.getLogger(DeleteAccountTaskFactory.class); + + @Autowired + DeleteSalesforceAccountTask deleteSalesforceAccountTask; + + public void deleteAccountTask(User user, String accountId, String taskId) { + logger.info("Delete Account Task Factory called"); + switch(user.getUserKind()) { + case UserConstants.SALESFORCE_USER_KIND: + deleteSalesforceAccountTask.deleteAccountTask(user, accountId, taskId); + break; + default: + throw new CustomException( + new ErrorObject( + "l_ca_dat_datf_1", + "something_went_wrong", + "Invalid user kind.") + ); + } + } +} diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteSalesforceAccountTask.java b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteSalesforceAccountTask.java new file mode 100644 index 00000000..5e418fc1 --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteSalesforceAccountTask.java @@ -0,0 +1,70 @@ +package com.salessparrow.api.lib.crmActions.deleteAccountTask; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.fasterxml.jackson.databind.JsonNode; +import com.salessparrow.api.domain.User; +import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.lib.Util; +import com.salessparrow.api.lib.errorLib.ParamErrorObject; +import com.salessparrow.api.lib.globalConstants.SalesforceConstants; +import com.salessparrow.api.lib.httpLib.HttpClient; +import com.salessparrow.api.lib.salesforce.dto.CompositeRequestDto; +import com.salessparrow.api.lib.salesforce.helper.MakeCompositeRequest; + +@Component +public class DeleteSalesforceAccountTask implements DeleteAccountTask{ + Logger logger = LoggerFactory.getLogger(DeleteSalesforceAccountTask.class); + + @Autowired + private SalesforceConstants salesforceConstants; + + @Autowired + private MakeCompositeRequest makeCompositeRequest; + + public void deleteAccountTask(User user, String accountId, String taskId) { + logger.info("Delete Salesforce Account Task called"); + + String salesforceUserId = user.getExternalUserId(); + + String url = salesforceConstants.salesforceDeleteAccountTaskUrl(taskId); + + CompositeRequestDto compositeReq = new CompositeRequestDto("DELETE", url, "DeleteTask"); + + List compositeRequests = new ArrayList(); + compositeRequests.add(compositeReq); + + HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, salesforceUserId); + + parseResponse(response.getResponseBody()); + + } + + private void parseResponse(String responseBody) { + logger.info("Parsing response body"); + Util util = new Util(); + JsonNode rootNode = util.getJsonNode(responseBody); + + JsonNode deleteNoteCompositeResponse = rootNode.get("compositeResponse").get(0); + Integer deleteNoteStatusCode = deleteNoteCompositeResponse.get("httpStatusCode").asInt(); + + if (deleteNoteStatusCode != 200 && deleteNoteStatusCode != 201 && deleteNoteStatusCode != 204) { + String errorBody = deleteNoteCompositeResponse.get("body").asText(); + + throw new CustomException( + new ParamErrorObject( + "l_ca_dan_dasn_pr_1", + errorBody, + Arrays.asList("invalid_task_id") + ) + ); + } + } +} diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/SalesforceConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/SalesforceConstants.java index 47fd777e..f2914a80 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/SalesforceConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/SalesforceConstants.java @@ -61,4 +61,8 @@ public String salesforceNotesContentUrl(String urlPrefix, String noteId){ public String salesforceCreateTaskUrl(){ return sObjectsPath() + "/Task"; } + + public String salesforceDeleteAccountTaskUrl(String taskId){ + return sObjectsPath() + "/Task/" + taskId; + } } diff --git a/src/main/java/com/salessparrow/api/services/accountTask/DeleteTaskService.java b/src/main/java/com/salessparrow/api/services/accountTask/DeleteTaskService.java new file mode 100644 index 00000000..37fd8e0c --- /dev/null +++ b/src/main/java/com/salessparrow/api/services/accountTask/DeleteTaskService.java @@ -0,0 +1,28 @@ +package com.salessparrow.api.services.accountTask; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.salessparrow.api.domain.User; +import com.salessparrow.api.lib.crmActions.deleteAccountTask.DeleteAccountTaskFactory; + +import jakarta.servlet.http.HttpServletRequest; + +@Service +public class DeleteTaskService { + + Logger logger = LoggerFactory.getLogger(DeleteTaskService.class); + + @Autowired + private DeleteAccountTaskFactory deleteAccountTaskFactory; + + public void deleteAccountTask(HttpServletRequest request, String accountId, String taskId) { + logger.info("Delete task in account service called"); + + User currentUser = (User) request.getAttribute("current_user"); + + deleteAccountTaskFactory.deleteAccountTask(currentUser, accountId, taskId); + } +} diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/DeleteAccountTaskTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/DeleteAccountTaskTest.java index 0515270a..5c0b6003 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/DeleteAccountTaskTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/DeleteAccountTaskTest.java @@ -93,7 +93,7 @@ public void deleteAccountTask(Scenario testScenario) throws Exception { // Perform the request String requestBody = objectMapper.writeValueAsString(testScenario.getInput().get("body")); - String url = "/api/v1/accounts/" + accountId + "/tasks" + taskId; + String url = "/api/v1/accounts/" + accountId + "/tasks/" + taskId; ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.delete(url) .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) @@ -105,6 +105,9 @@ public void deleteAccountTask(Scenario testScenario) throws Exception { String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); if(resultActions.andReturn().getResponse().getStatus() == 204) { + if (expectedOutput.equals("{}")) { + expectedOutput = ""; + } assertEquals(expectedOutput, actualOutput); } else { common.compareErrors(testScenario, actualOutput); From 88a3706703afb0a7fcec18394228c65bea2ba637 Mon Sep 17 00:00:00 2001 From: Yagnik Thummar Date: Mon, 28 Aug 2023 16:38:28 +0530 Subject: [PATCH 121/195] Added comments. --- .../deleteAccountTask/DeleteAccountTask.java | 3 +++ .../DeleteAccountTaskFactory.java | 12 ++++++++++++ .../DeleteSalesforceAccountTask.java | 19 +++++++++++++++++++ .../accountTask/DeleteTaskService.java | 12 ++++++++++++ 4 files changed, 46 insertions(+) diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteAccountTask.java b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteAccountTask.java index eb78b271..3a21e922 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteAccountTask.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteAccountTask.java @@ -4,6 +4,9 @@ import com.salessparrow.api.domain.User; +/** + * DeleteAccountTask is an interface for deleting a task in an account. + */ @Component public interface DeleteAccountTask { public void deleteAccountTask(User user, String accountId, String taskId); diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteAccountTaskFactory.java b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteAccountTaskFactory.java index 0a82281a..8419cf7d 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteAccountTaskFactory.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteAccountTaskFactory.java @@ -10,6 +10,9 @@ import com.salessparrow.api.lib.errorLib.ErrorObject; import com.salessparrow.api.lib.globalConstants.UserConstants; +/** + * DeleteAccountTaskFactory is a factory class that handles the deleting a task in an account. + */ @Component public class DeleteAccountTaskFactory { @@ -18,6 +21,15 @@ public class DeleteAccountTaskFactory { @Autowired DeleteSalesforceAccountTask deleteSalesforceAccountTask; + /** + * Deletes a task in an account. + * + * @param user + * @param accountId + * @param taskId + * + * @return void + */ public void deleteAccountTask(User user, String accountId, String taskId) { logger.info("Delete Account Task Factory called"); switch(user.getUserKind()) { diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteSalesforceAccountTask.java b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteSalesforceAccountTask.java index 5e418fc1..133e1e3f 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteSalesforceAccountTask.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteSalesforceAccountTask.java @@ -19,6 +19,9 @@ import com.salessparrow.api.lib.salesforce.dto.CompositeRequestDto; import com.salessparrow.api.lib.salesforce.helper.MakeCompositeRequest; +/** + * DeleteSalesforceAccountTask is a class that handles the deleting a task in an account for salesforce. + */ @Component public class DeleteSalesforceAccountTask implements DeleteAccountTask{ Logger logger = LoggerFactory.getLogger(DeleteSalesforceAccountTask.class); @@ -29,6 +32,15 @@ public class DeleteSalesforceAccountTask implements DeleteAccountTask{ @Autowired private MakeCompositeRequest makeCompositeRequest; + /** + * Deletes a task in an account for salesforce. + * + * @param user + * @param accountId + * @param taskId + * + * @return void + */ public void deleteAccountTask(User user, String accountId, String taskId) { logger.info("Delete Salesforce Account Task called"); @@ -47,6 +59,13 @@ public void deleteAccountTask(User user, String accountId, String taskId) { } + /** + * Parses the response from salesforce. + * + * @param responseBody + * + * @return void + */ private void parseResponse(String responseBody) { logger.info("Parsing response body"); Util util = new Util(); diff --git a/src/main/java/com/salessparrow/api/services/accountTask/DeleteTaskService.java b/src/main/java/com/salessparrow/api/services/accountTask/DeleteTaskService.java index 37fd8e0c..73506f4f 100644 --- a/src/main/java/com/salessparrow/api/services/accountTask/DeleteTaskService.java +++ b/src/main/java/com/salessparrow/api/services/accountTask/DeleteTaskService.java @@ -10,6 +10,9 @@ import jakarta.servlet.http.HttpServletRequest; +/** + * DeleteTaskService is a service class that handles the deleting a task in an account. + */ @Service public class DeleteTaskService { @@ -18,6 +21,15 @@ public class DeleteTaskService { @Autowired private DeleteAccountTaskFactory deleteAccountTaskFactory; + /** + * Deletes a task in an account. + * + * @param request + * @param accountId + * @param taskId + * + * @return void + */ public void deleteAccountTask(HttpServletRequest request, String accountId, String taskId) { logger.info("Delete task in account service called"); From 625c5c4db53e328b613ddb7b1d3b26b760871aaa Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Mon, 28 Aug 2023 16:40:16 +0530 Subject: [PATCH 122/195] Updated error response for delete note parse response --- .../DeleteSalesforceAccountNote.java | 22 +++++++++++++------ .../getAccounts/GetSalesforceAccounts.java | 2 +- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteSalesforceAccountNote.java b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteSalesforceAccountNote.java index 605c7cf1..26b5c991 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteSalesforceAccountNote.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteSalesforceAccountNote.java @@ -12,6 +12,7 @@ import com.salessparrow.api.domain.User; import com.salessparrow.api.exception.CustomException; import com.salessparrow.api.lib.Util; +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; @@ -74,13 +75,20 @@ public void parseResponse(String responseBody) { if (deleteNoteStatusCode != 200 && deleteNoteStatusCode != 201 && deleteNoteStatusCode != 204) { String errorBody = deleteNoteCompositeResponse.get("body").asText(); - throw new CustomException( - new ParamErrorObject( - "l_ca_dan_dasn_pr_1", - errorBody, - Arrays.asList("invalid_note_id") - ) - ); + // MALFORMED_ID or NOT_FOUND + if (deleteNoteStatusCode == 400 || deleteNoteStatusCode == 404) { + throw new CustomException( + new ParamErrorObject( + "l_ca_dan_dasn_pr_1", + errorBody, + Arrays.asList("invalid_note_id"))); + } else { + throw new CustomException( + new ErrorObject( + "l_ca_dan_dasn_pr_2", + "something_went_wrong", + errorBody)); + } } } } \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java index 73529e6e..6827b06b 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java @@ -82,7 +82,7 @@ public GetAccountsFormatterDto parseResponse(String responseBody) { throw new CustomException( new ErrorObject( "l_ca_ga_gsa_pr_1", - "bad_request", + "something_went_wrong", "Error in fetching accounts from salesforce")); } From a979843a50575eba23df38d3eb4a3db7f6d758da Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Mon, 28 Aug 2023 16:42:50 +0530 Subject: [PATCH 123/195] Updated error code for get tasks list parse response --- .../GetSalesforceAccountTasksList.java | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetSalesforceAccountTasksList.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetSalesforceAccountTasksList.java index 5f7a7a31..71a7b6e3 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetSalesforceAccountTasksList.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetSalesforceAccountTasksList.java @@ -19,6 +19,7 @@ import com.salessparrow.api.dto.formatter.GetTasksListFormatterDto; import com.salessparrow.api.exception.CustomException; import com.salessparrow.api.lib.Util; +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; @@ -89,13 +90,19 @@ public GetTasksListFormatterDto parseResponse(String responseBody) { if (getTasksStatusCode != 200 && getTasksStatusCode != 201) { String errorBody = getTasksCompositeResponse.get("body").asText(); - throw new CustomException( - new ParamErrorObject( - "l_ca_gatl_gsatl_pr_1", - errorBody, - Arrays.asList("invalid_account_id") - ) - ); + if (getTasksStatusCode == 400) { + throw new CustomException( + new ParamErrorObject( + "l_ca_gatl_gsatl_pr_1", + errorBody, + Arrays.asList("invalid_account_id"))); + } else { + throw new CustomException( + new ErrorObject( + "l_ca_gatl_gsatl_pr_2", + "something_went_wrong", + errorBody)); + } } JsonNode recordsNode = rootNode.get("compositeResponse").get(0).get("body").get("records");; From 71ef8cecef7f1e1b611c3bc76fd5a72bcfc2f3fa Mon Sep 17 00:00:00 2001 From: ajinkyac03 Date: Mon, 28 Aug 2023 16:43:21 +0530 Subject: [PATCH 124/195] Updated test cases and doc files. --- repo-docs/ENVIRONMENT_VARS.md | 7 +++- repo-docs/LOCAL_SETUP.md | 3 +- .../api/lib/GetCrmActionSuggestions.java | 18 ++++------ .../api/lib/openAi/OpenAiPayloadBuilder.java | 3 +- .../crmActionsSuggestions.scenarios.json | 36 +++++++++++++++++++ 5 files changed, 52 insertions(+), 15 deletions(-) diff --git a/repo-docs/ENVIRONMENT_VARS.md b/repo-docs/ENVIRONMENT_VARS.md index c7d7e05f..474686d2 100644 --- a/repo-docs/ENVIRONMENT_VARS.md +++ b/repo-docs/ENVIRONMENT_VARS.md @@ -80,4 +80,9 @@ This document provides descriptions for the environment variables used in the co ## COOKIE_DOMAIN - **Description:** Domain for the API cookies. -- **Example Value:** `localhost` \ No newline at end of file +- **Example Value:** `localhost` + +## OPENAI_API_KEY + +- **Description:** API key for the OpenAI API. +- **Example Value:** `sk-12345asdf` \ No newline at end of file diff --git a/repo-docs/LOCAL_SETUP.md b/repo-docs/LOCAL_SETUP.md index 65758490..3a68f435 100644 --- a/repo-docs/LOCAL_SETUP.md +++ b/repo-docs/LOCAL_SETUP.md @@ -66,7 +66,8 @@ $ touch test.secrets.json "LOCAL_KMS_ENDPOINT": "http://localkms:8080", "ERROR_MAIL_FROM": "", "ERROR_MAIL_TO": "", - "COOKIE_DOMAIN":"" + "COOKIE_DOMAIN": "", + "OPENAI_API_KEY: "" } ``` diff --git a/src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java b/src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java index 7339758d..70c0fed5 100644 --- a/src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java +++ b/src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java @@ -3,9 +3,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -21,6 +18,7 @@ import com.salessparrow.api.lib.errorLib.ErrorObject; import com.salessparrow.api.lib.openAi.OpenAiPayloadBuilder; import com.salessparrow.api.lib.openAi.OpenAiRequest; +import com.salessparrow.api.lib.validators.DateFormatValidator; /** * GetCrmActionSuggestions is a class for getting the crm action suggestions. @@ -33,6 +31,8 @@ public class GetCrmActionSuggestions { @Autowired private OpenAiPayloadBuilder openAiPayloadBuilder; + private DateFormatValidator dateFormatValidator = new DateFormatValidator(); + private Logger logger = org.slf4j.LoggerFactory.getLogger(SuggestionsController.class); /** @@ -80,13 +80,9 @@ private CrmActionSuggestionsFormatterDto parseResponse(String responseBody){ // Format the response check if duedate format is YYYY-MM-DD else remove duedate String dueDate = addTask.getDueDate(); - if (dueDate != null && dueDate.length() > 0) { - Pattern pattern = Pattern.compile("\\d{4}-\\d{2}-\\d{2}"); - Matcher matcher = pattern.matcher(dueDate); - if (matcher.find()) { - addTaskSuggestionEntityDto.setDueDate(dueDate); - } - } + if (dateFormatValidator.isValid(dueDate, null)) { + addTaskSuggestionEntityDto.setDueDate(dueDate); + } formattedTaskSuggestionEntityDtos.add(addTaskSuggestionEntityDto); } @@ -97,7 +93,7 @@ private CrmActionSuggestionsFormatterDto parseResponse(String responseBody){ } catch (Exception e) { throw new CustomException( new ErrorObject( - "l_c_gnl_gsnl_1", + "l_gcas_p_1", "something_went_wrong", e.getMessage() ) diff --git a/src/main/java/com/salessparrow/api/lib/openAi/OpenAiPayloadBuilder.java b/src/main/java/com/salessparrow/api/lib/openAi/OpenAiPayloadBuilder.java index a5fd0408..2ca2744c 100644 --- a/src/main/java/com/salessparrow/api/lib/openAi/OpenAiPayloadBuilder.java +++ b/src/main/java/com/salessparrow/api/lib/openAi/OpenAiPayloadBuilder.java @@ -52,8 +52,7 @@ public String payloadForCrmActionsSuggestions(String text) { " \"required\": [\"description\", \"due_date\"]\n" + " }\n" + " }\n" + - " },\n" + - " \"required\": [\"add_task\"]\n" + + " }\n" + " }\n" + " }\n" + " ]\n" + diff --git a/src/test/resources/data/controllers/suggestionsController/crmActionsSuggestions.scenarios.json b/src/test/resources/data/controllers/suggestionsController/crmActionsSuggestions.scenarios.json index 0709eb81..740e1765 100644 --- a/src/test/resources/data/controllers/suggestionsController/crmActionsSuggestions.scenarios.json +++ b/src/test/resources/data/controllers/suggestionsController/crmActionsSuggestions.scenarios.json @@ -40,6 +40,42 @@ ] } }, + { + "description": "Should return correct response for 0 suggestions", + "input": { + "text": "Text" + }, + "mocks":{ + "makeRequest":{ + "id": "chatcmpl-0000", + "object": "chat.completion", + "created": 1692945329, + "model": "gpt-3.5-turbo-0613", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": null, + "function_call": { + "name": "suggest_actions", + "arguments": "{\n \"add_task\": []\n}" + } + }, + "finish_reason": "function_call" + } + ], + "usage": { + "prompt_tokens": 168, + "completion_tokens": 52, + "total_tokens": 220 + } + } + }, + "output": { + "add_task_suggestions": [] + } + }, { "description": "Should remove due_date from the response if it is not in correct format", "input": { From b9dc3582e21183a3eb3a5f5589d3457ec0a422cc Mon Sep 17 00:00:00 2001 From: Yagnik Thummar Date: Mon, 28 Aug 2023 17:01:30 +0530 Subject: [PATCH 125/195] Code review changes: Fix error handling for salesforce response. --- .../DeleteSalesforceAccountTask.java | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteSalesforceAccountTask.java b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteSalesforceAccountTask.java index 133e1e3f..e89cf6d4 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteSalesforceAccountTask.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteSalesforceAccountTask.java @@ -13,6 +13,7 @@ import com.salessparrow.api.domain.User; import com.salessparrow.api.exception.CustomException; import com.salessparrow.api.lib.Util; +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; @@ -75,15 +76,23 @@ private void parseResponse(String responseBody) { Integer deleteNoteStatusCode = deleteNoteCompositeResponse.get("httpStatusCode").asInt(); if (deleteNoteStatusCode != 200 && deleteNoteStatusCode != 201 && deleteNoteStatusCode != 204) { - String errorBody = deleteNoteCompositeResponse.get("body").asText(); - - throw new CustomException( - new ParamErrorObject( - "l_ca_dan_dasn_pr_1", - errorBody, - Arrays.asList("invalid_task_id") - ) - ); + String errorBody = deleteNoteCompositeResponse.get("body").asText(); + + // MALFORMED_ID or NOT_FOUND + if (deleteNoteStatusCode == 400 || deleteNoteStatusCode != 404) { + + throw new CustomException( + new ParamErrorObject( + "l_ca_dan_dasn_pr_1", + errorBody, + Arrays.asList("invalid_task_id"))); + }else{ + throw new CustomException( + new ErrorObject( + "l_ca_dan_dasn_pr_2", + "something_went_wrong", + errorBody)); + } } } } From dbe8cc5b9715bd9725345872ab35f7f2fec0a596 Mon Sep 17 00:00:00 2001 From: Yagnik Thummar Date: Mon, 28 Aug 2023 17:05:53 +0530 Subject: [PATCH 126/195] Renaming create task lib files. --- .../api/controllers/AccountTaskController.java | 6 +++--- ...nAccountDto.java => CreateAccountTaskDto.java} | 2 +- .../createAccountTask/CreateAccountTask.java | 15 +++++++++++++++ .../CreateAccountTaskFactory.java} | 14 +++++++------- .../CreateSalesforceAccountTask.java} | 12 ++++++------ .../createTaskInAccount/CreateTaskInAccount.java | 15 --------------- .../services/accountTask/CreateTaskService.java | 10 +++++----- 7 files changed, 37 insertions(+), 37 deletions(-) rename src/main/java/com/salessparrow/api/dto/requestMapper/{CreateTaskInAccountDto.java => CreateAccountTaskDto.java} (95%) create mode 100644 src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateAccountTask.java rename src/main/java/com/salessparrow/api/lib/crmActions/{createTaskInAccount/CreateTaskInAccountFactory.java => createAccountTask/CreateAccountTaskFactory.java} (68%) rename src/main/java/com/salessparrow/api/lib/crmActions/{createTaskInAccount/CreateSalesforceTaskInAccount.java => createAccountTask/CreateSalesforceAccountTask.java} (90%) delete mode 100644 src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccount.java diff --git a/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java b/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java index 36f6612e..798185fa 100644 --- a/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java +++ b/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java @@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.RestController; import com.salessparrow.api.dto.formatter.CreateTaskFormatterDto; -import com.salessparrow.api.dto.requestMapper.CreateTaskInAccountDto; +import com.salessparrow.api.dto.requestMapper.CreateAccountTaskDto; import com.salessparrow.api.services.accountTask.CreateTaskService; import com.salessparrow.api.services.accountTask.DeleteTaskService; @@ -39,11 +39,11 @@ public class AccountTaskController { public ResponseEntity createTask( HttpServletRequest request, @PathVariable("account_id") String accountId, - @Valid @RequestBody CreateTaskInAccountDto task + @Valid @RequestBody CreateAccountTaskDto task ){ logger.info("Create task request received"); - CreateTaskFormatterDto createTaskFormatterDto = createTaskService.createTaskInAccount(request, accountId, task); + CreateTaskFormatterDto createTaskFormatterDto = createTaskService.createAccountTask(request, accountId, task); return ResponseEntity.status(HttpStatus.CREATED).body(createTaskFormatterDto); } diff --git a/src/main/java/com/salessparrow/api/dto/requestMapper/CreateTaskInAccountDto.java b/src/main/java/com/salessparrow/api/dto/requestMapper/CreateAccountTaskDto.java similarity index 95% rename from src/main/java/com/salessparrow/api/dto/requestMapper/CreateTaskInAccountDto.java rename to src/main/java/com/salessparrow/api/dto/requestMapper/CreateAccountTaskDto.java index 20f3d3e5..b1f6be7b 100644 --- a/src/main/java/com/salessparrow/api/dto/requestMapper/CreateTaskInAccountDto.java +++ b/src/main/java/com/salessparrow/api/dto/requestMapper/CreateAccountTaskDto.java @@ -10,7 +10,7 @@ @Data @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) -public class CreateTaskInAccountDto { +public class CreateAccountTaskDto { @NotBlank(message = "missing_crm_organization_user_id") private String crmOrganizationUserId; diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateAccountTask.java b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateAccountTask.java new file mode 100644 index 00000000..4e7b039d --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateAccountTask.java @@ -0,0 +1,15 @@ +package com.salessparrow.api.lib.crmActions.createAccountTask; + +import org.springframework.stereotype.Component; + +import com.salessparrow.api.domain.User; +import com.salessparrow.api.dto.formatter.CreateTaskFormatterDto; +import com.salessparrow.api.dto.requestMapper.CreateAccountTaskDto; + +/** + * CreateTask interface is interface for createTask for various CRM services + */ +@Component +public interface CreateAccountTask { + public CreateTaskFormatterDto createAccountTask(User User,String accountId, CreateAccountTaskDto task); +} diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccountFactory.java b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateAccountTaskFactory.java similarity index 68% rename from src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccountFactory.java rename to src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateAccountTaskFactory.java index 540f6ef3..8ac55a16 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccountFactory.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateAccountTaskFactory.java @@ -1,4 +1,4 @@ -package com.salessparrow.api.lib.crmActions.createTaskInAccount; +package com.salessparrow.api.lib.crmActions.createAccountTask; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -7,7 +7,7 @@ import com.salessparrow.api.domain.User; import com.salessparrow.api.dto.formatter.CreateTaskFormatterDto; -import com.salessparrow.api.dto.requestMapper.CreateTaskInAccountDto; +import com.salessparrow.api.dto.requestMapper.CreateAccountTaskDto; import com.salessparrow.api.exception.CustomException; import com.salessparrow.api.lib.errorLib.ErrorObject; import com.salessparrow.api.lib.globalConstants.UserConstants; @@ -16,12 +16,12 @@ * CreateTaskFactory class is responsible for creating a task in CRM */ @Component -public class CreateTaskInAccountFactory { +public class CreateAccountTaskFactory { - Logger logger = LoggerFactory.getLogger(CreateTaskInAccountFactory.class); + Logger logger = LoggerFactory.getLogger(CreateAccountTaskFactory.class); @Autowired - CreateSalesforceTaskInAccount createSalesforceTaskInAccount; + CreateSalesforceAccountTask createSalesforceAccountTask; /** * Create a task in CRM @@ -32,11 +32,11 @@ public class CreateTaskInAccountFactory { * * @return CreateTaskFormatterDto object */ - public CreateTaskFormatterDto createTaskInAccount(User user, String accountId, CreateTaskInAccountDto task) { + public CreateTaskFormatterDto createAccountTask(User user, String accountId, CreateAccountTaskDto task) { switch(user.getUserKind()) { case UserConstants.SALESFORCE_USER_KIND: logger.info("calling createTask of salesforceCreateTask"); - return createSalesforceTaskInAccount.createTaskInAccount(user, accountId, task); + return createSalesforceAccountTask.createAccountTask(user, accountId, task); default: throw new CustomException( new ErrorObject( diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateSalesforceTaskInAccount.java b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateSalesforceAccountTask.java similarity index 90% rename from src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateSalesforceTaskInAccount.java rename to src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateSalesforceAccountTask.java index 9427387f..087bf743 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateSalesforceTaskInAccount.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateSalesforceAccountTask.java @@ -1,4 +1,4 @@ -package com.salessparrow.api.lib.crmActions.createTaskInAccount; +package com.salessparrow.api.lib.crmActions.createAccountTask; import java.util.ArrayList; import java.util.HashMap; @@ -15,7 +15,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.salessparrow.api.domain.User; import com.salessparrow.api.dto.formatter.CreateTaskFormatterDto; -import com.salessparrow.api.dto.requestMapper.CreateTaskInAccountDto; +import com.salessparrow.api.dto.requestMapper.CreateAccountTaskDto; import com.salessparrow.api.exception.CustomException; import com.salessparrow.api.lib.Util; import com.salessparrow.api.lib.errorLib.ErrorObject; @@ -29,9 +29,9 @@ * CreateSalesforceTask class is responsible for creating a task in Salesforce */ @Component -public class CreateSalesforceTaskInAccount implements CreateTaskInAccount{ +public class CreateSalesforceAccountTask implements CreateAccountTask{ - Logger logger = LoggerFactory.getLogger(CreateSalesforceTaskInAccount.class); + Logger logger = LoggerFactory.getLogger(CreateSalesforceAccountTask.class); @Autowired private SalesforceConstants salesforceConstants; @@ -48,7 +48,7 @@ public class CreateSalesforceTaskInAccount implements CreateTaskInAccount{ * * @return CreateTaskFormatterDto object */ - public CreateTaskFormatterDto createTaskInAccount(User User, String accountId, CreateTaskInAccountDto task) { + public CreateTaskFormatterDto createAccountTask(User User, String accountId, CreateAccountTaskDto task) { String salesforceUserId = User.getExternalUserId(); String taskSubject = getTaskSubjectFromDescription(task); @@ -123,7 +123,7 @@ private CreateTaskFormatterDto parseResponse(String createTaskResponse){ * * @return String task subject */ - private String getTaskSubjectFromDescription(CreateTaskInAccountDto task) { + private String getTaskSubjectFromDescription(CreateAccountTaskDto task) { logger.info("getting task subject from description"); if (task.getDescription().length() < 60) { return task.getDescription(); diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccount.java b/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccount.java deleted file mode 100644 index c98b4e98..00000000 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createTaskInAccount/CreateTaskInAccount.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.salessparrow.api.lib.crmActions.createTaskInAccount; - -import org.springframework.stereotype.Component; - -import com.salessparrow.api.domain.User; -import com.salessparrow.api.dto.formatter.CreateTaskFormatterDto; -import com.salessparrow.api.dto.requestMapper.CreateTaskInAccountDto; - -/** - * CreateTask interface is interface for createTask for various CRM services - */ -@Component -public interface CreateTaskInAccount { - public CreateTaskFormatterDto createTaskInAccount(User User,String accountId, CreateTaskInAccountDto task); -} diff --git a/src/main/java/com/salessparrow/api/services/accountTask/CreateTaskService.java b/src/main/java/com/salessparrow/api/services/accountTask/CreateTaskService.java index 134fd8bf..eb86bdf7 100644 --- a/src/main/java/com/salessparrow/api/services/accountTask/CreateTaskService.java +++ b/src/main/java/com/salessparrow/api/services/accountTask/CreateTaskService.java @@ -7,8 +7,8 @@ import com.salessparrow.api.domain.User; import com.salessparrow.api.dto.formatter.CreateTaskFormatterDto; -import com.salessparrow.api.dto.requestMapper.CreateTaskInAccountDto; -import com.salessparrow.api.lib.crmActions.createTaskInAccount.CreateTaskInAccountFactory; +import com.salessparrow.api.dto.requestMapper.CreateAccountTaskDto; +import com.salessparrow.api.lib.crmActions.createAccountTask.CreateAccountTaskFactory; import jakarta.servlet.http.HttpServletRequest; @@ -20,7 +20,7 @@ public class CreateTaskService { Logger logger = LoggerFactory.getLogger(CreateTaskService.class); @Autowired - private CreateTaskInAccountFactory createTaskInAccountFactory; + private CreateAccountTaskFactory createAccountTaskFactory; /** * Create a task in CRM @@ -31,9 +31,9 @@ public class CreateTaskService { * * @return CreateTaskFormatterDto object */ - public CreateTaskFormatterDto createTaskInAccount(HttpServletRequest request, String accountId, CreateTaskInAccountDto task) { + public CreateTaskFormatterDto createAccountTask(HttpServletRequest request, String accountId, CreateAccountTaskDto task) { logger.info("inside createTask Service"); User currentUser = (User) request.getAttribute("current_user"); - return createTaskInAccountFactory.createTaskInAccount(currentUser, accountId, task); + return createAccountTaskFactory.createAccountTask(currentUser, accountId, task); } } From 384bf1ed8a425b9a44cae3bde6b91af94d39d122 Mon Sep 17 00:00:00 2001 From: amanbarbaria Date: Mon, 28 Aug 2023 17:07:50 +0530 Subject: [PATCH 127/195] Log DB Query time --- .../api/config/DynamoDBConfiguration.java | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java index 1cf12223..e0882af5 100644 --- a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java +++ b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java @@ -6,6 +6,8 @@ import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig; +import java.time.Instant; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Bean; @@ -23,14 +25,34 @@ public DynamoDBMapper dynamoDBMapper() { return new DynamoDBMapper(buildAmazonDynamoDB(), dynamoDBMapperConfig()) { @Override public T load(Class clazz, Object hashKey) { - logger.debug("DBQuery:Load: table-{} hashKey-{}", clazz.getSimpleName(), hashKey); - return defaultMapper.load(clazz, hashKey); + T response = null; + Instant startTimestamp = Instant.now(); + 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 e; + } + + Integer duration = (int) (Instant.now().toEpochMilli() - startTimestamp.toEpochMilli()); + logger.debug("({} ms)DBQuery:Load: table-{} hashKey-{}", duration, clazz.getSimpleName(), hashKey); + return response; } @Override public void save(T object) { - logger.debug("DBQuery:Save: table-{}", object.getClass().getSimpleName()); - defaultMapper.save(object); + Instant startTimestamp = Instant.now(); + try { + defaultMapper.save(object); + } catch (Exception e) { + logger.debug("DBQuery:Save: table-{}", object.getClass().getSimpleName()); + logger.error("DBQuery:Save: exception-{}", e); + throw e; + } + + Integer duration = (int) (Instant.now().toEpochMilli() - startTimestamp.toEpochMilli()); + logger.debug("({} ms)DBQuery:Save: table-{}", duration, object.getClass().getSimpleName()); } // Similarly, you can override other used methods like delete, batchSave, etc. similarly }; From 73c3ab1f22f7cf68bb5afd6c7fddf5fd7cdd50f9 Mon Sep 17 00:00:00 2001 From: amanbarbaria Date: Mon, 28 Aug 2023 17:08:41 +0530 Subject: [PATCH 128/195] Added db logs --- .../java/com/salessparrow/api/config/DynamoDBConfiguration.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java index e0882af5..6561d3b6 100644 --- a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java +++ b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java @@ -8,6 +8,8 @@ import java.time.Instant; +import java.time.Instant; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Bean; From f5ca36c14a1b433b36ae7617f06f0f8c1bd6c7fb Mon Sep 17 00:00:00 2001 From: Yagnik Thummar Date: Mon, 28 Aug 2023 17:10:56 +0530 Subject: [PATCH 129/195] Updating salesforce response handing. --- .../deleteAccountTask/DeleteSalesforceAccountTask.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteSalesforceAccountTask.java b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteSalesforceAccountTask.java index e89cf6d4..835451c2 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteSalesforceAccountTask.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteSalesforceAccountTask.java @@ -79,7 +79,7 @@ private void parseResponse(String responseBody) { String errorBody = deleteNoteCompositeResponse.get("body").asText(); // MALFORMED_ID or NOT_FOUND - if (deleteNoteStatusCode == 400 || deleteNoteStatusCode != 404) { + if (deleteNoteStatusCode == 400 || deleteNoteStatusCode == 404) { throw new CustomException( new ParamErrorObject( From f3d202ab8e56365f7c1c1c9b4080dceb90f54b27 Mon Sep 17 00:00:00 2001 From: amanbarbaria Date: Mon, 28 Aug 2023 17:11:23 +0530 Subject: [PATCH 130/195] Removed unused import --- .../java/com/salessparrow/api/config/DynamoDBConfiguration.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java index 6561d3b6..19a8168e 100644 --- a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java +++ b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java @@ -8,7 +8,6 @@ import java.time.Instant; -import java.time.Instant; import org.slf4j.Logger; import org.slf4j.LoggerFactory; From 687201b7df611d0d6d3fa24d39b7b1852f927098 Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Mon, 28 Aug 2023 18:16:32 +0530 Subject: [PATCH 131/195] Added soql code changes for queries --- .../helper/SalesforceQueryBuilder.java | 48 +++++++++---------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java index d8c7627f..93a31266 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java @@ -11,15 +11,6 @@ */ @Component public class SalesforceQueryBuilder { - public String formatStringForSoqlQueries(String input){ - // escaping special characters of SOQL queries Like ( ', ", \, %, _) - input = Util.escapeSpecialChars(input); - - // encoding the input to UrlEncoder - input = Util.urlEncoder(input); - - return input; - } /** * Get the list of accounts for a given searchTerm @@ -29,12 +20,16 @@ public String formatStringForSoqlQueries(String input){ * @return String */ public String getAccountsQuery(String searchTerm) { + searchTerm = Util.escapeSpecialChars(searchTerm); + + String query = ""; if (searchTerm == "") { - return "SELECT Id, Name FROM Account ORDER BY LastModifiedDate DESC LIMIT 20"; - } - searchTerm = formatStringForSoqlQueries(searchTerm); + query = "SELECT Id, Name FROM Account ORDER BY LastModifiedDate DESC LIMIT 20"; + } else { + query = "SELECT Id, Name FROM Account WHERE Name LIKE '%"+searchTerm+"%' ORDER BY LastModifiedDate DESC LIMIT 20"; + } - return "SELECT Id, Name FROM Account WHERE Name LIKE '%25"+searchTerm+"%25' ORDER BY LastModifiedDate DESC LIMIT 20"; + return Util.urlEncoder(query); } /** @@ -44,10 +39,10 @@ public String getAccountsQuery(String searchTerm) { * @return String */ public String getContentDocumentIdUrl(String accountId) { - accountId = Util.urlEncoder(accountId); + accountId = Util.escapeSpecialChars(accountId); - return "SELECT ContentDocumentId FROM ContentDocumentLink WHERE LinkedEntityId = '" - + accountId + "'"; + return Util.urlEncoder("SELECT ContentDocumentId FROM ContentDocumentLink WHERE LinkedEntityId = '" + + accountId + "'"); } /** @@ -65,27 +60,30 @@ public String getNoteListIdUrl(List documentIds) { queryBuilder.append(", "); } - String documentId = Util.urlEncoder(documentIds.get(i)); + String documentId = Util.escapeSpecialChars(documentIds.get(i)); queryBuilder.append("'").append(documentId).append("'"); } queryBuilder.append(") ORDER BY LastModifiedDate DESC LIMIT 5"); - return queryBuilder.toString(); + return Util.urlEncoder(queryBuilder.toString()); } public String getNoteDetailsUrl(String noteId){ - noteId = Util.urlEncoder(noteId); + noteId = Util.escapeSpecialChars(noteId); - return "SELECT Id, Title, TextPreview, CreatedBy.Name, LastModifiedDate FROM ContentNote WHERE Id = '" + noteId + "'"; + return Util.urlEncoder("SELECT Id, Title, TextPreview, CreatedBy.Name, LastModifiedDate FROM ContentNote WHERE Id = '" + noteId + "'"); } public String getCrmOrganizationUsersQuery(String searchTerm) { + searchTerm = Util.escapeSpecialChars(searchTerm); + String query = ""; + if (searchTerm == "") { - return "SELECT Id, Name FROM User ORDER BY LastModifiedDate DESC LIMIT 20"; - } - searchTerm = formatStringForSoqlQueries(searchTerm); + query = "SELECT Id, Name FROM User ORDER BY LastModifiedDate DESC LIMIT 20"; + } else { + query = "SELECT Id, Name FROM User WHERE Name LIKE '%"+searchTerm+"%' ORDER BY LastModifiedDate DESC LIMIT 20"; + } - return "SELECT Id, Name FROM User WHERE Name LIKE '%25"+searchTerm+"%25' ORDER BY LastModifiedDate DESC LIMIT 20"; + return Util.urlEncoder(query); } - } From f03a78a1421378d3255cf0fcbc7830946bcd317f Mon Sep 17 00:00:00 2001 From: amanbarbaria Date: Mon, 28 Aug 2023 18:44:52 +0530 Subject: [PATCH 132/195] Unit Test cases added for Repositories --- .../SalesforceOauthTokenRepository.java | 6 +++- .../SalesforceOrganizationRepository.java | 8 +++-- .../SalesforceUserRepository.java | 7 ++-- .../SalesforceOauthTokenRepositoryTest.java | 17 +++++----- .../SalesforceOrganizationRepositoryTest.java | 32 +++++++++---------- .../SalesforceUserRepositoryTest.java | 14 +++++--- .../ActiveSalesforceOauthToken.json | 0 .../ActiveSalesforceOrganization.json | 0 .../DeletedSalesforceOrganization.json | 0 .../salesforceUser/ActiveSalesforceUser.json | 0 .../ActiveSalesforceUserForLogin.json | 0 .../createNote.fixtures.json | 4 +-- .../getAccountList.fixtures.json | 4 +-- .../getNoteDetails.fixtures.json | 4 +-- .../getNotesList.fixtures.json | 4 +-- .../createTask.fixtures.json | 4 +-- .../authController/PostLogoutFixture.json | 2 +- .../PostSalesforceConnectFixture.json | 10 +++--- .../getCurrentUser.fixtures.json | 2 +- .../salesforceOauthTokenRepository.json | 2 +- .../salesforceOrganizationRepository.json | 2 +- .../salesforceUserRepository.json | 2 +- 22 files changed, 70 insertions(+), 54 deletions(-) rename src/test/resources/fixtures/{ => common}/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json (100%) rename src/test/resources/fixtures/{ => common}/repositories/salesforceOrganization/ActiveSalesforceOrganization.json (100%) rename src/test/resources/fixtures/{ => common}/repositories/salesforceOrganization/DeletedSalesforceOrganization.json (100%) rename src/test/resources/fixtures/{ => common}/repositories/salesforceUser/ActiveSalesforceUser.json (100%) rename src/test/resources/fixtures/{ => common}/repositories/salesforceUser/ActiveSalesforceUserForLogin.json (100%) diff --git a/src/main/java/com/salessparrow/api/repositories/SalesforceOauthTokenRepository.java b/src/main/java/com/salessparrow/api/repositories/SalesforceOauthTokenRepository.java index addf09c9..431ba697 100644 --- a/src/main/java/com/salessparrow/api/repositories/SalesforceOauthTokenRepository.java +++ b/src/main/java/com/salessparrow/api/repositories/SalesforceOauthTokenRepository.java @@ -17,8 +17,12 @@ @Repository public class SalesforceOauthTokenRepository { + private final DynamoDBMapper dynamoDBMapper; + @Autowired - private DynamoDBMapper dynamoDBMapper; + public SalesforceOauthTokenRepository(DynamoDBMapper dynamoDBMapper) { + this.dynamoDBMapper = dynamoDBMapper; + } /** * Saves a SalesforceOauthToken to the salesforce_oauth_tokens table. diff --git a/src/main/java/com/salessparrow/api/repositories/SalesforceOrganizationRepository.java b/src/main/java/com/salessparrow/api/repositories/SalesforceOrganizationRepository.java index 8e66e669..a6f6fd98 100644 --- a/src/main/java/com/salessparrow/api/repositories/SalesforceOrganizationRepository.java +++ b/src/main/java/com/salessparrow/api/repositories/SalesforceOrganizationRepository.java @@ -14,9 +14,13 @@ @Repository public class SalesforceOrganizationRepository { - @Autowired - private DynamoDBMapper dynamoDBMapper; + private final DynamoDBMapper dynamoDBMapper; + @Autowired + public SalesforceOrganizationRepository(DynamoDBMapper dynamoDBMapper) { + this.dynamoDBMapper = dynamoDBMapper; + } + /** * Saves a SalesforceOrganization to the salesforce_organizations table. * diff --git a/src/main/java/com/salessparrow/api/repositories/SalesforceUserRepository.java b/src/main/java/com/salessparrow/api/repositories/SalesforceUserRepository.java index 35c583e9..bf22ad44 100644 --- a/src/main/java/com/salessparrow/api/repositories/SalesforceUserRepository.java +++ b/src/main/java/com/salessparrow/api/repositories/SalesforceUserRepository.java @@ -17,9 +17,12 @@ @Repository public class SalesforceUserRepository { - @Autowired - private DynamoDBMapper dynamoDBMapper; + private final DynamoDBMapper dynamoDBMapper; + @Autowired + public SalesforceUserRepository(DynamoDBMapper dynamoDBMapper) { + this.dynamoDBMapper = dynamoDBMapper; + } /** * Saves a SalesforceUser to the salesforce_users table. * diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java index e66f1252..e8b20e24 100644 --- a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java @@ -2,20 +2,16 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Import; -import org.springframework.boot.test.mock.mockito.MockBean; - import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; - import java.io.IOException; - import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; - import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; import com.github.dynamobee.exception.DynamobeeException; import com.salessparrow.api.domain.SalesforceOauthToken; @@ -53,9 +49,6 @@ public void setUp() throws DynamobeeException, IOException { public void tearDown() { cleanup.perform(); } - - @MockBean - private DynamoDBMapper dynamoDBMapper; @Autowired private SalesforceOauthTokenRepository salesforceOauthTokenRepository; @@ -72,6 +65,10 @@ public void testSaveSalesforceOauthToken() { SalesforceOauthToken salesforceOauthTokenInvalid = new SalesforceOauthToken(); salesforceOauthTokenInvalid.setExternalUserId("externalUserId-2"); + // mock the DynamoDBMapper + DynamoDBMapper dynamoDBMapper = mock(DynamoDBMapper.class); + SalesforceOauthTokenRepository salesforceOauthTokenRepository = new SalesforceOauthTokenRepository(dynamoDBMapper); + // Mock the behavior to throw an exception when save is called doThrow(new CustomException(new ErrorObject("test:r_sotr_tssfot_1", "something_went_wrong", "mock db save error"))) .when(dynamoDBMapper) @@ -99,6 +96,10 @@ public void testGetSalesforceOauthTokenByExternalUserId() throws Exception{{ String testExternalUserId = "externalUserId-3"; + // mock the DynamoDBMapper + DynamoDBMapper dynamoDBMapper = mock(DynamoDBMapper.class); + SalesforceOauthTokenRepository salesforceOauthTokenRepository = new SalesforceOauthTokenRepository(dynamoDBMapper); + // Mock the behavior to throw an exception when load is called when(dynamoDBMapper.load(SalesforceOauthToken.class, testExternalUserId)).thenThrow( new CustomException(new ErrorObject("test:r_sotr_gsotbsfui_1", diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java index c321ba56..6497ac8d 100644 --- a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java @@ -2,20 +2,16 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Import; -import org.springframework.boot.test.mock.mockito.MockBean; - import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; - import java.io.IOException; - import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; - import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; import com.github.dynamobee.exception.DynamobeeException; import com.salessparrow.api.domain.SalesforceOrganization; @@ -53,9 +49,6 @@ public void setUp() throws DynamobeeException, IOException { public void tearDown() { cleanup.perform(); } - - @MockBean - private DynamoDBMapper dynamoDBMapper; @Autowired private SalesforceOrganizationRepository salesforceOrganizationRepository; @@ -72,6 +65,10 @@ public void testSaveSalesforceOrganization() { SalesforceOrganization salesforceOrganizationInvalid = new SalesforceOrganization(); salesforceOrganizationInvalid.setExternalOrganizationId("externalUserId-2"); + // mock the DynamoDBMapper + DynamoDBMapper dynamoDBMapper = mock(DynamoDBMapper.class); + SalesforceOrganizationRepository salesforceOrganizationRepository = new SalesforceOrganizationRepository(dynamoDBMapper); + // Mock the behavior to throw an exception when save is called doThrow(new CustomException(new ErrorObject("test:r_sor_tssfo_1", "something_went_wrong", "mock db save error"))) .when(dynamoDBMapper) @@ -88,19 +85,20 @@ public void testSaveSalesforceOrganization() { @Test public void testGetSalesforceOrganizationByExternalOrganizationId() throws Exception{{ - - // String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - // FixtureData fixtureData = common.loadFixture("classpath:fixtures/unit/repositories/salesforceOrganizationRepository.json", currentFunctionName); - // loadFixture.perform(fixtureData); + String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/unit/repositories/salesforceOrganizationRepository.json", currentFunctionName); + loadFixture.perform(fixtureData); - // //Valid Get Db Query - // SalesforceOrganization salesforceOrganizationResp = salesforceOrganizationRepository.getSalesforceOrganizationByExternalOrganizationId("000Org-id"); - // System.out.println("salesfo===========: " + salesforceOrganizationResp); - - // assertEquals("000Org-id", salesforceOrganizationResp.getExternalOrganizationId()); + //Valid Get Db Query + SalesforceOrganization salesforceOrganizationResp = salesforceOrganizationRepository.getSalesforceOrganizationByExternalOrganizationId("000Org-id"); + assertEquals("000Org-id", salesforceOrganizationResp.getExternalOrganizationId()); String testExternalOrganizationId = "externalUserId-2"; + // mock the DynamoDBMapper + DynamoDBMapper dynamoDBMapper = mock(DynamoDBMapper.class); + SalesforceOrganizationRepository salesforceOrganizationRepository = new SalesforceOrganizationRepository(dynamoDBMapper); + // Mock the behavior to throw an exception when load is called when(dynamoDBMapper.load(SalesforceOrganization.class, testExternalOrganizationId)).thenThrow( new CustomException(new ErrorObject("test:r_sor_gsotbsfui_1", diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java index cfc61449..2a05f181 100644 --- a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java @@ -2,11 +2,11 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Import; -import org.springframework.boot.test.mock.mockito.MockBean; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.io.IOException; @@ -53,9 +53,6 @@ public void setUp() throws DynamobeeException, IOException { public void tearDown() { cleanup.perform(); } - - @MockBean - private DynamoDBMapper dynamoDBMapper; @Autowired private SalesforceUserRepository salesforceUserRepository; @@ -71,6 +68,10 @@ public void testSaveSalesforceUser() { // Invalid Save Db Query without partition key SalesforceUser salesforceUserInvalid = new SalesforceUser(); salesforceUserInvalid.setExternalUserId("externalUserId-test2"); + + // mock the DynamoDBMapper + DynamoDBMapper dynamoDBMapper = mock(DynamoDBMapper.class); + SalesforceUserRepository salesforceUserRepository = new SalesforceUserRepository(dynamoDBMapper); // Mock the behavior to throw an exception when save is called doThrow(new CustomException(new ErrorObject("test:r_sotr_tssfu_1", "something_went_wrong", "mock db save error"))) @@ -99,6 +100,11 @@ public void testGetSalesforceUserByExternalUserId() throws Exception{{ String testExternalUserId = "externalUserId-test3"; + // mock the DynamoDBMapper + DynamoDBMapper dynamoDBMapper = mock(DynamoDBMapper.class); + SalesforceUserRepository salesforceUserRepository = new SalesforceUserRepository(dynamoDBMapper); + + // Mock the behavior to throw an exception when load is called when(dynamoDBMapper.load(SalesforceUser.class, testExternalUserId)).thenThrow( new CustomException(new ErrorObject("test:r_sur_gsotbsfui_1", diff --git a/src/test/resources/fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json b/src/test/resources/fixtures/common/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json similarity index 100% rename from src/test/resources/fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json rename to src/test/resources/fixtures/common/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json diff --git a/src/test/resources/fixtures/repositories/salesforceOrganization/ActiveSalesforceOrganization.json b/src/test/resources/fixtures/common/repositories/salesforceOrganization/ActiveSalesforceOrganization.json similarity index 100% rename from src/test/resources/fixtures/repositories/salesforceOrganization/ActiveSalesforceOrganization.json rename to src/test/resources/fixtures/common/repositories/salesforceOrganization/ActiveSalesforceOrganization.json diff --git a/src/test/resources/fixtures/repositories/salesforceOrganization/DeletedSalesforceOrganization.json b/src/test/resources/fixtures/common/repositories/salesforceOrganization/DeletedSalesforceOrganization.json similarity index 100% rename from src/test/resources/fixtures/repositories/salesforceOrganization/DeletedSalesforceOrganization.json rename to src/test/resources/fixtures/common/repositories/salesforceOrganization/DeletedSalesforceOrganization.json diff --git a/src/test/resources/fixtures/repositories/salesforceUser/ActiveSalesforceUser.json b/src/test/resources/fixtures/common/repositories/salesforceUser/ActiveSalesforceUser.json similarity index 100% rename from src/test/resources/fixtures/repositories/salesforceUser/ActiveSalesforceUser.json rename to src/test/resources/fixtures/common/repositories/salesforceUser/ActiveSalesforceUser.json diff --git a/src/test/resources/fixtures/repositories/salesforceUser/ActiveSalesforceUserForLogin.json b/src/test/resources/fixtures/common/repositories/salesforceUser/ActiveSalesforceUserForLogin.json similarity index 100% rename from src/test/resources/fixtures/repositories/salesforceUser/ActiveSalesforceUserForLogin.json rename to src/test/resources/fixtures/common/repositories/salesforceUser/ActiveSalesforceUserForLogin.json diff --git a/src/test/resources/fixtures/controllers/accountController/createNote.fixtures.json b/src/test/resources/fixtures/controllers/accountController/createNote.fixtures.json index c62d64b4..6741c9a3 100644 --- a/src/test/resources/fixtures/controllers/accountController/createNote.fixtures.json +++ b/src/test/resources/fixtures/controllers/accountController/createNote.fixtures.json @@ -2,12 +2,12 @@ "createNote": { "salesforce_users": [ { - "filepath": "classpath:fixtures/repositories/salesforceUser/ActiveSalesforceUser.json" + "filepath": "classpath:fixtures/common/repositories/salesforceUser/ActiveSalesforceUser.json" } ], "salesforce_oauth_tokens": [ { - "filepath": "classpath:fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" + "filepath": "classpath:fixtures/common/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" } ] } diff --git a/src/test/resources/fixtures/controllers/accountController/getAccountList.fixtures.json b/src/test/resources/fixtures/controllers/accountController/getAccountList.fixtures.json index 6444679c..a27c41cf 100644 --- a/src/test/resources/fixtures/controllers/accountController/getAccountList.fixtures.json +++ b/src/test/resources/fixtures/controllers/accountController/getAccountList.fixtures.json @@ -2,12 +2,12 @@ "getAccountList": { "salesforce_users": [ { - "filepath": "classpath:fixtures/repositories/salesforceUser/ActiveSalesforceUser.json" + "filepath": "classpath:fixtures/common/repositories/salesforceUser/ActiveSalesforceUser.json" } ], "salesforce_oauth_tokens": [ { - "filepath": "classpath:fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" + "filepath": "classpath:fixtures/common/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" } ] } diff --git a/src/test/resources/fixtures/controllers/accountController/getNoteDetails.fixtures.json b/src/test/resources/fixtures/controllers/accountController/getNoteDetails.fixtures.json index c9d6c0e7..f089a408 100644 --- a/src/test/resources/fixtures/controllers/accountController/getNoteDetails.fixtures.json +++ b/src/test/resources/fixtures/controllers/accountController/getNoteDetails.fixtures.json @@ -2,12 +2,12 @@ "getNoteDetails": { "salesforce_users": [ { - "filepath": "classpath:fixtures/repositories/salesforceUser/ActiveSalesforceUser.json" + "filepath": "classpath:fixtures/common/repositories/salesforceUser/ActiveSalesforceUser.json" } ], "salesforce_oauth_tokens": [ { - "filepath": "classpath:fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" + "filepath": "classpath:fixtures/common/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" } ] } diff --git a/src/test/resources/fixtures/controllers/accountController/getNotesList.fixtures.json b/src/test/resources/fixtures/controllers/accountController/getNotesList.fixtures.json index 8de43024..8118f7d9 100644 --- a/src/test/resources/fixtures/controllers/accountController/getNotesList.fixtures.json +++ b/src/test/resources/fixtures/controllers/accountController/getNotesList.fixtures.json @@ -2,12 +2,12 @@ "getNoteList": { "salesforce_users": [ { - "filepath": "classpath:fixtures/repositories/salesforceUser/ActiveSalesforceUser.json" + "filepath": "classpath:fixtures/common/repositories/salesforceUser/ActiveSalesforceUser.json" } ], "salesforce_oauth_tokens": [ { - "filepath": "classpath:fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" + "filepath": "classpath:fixtures/common/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" } ] } diff --git a/src/test/resources/fixtures/controllers/accountTaskController/createTask.fixtures.json b/src/test/resources/fixtures/controllers/accountTaskController/createTask.fixtures.json index 49f7f52b..acfc8044 100644 --- a/src/test/resources/fixtures/controllers/accountTaskController/createTask.fixtures.json +++ b/src/test/resources/fixtures/controllers/accountTaskController/createTask.fixtures.json @@ -2,12 +2,12 @@ "createTask": { "salesforce_users": [ { - "filepath": "classpath:fixtures/repositories/salesforceUser/ActiveSalesforceUser.json" + "filepath": "classpath:fixtures/common/repositories/salesforceUser/ActiveSalesforceUser.json" } ], "salesforce_oauth_tokens": [ { - "filepath": "classpath:fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" + "filepath": "classpath:fixtures/common/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" } ] } diff --git a/src/test/resources/fixtures/controllers/authController/PostLogoutFixture.json b/src/test/resources/fixtures/controllers/authController/PostLogoutFixture.json index 7f47e4a1..7d870c5d 100644 --- a/src/test/resources/fixtures/controllers/authController/PostLogoutFixture.json +++ b/src/test/resources/fixtures/controllers/authController/PostLogoutFixture.json @@ -2,7 +2,7 @@ "testPostLogout": { "salesforce_users": [ { - "filepath": "classpath:fixtures/repositories/salesforceUser/ActiveSalesforceUser.json" + "filepath": "classpath:fixtures/common/repositories/salesforceUser/ActiveSalesforceUser.json" } ] } diff --git a/src/test/resources/fixtures/controllers/authController/PostSalesforceConnectFixture.json b/src/test/resources/fixtures/controllers/authController/PostSalesforceConnectFixture.json index cfaf9f5a..d81e1ddd 100644 --- a/src/test/resources/fixtures/controllers/authController/PostSalesforceConnectFixture.json +++ b/src/test/resources/fixtures/controllers/authController/PostSalesforceConnectFixture.json @@ -2,23 +2,23 @@ "testPostSalesforceConnectLogin": { "salesforce_users": [ { - "filepath": "classpath:fixtures/repositories/salesforceUser/ActiveSalesforceUser.json" + "filepath": "classpath:fixtures/common/repositories/salesforceUser/ActiveSalesforceUser.json" }, { - "filepath": "classpath:fixtures/repositories/salesforceUser/ActiveSalesforceUserForLogin.json" + "filepath": "classpath:fixtures/common/repositories/salesforceUser/ActiveSalesforceUserForLogin.json" } ], "salesforce_oauth_tokens": [ { - "filepath": "classpath:fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" + "filepath": "classpath:fixtures/common/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" } ], "salesforce_organizations": [ { - "filepath": "classpath:fixtures/repositories/salesforceOrganization/ActiveSalesforceOrganization.json" + "filepath": "classpath:fixtures/common/repositories/salesforceOrganization/ActiveSalesforceOrganization.json" }, { - "filepath": "classpath:fixtures/repositories/salesforceOrganization/DeletedSalesforceOrganization.json" + "filepath": "classpath:fixtures/common/repositories/salesforceOrganization/DeletedSalesforceOrganization.json" } ] } diff --git a/src/test/resources/fixtures/controllers/userController/getCurrentUser.fixtures.json b/src/test/resources/fixtures/controllers/userController/getCurrentUser.fixtures.json index 60fa1ab8..ce145085 100644 --- a/src/test/resources/fixtures/controllers/userController/getCurrentUser.fixtures.json +++ b/src/test/resources/fixtures/controllers/userController/getCurrentUser.fixtures.json @@ -2,7 +2,7 @@ "getCurrentUser": { "salesforce_users": [ { - "filepath": "classpath:fixtures/repositories/salesforceUser/ActiveSalesforceUser.json" + "filepath": "classpath:fixtures/common/repositories/salesforceUser/ActiveSalesforceUser.json" } ] } diff --git a/src/test/resources/fixtures/unit/repositories/salesforceOauthTokenRepository.json b/src/test/resources/fixtures/unit/repositories/salesforceOauthTokenRepository.json index 719f6bdc..88ca7b51 100644 --- a/src/test/resources/fixtures/unit/repositories/salesforceOauthTokenRepository.json +++ b/src/test/resources/fixtures/unit/repositories/salesforceOauthTokenRepository.json @@ -2,7 +2,7 @@ "testGetSalesforceOauthTokenByExternalUserId": { "salesforce_oauth_tokens": [ { - "filepath": "classpath:fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" + "filepath": "classpath:fixtures/common/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" } ] } diff --git a/src/test/resources/fixtures/unit/repositories/salesforceOrganizationRepository.json b/src/test/resources/fixtures/unit/repositories/salesforceOrganizationRepository.json index afaf8013..22fe431b 100644 --- a/src/test/resources/fixtures/unit/repositories/salesforceOrganizationRepository.json +++ b/src/test/resources/fixtures/unit/repositories/salesforceOrganizationRepository.json @@ -2,7 +2,7 @@ "testGetSalesforceOrganizationByExternalOrganizationId": { "salesforce_organizations": [ { - "filepath": "classpath:fixtures/repositories/salesforceOrganization/ActiveSalesforceOrganization.json" + "filepath": "classpath:fixtures/common/repositories/salesforceOrganization/ActiveSalesforceOrganization.json" } ] } diff --git a/src/test/resources/fixtures/unit/repositories/salesforceUserRepository.json b/src/test/resources/fixtures/unit/repositories/salesforceUserRepository.json index 89b32d99..07fe3980 100644 --- a/src/test/resources/fixtures/unit/repositories/salesforceUserRepository.json +++ b/src/test/resources/fixtures/unit/repositories/salesforceUserRepository.json @@ -2,7 +2,7 @@ "testGetSalesforceUserByExternalUserId": { "salesforce_users": [ { - "filepath": "classpath:fixtures/repositories/salesforceUser/ActiveSalesforceUser.json" + "filepath": "classpath:fixtures/common/repositories/salesforceUser/ActiveSalesforceUser.json" } ] } From 5f3f98b48ba09f610b2c2249f1fa438ff4454238 Mon Sep 17 00:00:00 2001 From: amanbarbaria Date: Mon, 28 Aug 2023 18:54:37 +0530 Subject: [PATCH 133/195] Added SpringBootTest test annotation to unit test classes --- .../lib/salesforce/wrappers/SalesforceGetTokens.java | 12 ++++++------ .../globalConstants/SalesforceConstantsTest.java | 2 ++ .../api/unit/globalConstants/UserConstantsTest.java | 2 ++ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceGetTokens.java b/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceGetTokens.java index edcfd902..22e79738 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceGetTokens.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceGetTokens.java @@ -1,6 +1,6 @@ package com.salessparrow.api.lib.salesforce.wrappers; -import java.util.Arrays; +import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -53,13 +53,13 @@ public HttpResponse getTokens(String code, String redirectUri) { requestBody, 10000); } catch (Exception e) { - List paramErrorIdentifiers = Arrays.asList("invalid_code"); - ParamErrorObject paramErrorObject = new ParamErrorObject( + 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(paramErrorObject); + paramErrorIdentifiers)); } return response; } diff --git a/src/test/java/com/salessparrow/api/unit/globalConstants/SalesforceConstantsTest.java b/src/test/java/com/salessparrow/api/unit/globalConstants/SalesforceConstantsTest.java index 2dbd72a6..6a88b400 100644 --- a/src/test/java/com/salessparrow/api/unit/globalConstants/SalesforceConstantsTest.java +++ b/src/test/java/com/salessparrow/api/unit/globalConstants/SalesforceConstantsTest.java @@ -2,8 +2,10 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; import com.salessparrow.api.lib.globalConstants.SalesforceConstants; +@SpringBootTest public class SalesforceConstantsTest { @Test diff --git a/src/test/java/com/salessparrow/api/unit/globalConstants/UserConstantsTest.java b/src/test/java/com/salessparrow/api/unit/globalConstants/UserConstantsTest.java index 6b7f19a3..9e82eb4e 100644 --- a/src/test/java/com/salessparrow/api/unit/globalConstants/UserConstantsTest.java +++ b/src/test/java/com/salessparrow/api/unit/globalConstants/UserConstantsTest.java @@ -7,7 +7,9 @@ import com.salessparrow.api.lib.globalConstants.UserConstants; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import org.springframework.boot.test.context.SpringBootTest; +@SpringBootTest public class UserConstantsTest { @Test void testGetName() { From 0173a263a89ce4de7bf214a6ba3c29e0523e15b7 Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Mon, 28 Aug 2023 18:57:45 +0530 Subject: [PATCH 134/195] Url Encoded getAccountTasksQuery --- .../api/lib/salesforce/helper/SalesforceQueryBuilder.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java index 31204140..6de69b2b 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java @@ -40,8 +40,10 @@ public String getAccountsQuery(String searchTerm) { * @return String */ public String getAccountTasksQuery(String accountId) { - return "SELECT Id, Description, ActivityDate, CreatedBy.Name, Owner.Name, LastModifiedDate FROM Task WHERE WhatId='" - + accountId + "' ORDER BY LastModifiedDate DESC LIMIT 5"; + accountId = Util.escapeSpecialChars(accountId); + + return Util.urlEncoder("SELECT Id, Description, ActivityDate, CreatedBy.Name, Owner.Name, LastModifiedDate FROM Task WHERE WhatId='" + + accountId + "' ORDER BY LastModifiedDate DESC LIMIT 5"); } /** From b8a669309af0ceba9f550a1555a822a3f4bcef36 Mon Sep 17 00:00:00 2001 From: ajinkyac03 Date: Mon, 28 Aug 2023 19:18:50 +0530 Subject: [PATCH 135/195] 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 573697b07e66df74a3671cbe74b729aea3f2da44 Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Mon, 28 Aug 2023 19:20:09 +0530 Subject: [PATCH 136/195] Added code comments --- src/main/java/com/salessparrow/api/lib/Util.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/com/salessparrow/api/lib/Util.java b/src/main/java/com/salessparrow/api/lib/Util.java index da2f479c..b4e8be9b 100644 --- a/src/main/java/com/salessparrow/api/lib/Util.java +++ b/src/main/java/com/salessparrow/api/lib/Util.java @@ -69,6 +69,8 @@ public static String generateHeaderLogString(HttpServletRequest request) { /** * Escape special characters in a string for use in a regular expression. + * SOQL is important from security point of view. + * Refer https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql_select_quotedstringescapes.htm for more details. * * @param input * @@ -84,6 +86,13 @@ public static String escapeSpecialChars(String input) { return input; } + /** + * URL encode a string + * + * @param input + * + * @return String + */ public static String urlEncoder(String input){ if(input == null || input == "") return input; From d32ad85d841a407d0c61743955da2da752a82f5d Mon Sep 17 00:00:00 2001 From: amanbarbaria Date: Mon, 28 Aug 2023 19:29:30 +0530 Subject: [PATCH 137/195] moved folder fixtures/unit/repositories to fixtures/repositories --- .../unit/repositories/SalesforceOauthTokenRepositoryTest.java | 2 +- .../repositories/SalesforceOrganizationRepositoryTest.java | 2 +- .../api/unit/repositories/SalesforceUserRepositoryTest.java | 2 +- .../accountNoteController/deleteAccountNote.fixtures.json | 4 ++-- .../accountTaskController/deleteAccountTask.fixtures.json | 4 ++-- .../accountTaskController/getAccountTasksList.fixtures.json | 4 ++-- .../postCrmActionsSuggestions.fixtures.json | 2 +- .../repositories/salesforceOauthTokenRepository.json | 0 .../repositories/salesforceOrganizationRepository.json | 0 .../{unit => }/repositories/salesforceUserRepository.json | 0 10 files changed, 10 insertions(+), 10 deletions(-) rename src/test/resources/fixtures/{unit => }/repositories/salesforceOauthTokenRepository.json (100%) rename src/test/resources/fixtures/{unit => }/repositories/salesforceOrganizationRepository.json (100%) rename src/test/resources/fixtures/{unit => }/repositories/salesforceUserRepository.json (100%) diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java index e8b20e24..4d8a8d31 100644 --- a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java @@ -87,7 +87,7 @@ public void testSaveSalesforceOauthToken() { public void testGetSalesforceOauthTokenByExternalUserId() throws Exception{{ String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/unit/repositories/salesforceOauthTokenRepository.json", currentFunctionName); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/repositories/salesforceOauthTokenRepository.json", currentFunctionName); loadFixture.perform(fixtureData); //Valid Get Db Query diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java index 6497ac8d..37f090b8 100644 --- a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java @@ -86,7 +86,7 @@ public void testSaveSalesforceOrganization() { @Test public void testGetSalesforceOrganizationByExternalOrganizationId() throws Exception{{ String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/unit/repositories/salesforceOrganizationRepository.json", currentFunctionName); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/repositories/salesforceOrganizationRepository.json", currentFunctionName); loadFixture.perform(fixtureData); //Valid Get Db Query diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java index 2a05f181..a34c4edc 100644 --- a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java @@ -91,7 +91,7 @@ public void testSaveSalesforceUser() { public void testGetSalesforceUserByExternalUserId() throws Exception{{ String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/unit/repositories/salesforceUserRepository.json", currentFunctionName); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/repositories/salesforceUserRepository.json", currentFunctionName); loadFixture.perform(fixtureData); //Valid Get Db Query diff --git a/src/test/resources/fixtures/controllers/accountNoteController/deleteAccountNote.fixtures.json b/src/test/resources/fixtures/controllers/accountNoteController/deleteAccountNote.fixtures.json index bb801c75..10c6c018 100644 --- a/src/test/resources/fixtures/controllers/accountNoteController/deleteAccountNote.fixtures.json +++ b/src/test/resources/fixtures/controllers/accountNoteController/deleteAccountNote.fixtures.json @@ -2,12 +2,12 @@ "deleteAccountNote": { "salesforce_users": [ { - "filepath": "classpath:fixtures/repositories/salesforceUser/ActiveSalesforceUser.json" + "filepath": "classpath:fixtures/common/repositories/salesforceUser/ActiveSalesforceUser.json" } ], "salesforce_oauth_tokens": [ { - "filepath": "classpath:fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" + "filepath": "classpath:fixtures/common/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" } ] } diff --git a/src/test/resources/fixtures/controllers/accountTaskController/deleteAccountTask.fixtures.json b/src/test/resources/fixtures/controllers/accountTaskController/deleteAccountTask.fixtures.json index 9de4d059..f45e3a67 100644 --- a/src/test/resources/fixtures/controllers/accountTaskController/deleteAccountTask.fixtures.json +++ b/src/test/resources/fixtures/controllers/accountTaskController/deleteAccountTask.fixtures.json @@ -2,12 +2,12 @@ "deleteAccountTask": { "salesforce_users": [ { - "filepath": "classpath:fixtures/repositories/salesforceUser/ActiveSalesforceUser.json" + "filepath": "classpath:fixtures/common/repositories/salesforceUser/ActiveSalesforceUser.json" } ], "salesforce_oauth_tokens": [ { - "filepath": "classpath:fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" + "filepath": "classpath:fixtures/common/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" } ] } diff --git a/src/test/resources/fixtures/controllers/accountTaskController/getAccountTasksList.fixtures.json b/src/test/resources/fixtures/controllers/accountTaskController/getAccountTasksList.fixtures.json index 07052f62..7e9f2c8d 100644 --- a/src/test/resources/fixtures/controllers/accountTaskController/getAccountTasksList.fixtures.json +++ b/src/test/resources/fixtures/controllers/accountTaskController/getAccountTasksList.fixtures.json @@ -2,12 +2,12 @@ "getAccountTasksList": { "salesforce_users": [ { - "filepath": "classpath:fixtures/repositories/salesforceUser/ActiveSalesforceUser.json" + "filepath": "classpath:fixtures/common/repositories/salesforceUser/ActiveSalesforceUser.json" } ], "salesforce_oauth_tokens": [ { - "filepath": "classpath:fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" + "filepath": "classpath:fixtures/common/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" } ] } diff --git a/src/test/resources/fixtures/controllers/suggestionsController/postCrmActionsSuggestions.fixtures.json b/src/test/resources/fixtures/controllers/suggestionsController/postCrmActionsSuggestions.fixtures.json index 1aaed891..874c0367 100644 --- a/src/test/resources/fixtures/controllers/suggestionsController/postCrmActionsSuggestions.fixtures.json +++ b/src/test/resources/fixtures/controllers/suggestionsController/postCrmActionsSuggestions.fixtures.json @@ -2,7 +2,7 @@ "testPostCrmActionsSuggestions": { "salesforce_users": [ { - "filepath": "classpath:fixtures/repositories/salesforceUser/ActiveSalesforceUser.json" + "filepath": "classpath:fixtures/common/repositories/salesforceUser/ActiveSalesforceUser.json" } ] } diff --git a/src/test/resources/fixtures/unit/repositories/salesforceOauthTokenRepository.json b/src/test/resources/fixtures/repositories/salesforceOauthTokenRepository.json similarity index 100% rename from src/test/resources/fixtures/unit/repositories/salesforceOauthTokenRepository.json rename to src/test/resources/fixtures/repositories/salesforceOauthTokenRepository.json diff --git a/src/test/resources/fixtures/unit/repositories/salesforceOrganizationRepository.json b/src/test/resources/fixtures/repositories/salesforceOrganizationRepository.json similarity index 100% rename from src/test/resources/fixtures/unit/repositories/salesforceOrganizationRepository.json rename to src/test/resources/fixtures/repositories/salesforceOrganizationRepository.json diff --git a/src/test/resources/fixtures/unit/repositories/salesforceUserRepository.json b/src/test/resources/fixtures/repositories/salesforceUserRepository.json similarity index 100% rename from src/test/resources/fixtures/unit/repositories/salesforceUserRepository.json rename to src/test/resources/fixtures/repositories/salesforceUserRepository.json From e3d92ff2ccc041bcdba33d2238019b5bd074739f Mon Sep 17 00:00:00 2001 From: amanbarbaria Date: Mon, 28 Aug 2023 20:13:39 +0530 Subject: [PATCH 138/195] Merge branch fix --- .../getCrmOrganizationUserList.fixtures.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/resources/fixtures/controllers/crmOrganizationUserController/getCrmOrganizationUserList.fixtures.json b/src/test/resources/fixtures/controllers/crmOrganizationUserController/getCrmOrganizationUserList.fixtures.json index f994ae5b..c6b52ec9 100644 --- a/src/test/resources/fixtures/controllers/crmOrganizationUserController/getCrmOrganizationUserList.fixtures.json +++ b/src/test/resources/fixtures/controllers/crmOrganizationUserController/getCrmOrganizationUserList.fixtures.json @@ -2,12 +2,12 @@ "getCrmOrganizationUserList": { "salesforce_users": [ { - "filepath": "classpath:fixtures/repositories/salesforceUser/ActiveSalesforceUser.json" + "filepath": "classpath:fixtures/common/repositories/salesforceUser/ActiveSalesforceUser.json" } ], "salesforce_oauth_tokens": [ { - "filepath": "classpath:fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" + "filepath": "classpath:fixtures/common/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" } ] } From 92d444103f1bacb09e833eab9b899acddfb9de0d Mon Sep 17 00:00:00 2001 From: Yagnik Thummar Date: Mon, 28 Aug 2023 20:38:40 +0530 Subject: [PATCH 139/195] Handled empty string for escapeSpecialChar method. --- src/main/java/com/salessparrow/api/lib/Util.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/salessparrow/api/lib/Util.java b/src/main/java/com/salessparrow/api/lib/Util.java index b4e8be9b..2d29385d 100644 --- a/src/main/java/com/salessparrow/api/lib/Util.java +++ b/src/main/java/com/salessparrow/api/lib/Util.java @@ -77,6 +77,9 @@ public static String generateHeaderLogString(HttpServletRequest request) { * @return String */ public static String escapeSpecialChars(String input) { + if(input == null || input == "") + return input; + String[] specialChars = {"\\", "%", "'", "\"", "_"}; for (String specialChar : specialChars) { @@ -96,6 +99,7 @@ public static String escapeSpecialChars(String input) { public static String urlEncoder(String input){ if(input == null || input == "") return input; + try { return URLEncoder.encode(input, "UTF-8"); } catch (UnsupportedEncodingException e) { From 8ed31b95d69a0709b2ded370298f51f45fefc26b Mon Sep 17 00:00:00 2001 From: VRDighe Date: Mon, 28 Aug 2023 16:49:44 +0530 Subject: [PATCH 140/195] 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 7775e360b722e515c51b17bef39f63491da7d46a Mon Sep 17 00:00:00 2001 From: amanbarbaria Date: Tue, 29 Aug 2023 10:24:48 +0530 Subject: [PATCH 141/195] Changed folder structure to differentiate unit test cases & functional test cases. --- .../controllers/accountController/CreateNoteTest.java | 4 ++-- .../controllers/accountController/GetAccountListTest.java | 4 ++-- .../controllers/accountController/GetNoteDetailsTest.java | 4 ++-- .../controllers/accountController/GetNoteListTest.java | 4 ++-- .../accountNoteController/DeleteAccountNoteTest.java | 4 ++-- .../controllers/accountTaskController/CreateTaskTest.java | 4 ++-- .../accountTaskController/DeleteAccountTaskTest.java | 4 ++-- .../accountTaskController/GetAccountTasksListTest.java | 4 ++-- .../controllers/authController/GetRedirectUrlTest.java | 2 +- .../functional/controllers/authController/PostLogoutTest.java | 4 ++-- .../controllers/authController/PostSalesforceConnectTest.java | 4 ++-- .../GetCrmOrganizationUserListTest.java | 4 ++-- .../suggestionsController/PostCrmActionsSuggestionsTest.java | 4 ++-- .../controllers/userController/GetCurrentUserTest.java | 4 ++-- .../api/functional/exception/GlobalExceptionHandlerTest.java | 2 +- .../api/functional/interceptors/JsonOnlyInterceptorTest.java | 2 +- .../salessparrow/api/unit/lib/openAi/OpenAiRequestTest.java | 4 ++-- .../unit/repositories/SalesforceOauthTokenRepositoryTest.java | 2 +- .../repositories/SalesforceOrganizationRepositoryTest.java | 2 +- .../api/unit/repositories/SalesforceUserRepositoryTest.java | 2 +- .../controllers/accountController/createNote.scenarios.json | 0 .../accountController/getAccountList.scenarios.json | 0 .../accountController/getNoteDetails.scenarios.json | 0 .../controllers/accountController/getNotesList.scenarios.json | 0 .../accountNoteController/deleteAccountNote.scenarios.json | 0 .../accountTaskController/createTask.scenarios.json | 0 .../accountTaskController/deleteAccountTask.scenarios.json | 0 .../accountTaskController/getAccountTasksList.scenarios.json | 0 .../controllers/authController/Logout.scenarios.json | 0 .../authController/SalesforceConnect.scenarios.json | 0 .../controllers/authController/redirectUrl.scenarios.json | 0 .../getCrmOrganizationUserList.scenarios.json | 0 .../crmActionsSuggestions.scenarios.json | 0 .../controllers/userController/getCurrentUser.scenarios.json | 0 .../exceptions/globalExceptionHandler.scenarios.json | 0 .../interceptors/jsonOnlyInterceptor.scenarios.json | 0 .../data/{ => unit}/lib/openAi/openAiRequest.scenarios.json | 0 .../{ => unit}/lib/openAi/openAiRequestError.scenarios.json | 0 .../controllers/accountController/createNote.fixtures.json | 0 .../accountController/getAccountList.fixtures.json | 0 .../accountController/getNoteDetails.fixtures.json | 0 .../controllers/accountController/getNotesList.fixtures.json | 0 .../accountNoteController/deleteAccountNote.fixtures.json | 0 .../accountTaskController/createTask.fixtures.json | 0 .../accountTaskController/deleteAccountTask.fixtures.json | 0 .../accountTaskController/getAccountTasksList.fixtures.json | 0 .../controllers/authController/PostLogoutFixture.json | 0 .../authController/PostSalesforceConnectFixture.json | 0 .../getCrmOrganizationUserList.fixtures.json | 0 .../postCrmActionsSuggestions.fixtures.json | 0 .../controllers/userController/getCurrentUser.fixtures.json | 0 .../repositories/salesforceOauthTokenRepository.json | 0 .../repositories/salesforceOrganizationRepository.json | 0 .../{ => unit}/repositories/salesforceUserRepository.json | 0 54 files changed, 34 insertions(+), 34 deletions(-) rename src/test/resources/data/{ => functional}/controllers/accountController/createNote.scenarios.json (100%) rename src/test/resources/data/{ => functional}/controllers/accountController/getAccountList.scenarios.json (100%) rename src/test/resources/data/{ => functional}/controllers/accountController/getNoteDetails.scenarios.json (100%) rename src/test/resources/data/{ => functional}/controllers/accountController/getNotesList.scenarios.json (100%) rename src/test/resources/data/{ => functional}/controllers/accountNoteController/deleteAccountNote.scenarios.json (100%) rename src/test/resources/data/{ => functional}/controllers/accountTaskController/createTask.scenarios.json (100%) rename src/test/resources/data/{ => functional}/controllers/accountTaskController/deleteAccountTask.scenarios.json (100%) rename src/test/resources/data/{ => functional}/controllers/accountTaskController/getAccountTasksList.scenarios.json (100%) rename src/test/resources/data/{ => functional}/controllers/authController/Logout.scenarios.json (100%) rename src/test/resources/data/{ => functional}/controllers/authController/SalesforceConnect.scenarios.json (100%) rename src/test/resources/data/{ => functional}/controllers/authController/redirectUrl.scenarios.json (100%) rename src/test/resources/data/{ => functional}/controllers/crmOrganizationUserController/getCrmOrganizationUserList.scenarios.json (100%) rename src/test/resources/data/{ => functional}/controllers/suggestionsController/crmActionsSuggestions.scenarios.json (100%) rename src/test/resources/data/{ => functional}/controllers/userController/getCurrentUser.scenarios.json (100%) rename src/test/resources/data/{ => functional}/exceptions/globalExceptionHandler.scenarios.json (100%) rename src/test/resources/data/{ => functional}/interceptors/jsonOnlyInterceptor.scenarios.json (100%) rename src/test/resources/data/{ => unit}/lib/openAi/openAiRequest.scenarios.json (100%) rename src/test/resources/data/{ => unit}/lib/openAi/openAiRequestError.scenarios.json (100%) rename src/test/resources/fixtures/{ => functional}/controllers/accountController/createNote.fixtures.json (100%) rename src/test/resources/fixtures/{ => functional}/controllers/accountController/getAccountList.fixtures.json (100%) rename src/test/resources/fixtures/{ => functional}/controllers/accountController/getNoteDetails.fixtures.json (100%) rename src/test/resources/fixtures/{ => functional}/controllers/accountController/getNotesList.fixtures.json (100%) rename src/test/resources/fixtures/{ => functional}/controllers/accountNoteController/deleteAccountNote.fixtures.json (100%) rename src/test/resources/fixtures/{ => functional}/controllers/accountTaskController/createTask.fixtures.json (100%) rename src/test/resources/fixtures/{ => functional}/controllers/accountTaskController/deleteAccountTask.fixtures.json (100%) rename src/test/resources/fixtures/{ => functional}/controllers/accountTaskController/getAccountTasksList.fixtures.json (100%) rename src/test/resources/fixtures/{ => functional}/controllers/authController/PostLogoutFixture.json (100%) rename src/test/resources/fixtures/{ => functional}/controllers/authController/PostSalesforceConnectFixture.json (100%) rename src/test/resources/fixtures/{ => functional}/controllers/crmOrganizationUserController/getCrmOrganizationUserList.fixtures.json (100%) rename src/test/resources/fixtures/{ => functional}/controllers/suggestionsController/postCrmActionsSuggestions.fixtures.json (100%) rename src/test/resources/fixtures/{ => functional}/controllers/userController/getCurrentUser.fixtures.json (100%) rename src/test/resources/fixtures/{ => unit}/repositories/salesforceOauthTokenRepository.json (100%) rename src/test/resources/fixtures/{ => unit}/repositories/salesforceOrganizationRepository.json (100%) rename src/test/resources/fixtures/{ => unit}/repositories/salesforceUserRepository.json (100%) diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/CreateNoteTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/CreateNoteTest.java index cc11ccfc..50582928 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/CreateNoteTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/CreateNoteTest.java @@ -78,7 +78,7 @@ public void createNote(Scenario testScenario) throws Exception { // Load fixture data String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/controllers/accountController/createNote.fixtures.json", currentFunctionName); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/functional/controllers/accountController/createNote.fixtures.json", currentFunctionName); loadFixture.perform(fixtureData); // Read data from the scenario @@ -117,7 +117,7 @@ static Stream testScenariosProvider() throws IOException { } private static List loadScenarios() throws IOException { - String scenariosPath = "classpath:data/controllers/accountController/createNote.scenarios.json"; + String scenariosPath = "classpath:data/functional/controllers/accountController/createNote.scenarios.json"; Resource resource = new DefaultResourceLoader().getResource(scenariosPath); ObjectMapper objectMapper = new ObjectMapper(); diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java index ee9d86ac..5ba39578 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java @@ -77,7 +77,7 @@ public void tearDown() { public void getAccountList(Scenario testScenario) throws Exception { // Load fixture data String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/controllers/accountController/getAccountList.fixtures.json", currentFunctionName); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/functional/controllers/accountController/getAccountList.fixtures.json", currentFunctionName); loadFixture.perform(fixtureData); // Read data from the scenario @@ -115,7 +115,7 @@ static Stream testScenariosProvider() throws IOException { } private static List loadScenarios() throws IOException { - String scenariosPath = "classpath:data/controllers/accountController/getAccountList.scenarios.json"; + String scenariosPath = "classpath:data/functional/controllers/accountController/getAccountList.scenarios.json"; Resource resource = new DefaultResourceLoader().getResource(scenariosPath); ObjectMapper objectMapper = new ObjectMapper(); diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java index e11d4c8f..be28e02d 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java @@ -80,7 +80,7 @@ public void tearDown() { @MethodSource("testScenariosProvider") public void getNoteDetails(Scenario testScenario) throws Exception { String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/controllers/accountController/getNoteDetails.fixtures.json", currentFunctionName); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/functional/controllers/accountController/getNoteDetails.fixtures.json", currentFunctionName); loadFixture.perform(fixtureData); ObjectMapper objectMapper = new ObjectMapper(); @@ -123,7 +123,7 @@ static Stream testScenariosProvider() throws IOException { } private static List loadScenarios() throws IOException { - String scenariosPath = "classpath:data/controllers/accountController/getNoteDetails.scenarios.json"; + String scenariosPath = "classpath:data/functional/controllers/accountController/getNoteDetails.scenarios.json"; Resource resource = new DefaultResourceLoader().getResource(scenariosPath); ObjectMapper objectMapper = new ObjectMapper(); diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteListTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteListTest.java index f4d29f47..d87993c0 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteListTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteListTest.java @@ -91,7 +91,7 @@ public void tearDown() { public void getNoteList(Scenario testScenario) throws Exception{ String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); FixtureData fixtureData = common.loadFixture( - "classpath:fixtures/controllers/accountController/getNotesList.fixtures.json", + "classpath:fixtures/functional/controllers/accountController/getNotesList.fixtures.json", currentFunctionName ); loadFixture.perform(fixtureData); @@ -150,7 +150,7 @@ static Stream testScenariosProvider() throws IOException { } private static List loadScenarios() throws IOException { - String scenariosPath = "classpath:data/controllers/accountController/getNotesList.scenarios.json"; + String scenariosPath = "classpath:data/functional/controllers/accountController/getNotesList.scenarios.json"; Resource resource = new DefaultResourceLoader().getResource(scenariosPath); ObjectMapper objectMapper = new ObjectMapper(); diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountNoteController/DeleteAccountNoteTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountNoteController/DeleteAccountNoteTest.java index 51f0833e..c2c8e98f 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountNoteController/DeleteAccountNoteTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountNoteController/DeleteAccountNoteTest.java @@ -77,7 +77,7 @@ public void deleteAccountNote(Scenario testScenario) throws Exception { // Load fixture data String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/controllers/accountNoteController/deleteAccountNote.fixtures.json", currentFunctionName); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/functional/controllers/accountNoteController/deleteAccountNote.fixtures.json", currentFunctionName); loadFixture.perform(fixtureData); // Read data from the scenario @@ -110,7 +110,7 @@ static Stream testScenariosProvider() throws IOException { } private static List loadScenarios() throws IOException { - String scenariosPath = "classpath:data/controllers/accountNoteController/deleteAccountNote.scenarios.json"; + String scenariosPath = "classpath:data/functional/controllers/accountNoteController/deleteAccountNote.scenarios.json"; Resource resource = new DefaultResourceLoader().getResource(scenariosPath); ObjectMapper objectMapper = new ObjectMapper(); return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/CreateTaskTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/CreateTaskTest.java index a4b64459..68e7a8f6 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/CreateTaskTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/CreateTaskTest.java @@ -77,7 +77,7 @@ public void createTask(Scenario testScenario) throws Exception { // Load fixture data String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/controllers/accountTaskController/createTask.fixtures.json", currentFunctionName); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/functional/controllers/accountTaskController/createTask.fixtures.json", currentFunctionName); loadFixture.perform(fixtureData); // Read data from the scenario @@ -116,7 +116,7 @@ static Stream testScenariosProvider() throws IOException { } private static List loadScenarios() throws IOException { - String scenariosPath = "classpath:data/controllers/accountTaskController/createTask.scenarios.json"; + String scenariosPath = "classpath:data/functional/controllers/accountTaskController/createTask.scenarios.json"; Resource resource = new DefaultResourceLoader().getResource(scenariosPath); ObjectMapper objectMapper = new ObjectMapper(); return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/DeleteAccountTaskTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/DeleteAccountTaskTest.java index 5c0b6003..4cdd31f8 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/DeleteAccountTaskTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/DeleteAccountTaskTest.java @@ -77,7 +77,7 @@ public void deleteAccountTask(Scenario testScenario) throws Exception { // Load fixture data String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/controllers/accountTaskController/deleteAccountTask.fixtures.json", currentFunctionName); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/functional/controllers/accountTaskController/deleteAccountTask.fixtures.json", currentFunctionName); loadFixture.perform(fixtureData); // Read data from the scenario @@ -120,7 +120,7 @@ static Stream testScenariosProvider() throws IOException { } private static List loadScenarios() throws IOException { - String scenariosPath = "classpath:data/controllers/accountTaskController/deleteAccountTask.scenarios.json"; + String scenariosPath = "classpath:data/functional/controllers/accountTaskController/deleteAccountTask.scenarios.json"; Resource resource = new DefaultResourceLoader().getResource(scenariosPath); ObjectMapper objectMapper = new ObjectMapper(); return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/GetAccountTasksListTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/GetAccountTasksListTest.java index 0193f7e3..a9ee431b 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/GetAccountTasksListTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/GetAccountTasksListTest.java @@ -77,7 +77,7 @@ public void getAccountTasksList(Scenario testScenario) throws Exception { // Load fixture data String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/controllers/accountTaskController/getAccountTasksList.fixtures.json", currentFunctionName); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/functional/controllers/accountTaskController/getAccountTasksList.fixtures.json", currentFunctionName); loadFixture.perform(fixtureData); // Read data from the scenario @@ -109,7 +109,7 @@ static Stream testScenariosProvider() throws IOException { } private static List loadScenarios() throws IOException { - String scenariosPath = "classpath:data/controllers/accountTaskController/getAccountTasksList.scenarios.json"; + String scenariosPath = "classpath:data/functional/controllers/accountTaskController/getAccountTasksList.scenarios.json"; Resource resource = new DefaultResourceLoader().getResource(scenariosPath); ObjectMapper objectMapper = new ObjectMapper(); return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); diff --git a/src/test/java/com/salessparrow/api/functional/controllers/authController/GetRedirectUrlTest.java b/src/test/java/com/salessparrow/api/functional/controllers/authController/GetRedirectUrlTest.java index 4d8b7871..e6e33786 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/authController/GetRedirectUrlTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/authController/GetRedirectUrlTest.java @@ -32,7 +32,7 @@ public class GetRedirectUrlTest { @Test public void getRedirectUrl() throws Exception{ - List testDataItems = common.loadScenariosData("classpath:data/controllers/authController/redirectUrl.scenarios.json"); + List testDataItems = common.loadScenariosData("classpath:data/functional/controllers/authController/redirectUrl.scenarios.json"); for (Scenario testDataItem : testDataItems) { ObjectMapper objectMapper = new ObjectMapper(); 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 054f96cb..95cbac03 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 @@ -73,7 +73,7 @@ public void testPostLogout() throws Exception { }.getClass().getEnclosingMethod().getName(); FixtureData fixtureData = common.loadFixture( - "classpath:fixtures/controllers/authController/PostLogoutFixture.json", + "classpath:fixtures/functional/controllers/authController/PostLogoutFixture.json", currentFunctionName); loadFixture.perform(fixtureData); @@ -101,7 +101,7 @@ public void testPostLogout() throws Exception { } public List loadTestData(String key) throws IOException { - String scenariosPath = "classpath:data/controllers/authController/Logout.scenarios.json"; + String scenariosPath = "classpath:data/functional/controllers/authController/Logout.scenarios.json"; Resource resource = resourceLoader.getResource(scenariosPath); ObjectMapper objectMapper = new ObjectMapper(); 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 5d11b5e2..dafdf4c0 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 @@ -135,7 +135,7 @@ public void testPostSalesforceConnectLogin() throws Exception { }.getClass().getEnclosingMethod().getName(); FixtureData fixtureData = common.loadFixture( - "classpath:fixtures/controllers/authController/PostSalesforceConnectFixture.json", + "classpath:fixtures/functional/controllers/authController/PostSalesforceConnectFixture.json", currentFunctionName); loadFixture.perform(fixtureData); @@ -171,7 +171,7 @@ public void testPostSalesforceConnectLogin() throws Exception { } public List loadTestData(String key) throws IOException { - String scenariosPath = "classpath:data/controllers/authController/SalesforceConnect.scenarios.json"; + String scenariosPath = "classpath:data/functional/controllers/authController/SalesforceConnect.scenarios.json"; Resource resource = resourceLoader.getResource(scenariosPath); ObjectMapper objectMapper = new ObjectMapper(); diff --git a/src/test/java/com/salessparrow/api/functional/controllers/crmOrganizationUserController/GetCrmOrganizationUserListTest.java b/src/test/java/com/salessparrow/api/functional/controllers/crmOrganizationUserController/GetCrmOrganizationUserListTest.java index 1ef99b81..af3bbc42 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/crmOrganizationUserController/GetCrmOrganizationUserListTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/crmOrganizationUserController/GetCrmOrganizationUserListTest.java @@ -76,7 +76,7 @@ public void tearDown() { public void getCrmOrganizationUserList(Scenario testScenario) throws Exception { // Load fixture data String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/controllers/crmOrganizationUserController/getCrmOrganizationUserList.fixtures.json", currentFunctionName); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/functional/controllers/crmOrganizationUserController/getCrmOrganizationUserList.fixtures.json", currentFunctionName); loadFixture.perform(fixtureData); // Read data from the scenario @@ -119,7 +119,7 @@ static Stream testScenariosProvider() throws IOException { } private static List loadScenarios() throws IOException { - String scenariosPath = "classpath:data/controllers/crmOrganizationUserController/getCrmOrganizationUserList.scenarios.json"; + String scenariosPath = "classpath:data/functional/controllers/crmOrganizationUserController/getCrmOrganizationUserList.scenarios.json"; Resource resource = new DefaultResourceLoader().getResource(scenariosPath); ObjectMapper objectMapper = new ObjectMapper(); return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); diff --git a/src/test/java/com/salessparrow/api/functional/controllers/suggestionsController/PostCrmActionsSuggestionsTest.java b/src/test/java/com/salessparrow/api/functional/controllers/suggestionsController/PostCrmActionsSuggestionsTest.java index f808062b..4c31f70e 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/suggestionsController/PostCrmActionsSuggestionsTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/suggestionsController/PostCrmActionsSuggestionsTest.java @@ -72,11 +72,11 @@ public void tearDown() { @Test public void testPostCrmActionsSuggestions() throws Exception { String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/controllers/suggestionsController/postCrmActionsSuggestions.fixtures.json", + FixtureData fixtureData = common.loadFixture("classpath:fixtures/functional/controllers/suggestionsController/postCrmActionsSuggestions.fixtures.json", currentFunctionName); loadFixture.perform(fixtureData); - List testDataItems = common.loadScenariosData("classpath:data/controllers/suggestionsController/crmActionsSuggestions.scenarios.json"); + List testDataItems = common.loadScenariosData("classpath:data/functional/controllers/suggestionsController/crmActionsSuggestions.scenarios.json"); for (Scenario testDataItem : testDataItems) { ObjectMapper objectMapper = new ObjectMapper(); HttpResponse getAccountMockResponse = new HttpResponse(); diff --git a/src/test/java/com/salessparrow/api/functional/controllers/userController/GetCurrentUserTest.java b/src/test/java/com/salessparrow/api/functional/controllers/userController/GetCurrentUserTest.java index f14fdcba..0d11b37d 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/userController/GetCurrentUserTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/userController/GetCurrentUserTest.java @@ -61,11 +61,11 @@ public void tearDown() { @Test public void getCurrentUser() throws Exception{ String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/controllers/userController/getCurrentUser.fixtures.json", + FixtureData fixtureData = common.loadFixture("classpath:fixtures/functional/controllers/userController/getCurrentUser.fixtures.json", currentFunctionName); loadFixture.perform(fixtureData); - List testDataItems = common.loadScenariosData("classpath:data/controllers/userController/getCurrentUser.scenarios.json"); + List testDataItems = common.loadScenariosData("classpath:data/functional/controllers/userController/getCurrentUser.scenarios.json"); for (Scenario testDataItem : testDataItems) { ObjectMapper objectMapper = new ObjectMapper(); String expectedOutput = objectMapper.writeValueAsString(testDataItem.getOutput()); diff --git a/src/test/java/com/salessparrow/api/functional/exception/GlobalExceptionHandlerTest.java b/src/test/java/com/salessparrow/api/functional/exception/GlobalExceptionHandlerTest.java index 3bb72cd6..221d47e4 100644 --- a/src/test/java/com/salessparrow/api/functional/exception/GlobalExceptionHandlerTest.java +++ b/src/test/java/com/salessparrow/api/functional/exception/GlobalExceptionHandlerTest.java @@ -55,7 +55,7 @@ public void tearDown() { @Test public void handleNoHandlerFoundException() throws Exception{ - List testDataItems = common.loadScenariosData("classpath:data/exceptions/globalExceptionHandler.scenarios.json"); + List testDataItems = common.loadScenariosData("classpath:data/functional/exceptions/globalExceptionHandler.scenarios.json"); for (Scenario testDataItem : testDataItems) { ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/unknown-route") diff --git a/src/test/java/com/salessparrow/api/functional/interceptors/JsonOnlyInterceptorTest.java b/src/test/java/com/salessparrow/api/functional/interceptors/JsonOnlyInterceptorTest.java index 39dac315..c34fc2e9 100644 --- a/src/test/java/com/salessparrow/api/functional/interceptors/JsonOnlyInterceptorTest.java +++ b/src/test/java/com/salessparrow/api/functional/interceptors/JsonOnlyInterceptorTest.java @@ -55,7 +55,7 @@ public void tearDown() { @Test public void preHandle() throws Exception{ - List testDataItems = common.loadScenariosData("classpath:data/interceptors/jsonOnlyInterceptor.scenarios.json"); + List testDataItems = common.loadScenariosData("classpath:data/functional/interceptors/jsonOnlyInterceptor.scenarios.json"); for (Scenario testDataItem : testDataItems) { ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/auth/salesforce/redirect-url") .contentType(MediaType.ALL_VALUE)); diff --git a/src/test/java/com/salessparrow/api/unit/lib/openAi/OpenAiRequestTest.java b/src/test/java/com/salessparrow/api/unit/lib/openAi/OpenAiRequestTest.java index 0b7a1b23..a598d998 100644 --- a/src/test/java/com/salessparrow/api/unit/lib/openAi/OpenAiRequestTest.java +++ b/src/test/java/com/salessparrow/api/unit/lib/openAi/OpenAiRequestTest.java @@ -39,7 +39,7 @@ public class OpenAiRequestTest { @Test void testOpenAiRequest() throws IOException { - List testDataItems = common.loadScenariosData("classpath:data/lib/openAi/openAiRequest.scenarios.json"); + List testDataItems = common.loadScenariosData("classpath:data/unit/lib/openAi/openAiRequest.scenarios.json"); MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); for (Scenario testDataItem : testDataItems) { @@ -60,7 +60,7 @@ void testOpenAiRequest() throws IOException { @Test void testOpenAiRequestError() throws IOException { - List testDataItems = common.loadScenariosData("classpath:data/lib/openAi/openAiRequestError.scenarios.json"); + List testDataItems = common.loadScenariosData("classpath:data/unit/lib/openAi/openAiRequestError.scenarios.json"); MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); for (Scenario testDataItem : testDataItems) { diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java index 4d8a8d31..e8b20e24 100644 --- a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java @@ -87,7 +87,7 @@ public void testSaveSalesforceOauthToken() { public void testGetSalesforceOauthTokenByExternalUserId() throws Exception{{ String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/repositories/salesforceOauthTokenRepository.json", currentFunctionName); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/unit/repositories/salesforceOauthTokenRepository.json", currentFunctionName); loadFixture.perform(fixtureData); //Valid Get Db Query diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java index 37f090b8..6497ac8d 100644 --- a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java @@ -86,7 +86,7 @@ public void testSaveSalesforceOrganization() { @Test public void testGetSalesforceOrganizationByExternalOrganizationId() throws Exception{{ String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/repositories/salesforceOrganizationRepository.json", currentFunctionName); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/unit/repositories/salesforceOrganizationRepository.json", currentFunctionName); loadFixture.perform(fixtureData); //Valid Get Db Query diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java index a34c4edc..2a05f181 100644 --- a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java @@ -91,7 +91,7 @@ public void testSaveSalesforceUser() { public void testGetSalesforceUserByExternalUserId() throws Exception{{ String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/repositories/salesforceUserRepository.json", currentFunctionName); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/unit/repositories/salesforceUserRepository.json", currentFunctionName); loadFixture.perform(fixtureData); //Valid Get Db Query diff --git a/src/test/resources/data/controllers/accountController/createNote.scenarios.json b/src/test/resources/data/functional/controllers/accountController/createNote.scenarios.json similarity index 100% rename from src/test/resources/data/controllers/accountController/createNote.scenarios.json rename to src/test/resources/data/functional/controllers/accountController/createNote.scenarios.json diff --git a/src/test/resources/data/controllers/accountController/getAccountList.scenarios.json b/src/test/resources/data/functional/controllers/accountController/getAccountList.scenarios.json similarity index 100% rename from src/test/resources/data/controllers/accountController/getAccountList.scenarios.json rename to src/test/resources/data/functional/controllers/accountController/getAccountList.scenarios.json diff --git a/src/test/resources/data/controllers/accountController/getNoteDetails.scenarios.json b/src/test/resources/data/functional/controllers/accountController/getNoteDetails.scenarios.json similarity index 100% rename from src/test/resources/data/controllers/accountController/getNoteDetails.scenarios.json rename to src/test/resources/data/functional/controllers/accountController/getNoteDetails.scenarios.json diff --git a/src/test/resources/data/controllers/accountController/getNotesList.scenarios.json b/src/test/resources/data/functional/controllers/accountController/getNotesList.scenarios.json similarity index 100% rename from src/test/resources/data/controllers/accountController/getNotesList.scenarios.json rename to src/test/resources/data/functional/controllers/accountController/getNotesList.scenarios.json diff --git a/src/test/resources/data/controllers/accountNoteController/deleteAccountNote.scenarios.json b/src/test/resources/data/functional/controllers/accountNoteController/deleteAccountNote.scenarios.json similarity index 100% rename from src/test/resources/data/controllers/accountNoteController/deleteAccountNote.scenarios.json rename to src/test/resources/data/functional/controllers/accountNoteController/deleteAccountNote.scenarios.json diff --git a/src/test/resources/data/controllers/accountTaskController/createTask.scenarios.json b/src/test/resources/data/functional/controllers/accountTaskController/createTask.scenarios.json similarity index 100% rename from src/test/resources/data/controllers/accountTaskController/createTask.scenarios.json rename to src/test/resources/data/functional/controllers/accountTaskController/createTask.scenarios.json diff --git a/src/test/resources/data/controllers/accountTaskController/deleteAccountTask.scenarios.json b/src/test/resources/data/functional/controllers/accountTaskController/deleteAccountTask.scenarios.json similarity index 100% rename from src/test/resources/data/controllers/accountTaskController/deleteAccountTask.scenarios.json rename to src/test/resources/data/functional/controllers/accountTaskController/deleteAccountTask.scenarios.json diff --git a/src/test/resources/data/controllers/accountTaskController/getAccountTasksList.scenarios.json b/src/test/resources/data/functional/controllers/accountTaskController/getAccountTasksList.scenarios.json similarity index 100% rename from src/test/resources/data/controllers/accountTaskController/getAccountTasksList.scenarios.json rename to src/test/resources/data/functional/controllers/accountTaskController/getAccountTasksList.scenarios.json diff --git a/src/test/resources/data/controllers/authController/Logout.scenarios.json b/src/test/resources/data/functional/controllers/authController/Logout.scenarios.json similarity index 100% rename from src/test/resources/data/controllers/authController/Logout.scenarios.json rename to src/test/resources/data/functional/controllers/authController/Logout.scenarios.json diff --git a/src/test/resources/data/controllers/authController/SalesforceConnect.scenarios.json b/src/test/resources/data/functional/controllers/authController/SalesforceConnect.scenarios.json similarity index 100% rename from src/test/resources/data/controllers/authController/SalesforceConnect.scenarios.json rename to src/test/resources/data/functional/controllers/authController/SalesforceConnect.scenarios.json diff --git a/src/test/resources/data/controllers/authController/redirectUrl.scenarios.json b/src/test/resources/data/functional/controllers/authController/redirectUrl.scenarios.json similarity index 100% rename from src/test/resources/data/controllers/authController/redirectUrl.scenarios.json rename to src/test/resources/data/functional/controllers/authController/redirectUrl.scenarios.json diff --git a/src/test/resources/data/controllers/crmOrganizationUserController/getCrmOrganizationUserList.scenarios.json b/src/test/resources/data/functional/controllers/crmOrganizationUserController/getCrmOrganizationUserList.scenarios.json similarity index 100% rename from src/test/resources/data/controllers/crmOrganizationUserController/getCrmOrganizationUserList.scenarios.json rename to src/test/resources/data/functional/controllers/crmOrganizationUserController/getCrmOrganizationUserList.scenarios.json diff --git a/src/test/resources/data/controllers/suggestionsController/crmActionsSuggestions.scenarios.json b/src/test/resources/data/functional/controllers/suggestionsController/crmActionsSuggestions.scenarios.json similarity index 100% rename from src/test/resources/data/controllers/suggestionsController/crmActionsSuggestions.scenarios.json rename to src/test/resources/data/functional/controllers/suggestionsController/crmActionsSuggestions.scenarios.json diff --git a/src/test/resources/data/controllers/userController/getCurrentUser.scenarios.json b/src/test/resources/data/functional/controllers/userController/getCurrentUser.scenarios.json similarity index 100% rename from src/test/resources/data/controllers/userController/getCurrentUser.scenarios.json rename to src/test/resources/data/functional/controllers/userController/getCurrentUser.scenarios.json diff --git a/src/test/resources/data/exceptions/globalExceptionHandler.scenarios.json b/src/test/resources/data/functional/exceptions/globalExceptionHandler.scenarios.json similarity index 100% rename from src/test/resources/data/exceptions/globalExceptionHandler.scenarios.json rename to src/test/resources/data/functional/exceptions/globalExceptionHandler.scenarios.json diff --git a/src/test/resources/data/interceptors/jsonOnlyInterceptor.scenarios.json b/src/test/resources/data/functional/interceptors/jsonOnlyInterceptor.scenarios.json similarity index 100% rename from src/test/resources/data/interceptors/jsonOnlyInterceptor.scenarios.json rename to src/test/resources/data/functional/interceptors/jsonOnlyInterceptor.scenarios.json diff --git a/src/test/resources/data/lib/openAi/openAiRequest.scenarios.json b/src/test/resources/data/unit/lib/openAi/openAiRequest.scenarios.json similarity index 100% rename from src/test/resources/data/lib/openAi/openAiRequest.scenarios.json rename to src/test/resources/data/unit/lib/openAi/openAiRequest.scenarios.json diff --git a/src/test/resources/data/lib/openAi/openAiRequestError.scenarios.json b/src/test/resources/data/unit/lib/openAi/openAiRequestError.scenarios.json similarity index 100% rename from src/test/resources/data/lib/openAi/openAiRequestError.scenarios.json rename to src/test/resources/data/unit/lib/openAi/openAiRequestError.scenarios.json diff --git a/src/test/resources/fixtures/controllers/accountController/createNote.fixtures.json b/src/test/resources/fixtures/functional/controllers/accountController/createNote.fixtures.json similarity index 100% rename from src/test/resources/fixtures/controllers/accountController/createNote.fixtures.json rename to src/test/resources/fixtures/functional/controllers/accountController/createNote.fixtures.json diff --git a/src/test/resources/fixtures/controllers/accountController/getAccountList.fixtures.json b/src/test/resources/fixtures/functional/controllers/accountController/getAccountList.fixtures.json similarity index 100% rename from src/test/resources/fixtures/controllers/accountController/getAccountList.fixtures.json rename to src/test/resources/fixtures/functional/controllers/accountController/getAccountList.fixtures.json diff --git a/src/test/resources/fixtures/controllers/accountController/getNoteDetails.fixtures.json b/src/test/resources/fixtures/functional/controllers/accountController/getNoteDetails.fixtures.json similarity index 100% rename from src/test/resources/fixtures/controllers/accountController/getNoteDetails.fixtures.json rename to src/test/resources/fixtures/functional/controllers/accountController/getNoteDetails.fixtures.json diff --git a/src/test/resources/fixtures/controllers/accountController/getNotesList.fixtures.json b/src/test/resources/fixtures/functional/controllers/accountController/getNotesList.fixtures.json similarity index 100% rename from src/test/resources/fixtures/controllers/accountController/getNotesList.fixtures.json rename to src/test/resources/fixtures/functional/controllers/accountController/getNotesList.fixtures.json diff --git a/src/test/resources/fixtures/controllers/accountNoteController/deleteAccountNote.fixtures.json b/src/test/resources/fixtures/functional/controllers/accountNoteController/deleteAccountNote.fixtures.json similarity index 100% rename from src/test/resources/fixtures/controllers/accountNoteController/deleteAccountNote.fixtures.json rename to src/test/resources/fixtures/functional/controllers/accountNoteController/deleteAccountNote.fixtures.json diff --git a/src/test/resources/fixtures/controllers/accountTaskController/createTask.fixtures.json b/src/test/resources/fixtures/functional/controllers/accountTaskController/createTask.fixtures.json similarity index 100% rename from src/test/resources/fixtures/controllers/accountTaskController/createTask.fixtures.json rename to src/test/resources/fixtures/functional/controllers/accountTaskController/createTask.fixtures.json diff --git a/src/test/resources/fixtures/controllers/accountTaskController/deleteAccountTask.fixtures.json b/src/test/resources/fixtures/functional/controllers/accountTaskController/deleteAccountTask.fixtures.json similarity index 100% rename from src/test/resources/fixtures/controllers/accountTaskController/deleteAccountTask.fixtures.json rename to src/test/resources/fixtures/functional/controllers/accountTaskController/deleteAccountTask.fixtures.json diff --git a/src/test/resources/fixtures/controllers/accountTaskController/getAccountTasksList.fixtures.json b/src/test/resources/fixtures/functional/controllers/accountTaskController/getAccountTasksList.fixtures.json similarity index 100% rename from src/test/resources/fixtures/controllers/accountTaskController/getAccountTasksList.fixtures.json rename to src/test/resources/fixtures/functional/controllers/accountTaskController/getAccountTasksList.fixtures.json diff --git a/src/test/resources/fixtures/controllers/authController/PostLogoutFixture.json b/src/test/resources/fixtures/functional/controllers/authController/PostLogoutFixture.json similarity index 100% rename from src/test/resources/fixtures/controllers/authController/PostLogoutFixture.json rename to src/test/resources/fixtures/functional/controllers/authController/PostLogoutFixture.json diff --git a/src/test/resources/fixtures/controllers/authController/PostSalesforceConnectFixture.json b/src/test/resources/fixtures/functional/controllers/authController/PostSalesforceConnectFixture.json similarity index 100% rename from src/test/resources/fixtures/controllers/authController/PostSalesforceConnectFixture.json rename to src/test/resources/fixtures/functional/controllers/authController/PostSalesforceConnectFixture.json diff --git a/src/test/resources/fixtures/controllers/crmOrganizationUserController/getCrmOrganizationUserList.fixtures.json b/src/test/resources/fixtures/functional/controllers/crmOrganizationUserController/getCrmOrganizationUserList.fixtures.json similarity index 100% rename from src/test/resources/fixtures/controllers/crmOrganizationUserController/getCrmOrganizationUserList.fixtures.json rename to src/test/resources/fixtures/functional/controllers/crmOrganizationUserController/getCrmOrganizationUserList.fixtures.json diff --git a/src/test/resources/fixtures/controllers/suggestionsController/postCrmActionsSuggestions.fixtures.json b/src/test/resources/fixtures/functional/controllers/suggestionsController/postCrmActionsSuggestions.fixtures.json similarity index 100% rename from src/test/resources/fixtures/controllers/suggestionsController/postCrmActionsSuggestions.fixtures.json rename to src/test/resources/fixtures/functional/controllers/suggestionsController/postCrmActionsSuggestions.fixtures.json diff --git a/src/test/resources/fixtures/controllers/userController/getCurrentUser.fixtures.json b/src/test/resources/fixtures/functional/controllers/userController/getCurrentUser.fixtures.json similarity index 100% rename from src/test/resources/fixtures/controllers/userController/getCurrentUser.fixtures.json rename to src/test/resources/fixtures/functional/controllers/userController/getCurrentUser.fixtures.json diff --git a/src/test/resources/fixtures/repositories/salesforceOauthTokenRepository.json b/src/test/resources/fixtures/unit/repositories/salesforceOauthTokenRepository.json similarity index 100% rename from src/test/resources/fixtures/repositories/salesforceOauthTokenRepository.json rename to src/test/resources/fixtures/unit/repositories/salesforceOauthTokenRepository.json diff --git a/src/test/resources/fixtures/repositories/salesforceOrganizationRepository.json b/src/test/resources/fixtures/unit/repositories/salesforceOrganizationRepository.json similarity index 100% rename from src/test/resources/fixtures/repositories/salesforceOrganizationRepository.json rename to src/test/resources/fixtures/unit/repositories/salesforceOrganizationRepository.json diff --git a/src/test/resources/fixtures/repositories/salesforceUserRepository.json b/src/test/resources/fixtures/unit/repositories/salesforceUserRepository.json similarity index 100% rename from src/test/resources/fixtures/repositories/salesforceUserRepository.json rename to src/test/resources/fixtures/unit/repositories/salesforceUserRepository.json From afab7364ed166e81a6ce98004377b3e833a5296f Mon Sep 17 00:00:00 2001 From: amanbarbaria Date: Tue, 29 Aug 2023 12:37:42 +0530 Subject: [PATCH 142/195] Remove autowire from repository constructor --- .../api/lib/UserLoginCookieAuth.java | 4 +++- .../helper/SalesforceOAuthToken.java | 6 ++++-- .../salesforce/helper/SalesforceRequest.java | 6 ++++-- .../SalesforceOauthTokenRepository.java | 2 -- .../SalesforceOrganizationRepository.java | 2 -- .../repositories/SalesforceUserRepository.java | 2 -- .../api/services/salesforce/AuthService.java | 18 ++++++++---------- .../salessparrow/api/helper/LoadFixture.java | 12 +++++------- .../SalesforceOauthTokenRepositoryTest.java | 14 ++++++++------ .../SalesforceOrganizationRepositoryTest.java | 14 ++++++++------ .../SalesforceUserRepositoryTest.java | 14 ++++++++------ 11 files changed, 48 insertions(+), 46 deletions(-) diff --git a/src/main/java/com/salessparrow/api/lib/UserLoginCookieAuth.java b/src/main/java/com/salessparrow/api/lib/UserLoginCookieAuth.java index 4a537faa..5accfe32 100644 --- a/src/main/java/com/salessparrow/api/lib/UserLoginCookieAuth.java +++ b/src/main/java/com/salessparrow/api/lib/UserLoginCookieAuth.java @@ -10,6 +10,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; import com.salessparrow.api.config.CoreConstants; import com.salessparrow.api.domain.User; import com.salessparrow.api.exception.CustomException; @@ -41,7 +42,7 @@ public class UserLoginCookieAuth { private CookieHelper cookieHelper; @Autowired - private SalesforceUserRepository salesforceUserRepository; + private DynamoDBMapper dynamoDBMapper; /** * Validate and set cookie @@ -170,6 +171,7 @@ private void fetchAndValidateUser() { } private void fetchAndValidateSalesforceUser() { + SalesforceUserRepository salesforceUserRepository = new SalesforceUserRepository(dynamoDBMapper); User userObj = salesforceUserRepository.getSalesforceUserByExternalUserId(userId); if (userObj == null) { diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceOAuthToken.java b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceOAuthToken.java index 85dc84b0..34a0aaf4 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceOAuthToken.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceOAuthToken.java @@ -3,6 +3,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; import com.fasterxml.jackson.databind.JsonNode; import com.salessparrow.api.domain.SalesforceOauthToken; import com.salessparrow.api.lib.AwsKms; @@ -21,7 +22,7 @@ public class SalesforceOAuthToken { private AwsKms awsKms; @Autowired - private SalesforceOauthTokenRepository sfOauthTokenRepository; + private DynamoDBMapper dynamoDBMapper; @Autowired private SalesforceGetRefreshedAccessToken salesforceGetRefreshedAccessToken; @@ -66,7 +67,8 @@ private String updateAccessTokenInDatabase(String responseBody, SalesforceOauthT String encryptedAccessToken = awsKms.encryptToken(decryptedAccessToken); sfOAuthToken.setAccessToken(encryptedAccessToken); - sfOauthTokenRepository.saveSalesforceOauthToken(sfOAuthToken); + SalesforceOauthTokenRepository salesforceOauthTokenRepository = new SalesforceOauthTokenRepository(dynamoDBMapper); + salesforceOauthTokenRepository.saveSalesforceOauthToken(sfOAuthToken); return decryptedAccessToken; } diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceRequest.java b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceRequest.java index e863cf38..c6bb9dc5 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceRequest.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceRequest.java @@ -4,6 +4,7 @@ import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.client.WebClientResponseException; +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; import com.salessparrow.api.domain.SalesforceOauthToken; import com.salessparrow.api.exception.CustomException; import com.salessparrow.api.lib.errorLib.ErrorObject; @@ -19,7 +20,7 @@ public class SalesforceRequest { private SalesforceOAuthToken getAccessTokenService; @Autowired - private SalesforceOauthTokenRepository sfOauthTokenRepository; + private DynamoDBMapper dynamoDBMapper; /** * Make a request to the Salesforce API. @@ -30,7 +31,8 @@ public class SalesforceRequest { * @return T */ public T makeRequest(String salesforceUserId, SalesforceRequestInterface request) { - SalesforceOauthToken sfOAuthToken = sfOauthTokenRepository + SalesforceOauthTokenRepository salesforceOauthTokenRepository = new SalesforceOauthTokenRepository(dynamoDBMapper); + SalesforceOauthToken sfOAuthToken = salesforceOauthTokenRepository .getSalesforceOauthTokenByExternalUserId(salesforceUserId); String decryptedAccessToken = getAccessTokenService.fetchAccessToken(sfOAuthToken); diff --git a/src/main/java/com/salessparrow/api/repositories/SalesforceOauthTokenRepository.java b/src/main/java/com/salessparrow/api/repositories/SalesforceOauthTokenRepository.java index 431ba697..a04a1001 100644 --- a/src/main/java/com/salessparrow/api/repositories/SalesforceOauthTokenRepository.java +++ b/src/main/java/com/salessparrow/api/repositories/SalesforceOauthTokenRepository.java @@ -1,6 +1,5 @@ package com.salessparrow.api.repositories; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Repository; @@ -19,7 +18,6 @@ public class SalesforceOauthTokenRepository { private final DynamoDBMapper dynamoDBMapper; - @Autowired public SalesforceOauthTokenRepository(DynamoDBMapper dynamoDBMapper) { this.dynamoDBMapper = dynamoDBMapper; } diff --git a/src/main/java/com/salessparrow/api/repositories/SalesforceOrganizationRepository.java b/src/main/java/com/salessparrow/api/repositories/SalesforceOrganizationRepository.java index a6f6fd98..24bb0561 100644 --- a/src/main/java/com/salessparrow/api/repositories/SalesforceOrganizationRepository.java +++ b/src/main/java/com/salessparrow/api/repositories/SalesforceOrganizationRepository.java @@ -5,7 +5,6 @@ import com.salessparrow.api.exception.CustomException; import com.salessparrow.api.lib.errorLib.ErrorObject; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; /** @@ -16,7 +15,6 @@ public class SalesforceOrganizationRepository { private final DynamoDBMapper dynamoDBMapper; - @Autowired public SalesforceOrganizationRepository(DynamoDBMapper dynamoDBMapper) { this.dynamoDBMapper = dynamoDBMapper; } diff --git a/src/main/java/com/salessparrow/api/repositories/SalesforceUserRepository.java b/src/main/java/com/salessparrow/api/repositories/SalesforceUserRepository.java index bf22ad44..f7e1d878 100644 --- a/src/main/java/com/salessparrow/api/repositories/SalesforceUserRepository.java +++ b/src/main/java/com/salessparrow/api/repositories/SalesforceUserRepository.java @@ -1,6 +1,5 @@ package com.salessparrow.api.repositories; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Repository; @@ -19,7 +18,6 @@ public class SalesforceUserRepository { private final DynamoDBMapper dynamoDBMapper; - @Autowired public SalesforceUserRepository(DynamoDBMapper dynamoDBMapper) { this.dynamoDBMapper = dynamoDBMapper; } 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 1622b0f1..6a7e5103 100644 --- a/src/main/java/com/salessparrow/api/services/salesforce/AuthService.java +++ b/src/main/java/com/salessparrow/api/services/salesforce/AuthService.java @@ -5,6 +5,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -55,13 +56,7 @@ public class AuthService { private Util util; @Autowired - private SalesforceOauthTokenRepository salesforceOauthTokenRepository; - - @Autowired - private SalesforceUserRepository salesforceUserRepository; - - @Autowired - private SalesforceOrganizationRepository salesforceOrganizationRepository; + private DynamoDBMapper dynamoDBMapper; @Autowired private LocalCipher localCipher; @@ -138,6 +133,7 @@ private void validateAndUpsertSalesforceOrganization() { String salesforceOrganizationId = this.tokensData.getSalesforceOrganizationId(); + SalesforceOrganizationRepository salesforceOrganizationRepository = new SalesforceOrganizationRepository(dynamoDBMapper); SalesforceOrganization existingOrganizationData = salesforceOrganizationRepository .getSalesforceOrganizationByExternalOrganizationId(salesforceOrganizationId); @@ -159,8 +155,7 @@ private void validateAndUpsertSalesforceOrganization() { salesforceOrganization.setExternalOrganizationId(salesforceOrganizationId); salesforceOrganization.setStatus(SalesforceOrganization.Status.ACTIVE); - salesforceOrganizationRepository - .saveSalesforceOrganization(salesforceOrganization); + salesforceOrganizationRepository.saveSalesforceOrganization(salesforceOrganization); } /** @@ -192,6 +187,7 @@ private void upsertSalesforceOAuthTokens() { salesforceOauthToken.setStatus(SalesforceOauthToken.Status.ACTIVE); salesforceOauthToken.setIssuedAt(Long.parseLong(this.tokensData.getIssuedAt())); + SalesforceOauthTokenRepository salesforceOauthTokenRepository = new SalesforceOauthTokenRepository(dynamoDBMapper); this.salesforceOauthToken = salesforceOauthTokenRepository .saveSalesforceOauthToken(salesforceOauthToken); } @@ -203,6 +199,7 @@ private void upsertSalesforceOAuthTokens() { */ private void verifyExistingSalesforceUser() { String salesforceUserId = this.tokensData.getSalesforceUserId(); + SalesforceUserRepository salesforceUserRepository = new SalesforceUserRepository(dynamoDBMapper); SalesforceUser salesforceUser = salesforceUserRepository.getSalesforceUserByExternalUserId(salesforceUserId); if (salesforceUser != null) { @@ -257,7 +254,8 @@ private void createSalesforceUser() { salesforceUser.setCookieToken(encryptedCookieToken); salesforceUser.setEncryptionSalt(encryptedSalt); salesforceUser.setStatus(SalesforceUser.Status.ACTIVE); - + + SalesforceUserRepository salesforceUserRepository = new SalesforceUserRepository(dynamoDBMapper); this.salesforceUser = salesforceUserRepository.saveSalesforceUser(salesforceUser); this.decryptedSalt = decryptedSalt; } diff --git a/src/test/java/com/salessparrow/api/helper/LoadFixture.java b/src/test/java/com/salessparrow/api/helper/LoadFixture.java index be5c24df..06d0ef56 100644 --- a/src/test/java/com/salessparrow/api/helper/LoadFixture.java +++ b/src/test/java/com/salessparrow/api/helper/LoadFixture.java @@ -7,6 +7,7 @@ import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.salessparrow.api.domain.SalesforceOauthToken; @@ -24,13 +25,7 @@ public class LoadFixture { private ResourceLoader resourceLoader; @Autowired - private SalesforceUserRepository salesforceUserRepository; - - @Autowired - private SalesforceOauthTokenRepository salesforceOauthTokenRepository; - - @Autowired - private SalesforceOrganizationRepository salesforceOrganizationRepository; + private DynamoDBMapper dynamoDBMapper; /** * Load the fixture data. @@ -44,6 +39,7 @@ public void perform(FixtureData fixtureData) throws IOException { if (fixtureData.getSalesforce_users() != null) { for (FilePathData filePathData : fixtureData.getSalesforce_users()) { SalesforceUser salesforceUser = loadSalesForceUserFixture(filePathData.getFilepath()); + SalesforceUserRepository salesforceUserRepository = new SalesforceUserRepository(dynamoDBMapper); salesforceUserRepository.saveSalesforceUser(salesforceUser); } } @@ -51,6 +47,7 @@ public void perform(FixtureData fixtureData) throws IOException { if (fixtureData.getSalesforce_oauth_tokens() != null) { for (FilePathData filePathData : fixtureData.getSalesforce_oauth_tokens()) { SalesforceOauthToken salesforceOauth = loadSalesForceOAuthTokenFixture(filePathData.getFilepath()); + SalesforceOauthTokenRepository salesforceOauthTokenRepository = new SalesforceOauthTokenRepository(dynamoDBMapper); salesforceOauthTokenRepository.saveSalesforceOauthToken(salesforceOauth); } } @@ -58,6 +55,7 @@ public void perform(FixtureData fixtureData) throws IOException { if (fixtureData.getSalesforce_organizations() != null) { for (FilePathData filePathData : fixtureData.getSalesforce_organizations()) { SalesforceOrganization salesforceOrganization = loadSalesForceOrganizationFixture(filePathData.getFilepath()); + SalesforceOrganizationRepository salesforceOrganizationRepository = new SalesforceOrganizationRepository(dynamoDBMapper); salesforceOrganizationRepository.saveSalesforceOrganization(salesforceOrganization); } } diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java index e8b20e24..db4f2d01 100644 --- a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java @@ -50,14 +50,15 @@ public void tearDown() { cleanup.perform(); } - @Autowired - private SalesforceOauthTokenRepository salesforceOauthTokenRepository; + @Autowired + private DynamoDBMapper dynamoDBMapper; @Test public void testSaveSalesforceOauthToken() { //Valid Save Db Query SalesforceOauthToken salesforceOauthTokenValid = new SalesforceOauthToken(); salesforceOauthTokenValid.setExternalUserId("externalUserId-1"); + SalesforceOauthTokenRepository salesforceOauthTokenRepository = new SalesforceOauthTokenRepository(dynamoDBMapper); SalesforceOauthToken salesforceOauthTokenResp = salesforceOauthTokenRepository.saveSalesforceOauthToken(salesforceOauthTokenValid); assertEquals(salesforceOauthTokenValid.getExternalUserId(), salesforceOauthTokenResp.getExternalUserId()); @@ -67,7 +68,7 @@ public void testSaveSalesforceOauthToken() { // mock the DynamoDBMapper DynamoDBMapper dynamoDBMapper = mock(DynamoDBMapper.class); - SalesforceOauthTokenRepository salesforceOauthTokenRepository = new SalesforceOauthTokenRepository(dynamoDBMapper); + SalesforceOauthTokenRepository mockSalesforceOauthTokenRepository = new SalesforceOauthTokenRepository(dynamoDBMapper); // Mock the behavior to throw an exception when save is called doThrow(new CustomException(new ErrorObject("test:r_sotr_tssfot_1", "something_went_wrong", "mock db save error"))) @@ -77,7 +78,7 @@ public void testSaveSalesforceOauthToken() { // Test if CustomException is thrown with the expected error code CustomException thrownException = assertThrows( CustomException.class, - () -> salesforceOauthTokenRepository.saveSalesforceOauthToken(salesforceOauthTokenInvalid) + () -> mockSalesforceOauthTokenRepository.saveSalesforceOauthToken(salesforceOauthTokenInvalid) ); // Validate the error identifier to be a 500 error assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); @@ -91,6 +92,7 @@ public void testGetSalesforceOauthTokenByExternalUserId() throws Exception{{ loadFixture.perform(fixtureData); //Valid Get Db Query + SalesforceOauthTokenRepository salesforceOauthTokenRepository = new SalesforceOauthTokenRepository(dynamoDBMapper); SalesforceOauthToken salesforceOauthTokenResp = salesforceOauthTokenRepository.getSalesforceOauthTokenByExternalUserId("0055i00000AUxQHAA1"); assertEquals("0055i00000AUxQHAA1", salesforceOauthTokenResp.getExternalUserId()); @@ -98,7 +100,7 @@ public void testGetSalesforceOauthTokenByExternalUserId() throws Exception{{ // mock the DynamoDBMapper DynamoDBMapper dynamoDBMapper = mock(DynamoDBMapper.class); - SalesforceOauthTokenRepository salesforceOauthTokenRepository = new SalesforceOauthTokenRepository(dynamoDBMapper); + SalesforceOauthTokenRepository mockSalesforceOauthTokenRepository = new SalesforceOauthTokenRepository(dynamoDBMapper); // Mock the behavior to throw an exception when load is called when(dynamoDBMapper.load(SalesforceOauthToken.class, testExternalUserId)).thenThrow( @@ -109,7 +111,7 @@ public void testGetSalesforceOauthTokenByExternalUserId() throws Exception{{ // Test if CustomException is thrown with the expected error code CustomException thrownException = assertThrows( CustomException.class, - () -> salesforceOauthTokenRepository.getSalesforceOauthTokenByExternalUserId(testExternalUserId) + () -> mockSalesforceOauthTokenRepository.getSalesforceOauthTokenByExternalUserId(testExternalUserId) ); // Validate the error identifier to be a 500 error assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java index 6497ac8d..0775e59a 100644 --- a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java @@ -50,14 +50,15 @@ public void tearDown() { cleanup.perform(); } - @Autowired - private SalesforceOrganizationRepository salesforceOrganizationRepository; + @Autowired + private DynamoDBMapper dynamoDBMapper; @Test public void testSaveSalesforceOrganization() { //Valid Save Db Query SalesforceOrganization salesforceOrganizationValid = new SalesforceOrganization(); salesforceOrganizationValid.setExternalOrganizationId("externalUserId-1"); + SalesforceOrganizationRepository salesforceOrganizationRepository = new SalesforceOrganizationRepository(dynamoDBMapper); SalesforceOrganization salesforceOrganizationResp = salesforceOrganizationRepository.saveSalesforceOrganization(salesforceOrganizationValid); assertEquals(salesforceOrganizationValid.getExternalOrganizationId(), salesforceOrganizationResp.getExternalOrganizationId()); @@ -67,7 +68,7 @@ public void testSaveSalesforceOrganization() { // mock the DynamoDBMapper DynamoDBMapper dynamoDBMapper = mock(DynamoDBMapper.class); - SalesforceOrganizationRepository salesforceOrganizationRepository = new SalesforceOrganizationRepository(dynamoDBMapper); + SalesforceOrganizationRepository mockSalesforceOrganizationRepository = new SalesforceOrganizationRepository(dynamoDBMapper); // Mock the behavior to throw an exception when save is called doThrow(new CustomException(new ErrorObject("test:r_sor_tssfo_1", "something_went_wrong", "mock db save error"))) @@ -77,7 +78,7 @@ public void testSaveSalesforceOrganization() { // Test if CustomException is thrown with the expected error code CustomException thrownException = assertThrows( CustomException.class, - () -> salesforceOrganizationRepository.saveSalesforceOrganization(salesforceOrganizationInvalid) + () -> mockSalesforceOrganizationRepository.saveSalesforceOrganization(salesforceOrganizationInvalid) ); // Validate the error identifier to be a 500 error assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); @@ -90,6 +91,7 @@ public void testGetSalesforceOrganizationByExternalOrganizationId() throws Excep loadFixture.perform(fixtureData); //Valid Get Db Query + SalesforceOrganizationRepository salesforceOrganizationRepository = new SalesforceOrganizationRepository(dynamoDBMapper); SalesforceOrganization salesforceOrganizationResp = salesforceOrganizationRepository.getSalesforceOrganizationByExternalOrganizationId("000Org-id"); assertEquals("000Org-id", salesforceOrganizationResp.getExternalOrganizationId()); @@ -97,7 +99,7 @@ public void testGetSalesforceOrganizationByExternalOrganizationId() throws Excep // mock the DynamoDBMapper DynamoDBMapper dynamoDBMapper = mock(DynamoDBMapper.class); - SalesforceOrganizationRepository salesforceOrganizationRepository = new SalesforceOrganizationRepository(dynamoDBMapper); + SalesforceOrganizationRepository mockSalesforceOrganizationRepository = new SalesforceOrganizationRepository(dynamoDBMapper); // Mock the behavior to throw an exception when load is called when(dynamoDBMapper.load(SalesforceOrganization.class, testExternalOrganizationId)).thenThrow( @@ -108,7 +110,7 @@ public void testGetSalesforceOrganizationByExternalOrganizationId() throws Excep // Test if CustomException is thrown with the expected error code CustomException thrownException = assertThrows( CustomException.class, - () -> salesforceOrganizationRepository.getSalesforceOrganizationByExternalOrganizationId(testExternalOrganizationId) + () -> mockSalesforceOrganizationRepository.getSalesforceOrganizationByExternalOrganizationId(testExternalOrganizationId) ); // Validate the error identifier to be a 500 error assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java index 2a05f181..d2dc15d2 100644 --- a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java @@ -54,14 +54,15 @@ public void tearDown() { cleanup.perform(); } - @Autowired - private SalesforceUserRepository salesforceUserRepository; + @Autowired + private DynamoDBMapper dynamoDBMapper; @Test public void testSaveSalesforceUser() { //Valid Save Db Query SalesforceUser salesforceUserValid = new SalesforceUser(); salesforceUserValid.setExternalUserId("externalUserId-test1"); + SalesforceUserRepository salesforceUserRepository = new SalesforceUserRepository(dynamoDBMapper); SalesforceUser salesforceUserResp = salesforceUserRepository.saveSalesforceUser(salesforceUserValid); assertEquals(salesforceUserValid.getExternalUserId(), salesforceUserResp.getExternalUserId()); @@ -71,7 +72,7 @@ public void testSaveSalesforceUser() { // mock the DynamoDBMapper DynamoDBMapper dynamoDBMapper = mock(DynamoDBMapper.class); - SalesforceUserRepository salesforceUserRepository = new SalesforceUserRepository(dynamoDBMapper); + SalesforceUserRepository mockSalesforceUserRepository = new SalesforceUserRepository(dynamoDBMapper); // Mock the behavior to throw an exception when save is called doThrow(new CustomException(new ErrorObject("test:r_sotr_tssfu_1", "something_went_wrong", "mock db save error"))) @@ -81,7 +82,7 @@ public void testSaveSalesforceUser() { // Test if CustomException is thrown with the expected error code CustomException thrownException = assertThrows( CustomException.class, - () -> salesforceUserRepository.saveSalesforceUser(salesforceUserInvalid) + () -> mockSalesforceUserRepository.saveSalesforceUser(salesforceUserInvalid) ); // Validate the error identifier to be a 500 error assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); @@ -95,6 +96,7 @@ public void testGetSalesforceUserByExternalUserId() throws Exception{{ loadFixture.perform(fixtureData); //Valid Get Db Query + SalesforceUserRepository salesforceUserRepository = new SalesforceUserRepository(dynamoDBMapper); SalesforceUser salesforceUserResp = salesforceUserRepository.getSalesforceUserByExternalUserId("0055i00000AUxQHAA1"); assertEquals("0055i00000AUxQHAA1", salesforceUserResp.getExternalUserId()); @@ -102,7 +104,7 @@ public void testGetSalesforceUserByExternalUserId() throws Exception{{ // mock the DynamoDBMapper DynamoDBMapper dynamoDBMapper = mock(DynamoDBMapper.class); - SalesforceUserRepository salesforceUserRepository = new SalesforceUserRepository(dynamoDBMapper); + SalesforceUserRepository mockSalesforceUserRepository = new SalesforceUserRepository(dynamoDBMapper); // Mock the behavior to throw an exception when load is called @@ -114,7 +116,7 @@ public void testGetSalesforceUserByExternalUserId() throws Exception{{ // Test if CustomException is thrown with the expected error code CustomException thrownException = assertThrows( CustomException.class, - () -> salesforceUserRepository.getSalesforceUserByExternalUserId(testExternalUserId) + () -> mockSalesforceUserRepository.getSalesforceUserByExternalUserId(testExternalUserId) ); // Validate the error identifier to be a 500 error assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); From fb9c77c522f2620d7932f3d7742280ad0ac4aaf0 Mon Sep 17 00:00:00 2001 From: amanbarbaria Date: Tue, 29 Aug 2023 13:08:04 +0530 Subject: [PATCH 143/195] 1. preserve the original stack trace on db exception. 2. Use the faster System.currentTimeMillis() instead of Instant.now().toEpochMilli() --- .../api/config/DynamoDBConfiguration.java | 12 ++++++------ 1 file changed, 6 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 19a8168e..e523da35 100644 --- a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java +++ b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java @@ -27,32 +27,32 @@ public DynamoDBMapper dynamoDBMapper() { @Override public T load(Class clazz, Object hashKey) { T response = null; - Instant startTimestamp = Instant.now(); + long startTimestamp = System.currentTimeMillis(); 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 e; + throw new RuntimeException("Error during load database operation", e); } - Integer duration = (int) (Instant.now().toEpochMilli() - startTimestamp.toEpochMilli()); + long duration = System.currentTimeMillis() - startTimestamp; logger.debug("({} ms)DBQuery:Load: table-{} hashKey-{}", duration, clazz.getSimpleName(), hashKey); return response; } @Override public void save(T object) { - Instant startTimestamp = Instant.now(); + long startTimestamp = System.currentTimeMillis(); try { defaultMapper.save(object); } catch (Exception e) { logger.debug("DBQuery:Save: table-{}", object.getClass().getSimpleName()); logger.error("DBQuery:Save: exception-{}", e); - throw e; + throw new RuntimeException("Error during save database operation", e); } - Integer duration = (int) (Instant.now().toEpochMilli() - startTimestamp.toEpochMilli()); + 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 From 4c802706fb9b94e4c0a43d826865ecbea42160a5 Mon Sep 17 00:00:00 2001 From: amanbarbaria Date: Tue, 29 Aug 2023 13:09:58 +0530 Subject: [PATCH 144/195] 1. use dependency injection for repositories --- .../salessparrow/api/lib/UserLoginCookieAuth.java | 4 +--- .../salesforce/helper/SalesforceOAuthToken.java | 4 +--- .../lib/salesforce/helper/SalesforceRequest.java | 4 +--- .../api/services/salesforce/AuthService.java | 13 +++++++------ .../com/salessparrow/api/helper/LoadFixture.java | 14 +++++++++----- 5 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/salessparrow/api/lib/UserLoginCookieAuth.java b/src/main/java/com/salessparrow/api/lib/UserLoginCookieAuth.java index 5accfe32..4a537faa 100644 --- a/src/main/java/com/salessparrow/api/lib/UserLoginCookieAuth.java +++ b/src/main/java/com/salessparrow/api/lib/UserLoginCookieAuth.java @@ -10,7 +10,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; import com.salessparrow.api.config.CoreConstants; import com.salessparrow.api.domain.User; import com.salessparrow.api.exception.CustomException; @@ -42,7 +41,7 @@ public class UserLoginCookieAuth { private CookieHelper cookieHelper; @Autowired - private DynamoDBMapper dynamoDBMapper; + private SalesforceUserRepository salesforceUserRepository; /** * Validate and set cookie @@ -171,7 +170,6 @@ private void fetchAndValidateUser() { } private void fetchAndValidateSalesforceUser() { - SalesforceUserRepository salesforceUserRepository = new SalesforceUserRepository(dynamoDBMapper); User userObj = salesforceUserRepository.getSalesforceUserByExternalUserId(userId); if (userObj == null) { diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceOAuthToken.java b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceOAuthToken.java index 34a0aaf4..dba11f8e7 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceOAuthToken.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceOAuthToken.java @@ -3,7 +3,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; import com.fasterxml.jackson.databind.JsonNode; import com.salessparrow.api.domain.SalesforceOauthToken; import com.salessparrow.api.lib.AwsKms; @@ -22,7 +21,7 @@ public class SalesforceOAuthToken { private AwsKms awsKms; @Autowired - private DynamoDBMapper dynamoDBMapper; + private SalesforceOauthTokenRepository salesforceOauthTokenRepository; @Autowired private SalesforceGetRefreshedAccessToken salesforceGetRefreshedAccessToken; @@ -67,7 +66,6 @@ private String updateAccessTokenInDatabase(String responseBody, SalesforceOauthT String encryptedAccessToken = awsKms.encryptToken(decryptedAccessToken); sfOAuthToken.setAccessToken(encryptedAccessToken); - SalesforceOauthTokenRepository salesforceOauthTokenRepository = new SalesforceOauthTokenRepository(dynamoDBMapper); salesforceOauthTokenRepository.saveSalesforceOauthToken(sfOAuthToken); return decryptedAccessToken; diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceRequest.java b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceRequest.java index c6bb9dc5..9f999e5d 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceRequest.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceRequest.java @@ -4,7 +4,6 @@ import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.client.WebClientResponseException; -import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; import com.salessparrow.api.domain.SalesforceOauthToken; import com.salessparrow.api.exception.CustomException; import com.salessparrow.api.lib.errorLib.ErrorObject; @@ -20,7 +19,7 @@ public class SalesforceRequest { private SalesforceOAuthToken getAccessTokenService; @Autowired - private DynamoDBMapper dynamoDBMapper; + private SalesforceOauthTokenRepository salesforceOauthTokenRepository; /** * Make a request to the Salesforce API. @@ -31,7 +30,6 @@ public class SalesforceRequest { * @return T */ public T makeRequest(String salesforceUserId, SalesforceRequestInterface request) { - SalesforceOauthTokenRepository salesforceOauthTokenRepository = new SalesforceOauthTokenRepository(dynamoDBMapper); SalesforceOauthToken sfOAuthToken = salesforceOauthTokenRepository .getSalesforceOauthTokenByExternalUserId(salesforceUserId); 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 6a7e5103..45de9a62 100644 --- a/src/main/java/com/salessparrow/api/services/salesforce/AuthService.java +++ b/src/main/java/com/salessparrow/api/services/salesforce/AuthService.java @@ -5,7 +5,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -56,7 +55,13 @@ public class AuthService { private Util util; @Autowired - private DynamoDBMapper dynamoDBMapper; + private SalesforceUserRepository salesforceUserRepository; + + @Autowired + private SalesforceOauthTokenRepository salesforceOauthTokenRepository; + + @Autowired + private SalesforceOrganizationRepository salesforceOrganizationRepository; @Autowired private LocalCipher localCipher; @@ -133,7 +138,6 @@ private void validateAndUpsertSalesforceOrganization() { String salesforceOrganizationId = this.tokensData.getSalesforceOrganizationId(); - SalesforceOrganizationRepository salesforceOrganizationRepository = new SalesforceOrganizationRepository(dynamoDBMapper); SalesforceOrganization existingOrganizationData = salesforceOrganizationRepository .getSalesforceOrganizationByExternalOrganizationId(salesforceOrganizationId); @@ -187,7 +191,6 @@ private void upsertSalesforceOAuthTokens() { salesforceOauthToken.setStatus(SalesforceOauthToken.Status.ACTIVE); salesforceOauthToken.setIssuedAt(Long.parseLong(this.tokensData.getIssuedAt())); - SalesforceOauthTokenRepository salesforceOauthTokenRepository = new SalesforceOauthTokenRepository(dynamoDBMapper); this.salesforceOauthToken = salesforceOauthTokenRepository .saveSalesforceOauthToken(salesforceOauthToken); } @@ -199,7 +202,6 @@ private void upsertSalesforceOAuthTokens() { */ private void verifyExistingSalesforceUser() { String salesforceUserId = this.tokensData.getSalesforceUserId(); - SalesforceUserRepository salesforceUserRepository = new SalesforceUserRepository(dynamoDBMapper); SalesforceUser salesforceUser = salesforceUserRepository.getSalesforceUserByExternalUserId(salesforceUserId); if (salesforceUser != null) { @@ -255,7 +257,6 @@ private void createSalesforceUser() { salesforceUser.setEncryptionSalt(encryptedSalt); salesforceUser.setStatus(SalesforceUser.Status.ACTIVE); - SalesforceUserRepository salesforceUserRepository = new SalesforceUserRepository(dynamoDBMapper); this.salesforceUser = salesforceUserRepository.saveSalesforceUser(salesforceUser); this.decryptedSalt = decryptedSalt; } diff --git a/src/test/java/com/salessparrow/api/helper/LoadFixture.java b/src/test/java/com/salessparrow/api/helper/LoadFixture.java index 06d0ef56..59851447 100644 --- a/src/test/java/com/salessparrow/api/helper/LoadFixture.java +++ b/src/test/java/com/salessparrow/api/helper/LoadFixture.java @@ -7,7 +7,6 @@ import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; -import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.salessparrow.api.domain.SalesforceOauthToken; @@ -25,7 +24,15 @@ public class LoadFixture { private ResourceLoader resourceLoader; @Autowired - private DynamoDBMapper dynamoDBMapper; + private SalesforceUserRepository salesforceUserRepository; + + + @Autowired + private SalesforceOauthTokenRepository salesforceOauthTokenRepository; + + + @Autowired + private SalesforceOrganizationRepository salesforceOrganizationRepository; /** * Load the fixture data. @@ -39,7 +46,6 @@ public void perform(FixtureData fixtureData) throws IOException { if (fixtureData.getSalesforce_users() != null) { for (FilePathData filePathData : fixtureData.getSalesforce_users()) { SalesforceUser salesforceUser = loadSalesForceUserFixture(filePathData.getFilepath()); - SalesforceUserRepository salesforceUserRepository = new SalesforceUserRepository(dynamoDBMapper); salesforceUserRepository.saveSalesforceUser(salesforceUser); } } @@ -47,7 +53,6 @@ public void perform(FixtureData fixtureData) throws IOException { if (fixtureData.getSalesforce_oauth_tokens() != null) { for (FilePathData filePathData : fixtureData.getSalesforce_oauth_tokens()) { SalesforceOauthToken salesforceOauth = loadSalesForceOAuthTokenFixture(filePathData.getFilepath()); - SalesforceOauthTokenRepository salesforceOauthTokenRepository = new SalesforceOauthTokenRepository(dynamoDBMapper); salesforceOauthTokenRepository.saveSalesforceOauthToken(salesforceOauth); } } @@ -55,7 +60,6 @@ public void perform(FixtureData fixtureData) throws IOException { if (fixtureData.getSalesforce_organizations() != null) { for (FilePathData filePathData : fixtureData.getSalesforce_organizations()) { SalesforceOrganization salesforceOrganization = loadSalesForceOrganizationFixture(filePathData.getFilepath()); - SalesforceOrganizationRepository salesforceOrganizationRepository = new SalesforceOrganizationRepository(dynamoDBMapper); salesforceOrganizationRepository.saveSalesforceOrganization(salesforceOrganization); } } From 436a6eba73767207d687b585d2e5879c222dd89d Mon Sep 17 00:00:00 2001 From: amanbarbaria Date: Tue, 29 Aug 2023 14:11:56 +0530 Subject: [PATCH 145/195] 1. Flush all cache on cleanup for test cases --- src/test/java/com/salessparrow/api/helper/Cleanup.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/salessparrow/api/helper/Cleanup.java b/src/test/java/com/salessparrow/api/helper/Cleanup.java index 86125963..8f8fa4aa 100644 --- a/src/test/java/com/salessparrow/api/helper/Cleanup.java +++ b/src/test/java/com/salessparrow/api/helper/Cleanup.java @@ -4,6 +4,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.cache.CacheManager; /** * This class is used to clean the setup after each test. @@ -16,6 +17,9 @@ public class Cleanup { @Autowired private DropTables dropTables; + @Autowired + private CacheManager cacheManager; + /** * Clean the setup after each test. * - Flush the cache @@ -32,8 +36,10 @@ public void perform() { * Flush the cache. */ private void flushCache(){ - logger.info("Cleanup: Flushing cache"); - } + logger.info("Setup: Flushing cache"); + cacheManager.getCacheNames().stream().forEach(cacheName -> { + cacheManager.getCache(cacheName).clear(); + }); } /** * Drop the tables. From 1726722ec106d300a8fc83454da4c06dbc6ae8e0 Mon Sep 17 00:00:00 2001 From: amanbarbaria Date: Tue, 29 Aug 2023 14:17:31 +0530 Subject: [PATCH 146/195] 1. optimizate repositories unit test cases to create the repository instance only once --- .../SalesforceOauthTokenRepositoryTest.java | 11 +++++++---- .../SalesforceOrganizationRepositoryTest.java | 9 +++++---- .../repositories/SalesforceUserRepositoryTest.java | 14 ++++++++------ 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java index db4f2d01..d61ff0c8 100644 --- a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java @@ -40,9 +40,13 @@ public class SalesforceOauthTokenRepositoryTest { @Autowired private LoadFixture loadFixture; + private SalesforceOauthTokenRepository salesforceOauthTokenRepository; + @BeforeEach public void setUp() throws DynamobeeException, IOException { setup.perform(); + this.salesforceOauthTokenRepository = new SalesforceOauthTokenRepository(dynamoDBMapper); + } @AfterEach @@ -58,8 +62,8 @@ public void testSaveSalesforceOauthToken() { //Valid Save Db Query SalesforceOauthToken salesforceOauthTokenValid = new SalesforceOauthToken(); salesforceOauthTokenValid.setExternalUserId("externalUserId-1"); - SalesforceOauthTokenRepository salesforceOauthTokenRepository = new SalesforceOauthTokenRepository(dynamoDBMapper); - SalesforceOauthToken salesforceOauthTokenResp = salesforceOauthTokenRepository.saveSalesforceOauthToken(salesforceOauthTokenValid); + + SalesforceOauthToken salesforceOauthTokenResp = this.salesforceOauthTokenRepository.saveSalesforceOauthToken(salesforceOauthTokenValid); assertEquals(salesforceOauthTokenValid.getExternalUserId(), salesforceOauthTokenResp.getExternalUserId()); // Invalid Save Db Query without partition key @@ -92,8 +96,7 @@ public void testGetSalesforceOauthTokenByExternalUserId() throws Exception{{ loadFixture.perform(fixtureData); //Valid Get Db Query - SalesforceOauthTokenRepository salesforceOauthTokenRepository = new SalesforceOauthTokenRepository(dynamoDBMapper); - SalesforceOauthToken salesforceOauthTokenResp = salesforceOauthTokenRepository.getSalesforceOauthTokenByExternalUserId("0055i00000AUxQHAA1"); + SalesforceOauthToken salesforceOauthTokenResp = this.salesforceOauthTokenRepository.getSalesforceOauthTokenByExternalUserId("0055i00000AUxQHAA1"); assertEquals("0055i00000AUxQHAA1", salesforceOauthTokenResp.getExternalUserId()); String testExternalUserId = "externalUserId-3"; diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java index 0775e59a..a55682ac 100644 --- a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java @@ -40,9 +40,12 @@ public class SalesforceOrganizationRepositoryTest { @Autowired private LoadFixture loadFixture; + private SalesforceOrganizationRepository salesforceOrganizationRepository; + @BeforeEach public void setUp() throws DynamobeeException, IOException { setup.perform(); + this.salesforceOrganizationRepository = new SalesforceOrganizationRepository(dynamoDBMapper); } @AfterEach @@ -58,8 +61,7 @@ public void testSaveSalesforceOrganization() { //Valid Save Db Query SalesforceOrganization salesforceOrganizationValid = new SalesforceOrganization(); salesforceOrganizationValid.setExternalOrganizationId("externalUserId-1"); - SalesforceOrganizationRepository salesforceOrganizationRepository = new SalesforceOrganizationRepository(dynamoDBMapper); - SalesforceOrganization salesforceOrganizationResp = salesforceOrganizationRepository.saveSalesforceOrganization(salesforceOrganizationValid); + SalesforceOrganization salesforceOrganizationResp = this.salesforceOrganizationRepository.saveSalesforceOrganization(salesforceOrganizationValid); assertEquals(salesforceOrganizationValid.getExternalOrganizationId(), salesforceOrganizationResp.getExternalOrganizationId()); // Invalid Save Db Query without partition key @@ -91,8 +93,7 @@ public void testGetSalesforceOrganizationByExternalOrganizationId() throws Excep loadFixture.perform(fixtureData); //Valid Get Db Query - SalesforceOrganizationRepository salesforceOrganizationRepository = new SalesforceOrganizationRepository(dynamoDBMapper); - SalesforceOrganization salesforceOrganizationResp = salesforceOrganizationRepository.getSalesforceOrganizationByExternalOrganizationId("000Org-id"); + SalesforceOrganization salesforceOrganizationResp = this.salesforceOrganizationRepository.getSalesforceOrganizationByExternalOrganizationId("000Org-id"); assertEquals("000Org-id", salesforceOrganizationResp.getExternalOrganizationId()); String testExternalOrganizationId = "externalUserId-2"; diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java index d2dc15d2..01f86a16 100644 --- a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java @@ -44,9 +44,15 @@ public class SalesforceUserRepositoryTest { @Autowired private LoadFixture loadFixture; + @Autowired + private DynamoDBMapper dynamoDBMapper; + + private SalesforceUserRepository salesforceUserRepository; + @BeforeEach public void setUp() throws DynamobeeException, IOException { setup.perform(); + this.salesforceUserRepository = new SalesforceUserRepository(dynamoDBMapper); } @AfterEach @@ -54,16 +60,13 @@ public void tearDown() { cleanup.perform(); } - @Autowired - private DynamoDBMapper dynamoDBMapper; @Test public void testSaveSalesforceUser() { //Valid Save Db Query SalesforceUser salesforceUserValid = new SalesforceUser(); salesforceUserValid.setExternalUserId("externalUserId-test1"); - SalesforceUserRepository salesforceUserRepository = new SalesforceUserRepository(dynamoDBMapper); - SalesforceUser salesforceUserResp = salesforceUserRepository.saveSalesforceUser(salesforceUserValid); + SalesforceUser salesforceUserResp = this.salesforceUserRepository.saveSalesforceUser(salesforceUserValid); assertEquals(salesforceUserValid.getExternalUserId(), salesforceUserResp.getExternalUserId()); // Invalid Save Db Query without partition key @@ -96,8 +99,7 @@ public void testGetSalesforceUserByExternalUserId() throws Exception{{ loadFixture.perform(fixtureData); //Valid Get Db Query - SalesforceUserRepository salesforceUserRepository = new SalesforceUserRepository(dynamoDBMapper); - SalesforceUser salesforceUserResp = salesforceUserRepository.getSalesforceUserByExternalUserId("0055i00000AUxQHAA1"); + SalesforceUser salesforceUserResp = this.salesforceUserRepository.getSalesforceUserByExternalUserId("0055i00000AUxQHAA1"); assertEquals("0055i00000AUxQHAA1", salesforceUserResp.getExternalUserId()); String testExternalUserId = "externalUserId-test3"; From a3add3049164e53065b545ab6851debf3a762f46 Mon Sep 17 00:00:00 2001 From: amanbarbaria Date: Tue, 29 Aug 2023 15:13:49 +0530 Subject: [PATCH 147/195] Refactored repositories unit test cases as per suggestions --- .../api/config/DynamoDBConfiguration.java | 2 - .../SalesforceOauthTokenRepositoryTest.java | 152 +++++++++-------- .../SalesforceOrganizationRepositoryTest.java | 149 +++++++++-------- .../SalesforceUserRepositoryTest.java | 154 ++++++++++-------- .../salesforceOauthTokenRepository.json | 2 +- .../salesforceOrganizationRepository.json | 2 +- .../salesforceUserRepository.json | 2 +- 7 files changed, 254 insertions(+), 209 deletions(-) diff --git a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java index e523da35..a0a442b4 100644 --- a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java +++ b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java @@ -6,8 +6,6 @@ import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig; -import java.time.Instant; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java index d61ff0c8..58d18c00 100644 --- a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java @@ -1,5 +1,6 @@ package com.salessparrow.api.unit.repositories; +import com.salessparrow.api.config.DynamoDBConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Import; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -13,6 +14,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; +import com.amazonaws.services.dynamodbv2.model.AmazonDynamoDBException; import com.github.dynamobee.exception.DynamobeeException; import com.salessparrow.api.domain.SalesforceOauthToken; import com.salessparrow.api.exception.CustomException; @@ -21,9 +23,7 @@ import com.salessparrow.api.helper.FixtureData; import com.salessparrow.api.helper.LoadFixture; import com.salessparrow.api.helper.Setup; -import com.salessparrow.api.lib.errorLib.ErrorObject; import com.salessparrow.api.repositories.SalesforceOauthTokenRepository; - @SpringBootTest @Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) public class SalesforceOauthTokenRepositoryTest { @@ -40,13 +40,21 @@ public class SalesforceOauthTokenRepositoryTest { @Autowired private LoadFixture loadFixture; - private SalesforceOauthTokenRepository salesforceOauthTokenRepository; + private DynamoDBMapper mockDynamoDBMapper; + + private SalesforceOauthTokenRepository realSalesforceOauthTokenRepository; + + private SalesforceOauthTokenRepository mockSalesforceOauthTokenRepository; @BeforeEach public void setUp() throws DynamobeeException, IOException { setup.perform(); - this.salesforceOauthTokenRepository = new SalesforceOauthTokenRepository(dynamoDBMapper); + // Use your Spring bean here + DynamoDBMapper dynamoDBMapper = new DynamoDBConfiguration().dynamoDBMapper(); + this.realSalesforceOauthTokenRepository = new SalesforceOauthTokenRepository(dynamoDBMapper); + this.mockDynamoDBMapper = mock(DynamoDBMapper.class); // Mocked instance + this.mockSalesforceOauthTokenRepository = new SalesforceOauthTokenRepository(mockDynamoDBMapper); } @AfterEach @@ -54,70 +62,76 @@ public void tearDown() { cleanup.perform(); } - @Autowired - private DynamoDBMapper dynamoDBMapper; - - @Test - public void testSaveSalesforceOauthToken() { - //Valid Save Db Query - SalesforceOauthToken salesforceOauthTokenValid = new SalesforceOauthToken(); - salesforceOauthTokenValid.setExternalUserId("externalUserId-1"); - - SalesforceOauthToken salesforceOauthTokenResp = this.salesforceOauthTokenRepository.saveSalesforceOauthToken(salesforceOauthTokenValid); - assertEquals(salesforceOauthTokenValid.getExternalUserId(), salesforceOauthTokenResp.getExternalUserId()); - - // Invalid Save Db Query without partition key - SalesforceOauthToken salesforceOauthTokenInvalid = new SalesforceOauthToken(); - salesforceOauthTokenInvalid.setExternalUserId("externalUserId-2"); - - // mock the DynamoDBMapper - DynamoDBMapper dynamoDBMapper = mock(DynamoDBMapper.class); - SalesforceOauthTokenRepository mockSalesforceOauthTokenRepository = new SalesforceOauthTokenRepository(dynamoDBMapper); - - // Mock the behavior to throw an exception when save is called - doThrow(new CustomException(new ErrorObject("test:r_sotr_tssfot_1", "something_went_wrong", "mock db save error"))) - .when(dynamoDBMapper) - .save(salesforceOauthTokenInvalid); - - // Test if CustomException is thrown with the expected error code - CustomException thrownException = assertThrows( - CustomException.class, - () -> mockSalesforceOauthTokenRepository.saveSalesforceOauthToken(salesforceOauthTokenInvalid) - ); - // Validate the error identifier to be a 500 error - assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); - } - - @Test - public void testGetSalesforceOauthTokenByExternalUserId() throws Exception{{ - - String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/unit/repositories/salesforceOauthTokenRepository.json", currentFunctionName); - loadFixture.perform(fixtureData); - - //Valid Get Db Query - SalesforceOauthToken salesforceOauthTokenResp = this.salesforceOauthTokenRepository.getSalesforceOauthTokenByExternalUserId("0055i00000AUxQHAA1"); - assertEquals("0055i00000AUxQHAA1", salesforceOauthTokenResp.getExternalUserId()); - - String testExternalUserId = "externalUserId-3"; - - // mock the DynamoDBMapper - DynamoDBMapper dynamoDBMapper = mock(DynamoDBMapper.class); - SalesforceOauthTokenRepository mockSalesforceOauthTokenRepository = new SalesforceOauthTokenRepository(dynamoDBMapper); - - // Mock the behavior to throw an exception when load is called - when(dynamoDBMapper.load(SalesforceOauthToken.class, testExternalUserId)).thenThrow( - new CustomException(new ErrorObject("test:r_sotr_gsotbsfui_1", - "something_went_wrong","mock db query error"))); - - // Mock Invalid Get Db Query - // Test if CustomException is thrown with the expected error code - CustomException thrownException = assertThrows( - CustomException.class, - () -> mockSalesforceOauthTokenRepository.getSalesforceOauthTokenByExternalUserId(testExternalUserId) - ); - // Validate the error identifier to be a 500 error - assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); - } + /** + * Test valid case for saveSalesforceOauthToken method + */ + @Test + public void testValidSaveSalesforceOauthToken() { + //Valid Save Db Query + SalesforceOauthToken salesforceOauthTokenValid = new SalesforceOauthToken(); + salesforceOauthTokenValid.setExternalUserId("externalUserId-1"); + + SalesforceOauthToken salesforceOauthTokenResp = this.realSalesforceOauthTokenRepository.saveSalesforceOauthToken(salesforceOauthTokenValid); + assertEquals(salesforceOauthTokenValid.getExternalUserId(), salesforceOauthTokenResp.getExternalUserId()); } + + /** + * Test invlaid case for saveSalesforceOauthToken method + */ + @Test + public void testInvalidSaveSalesforceOauthToken() { + // Invalid Save Db Query without partition key + SalesforceOauthToken salesforceOauthTokenInvalid = new SalesforceOauthToken(); + salesforceOauthTokenInvalid.setExternalUserId("externalUserId-2"); + + // Mock the behavior to throw an exception when save is called + doThrow(new AmazonDynamoDBException("mock db save error")) + .when(mockDynamoDBMapper) + .save(salesforceOauthTokenInvalid); + + // Test if CustomException is thrown with the expected error code + CustomException thrownException = assertThrows( + CustomException.class, + () -> mockSalesforceOauthTokenRepository.saveSalesforceOauthToken(salesforceOauthTokenInvalid) + ); + // Validate the error identifier to be a 500 error + assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); + } + + /** + * Test valid case for getSalesforceOauthTokenByExternalUserId method + */ + @Test + public void testValidGetSalesforceOauthTokenByExternalUserId() throws Exception{ + + String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/unit/repositories/salesforceOauthTokenRepository.json", currentFunctionName); + loadFixture.perform(fixtureData); + + //Valid Get Db Query + SalesforceOauthToken salesforceOauthTokenResp = this.realSalesforceOauthTokenRepository.getSalesforceOauthTokenByExternalUserId("0055i00000AUxQHAA1"); + assertEquals("0055i00000AUxQHAA1", salesforceOauthTokenResp.getExternalUserId()); + } + + /** + * Test invalid case for getSalesforceOauthTokenByExternalUserId method + */ + @Test + public void testInvalidGetSalesforceOauthTokenByExternalUserId() throws Exception{ + + String testExternalUserId = "externalUserId-3"; + + // Mock the behavior to throw an exception when load is called + when(mockDynamoDBMapper.load(SalesforceOauthToken.class, testExternalUserId)).thenThrow( + new AmazonDynamoDBException("mock db get error")); + + // Mock Invalid Get Db Query + // Test if CustomException is thrown with the expected error code + CustomException thrownException = assertThrows( + CustomException.class, + () -> mockSalesforceOauthTokenRepository.getSalesforceOauthTokenByExternalUserId(testExternalUserId) + ); + // Validate the error identifier to be a 500 error + assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); + } } diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java index a55682ac..0767323b 100644 --- a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java @@ -13,7 +13,9 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; +import com.amazonaws.services.dynamodbv2.model.AmazonDynamoDBException; import com.github.dynamobee.exception.DynamobeeException; +import com.salessparrow.api.config.DynamoDBConfiguration; import com.salessparrow.api.domain.SalesforceOrganization; import com.salessparrow.api.exception.CustomException; import com.salessparrow.api.helper.Cleanup; @@ -21,7 +23,6 @@ import com.salessparrow.api.helper.FixtureData; import com.salessparrow.api.helper.LoadFixture; import com.salessparrow.api.helper.Setup; -import com.salessparrow.api.lib.errorLib.ErrorObject; import com.salessparrow.api.repositories.SalesforceOrganizationRepository; @SpringBootTest @@ -40,12 +41,21 @@ public class SalesforceOrganizationRepositoryTest { @Autowired private LoadFixture loadFixture; - private SalesforceOrganizationRepository salesforceOrganizationRepository; + private DynamoDBMapper mockDynamoDBMapper; + + private SalesforceOrganizationRepository realSalesforceOrganizationRepository; + + private SalesforceOrganizationRepository mockSalesforceOrganizationRepository; @BeforeEach public void setUp() throws DynamobeeException, IOException { - setup.perform(); - this.salesforceOrganizationRepository = new SalesforceOrganizationRepository(dynamoDBMapper); + setup.perform(); + // Use your Spring bean here + DynamoDBMapper dynamoDBMapper = new DynamoDBConfiguration().dynamoDBMapper(); + this.realSalesforceOrganizationRepository = new SalesforceOrganizationRepository(dynamoDBMapper); + + this.mockDynamoDBMapper = mock(DynamoDBMapper.class); // Mocked instance + this.mockSalesforceOrganizationRepository = new SalesforceOrganizationRepository(mockDynamoDBMapper); } @AfterEach @@ -53,68 +63,73 @@ public void tearDown() { cleanup.perform(); } - @Autowired - private DynamoDBMapper dynamoDBMapper; - - @Test - public void testSaveSalesforceOrganization() { - //Valid Save Db Query - SalesforceOrganization salesforceOrganizationValid = new SalesforceOrganization(); - salesforceOrganizationValid.setExternalOrganizationId("externalUserId-1"); - SalesforceOrganization salesforceOrganizationResp = this.salesforceOrganizationRepository.saveSalesforceOrganization(salesforceOrganizationValid); - assertEquals(salesforceOrganizationValid.getExternalOrganizationId(), salesforceOrganizationResp.getExternalOrganizationId()); - - // Invalid Save Db Query without partition key - SalesforceOrganization salesforceOrganizationInvalid = new SalesforceOrganization(); - salesforceOrganizationInvalid.setExternalOrganizationId("externalUserId-2"); - - // mock the DynamoDBMapper - DynamoDBMapper dynamoDBMapper = mock(DynamoDBMapper.class); - SalesforceOrganizationRepository mockSalesforceOrganizationRepository = new SalesforceOrganizationRepository(dynamoDBMapper); - - // Mock the behavior to throw an exception when save is called - doThrow(new CustomException(new ErrorObject("test:r_sor_tssfo_1", "something_went_wrong", "mock db save error"))) - .when(dynamoDBMapper) - .save(salesforceOrganizationInvalid); - - // Test if CustomException is thrown with the expected error code - CustomException thrownException = assertThrows( - CustomException.class, - () -> mockSalesforceOrganizationRepository.saveSalesforceOrganization(salesforceOrganizationInvalid) - ); - // Validate the error identifier to be a 500 error - assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); - } - - @Test - public void testGetSalesforceOrganizationByExternalOrganizationId() throws Exception{{ - String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/unit/repositories/salesforceOrganizationRepository.json", currentFunctionName); - loadFixture.perform(fixtureData); - - //Valid Get Db Query - SalesforceOrganization salesforceOrganizationResp = this.salesforceOrganizationRepository.getSalesforceOrganizationByExternalOrganizationId("000Org-id"); - assertEquals("000Org-id", salesforceOrganizationResp.getExternalOrganizationId()); - - String testExternalOrganizationId = "externalUserId-2"; - - // mock the DynamoDBMapper - DynamoDBMapper dynamoDBMapper = mock(DynamoDBMapper.class); - SalesforceOrganizationRepository mockSalesforceOrganizationRepository = new SalesforceOrganizationRepository(dynamoDBMapper); - - // Mock the behavior to throw an exception when load is called - when(dynamoDBMapper.load(SalesforceOrganization.class, testExternalOrganizationId)).thenThrow( - new CustomException(new ErrorObject("test:r_sor_gsotbsfui_1", - "something_went_wrong","mock db query error"))); - - // Mock Invalid Get Db Query - // Test if CustomException is thrown with the expected error code - CustomException thrownException = assertThrows( - CustomException.class, - () -> mockSalesforceOrganizationRepository.getSalesforceOrganizationByExternalOrganizationId(testExternalOrganizationId) - ); - // Validate the error identifier to be a 500 error - assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); - } + /** + * Test Valid Save Db Query + */ + @Test + public void testValidSaveSalesforceOrganization() { + //Valid Save Db Query + SalesforceOrganization salesforceOrganizationValid = new SalesforceOrganization(); + salesforceOrganizationValid.setExternalOrganizationId("externalUserId-1"); + SalesforceOrganization salesforceOrganizationResp = this.realSalesforceOrganizationRepository.saveSalesforceOrganization(salesforceOrganizationValid); + assertEquals(salesforceOrganizationValid.getExternalOrganizationId(), salesforceOrganizationResp.getExternalOrganizationId()); } + + /** + * Test Invalid Save Db Query + */ + @Test + public void testInvalidSaveSalesforceOrganization() { + // Invalid Save Db Query without partition key + SalesforceOrganization salesforceOrganizationInvalid = new SalesforceOrganization(); + salesforceOrganizationInvalid.setExternalOrganizationId("externalUserId-2"); + + // Mock the behavior to throw an exception when save is called + doThrow(new AmazonDynamoDBException("mock db save error")) + .when(mockDynamoDBMapper) + .save(salesforceOrganizationInvalid); + + // Test if CustomException is thrown with the expected error code + CustomException thrownException = assertThrows( + CustomException.class, + () -> mockSalesforceOrganizationRepository.saveSalesforceOrganization(salesforceOrganizationInvalid) + ); + // Validate the error identifier to be a 500 error + assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); + } + + /** + * Test Valid Get Db Query + */ + @Test + public void testValidGetSalesforceOrganizationByExternalOrganizationId() throws Exception{ + String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/unit/repositories/salesforceOrganizationRepository.json", currentFunctionName); + loadFixture.perform(fixtureData); + + //Valid Get Db Query + SalesforceOrganization salesforceOrganizationResp = this.realSalesforceOrganizationRepository.getSalesforceOrganizationByExternalOrganizationId("000Org-id"); + assertEquals("000Org-id", salesforceOrganizationResp.getExternalOrganizationId()); + } + + /** + * Test Invalid Get Db Query + */ + @Test + public void testInvalidGetSalesforceOrganizationByExternalOrganizationId() throws Exception{ + String testExternalOrganizationId = "externalUserId-2"; + + // Mock the behavior to throw an exception when load is called + when(mockDynamoDBMapper.load(SalesforceOrganization.class, testExternalOrganizationId)).thenThrow( + new AmazonDynamoDBException("mock db get error")); + + // Mock Invalid Get Db Query + // Test if CustomException is thrown with the expected error code + CustomException thrownException = assertThrows( + CustomException.class, + () -> mockSalesforceOrganizationRepository.getSalesforceOrganizationByExternalOrganizationId(testExternalOrganizationId) + ); + // Validate the error identifier to be a 500 error + assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); + } } diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java index 01f86a16..cb0cad51 100644 --- a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java @@ -17,7 +17,9 @@ import org.springframework.beans.factory.annotation.Autowired; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; +import com.amazonaws.services.dynamodbv2.model.AmazonDynamoDBException; import com.github.dynamobee.exception.DynamobeeException; +import com.salessparrow.api.config.DynamoDBConfiguration; import com.salessparrow.api.domain.SalesforceUser; import com.salessparrow.api.exception.CustomException; import com.salessparrow.api.helper.Cleanup; @@ -25,7 +27,6 @@ import com.salessparrow.api.helper.FixtureData; import com.salessparrow.api.helper.LoadFixture; import com.salessparrow.api.helper.Setup; -import com.salessparrow.api.lib.errorLib.ErrorObject; import com.salessparrow.api.repositories.SalesforceUserRepository; @SpringBootTest @@ -44,15 +45,21 @@ public class SalesforceUserRepositoryTest { @Autowired private LoadFixture loadFixture; - @Autowired - private DynamoDBMapper dynamoDBMapper; + private DynamoDBMapper mockDynamoDBMapper; + + private SalesforceUserRepository realSalesforceUserRepository; - private SalesforceUserRepository salesforceUserRepository; + private SalesforceUserRepository mockSalesforceUserRepository; @BeforeEach public void setUp() throws DynamobeeException, IOException { setup.perform(); - this.salesforceUserRepository = new SalesforceUserRepository(dynamoDBMapper); + // Use your Spring bean here + DynamoDBMapper dynamoDBMapper = new DynamoDBConfiguration().dynamoDBMapper(); + this.realSalesforceUserRepository = new SalesforceUserRepository(dynamoDBMapper); + + this.mockDynamoDBMapper = mock(DynamoDBMapper.class); // Mocked instance + this.mockSalesforceUserRepository = new SalesforceUserRepository(mockDynamoDBMapper); } @AfterEach @@ -60,68 +67,79 @@ public void tearDown() { cleanup.perform(); } + /** + * Test Valid Save Db Query + * + */ + @Test + public void testValidSaveSalesforceUser() { + //Valid Save Db Query + SalesforceUser salesforceUserValid = new SalesforceUser(); + salesforceUserValid.setExternalUserId("externalUserId-test1"); + SalesforceUser salesforceUserResp = this.realSalesforceUserRepository.saveSalesforceUser(salesforceUserValid); + assertEquals(salesforceUserValid.getExternalUserId(), salesforceUserResp.getExternalUserId()); + } + + /** + * Test Invalid Save Db Query + * + */ + @Test + public void testInvalidSaveSalesforceUser() { + // Invalid Save Db Query without partition key + SalesforceUser salesforceUserInvalid = new SalesforceUser(); + salesforceUserInvalid.setExternalUserId("externalUserId-test2"); + + // Mock the behavior to throw an exception when save is called + doThrow(new AmazonDynamoDBException("mock db save error")) + .when(mockDynamoDBMapper) + .save(salesforceUserInvalid); + + // Test if CustomException is thrown with the expected error code + CustomException thrownException = assertThrows( + CustomException.class, + () -> mockSalesforceUserRepository.saveSalesforceUser(salesforceUserInvalid) + ); + // Validate the error identifier to be a 500 error + assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); + } + + /** + * Test Valid Get Db Query + * + * @throws Exception + */ + @Test + public void testValidGetSalesforceUserByExternalUserId() throws Exception{ + String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture("classpath:fixtures/unit/repositories/salesforceUserRepository.json", currentFunctionName); + loadFixture.perform(fixtureData); + + //Valid Get Db Query + SalesforceUser salesforceUserResp = this.realSalesforceUserRepository.getSalesforceUserByExternalUserId("0055i00000AUxQHAA1"); + assertEquals("0055i00000AUxQHAA1", salesforceUserResp.getExternalUserId()); + } - @Test - public void testSaveSalesforceUser() { - //Valid Save Db Query - SalesforceUser salesforceUserValid = new SalesforceUser(); - salesforceUserValid.setExternalUserId("externalUserId-test1"); - SalesforceUser salesforceUserResp = this.salesforceUserRepository.saveSalesforceUser(salesforceUserValid); - assertEquals(salesforceUserValid.getExternalUserId(), salesforceUserResp.getExternalUserId()); - - // Invalid Save Db Query without partition key - SalesforceUser salesforceUserInvalid = new SalesforceUser(); - salesforceUserInvalid.setExternalUserId("externalUserId-test2"); - - // mock the DynamoDBMapper - DynamoDBMapper dynamoDBMapper = mock(DynamoDBMapper.class); - SalesforceUserRepository mockSalesforceUserRepository = new SalesforceUserRepository(dynamoDBMapper); - - // Mock the behavior to throw an exception when save is called - doThrow(new CustomException(new ErrorObject("test:r_sotr_tssfu_1", "something_went_wrong", "mock db save error"))) - .when(dynamoDBMapper) - .save(salesforceUserInvalid); - - // Test if CustomException is thrown with the expected error code - CustomException thrownException = assertThrows( - CustomException.class, - () -> mockSalesforceUserRepository.saveSalesforceUser(salesforceUserInvalid) - ); - // Validate the error identifier to be a 500 error - assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); - } - - @Test - public void testGetSalesforceUserByExternalUserId() throws Exception{{ - - String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/unit/repositories/salesforceUserRepository.json", currentFunctionName); - loadFixture.perform(fixtureData); - - //Valid Get Db Query - SalesforceUser salesforceUserResp = this.salesforceUserRepository.getSalesforceUserByExternalUserId("0055i00000AUxQHAA1"); - assertEquals("0055i00000AUxQHAA1", salesforceUserResp.getExternalUserId()); - - String testExternalUserId = "externalUserId-test3"; - - // mock the DynamoDBMapper - DynamoDBMapper dynamoDBMapper = mock(DynamoDBMapper.class); - SalesforceUserRepository mockSalesforceUserRepository = new SalesforceUserRepository(dynamoDBMapper); - - - // Mock the behavior to throw an exception when load is called - when(dynamoDBMapper.load(SalesforceUser.class, testExternalUserId)).thenThrow( - new CustomException(new ErrorObject("test:r_sur_gsotbsfui_1", - "something_went_wrong","mock db query error"))); - - // Mock Invalid Get Db Query - // Test if CustomException is thrown with the expected error code - CustomException thrownException = assertThrows( - CustomException.class, - () -> mockSalesforceUserRepository.getSalesforceUserByExternalUserId(testExternalUserId) - ); - // Validate the error identifier to be a 500 error - assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); - } + /** + * Test Invalid Get Db Query + * + * @throws Exception + */ + @Test + public void testInvalidGetSalesforceUserByExternalUserId() throws Exception{ + String testExternalUserId = "externalUserId-test3"; + + // Mock the behavior to throw an exception when load is called + when(mockDynamoDBMapper.load(SalesforceUser.class, testExternalUserId)).thenThrow( + new AmazonDynamoDBException("mock db get error")); + + // Mock Invalid Get Db Query + // Test if CustomException is thrown with the expected error code + CustomException thrownException = assertThrows( + CustomException.class, + () -> mockSalesforceUserRepository.getSalesforceUserByExternalUserId(testExternalUserId) + ); + // Validate the error identifier to be a 500 error + assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); } -} +} diff --git a/src/test/resources/fixtures/unit/repositories/salesforceOauthTokenRepository.json b/src/test/resources/fixtures/unit/repositories/salesforceOauthTokenRepository.json index 88ca7b51..0319184d 100644 --- a/src/test/resources/fixtures/unit/repositories/salesforceOauthTokenRepository.json +++ b/src/test/resources/fixtures/unit/repositories/salesforceOauthTokenRepository.json @@ -1,5 +1,5 @@ { - "testGetSalesforceOauthTokenByExternalUserId": { + "testValidGetSalesforceOauthTokenByExternalUserId": { "salesforce_oauth_tokens": [ { "filepath": "classpath:fixtures/common/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" diff --git a/src/test/resources/fixtures/unit/repositories/salesforceOrganizationRepository.json b/src/test/resources/fixtures/unit/repositories/salesforceOrganizationRepository.json index 22fe431b..182d0bdc 100644 --- a/src/test/resources/fixtures/unit/repositories/salesforceOrganizationRepository.json +++ b/src/test/resources/fixtures/unit/repositories/salesforceOrganizationRepository.json @@ -1,5 +1,5 @@ { - "testGetSalesforceOrganizationByExternalOrganizationId": { + "testValidGetSalesforceOrganizationByExternalOrganizationId": { "salesforce_organizations": [ { "filepath": "classpath:fixtures/common/repositories/salesforceOrganization/ActiveSalesforceOrganization.json" diff --git a/src/test/resources/fixtures/unit/repositories/salesforceUserRepository.json b/src/test/resources/fixtures/unit/repositories/salesforceUserRepository.json index 07fe3980..6690113f 100644 --- a/src/test/resources/fixtures/unit/repositories/salesforceUserRepository.json +++ b/src/test/resources/fixtures/unit/repositories/salesforceUserRepository.json @@ -1,5 +1,5 @@ { - "testGetSalesforceUserByExternalUserId": { + "testValidGetSalesforceUserByExternalUserId": { "salesforce_users": [ { "filepath": "classpath:fixtures/common/repositories/salesforceUser/ActiveSalesforceUser.json" From b414a757091f4e3752b8a1e489742b1aec504eb9 Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Tue, 29 Aug 2023 17:04:48 +0530 Subject: [PATCH 148/195] Added Salesforce wrapper files unit test case --- .../wrappers/SalesforceGetIdentityTest.java | 87 +++++++++++++++++++ .../SalesforceGetNoteContentTest.java | 64 ++++++++++++++ ...SalesforceGetRefreshedAccessTokenTest.java | 52 +++++++++++ .../wrappers/SalesforceGetTokensTest.java | 87 +++++++++++++++++++ 4 files changed, 290 insertions(+) create mode 100644 src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetIdentityTest.java create mode 100644 src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetNoteContentTest.java create mode 100644 src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetRefreshedAccessTokenTest.java create mode 100644 src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetTokensTest.java diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetIdentityTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetIdentityTest.java new file mode 100644 index 00000000..e934b22f --- /dev/null +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetIdentityTest.java @@ -0,0 +1,87 @@ +package com.salessparrow.api.unit.lib.salesforce.wrappers; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyMap; +import static org.mockito.ArgumentMatchers.anyString; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.beans.factory.annotation.Autowired; +import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.lib.errorLib.ErrorObject; +import com.salessparrow.api.lib.httpLib.HttpClient; +import com.salessparrow.api.lib.httpLib.HttpClient.HttpResponse; +import com.salessparrow.api.lib.salesforce.wrappers.SalesforceGetIdentity; + +@SpringBootTest +@Import({SalesforceGetIdentity.class}) +public class SalesforceGetIdentityTest { + + @Autowired + private SalesforceGetIdentity salesforceGetIdentity; + + @Test + public void testGetUserIdentity_Success() throws Exception { + MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); + + String instanceUrl = "https://example.com"; + String accessToken = "dummyAccessToken"; + + Map headers = new HashMap<>(); + headers.put("Authorization", "Bearer " + accessToken); + + String responseBody = "Mock Response Body"; + HttpResponse mockResponse = new HttpResponse(); + mockResponse.setResponseBody(responseBody); + + httpClientMockedStatic.when(() -> HttpClient.makeGetRequest(anyString(), anyMap(), anyInt())) + .thenReturn(mockResponse); + + HttpResponse actualResponse = salesforceGetIdentity.getUserIdentity(instanceUrl, accessToken); + + // Assertions + assertEquals(mockResponse.getResponseBody(), actualResponse.getResponseBody()); + + httpClientMockedStatic.close(); + } + + @Test + public void testGetUserIdentity_Exception() throws Exception { + MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); + + String instanceUrl = "https://example.com"; + String accessToken = "dummyAccessToken"; + + Map headers = new HashMap<>(); + headers.put("Authorization", "Bearer " + accessToken); + + String responseBody = "Mock Response Body"; + HttpResponse mockResponse = new HttpResponse(); + mockResponse.setResponseBody(responseBody); + + httpClientMockedStatic.when(() -> HttpClient.makeGetRequest(anyString(), anyMap(), anyInt())) + .thenThrow(new RuntimeException("Some error occurred")); + + CustomException exception = assertThrows(CustomException.class, () -> { + salesforceGetIdentity.getUserIdentity(instanceUrl, accessToken); + }); + + // Assertions + assertNotNull(exception); + ErrorObject errorObject = exception.getErrorObject(); + assertNotNull(errorObject); + assertEquals("l_s_w_sgi_gui_1", errorObject.getInternalErrorIdentifier()); + assertEquals("bad_request", errorObject.getApiErrorIdentifier()); + + httpClientMockedStatic.close(); + } +} diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetNoteContentTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetNoteContentTest.java new file mode 100644 index 00000000..a4aa52f4 --- /dev/null +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetNoteContentTest.java @@ -0,0 +1,64 @@ +package com.salessparrow.api.unit.lib.salesforce.wrappers; + +import com.salessparrow.api.lib.globalConstants.SalesforceConstants; +import com.salessparrow.api.lib.httpLib.HttpClient; +import com.salessparrow.api.lib.salesforce.helper.SalesforceRequest; +import com.salessparrow.api.lib.salesforce.helper.SalesforceRequestInterface; +import com.salessparrow.api.lib.salesforce.wrappers.SalesforceGetNoteContent; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.util.ReflectionTestUtils; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +@SpringBootTest +public class SalesforceGetNoteContentTest { + + @Autowired + private SalesforceGetNoteContent salesforceGetNoteContent; + + @Mock + private SalesforceConstants salesforceConstants; + + @Mock + private SalesforceRequest salesforceRequest; + + @BeforeEach + public void setUp() { + MockitoAnnotations.openMocks(this); + ReflectionTestUtils.setField(salesforceGetNoteContent, "salesforceConstants", salesforceConstants); + ReflectionTestUtils.setField(salesforceGetNoteContent, "salesforceOauthRequest", salesforceRequest); + } + + @Test + public void testGetNoteContent() { + String noteId = "note123"; + String salesforceUserId = "user123"; + + // Mock SalesforceConstants + when(salesforceConstants.timeoutMillis()).thenReturn(5000); + + // Mock SalesforceRequest + when(salesforceRequest.makeRequest(eq(salesforceUserId), any(SalesforceRequestInterface.class))) + .thenReturn(new HttpClient.HttpResponse(200, "Note Content", null, "text/plain")); + + // Test the method + HttpClient.HttpResponse response = salesforceGetNoteContent.getNoteContent(noteId, salesforceUserId); + + // Verify that the methods were called with the expected parameters + verify(salesforceConstants).timeoutMillis(); + verify(salesforceRequest).makeRequest(eq(salesforceUserId), any(SalesforceRequestInterface.class)); + + // Verify the response + assertEquals(200, response.getStatusCode()); + assertEquals("Note Content", response.getResponseBody()); + assertEquals("text/plain", response.getContentType()); + } +} diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetRefreshedAccessTokenTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetRefreshedAccessTokenTest.java new file mode 100644 index 00000000..4752f5cb --- /dev/null +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetRefreshedAccessTokenTest.java @@ -0,0 +1,52 @@ +package com.salessparrow.api.unit.lib.salesforce.wrappers; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyMap; +import static org.mockito.ArgumentMatchers.anyString; + +import java.util.HashMap; +import java.util.Map; + +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.context.annotation.Import; + +import com.salessparrow.api.lib.httpLib.HttpClient; +import com.salessparrow.api.lib.httpLib.HttpClient.HttpResponse; +import com.salessparrow.api.lib.salesforce.wrappers.SalesforceGetRefreshedAccessToken; + +@SpringBootTest +@Import({SalesforceGetRefreshedAccessToken.class}) +public class SalesforceGetRefreshedAccessTokenTest { + + @Autowired + private SalesforceGetRefreshedAccessToken salesforceGetRefreshedAccessToken; + + @Test + public void testSalesforceGetRefreshedAccessToken() throws Exception { + MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); + + String refreshToken = "dummyRefreshToken"; + + Map headers = new HashMap<>(); + headers.put("Authorization", "Bearer " + refreshToken); + + String responseBody = "Mock Response Body"; + HttpResponse mockResponse = new HttpResponse(); + mockResponse.setResponseBody(responseBody); + + httpClientMockedStatic.when(() -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt())) + .thenReturn(mockResponse); + + HttpResponse actualResponse = salesforceGetRefreshedAccessToken.getRefreshedAccessToken(refreshToken); + + // Assertions + assertEquals(mockResponse.getResponseBody(), actualResponse.getResponseBody()); + + httpClientMockedStatic.close(); + } +} diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetTokensTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetTokensTest.java new file mode 100644 index 00000000..f162565a --- /dev/null +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetTokensTest.java @@ -0,0 +1,87 @@ +package com.salessparrow.api.unit.lib.salesforce.wrappers; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyMap; +import static org.mockito.ArgumentMatchers.anyString; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.beans.factory.annotation.Autowired; +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.httpLib.HttpClient; +import com.salessparrow.api.lib.httpLib.HttpClient.HttpResponse; +import com.salessparrow.api.lib.salesforce.wrappers.SalesforceGetTokens; + +@SpringBootTest +@Import({SalesforceGetTokens.class}) +public class SalesforceGetTokensTest { + + @Autowired + private SalesforceGetTokens salesforceGetTokens; + + @Test + public void testSalesforceGetTokens_Success() throws Exception { + MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); + + String code = "dummyCode"; + String redirectUri = "dummyRedirectUri"; + + Map headers = new HashMap<>(); + headers.put("Authorization", "Dummy Bearer Header"); + + String responseBody = "Mock Response Body"; + HttpResponse mockResponse = new HttpResponse(); + mockResponse.setResponseBody(responseBody); + + httpClientMockedStatic.when(() -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt())) + .thenReturn(mockResponse); + + HttpResponse actualResponse = salesforceGetTokens.getTokens(code, redirectUri); + + // Assertions + assertEquals(mockResponse.getResponseBody(), actualResponse.getResponseBody()); + + httpClientMockedStatic.close(); + } + + @Test + public void testSalesforceGetTokens_Exception() throws Exception { + MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); + + String code = "dummyCode"; + String redirectUri = "dummyRedirectUri"; + + Map headers = new HashMap<>(); + headers.put("Authorization", "Dummy Bearer Header"); + + String responseBody = "Mock Response Body"; + HttpResponse mockResponse = new HttpResponse(); + mockResponse.setResponseBody(responseBody); + + httpClientMockedStatic.when(() -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt())) + .thenThrow(new RuntimeException("Some error occurred")); + + CustomException exception = assertThrows(CustomException.class, () -> { + salesforceGetTokens.getTokens(code, redirectUri); + }); + + // Assertions + assertNotNull(exception); + ParamErrorObject paramErrorObject = exception.getParamErrorObject(); + assertNotNull(paramErrorObject); + assertEquals("l_s_w_sgt_gt_1", paramErrorObject.getInternalErrorIdentifier()); + + httpClientMockedStatic.close(); + } +} From 03d36d4f00ea44d44a58e475316aedca448ec3b6 Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Tue, 29 Aug 2023 19:28:37 +0530 Subject: [PATCH 149/195] Added unit test cases for helper files --- .../helper/MakeCompositeRequestTest.java | 60 +++++++++ .../helper/SalesforceOAuthTokenTest.java | 84 ++++++++++++ .../helper/SalesforceRequestTest.java | 124 ++++++++++++++++++ 3 files changed, 268 insertions(+) create mode 100644 src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/MakeCompositeRequestTest.java create mode 100644 src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceOAuthTokenTest.java create mode 100644 src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceRequestTest.java diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/MakeCompositeRequestTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/MakeCompositeRequestTest.java new file mode 100644 index 00000000..03ba8114 --- /dev/null +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/MakeCompositeRequestTest.java @@ -0,0 +1,60 @@ +package com.salessparrow.api.unit.lib.salesforce.helper; + +import com.salessparrow.api.lib.globalConstants.SalesforceConstants; +import com.salessparrow.api.lib.httpLib.HttpClient; +import com.salessparrow.api.lib.salesforce.dto.CompositeRequestDto; +import com.salessparrow.api.lib.salesforce.helper.MakeCompositeRequest; +import com.salessparrow.api.lib.salesforce.helper.SalesforceRequest; +import com.salessparrow.api.lib.salesforce.helper.SalesforceRequestInterface; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.*; + +@SpringBootTest +public class MakeCompositeRequestTest { + + @Mock + private SalesforceRequest salesforceRequest; + + @Mock + private SalesforceConstants salesforceConstants; + + @InjectMocks + private MakeCompositeRequest makeCompositeRequest; + + @BeforeEach + public void setUp() { + MockitoAnnotations.openMocks(this); + } + + @Test + public void testMakePostRequest() { + + List compositeRequests = new ArrayList<>(); + CompositeRequestDto requestDto = new CompositeRequestDto("endpoint", "method", null); + compositeRequests.add(requestDto); + + when(salesforceConstants.timeoutMillis()).thenReturn(5000); + + when(salesforceConstants.salesforceCompositeUrl(anyString())).thenReturn("composite_url"); + + when(salesforceRequest.makeRequest(anyString(), any(SalesforceRequestInterface.class))) + .thenReturn(new HttpClient.HttpResponse(200, "response", null, "application/json")); + + HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, "user_id"); + + assertEquals(200, response.getStatusCode()); + assertEquals("response", response.getResponseBody()); + } +} + diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceOAuthTokenTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceOAuthTokenTest.java new file mode 100644 index 00000000..49430fff --- /dev/null +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceOAuthTokenTest.java @@ -0,0 +1,84 @@ +package com.salessparrow.api.unit.lib.salesforce.helper; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.salessparrow.api.domain.SalesforceOauthToken; +import com.salessparrow.api.lib.AwsKms; +import com.salessparrow.api.lib.Util; +import com.salessparrow.api.lib.httpLib.HttpClient; +import com.salessparrow.api.lib.salesforce.helper.SalesforceOAuthToken; +import com.salessparrow.api.lib.salesforce.wrappers.SalesforceGetRefreshedAccessToken; +import com.salessparrow.api.repositories.SalesforceOauthTokenRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +public class SalesforceOAuthTokenTest { + + @Mock + private AwsKms awsKms; + + @Mock + private SalesforceOauthTokenRepository salesforceOauthTokenRepository; + + @Mock + private SalesforceGetRefreshedAccessToken salesforceGetRefreshedAccessToken; + + @Mock + private Util util; + + @InjectMocks + private SalesforceOAuthToken salesforceOauthToken; + + @BeforeEach + public void setUp() { + MockitoAnnotations.openMocks(this); + } + + @Test + public void testFetchAccessToken() { + + SalesforceOauthToken sfOAuthToken = new SalesforceOauthToken(); + sfOAuthToken.setAccessToken("encrypted_access_token"); + + when(awsKms.decryptToken("encrypted_access_token")).thenReturn("decrypted_access_token"); + + String decryptedAccessToken = salesforceOauthToken.fetchAccessToken(sfOAuthToken); + + assertEquals("decrypted_access_token", decryptedAccessToken); + } + + @Test + public void testUpdateAndGetRefreshedAccessToken() throws Exception { + + SalesforceOauthToken sfOAuthToken = new SalesforceOauthToken(); + sfOAuthToken.setRefreshToken("encrypted_refresh_token"); + + String responseBody = "{\"access_token\":\"new_access_token\"}"; + ObjectMapper map = new ObjectMapper(); + JsonNode responseBodyNode = map.readTree(responseBody); + + when(awsKms.decryptToken("encrypted_refresh_token")).thenReturn("decrypted_refresh_token"); + + HttpClient.HttpResponse response = new HttpClient.HttpResponse(200, responseBody, null, "application/json"); + when(salesforceGetRefreshedAccessToken.getRefreshedAccessToken("decrypted_refresh_token")).thenReturn(response); + + when(util.getJsonNode(responseBody)).thenReturn(responseBodyNode); + + when(awsKms.encryptToken("new_access_token")).thenReturn("encrypted_access_token"); + + when(salesforceOauthTokenRepository.saveSalesforceOauthToken(any(SalesforceOauthToken.class))) + .thenAnswer(invocation -> invocation.getArgument(0)); // Return the argument back + + String decryptedAccessToken = salesforceOauthToken.updateAndGetRefreshedAccessToken(sfOAuthToken); + + assertEquals("new_access_token", decryptedAccessToken); + } +} + diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceRequestTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceRequestTest.java new file mode 100644 index 00000000..9faa9917 --- /dev/null +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceRequestTest.java @@ -0,0 +1,124 @@ +package com.salessparrow.api.unit.lib.salesforce.helper; + +import com.salessparrow.api.domain.SalesforceOauthToken; +import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.lib.salesforce.helper.SalesforceOAuthToken; +import com.salessparrow.api.lib.salesforce.helper.SalesforceRequest; +import com.salessparrow.api.lib.salesforce.helper.SalesforceRequestInterface; +import com.salessparrow.api.repositories.SalesforceOauthTokenRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.web.reactive.function.client.WebClientResponseException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +@SpringBootTest +public class SalesforceRequestTest { + + @Mock + private SalesforceOAuthToken salesforceOAuthToken; + + @Mock + private SalesforceOauthTokenRepository sfOauthTokenRepository; + + @InjectMocks + private SalesforceRequest salesforceRequest; + + @BeforeEach + public void setUp() { + MockitoAnnotations.openMocks(this); + } + + @Test + public void testMakeRequest_Success() { + + SalesforceOauthToken sfOAuthToken = new SalesforceOauthToken(); + sfOAuthToken.setAccessToken("access_token"); + sfOAuthToken.setInstanceUrl("https://instance.url"); + + when(sfOauthTokenRepository.getSalesforceOauthTokenByExternalUserId("user123")) + .thenReturn(sfOAuthToken); + + // Mock SalesforceOAuthToken + when(salesforceOAuthToken.fetchAccessToken(any(SalesforceOauthToken.class))) + .thenReturn("access_token"); + + // Mock SalesforceRequestInterface + SalesforceRequestInterface requestInterface = (token, instanceUrl) -> "Response"; + + // Test the method + String response = salesforceRequest.makeRequest("user123", requestInterface); + + // Verify that the methods were called with the expected parameters + verify(sfOauthTokenRepository).getSalesforceOauthTokenByExternalUserId("user123"); + verify(salesforceOAuthToken).fetchAccessToken(sfOAuthToken); + + // Verify the response + assertEquals("Response", response); + } + + @Test + public void testMakeRequest_WebClientResponseException() { + + SalesforceOauthToken sfOAuthToken = new SalesforceOauthToken(); + sfOAuthToken.setAccessToken("access_token"); + sfOAuthToken.setInstanceUrl("https://instance.url"); + + when(sfOauthTokenRepository.getSalesforceOauthTokenByExternalUserId("user123")) + .thenReturn(sfOAuthToken); + + // Mock SalesforceOAuthToken + when(salesforceOAuthToken.fetchAccessToken(any(SalesforceOauthToken.class))) + .thenReturn("access_token"); + + // Mock SalesforceRequestInterface + SalesforceRequestInterface requestInterface = (token, instanceUrl) -> { + throw new WebClientResponseException(401, "Unauthorized", null, null, null); + }; + + // Test the method and expect a CustomException + assertThrows(CustomException.class, () -> salesforceRequest.makeRequest("user123", requestInterface)); + + // Verify that the methods were called with the expected parameters + verify(sfOauthTokenRepository).getSalesforceOauthTokenByExternalUserId("user123"); + verify(salesforceOAuthToken).fetchAccessToken(sfOAuthToken); + verify(salesforceOAuthToken, times(1)).updateAndGetRefreshedAccessToken(sfOAuthToken); + } + + @Test + public void testMakeRequest_InternalServerErrorException() { + + SalesforceOauthToken sfOAuthToken = new SalesforceOauthToken(); + sfOAuthToken.setAccessToken("access_token"); + sfOAuthToken.setInstanceUrl("https://instance.url"); + + when(sfOauthTokenRepository.getSalesforceOauthTokenByExternalUserId("user123")) + .thenReturn(sfOAuthToken); + + // Mock SalesforceOAuthToken + when(salesforceOAuthToken.fetchAccessToken(any(SalesforceOauthToken.class))) + .thenReturn("access_token"); + + // Mock SalesforceRequestInterface + SalesforceRequestInterface requestInterface = (token, instanceUrl) -> { + throw new WebClientResponseException(500, "Internal Server Error", null, null, null); + }; + + // Test the method and expect a CustomException + assertThrows(CustomException.class, () -> salesforceRequest.makeRequest("user123", requestInterface)); + + // Verify that the methods were called with the expected parameters + verify(sfOauthTokenRepository).getSalesforceOauthTokenByExternalUserId("user123"); + verify(salesforceOAuthToken).fetchAccessToken(sfOAuthToken); + + // Verify that the updateAndGetRefreshedAccessToken method was not called + verify(salesforceOAuthToken, never()).updateAndGetRefreshedAccessToken(sfOAuthToken); + } +} From 9a2c5b921c6007240f393c3cae89edaadfe3d551 Mon Sep 17 00:00:00 2001 From: VRDighe Date: Tue, 29 Aug 2023 20:24:02 +0530 Subject: [PATCH 150/195] 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 f178f5304edf167efc276606c05f6dc3ee049917 Mon Sep 17 00:00:00 2001 From: amanbarbaria Date: Tue, 29 Aug 2023 21:00:31 +0530 Subject: [PATCH 151/195] Fix: Handle save method to differentiate between create and update --- .../java/com/salessparrow/api/lib/Util.java | 2 +- .../helper/SalesforceOAuthToken.java | 2 +- .../SalesforceOauthTokenRepository.java | 27 +++++- .../SalesforceOrganizationRepository.java | 31 +++++- .../SalesforceUserRepository.java | 34 ++++++- .../api/services/salesforce/AuthService.java | 33 ++----- .../salessparrow/api/helper/LoadFixture.java | 13 +-- .../SalesforceOauthTokenRepositoryTest.java | 96 +++++++++++++------ .../SalesforceOrganizationRepositoryTest.java | 43 ++++++++- .../SalesforceUserRepositoryTest.java | 53 ++++++++-- ...esforceOauthTokenRepository.scenarios.json | 6 +- 11 files changed, 257 insertions(+), 83 deletions(-) diff --git a/src/main/java/com/salessparrow/api/lib/Util.java b/src/main/java/com/salessparrow/api/lib/Util.java index 9e09ed2d..d813f383 100644 --- a/src/main/java/com/salessparrow/api/lib/Util.java +++ b/src/main/java/com/salessparrow/api/lib/Util.java @@ -75,7 +75,7 @@ public static String generateHeaderLogString(HttpServletRequest request) { * * @return Date */ - public Date getCurrentTimeInDateFormat() { + public static Date getCurrentTimeInDateFormat() { Instant currentTimestamp = Instant.now(); return Date.from(currentTimestamp.atOffset(ZoneOffset.UTC).toInstant()); } diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceOAuthToken.java b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceOAuthToken.java index dba11f8e7..ba51b3b6 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceOAuthToken.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceOAuthToken.java @@ -66,7 +66,7 @@ private String updateAccessTokenInDatabase(String responseBody, SalesforceOauthT String encryptedAccessToken = awsKms.encryptToken(decryptedAccessToken); sfOAuthToken.setAccessToken(encryptedAccessToken); - salesforceOauthTokenRepository.saveSalesforceOauthToken(sfOAuthToken); + salesforceOauthTokenRepository.updateSalesforceOauthToken(sfOAuthToken); return decryptedAccessToken; } diff --git a/src/main/java/com/salessparrow/api/repositories/SalesforceOauthTokenRepository.java b/src/main/java/com/salessparrow/api/repositories/SalesforceOauthTokenRepository.java index c48bb4ee..c5090325 100644 --- a/src/main/java/com/salessparrow/api/repositories/SalesforceOauthTokenRepository.java +++ b/src/main/java/com/salessparrow/api/repositories/SalesforceOauthTokenRepository.java @@ -7,6 +7,7 @@ import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; import com.salessparrow.api.domain.SalesforceOauthToken; import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.lib.Util; import com.salessparrow.api.lib.errorLib.ErrorObject; import com.salessparrow.api.lib.globalConstants.CacheConstants; @@ -22,6 +23,30 @@ public SalesforceOauthTokenRepository(DynamoDBMapper dynamoDBMapper) { this.dynamoDBMapper = dynamoDBMapper; } + /** + * Insert a SalesforceOauthToken to the salesforce_oauth_tokens table. + * + * @param salesforceOauthToken + * + * @return SalesforceOauthToken + */ + @CacheEvict(value = CacheConstants.SS_SALESFORCE_OAUTH_TOKEN_CACHE, key = "#salesforceOauthToken.externalUserId") + public SalesforceOauthToken createSalesforceOauthToken(SalesforceOauthToken salesforceOauthToken) { + // Create a row with status active and created at as current time + salesforceOauthToken.setStatus(SalesforceOauthToken.Status.ACTIVE); + salesforceOauthToken.setCreatedAt(Util.getCurrentTimeInDateFormat()); + + try { + dynamoDBMapper.save(salesforceOauthToken); + } catch (Exception e) { + throw new CustomException(new ErrorObject( + "r_sotr_csot_1", + "something_went_wrong", + e.getMessage())); + } + return salesforceOauthToken; + } + /** * Saves a SalesforceOauthToken to the salesforce_oauth_tokens table. * @@ -30,7 +55,7 @@ public SalesforceOauthTokenRepository(DynamoDBMapper dynamoDBMapper) { * @return SalesforceOauthToken */ @CacheEvict(value = CacheConstants.SS_SALESFORCE_OAUTH_TOKEN_CACHE, key = "#salesforceOauthToken.externalUserId") - public SalesforceOauthToken saveSalesforceOauthToken(SalesforceOauthToken salesforceOauthToken) { + public SalesforceOauthToken updateSalesforceOauthToken(SalesforceOauthToken salesforceOauthToken) { try { dynamoDBMapper.save(salesforceOauthToken); } catch (Exception e) { diff --git a/src/main/java/com/salessparrow/api/repositories/SalesforceOrganizationRepository.java b/src/main/java/com/salessparrow/api/repositories/SalesforceOrganizationRepository.java index 24bb0561..3d861c39 100644 --- a/src/main/java/com/salessparrow/api/repositories/SalesforceOrganizationRepository.java +++ b/src/main/java/com/salessparrow/api/repositories/SalesforceOrganizationRepository.java @@ -3,8 +3,8 @@ import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; import com.salessparrow.api.domain.SalesforceOrganization; import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.lib.Util; import com.salessparrow.api.lib.errorLib.ErrorObject; - import org.springframework.stereotype.Repository; /** @@ -18,15 +18,38 @@ public class SalesforceOrganizationRepository { public SalesforceOrganizationRepository(DynamoDBMapper dynamoDBMapper) { this.dynamoDBMapper = dynamoDBMapper; } - + + /** + * Insert a SalesforceOrganization to the salesforce_organizations table. + * + * @param sfo + * + * @return SalesforceOrganization + */ + public SalesforceOrganization createSalesforceOrganization(SalesforceOrganization sfo) { + // Create a row with status active and created at as current time + sfo.setStatus(SalesforceOrganization.Status.ACTIVE); + sfo.setCreatedAt(Util.getCurrentTimeInDateFormat()); + + try { + dynamoDBMapper.save(sfo); + } catch (Exception e) { + throw new CustomException(new ErrorObject( + "r_sor_cso_1", + "something_went_wrong", + e.getMessage())); + } + return sfo; + } + /** - * Saves a SalesforceOrganization to the salesforce_organizations table. + * Update a SalesforceOrganization to the salesforce_organizations table. * * @param sfo * * @return SalesforceOrganization */ - public SalesforceOrganization saveSalesforceOrganization(SalesforceOrganization sfo) { + public SalesforceOrganization updateSalesforceOrganization(SalesforceOrganization sfo) { try { dynamoDBMapper.save(sfo); } catch (Exception e) { diff --git a/src/main/java/com/salessparrow/api/repositories/SalesforceUserRepository.java b/src/main/java/com/salessparrow/api/repositories/SalesforceUserRepository.java index e271cd73..bfdd2379 100644 --- a/src/main/java/com/salessparrow/api/repositories/SalesforceUserRepository.java +++ b/src/main/java/com/salessparrow/api/repositories/SalesforceUserRepository.java @@ -1,5 +1,4 @@ package com.salessparrow.api.repositories; - import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Repository; @@ -7,6 +6,7 @@ import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; import com.salessparrow.api.domain.SalesforceUser; import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.lib.Util; import com.salessparrow.api.lib.errorLib.ErrorObject; import com.salessparrow.api.lib.globalConstants.CacheConstants; @@ -21,21 +21,47 @@ public class SalesforceUserRepository { public SalesforceUserRepository(DynamoDBMapper dynamoDBMapper) { this.dynamoDBMapper = dynamoDBMapper; } + + /** + * Insert a SalesforceUser to the salesforce_users table. + * + * @param salesforceUser + * + * @return SalesforceUser + */ + @CacheEvict(value = CacheConstants.SS_SALESFORCE_USER_CACHE, key = "#salesforceUser.externalUserId") + public SalesforceUser createSalesforceUser(SalesforceUser salesforceUser) { + // Create a row with status active and created at as current time + salesforceUser.setStatus(SalesforceUser.Status.ACTIVE); + salesforceUser.setCreatedAt(Util.getCurrentTimeInDateFormat()); + + try { + dynamoDBMapper.save(salesforceUser); + } catch (Exception e) { + throw new CustomException( + new ErrorObject( + "r_sur_csu_1", + "something_went_wrong", + e.getMessage())); + } + return salesforceUser; + } + /** - * Saves a SalesforceUser to the salesforce_users table. + * Updates a SalesforceUser to the salesforce_users table. * * @param salesforceUser * * @return SalesforceUser */ @CacheEvict(value = CacheConstants.SS_SALESFORCE_USER_CACHE, key = "#salesforceUser.externalUserId") - public SalesforceUser saveSalesforceUser(SalesforceUser salesforceUser) { + public SalesforceUser updateSalesforceUser(SalesforceUser salesforceUser) { try { dynamoDBMapper.save(salesforceUser); } catch (Exception e) { throw new CustomException( new ErrorObject( - "r_sur_ssu_1", + "r_sur_usu_1", "something_went_wrong", e.getMessage())); } 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 76750747..38f0c44f 100644 --- a/src/main/java/com/salessparrow/api/services/salesforce/AuthService.java +++ b/src/main/java/com/salessparrow/api/services/salesforce/AuthService.java @@ -157,10 +157,8 @@ private void validateAndSaveSalesforceOrganization() { logger.info("Creating Salesforce Organization in DB"); SalesforceOrganization salesforceOrganization = new SalesforceOrganization(); salesforceOrganization.setExternalOrganizationId(salesforceOrganizationId); - salesforceOrganization.setStatus(SalesforceOrganization.Status.ACTIVE); - salesforceOrganization.setCreatedAt(util.getCurrentTimeInDateFormat()); salesforceOrganizationRepository - .saveSalesforceOrganization(salesforceOrganization); + .createSalesforceOrganization(salesforceOrganization); } /** @@ -174,7 +172,6 @@ private void upsertSalesforceOAuthTokens() { long currentTime = System.currentTimeMillis(); String encryptedAccessToken = awsKms.encryptToken(this.tokensData.getAccessToken()); - logger.info("Time in ms for encryption : " + (System.currentTimeMillis() - currentTime)); String encryptedRefreshToken = awsKms.encryptToken(this.tokensData.getRefreshToken()); @@ -183,37 +180,27 @@ private void upsertSalesforceOAuthTokens() { SalesforceOauthToken existingSalesforceOauthToken = salesforceOauthTokenRepository .getSalesforceOauthTokenByExternalUserId(salesforceUserId); - if (existingSalesforceOauthToken != null) { - logger.info("Salesforce OAuth Token already exists"); - SalesforceOauthToken salesforceOauthToken = new SalesforceOauthToken(); salesforceOauthToken.setExternalUserId(salesforceUserId); + salesforceOauthToken.setIdentityUrl(this.tokensData.getId()); salesforceOauthToken.setAccessToken(encryptedAccessToken); salesforceOauthToken.setRefreshToken(encryptedRefreshToken); salesforceOauthToken.setSignature(this.tokensData.getSignature()); salesforceOauthToken.setIdToken(this.tokensData.getIdToken()); + salesforceOauthToken.setInstanceUrl(this.tokensData.getInstanceUrl()); salesforceOauthToken.setIssuedAt(Long.parseLong(this.tokensData.getIssuedAt())); + if (existingSalesforceOauthToken != null) { + logger.info("Salesforce OAuth Token already exists"); this.salesforceOauthToken = salesforceOauthTokenRepository - .saveSalesforceOauthToken(salesforceOauthToken); + .updateSalesforceOauthToken(salesforceOauthToken); } else { logger.info("Salesforce OAuth Token does not exists. Creating new one."); - SalesforceOauthToken salesforceOauthToken = new SalesforceOauthToken(); - salesforceOauthToken.setExternalUserId(salesforceUserId); - salesforceOauthToken.setIdentityUrl(this.tokensData.getId()); - salesforceOauthToken.setAccessToken(encryptedAccessToken); - salesforceOauthToken.setRefreshToken(encryptedRefreshToken); - salesforceOauthToken.setSignature(this.tokensData.getSignature()); - salesforceOauthToken.setIdToken(this.tokensData.getIdToken()); - salesforceOauthToken.setInstanceUrl(this.tokensData.getInstanceUrl()); - salesforceOauthToken.setStatus(SalesforceOauthToken.Status.ACTIVE); - salesforceOauthToken.setIssuedAt(Long.parseLong(this.tokensData.getIssuedAt())); - salesforceOauthToken.setCreatedAt(util.getCurrentTimeInDateFormat()); - this.salesforceOauthToken = salesforceOauthTokenRepository - .saveSalesforceOauthToken(salesforceOauthToken); + .createSalesforceOauthToken(salesforceOauthToken); } + } /** @@ -276,10 +263,8 @@ private void createSalesforceUser() { salesforceUser.setUserKind(UserConstants.SALESFORCE_USER_KIND); salesforceUser.setCookieToken(encryptedCookieToken); salesforceUser.setEncryptionSalt(encryptedSalt); - salesforceUser.setStatus(SalesforceUser.Status.ACTIVE); - salesforceUser.setCreatedAt(util.getCurrentTimeInDateFormat()); - this.salesforceUser = salesforceUserRepository.saveSalesforceUser(salesforceUser); + this.salesforceUser = salesforceUserRepository.createSalesforceUser(salesforceUser); this.decryptedSalt = decryptedSalt; } diff --git a/src/test/java/com/salessparrow/api/helper/LoadFixture.java b/src/test/java/com/salessparrow/api/helper/LoadFixture.java index 29b358d5..334f87d0 100644 --- a/src/test/java/com/salessparrow/api/helper/LoadFixture.java +++ b/src/test/java/com/salessparrow/api/helper/LoadFixture.java @@ -7,6 +7,7 @@ import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; +import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.salessparrow.api.domain.SalesforceOauthToken; @@ -24,6 +25,9 @@ public class LoadFixture { @Autowired private ResourceLoader resourceLoader; + @Autowired + private DynamoDBMapper dynamoDBMapper; + @Autowired private SalesforceUserRepository salesforceUserRepository; @@ -50,24 +54,21 @@ public void perform(FixtureData fixtureData) throws IOException { if (fixtureData.getSalesforce_users() != null) { for (FilePathData filePathData : fixtureData.getSalesforce_users()) { SalesforceUser salesforceUser = loadSalesForceUserFixture(filePathData.getFilepath()); - salesforceUser.setCreatedAt(util.getCurrentTimeInDateFormat()); - salesforceUserRepository.saveSalesforceUser(salesforceUser); + dynamoDBMapper.save(salesforceUser); } } if (fixtureData.getSalesforce_oauth_tokens() != null) { for (FilePathData filePathData : fixtureData.getSalesforce_oauth_tokens()) { SalesforceOauthToken salesforceOauth = loadSalesForceOAuthTokenFixture(filePathData.getFilepath()); - salesforceOauth.setCreatedAt(util.getCurrentTimeInDateFormat()); - salesforceOauthTokenRepository.saveSalesforceOauthToken(salesforceOauth); + dynamoDBMapper.save(salesforceOauth); } } if (fixtureData.getSalesforce_organizations() != null) { for (FilePathData filePathData : fixtureData.getSalesforce_organizations()) { SalesforceOrganization salesforceOrganization = loadSalesForceOrganizationFixture(filePathData.getFilepath()); - salesforceOrganization.setCreatedAt(util.getCurrentTimeInDateFormat()); - salesforceOrganizationRepository.saveSalesforceOrganization(salesforceOrganization); + dynamoDBMapper.save(salesforceOrganization); } } diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java index 7d4f2ee4..4a94b939 100644 --- a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java @@ -86,25 +86,61 @@ public void tearDown() { cleanup.perform(); } + /** + * Test valid case for createSalesforceOauthToken method + */ + @Test + public void testValidCreateSalesforceOauthToken() { + //Valid Create Db Query + SalesforceOauthToken salesforceOauthTokenValid = new SalesforceOauthToken(); + salesforceOauthTokenValid.setExternalUserId("externalUserId-1"); + + SalesforceOauthToken salesforceOauthTokenResp = this.realSalesforceOauthTokenRepository.createSalesforceOauthToken(salesforceOauthTokenValid); + assertEquals(salesforceOauthTokenValid.getExternalUserId(), salesforceOauthTokenResp.getExternalUserId()); + } + + /** + * Test invlaid case for createSalesforceOauthToken method + */ + @Test + public void testInvalidCreateSalesforceOauthToken() { + // Invalid Create Db Query without partition key + SalesforceOauthToken salesforceOauthTokenInvalid = new SalesforceOauthToken(); + salesforceOauthTokenInvalid.setExternalUserId("externalUserId-2"); + + // Mock the behavior to throw an exception when save is called + doThrow(new AmazonDynamoDBException("mock db save error")) + .when(mockDynamoDBMapper) + .save(salesforceOauthTokenInvalid); + + // Test if CustomException is thrown with the expected error code + CustomException thrownException = assertThrows( + CustomException.class, + () -> mockSalesforceOauthTokenRepository.createSalesforceOauthToken(salesforceOauthTokenInvalid) + ); + // Validate the error identifier to be a 500 error + assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); + } + /** - * Test valid case for saveSalesforceOauthToken method + * Test valid case for updateSalesforceOauthToken method */ @Test - public void testValidSaveSalesforceOauthToken() { - //Valid Save Db Query + public void testValidUpdateSalesforceOauthToken() { + //Valid Update Db Query SalesforceOauthToken salesforceOauthTokenValid = new SalesforceOauthToken(); salesforceOauthTokenValid.setExternalUserId("externalUserId-1"); - SalesforceOauthToken salesforceOauthTokenResp = this.realSalesforceOauthTokenRepository.saveSalesforceOauthToken(salesforceOauthTokenValid); + SalesforceOauthToken salesforceOauthTokenResp = this.realSalesforceOauthTokenRepository.updateSalesforceOauthToken(salesforceOauthTokenValid); assertEquals(salesforceOauthTokenValid.getExternalUserId(), salesforceOauthTokenResp.getExternalUserId()); } /** - * Test invlaid case for saveSalesforceOauthToken method + * Test invlaid case for updateSalesforceOauthToken method */ @Test - public void testInvalidSaveSalesforceOauthToken() { - // Invalid Save Db Query without partition key + public void testInvalidUpdateSalesforceOauthToken() { + // Invalid Update Db Query without partition key SalesforceOauthToken salesforceOauthTokenInvalid = new SalesforceOauthToken(); salesforceOauthTokenInvalid.setExternalUserId("externalUserId-2"); @@ -116,7 +152,7 @@ public void testInvalidSaveSalesforceOauthToken() { // Test if CustomException is thrown with the expected error code CustomException thrownException = assertThrows( CustomException.class, - () -> mockSalesforceOauthTokenRepository.saveSalesforceOauthToken(salesforceOauthTokenInvalid) + () -> mockSalesforceOauthTokenRepository.updateSalesforceOauthToken(salesforceOauthTokenInvalid) ); // Validate the error identifier to be a 500 error assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); @@ -159,6 +195,11 @@ public void testInvalidGetSalesforceOauthTokenByExternalUserId() throws Exceptio assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); } + /** + * Test valid case for insert method and verify the inserted data + * + * @throws Exception + */ @Test public void testInsert() throws Exception { String currentFunctionName = new Object() {}.getClass() @@ -174,10 +215,10 @@ public void testInsert() throws Exception { objectMapper.writeValueAsString(testDataItem.getInput()), new TypeReference() { }); - salesforceOauthToken.setCreatedAt(util.getCurrentTimeInDateFormat()); + salesforceOauthToken.setCreatedAt(Util.getCurrentTimeInDateFormat()); SalesforceOauthToken insertedSalesforceOauthToken = this.realSalesforceOauthTokenRepository - .saveSalesforceOauthToken(salesforceOauthToken); + .updateSalesforceOauthToken(salesforceOauthToken); assertNotNull(insertedSalesforceOauthToken); assertNotNull(insertedSalesforceOauthToken.getExternalUserId()); @@ -186,6 +227,10 @@ public void testInsert() throws Exception { } } + /** + * Test valid case for update method and verify the updated data + * @throws Exception + */ @Test public void testUpdate() throws Exception { String currentFunctionName = new Object() {}.getClass() @@ -199,27 +244,23 @@ public void testUpdate() throws Exception { List testDataItems = loadTestData(currentFunctionName); for (Scenario testDataItem : testDataItems) { - System.out.println("Test description: " + testDataItem.getDescription()); ObjectMapper objectMapper = new ObjectMapper(); SalesforceOauthToken salesforceOauthToken = objectMapper.readValue( objectMapper.writeValueAsString(testDataItem.getInput()), new TypeReference() { }); - + SalesforceOauthToken existingSalesforceOauthToken = this.realSalesforceOauthTokenRepository .getSalesforceOauthTokenByExternalUserId(salesforceOauthToken.getExternalUserId()); - System.out.println("existingSalesforceOauthToken: " + existingSalesforceOauthToken); this.realSalesforceOauthTokenRepository - .saveSalesforceOauthToken(salesforceOauthToken); + .updateSalesforceOauthToken(salesforceOauthToken); SalesforceOauthToken updatedSalesforceOauthToken = this.realSalesforceOauthTokenRepository .getSalesforceOauthTokenByExternalUserId(salesforceOauthToken.getExternalUserId()); - System.out.println("updatedSalesforceOauthToken: " + updatedSalesforceOauthToken); - assertNotNull(updatedSalesforceOauthToken); assertNotNull(updatedSalesforceOauthToken.getUpdatedAt()); assertEquals(updatedSalesforceOauthToken.getCreatedAt(), existingSalesforceOauthToken.getCreatedAt()); @@ -229,24 +270,23 @@ public void testUpdate() throws Exception { } } + /** + * Test valid case for update with null attributes + * + * @throws Exception + */ @Test public void testUpdateWithNullAttributes() throws Exception { String currentFunctionName = new Object() { }.getClass().getEnclosingMethod().getName(); FixtureData fixtureData = common.loadFixture( - "classpath:fixtures/repositories/salesforceOauthTokenRepository.fixture.json", + "classpath:fixtures/unit/repositories/salesforceOauthTokenRepository.fixture.json", currentFunctionName); loadFixture.perform(fixtureData); - System.out.println("Test description: " + "Update with null attributes"); - List testDataItems = loadTestData(currentFunctionName); - - System.out.println("Test description: " + "After Update with null attributes"); - for (Scenario testDataItem : testDataItems) { - System.out.println("Test description: " + testDataItem.getDescription()); ObjectMapper objectMapper = new ObjectMapper(); SalesforceOauthToken salesforceOauthToken = objectMapper.readValue( @@ -257,20 +297,22 @@ public void testUpdateWithNullAttributes() throws Exception { SalesforceOauthToken existingSalesforceOauthToken = this.realSalesforceOauthTokenRepository .getSalesforceOauthTokenByExternalUserId(salesforceOauthToken.getExternalUserId()); - System.out.println("existingSalesforceOauthToken: " + existingSalesforceOauthToken); - this.realSalesforceOauthTokenRepository - .saveSalesforceOauthToken(salesforceOauthToken); + .updateSalesforceOauthToken(salesforceOauthToken); SalesforceOauthToken updatedSalesforceOauthToken = this.realSalesforceOauthTokenRepository .getSalesforceOauthTokenByExternalUserId(salesforceOauthToken.getExternalUserId()); - System.out.println("updatedSalesforceOauthToken: " + updatedSalesforceOauthToken); assertEquals(updatedSalesforceOauthToken.getAccessToken(), salesforceOauthToken.getAccessToken()); assertEquals(updatedSalesforceOauthToken.getIdToken(), existingSalesforceOauthToken.getIdToken()); } } + /** + * Load test data scenarios from json file + * + * @throws Exception + */ public List loadTestData(String key) throws IOException { String scenariosPath = "classpath:data/unit/repositories/salesforceOauthTokenRepository.scenarios.json"; Resource resource = resourceLoader.getResource(scenariosPath); diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java index 0767323b..cda9404c 100644 --- a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java @@ -62,16 +62,51 @@ public void setUp() throws DynamobeeException, IOException { public void tearDown() { cleanup.perform(); } + + /** + * Test Valid Save Db Query + */ + @Test + public void testValidCreateSalesforceOrganization() { + //Valid Create Db Query + SalesforceOrganization salesforceOrganizationValid = new SalesforceOrganization(); + salesforceOrganizationValid.setExternalOrganizationId("externalUserId-1"); + SalesforceOrganization salesforceOrganizationResp = this.realSalesforceOrganizationRepository.createSalesforceOrganization(salesforceOrganizationValid); + assertEquals(salesforceOrganizationValid.getExternalOrganizationId(), salesforceOrganizationResp.getExternalOrganizationId()); + } + + /** + * Test Invalid Create Db Query + */ + @Test + public void testInvalidCreateSalesforceOrganization() { + // Invalid Create Db Query without partition key + SalesforceOrganization salesforceOrganizationInvalid = new SalesforceOrganization(); + salesforceOrganizationInvalid.setExternalOrganizationId("externalUserId-2"); + + // Mock the behavior to throw an exception when save is called + doThrow(new AmazonDynamoDBException("mock db save error")) + .when(mockDynamoDBMapper) + .save(salesforceOrganizationInvalid); + + // Test if CustomException is thrown with the expected error code + CustomException thrownException = assertThrows( + CustomException.class, + () -> mockSalesforceOrganizationRepository.createSalesforceOrganization(salesforceOrganizationInvalid) + ); + // Validate the error identifier to be a 500 error + assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); + } /** * Test Valid Save Db Query */ @Test - public void testValidSaveSalesforceOrganization() { + public void testValidUpdateSalesforceOrganization() { //Valid Save Db Query SalesforceOrganization salesforceOrganizationValid = new SalesforceOrganization(); salesforceOrganizationValid.setExternalOrganizationId("externalUserId-1"); - SalesforceOrganization salesforceOrganizationResp = this.realSalesforceOrganizationRepository.saveSalesforceOrganization(salesforceOrganizationValid); + SalesforceOrganization salesforceOrganizationResp = this.realSalesforceOrganizationRepository.updateSalesforceOrganization(salesforceOrganizationValid); assertEquals(salesforceOrganizationValid.getExternalOrganizationId(), salesforceOrganizationResp.getExternalOrganizationId()); } @@ -79,7 +114,7 @@ public void testValidSaveSalesforceOrganization() { * Test Invalid Save Db Query */ @Test - public void testInvalidSaveSalesforceOrganization() { + public void testInvalidUpdateSalesforceOrganization() { // Invalid Save Db Query without partition key SalesforceOrganization salesforceOrganizationInvalid = new SalesforceOrganization(); salesforceOrganizationInvalid.setExternalOrganizationId("externalUserId-2"); @@ -92,7 +127,7 @@ public void testInvalidSaveSalesforceOrganization() { // Test if CustomException is thrown with the expected error code CustomException thrownException = assertThrows( CustomException.class, - () -> mockSalesforceOrganizationRepository.saveSalesforceOrganization(salesforceOrganizationInvalid) + () -> mockSalesforceOrganizationRepository.updateSalesforceOrganization(salesforceOrganizationInvalid) ); // Validate the error identifier to be a 500 error assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java index cb0cad51..eaa2de11 100644 --- a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java @@ -68,25 +68,25 @@ public void tearDown() { } /** - * Test Valid Save Db Query + * Test Valid Create Db Query * */ @Test - public void testValidSaveSalesforceUser() { - //Valid Save Db Query + public void testValidCreateSalesforceUser() { + //Valid Create Db Query SalesforceUser salesforceUserValid = new SalesforceUser(); salesforceUserValid.setExternalUserId("externalUserId-test1"); - SalesforceUser salesforceUserResp = this.realSalesforceUserRepository.saveSalesforceUser(salesforceUserValid); + SalesforceUser salesforceUserResp = this.realSalesforceUserRepository.createSalesforceUser(salesforceUserValid); assertEquals(salesforceUserValid.getExternalUserId(), salesforceUserResp.getExternalUserId()); } /** - * Test Invalid Save Db Query + * Test Invalid Create Db Query * */ @Test - public void testInvalidSaveSalesforceUser() { - // Invalid Save Db Query without partition key + public void testInvalidCreateSalesforceUser() { + // Invalid Create Db Query without partition key SalesforceUser salesforceUserInvalid = new SalesforceUser(); salesforceUserInvalid.setExternalUserId("externalUserId-test2"); @@ -98,7 +98,44 @@ public void testInvalidSaveSalesforceUser() { // Test if CustomException is thrown with the expected error code CustomException thrownException = assertThrows( CustomException.class, - () -> mockSalesforceUserRepository.saveSalesforceUser(salesforceUserInvalid) + () -> mockSalesforceUserRepository.createSalesforceUser(salesforceUserInvalid) + ); + // Validate the error identifier to be a 500 error + assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); + } + + /** + * Test Valid Update Db Query + * + */ + @Test + public void testValidUpdateSalesforceUser() { + //Valid Update Db Query + SalesforceUser salesforceUserValid = new SalesforceUser(); + salesforceUserValid.setExternalUserId("externalUserId-test1"); + SalesforceUser salesforceUserResp = this.realSalesforceUserRepository.updateSalesforceUser(salesforceUserValid); + assertEquals(salesforceUserValid.getExternalUserId(), salesforceUserResp.getExternalUserId()); + } + + /** + * Test Invalid Update Db Query + * + */ + @Test + public void testInvalidUpdateSalesforceUser() { + // Invalid Update Db Query without partition key + SalesforceUser salesforceUserInvalid = new SalesforceUser(); + salesforceUserInvalid.setExternalUserId("externalUserId-test2"); + + // Mock the behavior to throw an exception when save is called + doThrow(new AmazonDynamoDBException("mock db save error")) + .when(mockDynamoDBMapper) + .save(salesforceUserInvalid); + + // Test if CustomException is thrown with the expected error code + CustomException thrownException = assertThrows( + CustomException.class, + () -> mockSalesforceUserRepository.updateSalesforceUser(salesforceUserInvalid) ); // Validate the error identifier to be a 500 error assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); diff --git a/src/test/resources/data/unit/repositories/salesforceOauthTokenRepository.scenarios.json b/src/test/resources/data/unit/repositories/salesforceOauthTokenRepository.scenarios.json index b9675a1a..a755c994 100644 --- a/src/test/resources/data/unit/repositories/salesforceOauthTokenRepository.scenarios.json +++ b/src/test/resources/data/unit/repositories/salesforceOauthTokenRepository.scenarios.json @@ -10,7 +10,7 @@ "idToken": "eyJraWQiOiI", "identityUrl": "https://test.salesforce.com/id/00D1e0000000NRYEA2/0055i00000AUxQHAA1", "issuedAt": "1692265987212", - "externalUserId": "00112233445566AAA1", + "externalUserId": "0055i00000AUxQHAA1", "status": "ACTIVE" }, "output": {} @@ -20,7 +20,7 @@ { "description": "Update Existing Item", "input": { - "externalUserId": "00112233445566AAA1", + "externalUserId": "0055i00000AUxQHAA1", "accessToken": "updatedAccessToken", "refreshToken": "updatedRefreshToken" }, @@ -31,7 +31,7 @@ { "description": "Skip Null Attributes During Update", "input": { - "externalUserId": "00112233445566AAA1", + "externalUserId": "0055i00000AUxQHAA1", "accessToken": "newAccessToken", "idToken": null }, From 4094d3e62b7f84fd5dca13f15c82dc753dde2fe7 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Tue, 29 Aug 2023 21:55:51 +0530 Subject: [PATCH 152/195] added sanitization filter for request sanitization --- pom.xml | 12 ++ repo-docs/LOCAL_SETUP.md | 2 +- .../salessparrow/api/config/FilterConfig.java | 16 ++ .../api/config/InterceptorConfig.java | 11 +- .../api/filter/SanitizationFilter.java | 151 ++++++++++++++++++ .../lib/wrappers/SanitizedRequestWrapper.java | 117 ++++++++++++++ .../unit/filters/SanitizationFilterTest.java | 112 +++++++++++++ 7 files changed, 419 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/salessparrow/api/filter/SanitizationFilter.java create mode 100644 src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java create mode 100644 src/test/java/com/salessparrow/api/unit/filters/SanitizationFilterTest.java diff --git a/pom.xml b/pom.xml index 61b5ee1d..82ac4270 100644 --- a/pom.xml +++ b/pom.xml @@ -157,6 +157,18 @@ 2.20.132 + + com.googlecode.owasp-java-html-sanitizer + owasp-java-html-sanitizer + 20220608.1 + + + + org.apache.commons + commons-text + 1.10.0 + + diff --git a/repo-docs/LOCAL_SETUP.md b/repo-docs/LOCAL_SETUP.md index 3a68f435..e2c3bc59 100644 --- a/repo-docs/LOCAL_SETUP.md +++ b/repo-docs/LOCAL_SETUP.md @@ -67,7 +67,7 @@ $ touch test.secrets.json "ERROR_MAIL_FROM": "", "ERROR_MAIL_TO": "", "COOKIE_DOMAIN": "", - "OPENAI_API_KEY: "" + "OPENAI_API_KEY": "" } ``` diff --git a/src/main/java/com/salessparrow/api/config/FilterConfig.java b/src/main/java/com/salessparrow/api/config/FilterConfig.java index d7d6e7b1..5fed9df3 100644 --- a/src/main/java/com/salessparrow/api/config/FilterConfig.java +++ b/src/main/java/com/salessparrow/api/config/FilterConfig.java @@ -5,6 +5,7 @@ import org.springframework.context.annotation.Configuration; import com.salessparrow.api.filter.SameSiteCookieFilter; +import com.salessparrow.api.filter.SanitizationFilter; @Configuration public class FilterConfig { @@ -18,6 +19,21 @@ public FilterRegistrationBean sameSiteCookieFilter() { FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new SameSiteCookieFilter()); registrationBean.addUrlPatterns("/*"); // or specific URL patterns + registrationBean.setOrder(1); + return registrationBean; + } + + /** + * Register SanitizationFilter + * + * @return FilterRegistrationBean + */ + @Bean + public FilterRegistrationBean sanitizationFilter() { + FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); + registrationBean.setFilter(new SanitizationFilter()); + registrationBean.addUrlPatterns("/*"); + registrationBean.setOrder(0); return registrationBean; } } diff --git a/src/main/java/com/salessparrow/api/config/InterceptorConfig.java b/src/main/java/com/salessparrow/api/config/InterceptorConfig.java index af8f27a6..2f431b29 100644 --- a/src/main/java/com/salessparrow/api/config/InterceptorConfig.java +++ b/src/main/java/com/salessparrow/api/config/InterceptorConfig.java @@ -25,7 +25,12 @@ public class InterceptorConfig implements WebMvcConfigurer { @Autowired private final UserAuthInterceptor userAuthInterceptor; - public InterceptorConfig(UserAuthInterceptor userAuthInterceptor, JsonOnlyInterceptor jsonOnlyInterceptor, LoggerInterceptor loggerInterceptor, V1Interceptor V1Interceptor) { + public InterceptorConfig( + UserAuthInterceptor userAuthInterceptor, + JsonOnlyInterceptor jsonOnlyInterceptor, + LoggerInterceptor loggerInterceptor, + V1Interceptor V1Interceptor + ) { this.userAuthInterceptor = userAuthInterceptor; this.loggerInterceptor = loggerInterceptor; this.V1Interceptor = V1Interceptor; @@ -34,15 +39,19 @@ public InterceptorConfig(UserAuthInterceptor userAuthInterceptor, JsonOnlyInterc @Override public void addInterceptors(InterceptorRegistry registry) { + /* Add logger interceptor to all the routes */ registry.addInterceptor(loggerInterceptor) .addPathPatterns("/**"); + /* Add json only interceptor to all the routes */ registry.addInterceptor(jsonOnlyInterceptor) .addPathPatterns("/**"); + /* Add v1 interceptor only to all the routes */ registry.addInterceptor(V1Interceptor) .addPathPatterns("/api/v1/**"); + /* Add user auth interceptor to all the routes except the ones below */ registry.addInterceptor(userAuthInterceptor) .addPathPatterns("/**") .excludePathPatterns("/api/v1/auth/salesforce/**") diff --git a/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java b/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java new file mode 100644 index 00000000..8b8bf760 --- /dev/null +++ b/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java @@ -0,0 +1,151 @@ +package com.salessparrow.api.filter; + +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; + +import org.owasp.html.HtmlPolicyBuilder; +import org.owasp.html.PolicyFactory; + +import com.salessparrow.api.lib.wrappers.SanitizedRequestWrapper; + +import java.io.BufferedReader; +import java.io.IOException; +import java.util.Enumeration; + +/** + * Class to sanitize the request + */ +public class SanitizationFilter implements Filter { + private SanitizedRequestWrapper sanitizedRequest; + + private final PolicyFactory policy = new HtmlPolicyBuilder() + .allowElements( + "a", "label", "h1", "h2", "h3", "h4", "h5", "h6", + "p", "i", "b", "u", "strong", "em", "strike", "code", "hr", "br", "div", + "table", "thead", "caption", "tbody", "tr", "th", "td", "pre") + .allowUrlProtocols("https") + .allowAttributes("href").onElements("a") + .allowAttributes("target").onElements("a") + .allowAttributes("class").globally() + .allowAttributes("id").globally() + .disallowElements( + "script", "iframe", "object", "embed", "form", "input", "button", "select", + "textarea", "style", "link", "meta", "base" + ) + .toFactory(); + + @Override + public void init(FilterConfig filterConfig) { + } + + /** + * Method to sanitize the request + * + * @param servletRequest - Servlet request object + * @param servletResponse - Servlet response object + * @param chain - Filter chain - Filter chain + * + * @throws IOException - IOException + * @throws ServletException - ServletException + * + * @return void + */ + @Override + public void doFilter( + ServletRequest servletRequest, + ServletResponse servletResponse, + FilterChain chain + ) throws IOException, ServletException { + HttpServletRequest request = (HttpServletRequest) servletRequest; + sanitizeRequestBody(request); + sanitizeRequestParams(); + sanitizeRequestHeaders(); + + chain.doFilter(sanitizedRequest, servletResponse); + } + + /** + * Method to sanitize the request body + * + * @param request - Servlet request object + * + * @return void + */ + private void sanitizeRequestBody(HttpServletRequest request) { + String originalBody = getRequestBody(request); + String sanitizedBody = sanitizeHtml(originalBody); + this.sanitizedRequest = new SanitizedRequestWrapper(request, sanitizedBody); + } + + /** + * Method to sanitize the request params + * + * @return void + */ + private void sanitizeRequestParams() { + this.sanitizedRequest.getParameterMap().forEach((key, value) -> { + String sanitizedValue = sanitizeHtml(value[0]); + this.sanitizedRequest.setParameter(key, sanitizedValue); + }); + } + + /** + * Method to sanitize the request headers + * + * @return void + */ + private void sanitizeRequestHeaders() { + Enumeration headerNames = this.sanitizedRequest.getHeaderNames(); + + if (headerNames != null && headerNames.hasMoreElements()) { + this.sanitizedRequest.getHeaderNames().asIterator().forEachRemaining(headerName -> { + String sanitizedValue = sanitizeHtml(this.sanitizedRequest.getHeader(headerName)); + this.sanitizedRequest.setHeader(headerName, sanitizedValue); + }); + } + } + + /** + * Method to get the request body + * + * @param request - Servlet request object + * @return String - Request body + */ + private String getRequestBody(HttpServletRequest request) { + try { + BufferedReader reader = request.getReader(); + String line; + StringBuilder requestBody = new StringBuilder(); + while ((line = reader.readLine()) != null) { + requestBody.append(line); + } + return requestBody.toString(); + } catch (IOException e) { + e.printStackTrace(); + return ""; + } + } + + /** + * Method to sanitize the html + * + * @param input - Input string + * @return String - Sanitized string + */ + public String sanitizeHtml(String input) { + String sanitizedInput = policy.sanitize(input); + return sanitizedInput; + } + + /** + * Method to destroy the filter + */ + @Override + public void destroy() { + } +} diff --git a/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java b/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java new file mode 100644 index 00000000..34f6f7bf --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java @@ -0,0 +1,117 @@ +package com.salessparrow.api.lib.wrappers; + +import jakarta.servlet.ReadListener; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequestWrapper; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.text.StringEscapeUtils; + +/** + * Custom request wrapper to sanitize the request body + */ +public class SanitizedRequestWrapper extends HttpServletRequestWrapper { + private final String sanitizedBody; + + private Map sanitizedParams; + + private Map sanitizedHeaders; + + public SanitizedRequestWrapper(HttpServletRequest request, String sanitizedBody) { + super(request); + this.sanitizedBody = StringEscapeUtils.unescapeHtml4(sanitizedBody); + this.sanitizedParams = new HashMap<>(); + this.sanitizedHeaders = new HashMap<>(); + } + + /** + * Method to get the request body as buffered reader + */ + @Override + public BufferedReader getReader() throws IOException { + return new BufferedReader( + new InputStreamReader( + new ByteArrayInputStream(sanitizedBody.getBytes()))); + } + + /** + * Method to get the request body as input stream + */ + @Override + public ServletInputStream getInputStream() throws IOException { + final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(sanitizedBody.getBytes()); + + return new ServletInputStream() { + @Override + public int read() throws IOException { + return byteArrayInputStream.read(); + } + + @Override + public boolean isFinished() { + return byteArrayInputStream.available() == 0; + } + + @Override + public boolean isReady() { + return true; + } + + @Override + public void setReadListener(ReadListener readListener) { + throw new UnsupportedOperationException("Not implemented"); + } + }; + } + + /** + * Method to set the request parameter value by key + * + * @param key + * @param value + * + * @return void + */ + public void setParameter(String key, String value) { + this.sanitizedParams.put(key, value); + } + + /** + * Method to get the request parameter value by + * key from the sanitized params map if present + * else from the super class + * + * @param key - Request parameter key + * + * @return String - Request parameter value + */ + @Override + public String getParameter(String key) { + return this.sanitizedParams.getOrDefault(key, super.getParameter(key)); + } + + /** + * Method to get the request parameter map + * + * @param key - header key + * @param value - header value + * + * @return void + */ + public void setHeader(String key, String value) { + this.sanitizedHeaders.put(key, value); + } + + @Override + public String getHeader(String key) { + return this.sanitizedHeaders.getOrDefault(key, super.getHeader(key)); + } +} + diff --git a/src/test/java/com/salessparrow/api/unit/filters/SanitizationFilterTest.java b/src/test/java/com/salessparrow/api/unit/filters/SanitizationFilterTest.java new file mode 100644 index 00000000..cbac61c3 --- /dev/null +++ b/src/test/java/com/salessparrow/api/unit/filters/SanitizationFilterTest.java @@ -0,0 +1,112 @@ +package com.salessparrow.api.unit.filters; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import com.salessparrow.api.filter.SanitizationFilter; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringReader; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +public class SanitizationFilterTest { + + @Mock + private HttpServletRequest request; + + @Mock + private HttpServletResponse response; + + @Mock + private FilterChain chain; + + private SanitizationFilter filter; + + @BeforeEach + public void setUp() { + MockitoAnnotations.initMocks(this); + filter = new SanitizationFilter(); + filter.init(null); + } + + @Test + public void testSanitizeHtmlRemovesScriptTags() { + String input = ""; + String expected = ""; // Expecting empty string after removing script tags + + String sanitized = filter.sanitizeHtml(input); + assertEquals(expected, sanitized); + } + + @Test + public void testSanitizeHtmlAllowsSafeTags() { + String input = "

Paragraph

"; + String expected = "

Paragraph

"; // The string should remain unchanged + + String sanitized = filter.sanitizeHtml(input); + assertEquals(expected, sanitized); + } + + @Test + public void testDoFilterSanitizesScriptTags() throws Exception { + ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(ServletRequest.class); + + String input = ""; + StringReader stringReader = new StringReader(input); + BufferedReader reader = new BufferedReader(stringReader); + + when(request.getReader()).thenReturn(reader); + filter.doFilter(request, response, chain); + + verify(chain).doFilter(argumentCaptor.capture(), eq(response)); + + ServletRequest capturedRequest = argumentCaptor.getValue(); + String sanitizedBody = convertInputStreamToString(capturedRequest.getInputStream()); + + assertEquals("", sanitizedBody); + } + + @Test + public void testDoFilterAllowsSafeTags() throws Exception { + ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(ServletRequest.class); + + String input = "

Paragraph

"; + StringReader stringReader = new StringReader(input); + BufferedReader reader = new BufferedReader(stringReader); + + when(request.getReader()).thenReturn(reader); + filter.doFilter(request, response, chain); + + verify(chain).doFilter(argumentCaptor.capture(), eq(response)); + + ServletRequest capturedRequest = argumentCaptor.getValue(); + String sanitizedBody = convertInputStreamToString(capturedRequest.getInputStream()); + + assertEquals("

Paragraph

", sanitizedBody); + } + + private String convertInputStreamToString(InputStream inputStream) throws Exception { + try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream))) { + StringBuilder sb = new StringBuilder(); + String line; + while ((line = br.readLine()) != null) { + sb.append(line); + } + return sb.toString(); + } + } +} + From 9c4b7bc7955dba5a3fb199c81ffc6e751d99811b Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Tue, 29 Aug 2023 22:29:47 +0530 Subject: [PATCH 153/195] added review changes for sanitization filter --- .../api/filter/SanitizationFilter.java | 16 ++++++++++++---- .../api/unit/filters/SanitizationFilterTest.java | 2 +- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java b/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java index 8b8bf760..aa899959 100644 --- a/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java +++ b/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java @@ -15,7 +15,11 @@ import java.io.BufferedReader; import java.io.IOException; +import java.util.Collections; import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * Class to sanitize the request @@ -61,6 +65,9 @@ public void doFilter( ServletResponse servletResponse, FilterChain chain ) throws IOException, ServletException { + if (!(servletRequest instanceof HttpServletRequest)) { + throw new ServletException("Can only process HttpServletRequest"); + } HttpServletRequest request = (HttpServletRequest) servletRequest; sanitizeRequestBody(request); sanitizeRequestParams(); @@ -88,7 +95,8 @@ private void sanitizeRequestBody(HttpServletRequest request) { * @return void */ private void sanitizeRequestParams() { - this.sanitizedRequest.getParameterMap().forEach((key, value) -> { + Map parameterMapCopy = new HashMap<>(this.sanitizedRequest.getParameterMap()); + parameterMapCopy.forEach((key, value) -> { String sanitizedValue = sanitizeHtml(value[0]); this.sanitizedRequest.setParameter(key, sanitizedValue); }); @@ -103,7 +111,8 @@ private void sanitizeRequestHeaders() { Enumeration headerNames = this.sanitizedRequest.getHeaderNames(); if (headerNames != null && headerNames.hasMoreElements()) { - this.sanitizedRequest.getHeaderNames().asIterator().forEachRemaining(headerName -> { + List headerNamesCopy = Collections.list(this.sanitizedRequest.getHeaderNames()); + headerNamesCopy.forEach(headerName -> { String sanitizedValue = sanitizeHtml(this.sanitizedRequest.getHeader(headerName)); this.sanitizedRequest.setHeader(headerName, sanitizedValue); }); @@ -126,8 +135,7 @@ private String getRequestBody(HttpServletRequest request) { } return requestBody.toString(); } catch (IOException e) { - e.printStackTrace(); - return ""; + throw new RuntimeException("Error reading request body", e); } } diff --git a/src/test/java/com/salessparrow/api/unit/filters/SanitizationFilterTest.java b/src/test/java/com/salessparrow/api/unit/filters/SanitizationFilterTest.java index cbac61c3..9b141fe3 100644 --- a/src/test/java/com/salessparrow/api/unit/filters/SanitizationFilterTest.java +++ b/src/test/java/com/salessparrow/api/unit/filters/SanitizationFilterTest.java @@ -103,7 +103,7 @@ private String convertInputStreamToString(InputStream inputStream) throws Except StringBuilder sb = new StringBuilder(); String line; while ((line = br.readLine()) != null) { - sb.append(line); + sb.append(line); } return sb.toString(); } From 42e03d2e0718daa4a359612478911fab489801f2 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Tue, 29 Aug 2023 22:58:50 +0530 Subject: [PATCH 154/195] added code formatter --- pom.xml | 20 + .../com/salessparrow/api/SalesSparrowApi.java | 4 +- .../api/changelogs/DatabaseChangelog.java | 36 +- .../salessparrow/api/config/AwsConfig.java | 83 ++- .../api/config/CoreConstants.java | 218 ++++---- .../salessparrow/api/config/CorsConfig.java | 22 +- .../api/config/DynamoBeeConfig.java | 23 +- .../api/config/DynamoDBConfiguration.java | 39 +- .../salessparrow/api/config/FilterConfig.java | 25 +- .../api/config/InterceptorConfig.java | 71 ++- .../api/config/MemcachedConfig.java | 163 +++--- .../api/config/SecurityConfig.java | 126 ++--- .../api/controllers/AccountController.java | 22 +- .../controllers/AccountNoteController.java | 118 ++-- .../controllers/AccountTaskController.java | 90 ++-- .../api/controllers/AuthController.java | 68 +-- .../CrmOrganizationUserController.java | 35 +- .../api/controllers/HealthCheck.java | 11 +- .../controllers/SuggestionsController.java | 18 +- .../api/controllers/UserController.java | 17 +- .../api/domain/SalesforceOauthToken.java | 126 ++--- .../api/domain/SalesforceOrganization.java | 115 ++-- .../api/domain/SalesforceUser.java | 132 ++--- .../com/salessparrow/api/domain/User.java | 12 +- .../api/dto/entities/AccountEntity.java | 7 +- .../entities/AddTaskSuggestionEntityDto.java | 7 +- .../entities/CrmOrganizationUserEntity.java | 7 +- .../dto/entities/CurrentUserEntityDto.java | 47 +- .../api/dto/entities/NoteDetailEntity.java | 33 +- .../api/dto/entities/NoteEntity.java | 32 +- .../api/dto/entities/TaskEntity.java | 19 +- .../dto/formatter/CreateNoteFormatterDto.java | 4 +- .../dto/formatter/CreateTaskFormatterDto.java | 4 +- .../CrmActionSuggestionsFormatterDto.java | 7 +- .../formatter/GetAccountsFormatterDto.java | 7 +- .../GetCrmOrganizationUsersFormatterDto.java | 7 +- .../formatter/GetCurrentUserFormatterDto.java | 7 +- .../formatter/GetNoteDetailsFormatterDto.java | 11 +- .../formatter/GetNotesListFormatterDto.java | 19 +- .../formatter/GetTasksListFormatterDto.java | 7 +- .../formatter/RedirectUrlFormatterDto.java | 7 +- .../SalesforceConnectFormatterDto.java | 10 +- .../requestMapper/CreateAccountTaskDto.java | 15 +- .../CrmActionsSuggestionsDto.java | 8 +- .../api/dto/requestMapper/GetAccountsDto.java | 6 +- .../GetCrmOrganizationUsersDto.java | 6 +- .../api/dto/requestMapper/NoteDto.java | 9 +- .../requestMapper/SalesforceConnectDto.java | 45 +- .../SalesforceRedirectUrlDto.java | 12 +- .../api/exception/CustomException.java | 31 +- .../api/exception/ErrorResponse.java | 192 ++++--- .../api/exception/GlobalExceptionHandler.java | 230 ++++---- .../api/filter/SameSiteCookieFilter.java | 154 +++--- .../api/interceptors/JsonOnlyInterceptor.java | 46 +- .../api/interceptors/LoggerInterceptor.java | 85 +-- .../api/interceptors/UserAuthInterceptor.java | 114 ++-- .../api/interceptors/V1Interceptor.java | 31 +- .../java/com/salessparrow/api/lib/AwsKms.java | 112 ++-- .../salessparrow/api/lib/Base64Helper.java | 22 +- .../salessparrow/api/lib/CookieHelper.java | 212 ++++---- .../api/lib/ErrorEmailService.java | 121 +++-- .../api/lib/GetCrmActionSuggestions.java | 171 +++--- .../com/salessparrow/api/lib/LocalCipher.java | 169 +++--- .../api/lib/UserLoginCookieAuth.java | 364 ++++++------- .../java/com/salessparrow/api/lib/Util.java | 196 ++++--- .../createAccountNote/CreateNoteFactory.java | 10 +- .../CreateNoteInterface.java | 5 +- .../CreateSalesforceNote.java | 218 ++++---- .../createAccountTask/CreateAccountTask.java | 4 +- .../CreateAccountTaskFactory.java | 46 +- .../CreateSalesforceAccountTask.java | 191 +++---- .../DeleteAccountNoteFactory.java | 62 ++- .../DeleteAccountNoteInterface.java | 7 +- .../DeleteSalesforceAccountNote.java | 129 +++-- .../deleteAccountTask/DeleteAccountTask.java | 4 +- .../DeleteAccountTaskFactory.java | 54 +- .../DeleteSalesforceAccountTask.java | 137 +++-- .../GetAccountNoteDetails.java | 4 +- .../GetAccountNoteDetailsFactory.java | 41 +- .../GetSalesforceAccountNoteDetails.java | 187 +++---- .../GetAccountNoteListFactory.java | 44 +- .../GetAccountNotesList.java | 5 +- .../GetSalesforceAccountNotesList.java | 296 +++++----- .../GetAccountTasksListFactory.java | 54 +- .../GetAccountTasksListInterface.java | 7 +- .../GetSalesforceAccountTasksList.java | 177 +++--- .../crmActions/getAccounts/GetAccounts.java | 3 +- .../getAccounts/GetAccountsFactory.java | 41 +- .../getAccounts/GetSalesforceAccounts.java | 147 +++-- .../GetCrmOrganizationUsers.java | 7 +- .../GetCrmOrganizationUsersFactory.java | 47 +- .../GetSalesforceCrmOrganizationUsers.java | 158 +++--- .../customAnnotations/ValidDateFormat.java | 8 +- .../customAnnotations/ValidRedirectUri.java | 8 +- .../api/lib/errorLib/ErrorConfig.java | 23 +- .../api/lib/errorLib/ErrorObject.java | 26 +- .../api/lib/errorLib/ErrorResponseObject.java | 52 +- .../api/lib/errorLib/ParamErrorConfig.java | 43 +- .../api/lib/errorLib/ParamErrorObject.java | 29 +- .../api/lib/globalConstants/ApiSource.java | 3 +- .../lib/globalConstants/CacheConstants.java | 15 +- .../lib/globalConstants/CookieConstants.java | 7 +- .../DynamoDbTableNameConstants.java | 43 +- .../lib/globalConstants/OpenAiConstants.java | 13 +- .../globalConstants/SalesforceConstants.java | 97 ++-- .../lib/globalConstants/SecretConstants.java | 296 +++++----- .../lib/globalConstants/UserConstants.java | 14 +- .../config/dynamoBeeConfigConstants.java | 19 +- .../api/lib/httpLib/HttpClient.java | 141 ++--- .../api/lib/openAi/OpenAiPayloadBuilder.java | 91 ++-- .../api/lib/openAi/OpenAiRequest.java | 82 ++- .../salesforce/dto/CompositeRequestDto.java | 40 +- .../salesforce/dto/SalesforceAccountDto.java | 19 +- .../dto/SalesforceCreateNoteDto.java | 10 +- .../dto/SalesforceCreateTaskDto.java | 4 +- .../dto/SalesforceCrmOrganizationUserDto.java | 29 +- .../dto/SalesforceGetIdentityDto.java | 16 +- .../dto/SalesforceGetNoteDetailsDto.java | 40 +- .../dto/SalesforceGetNoteIdDto.java | 4 +- .../dto/SalesforceGetNotesListDto.java | 42 +- .../dto/SalesforceGetTasksListDto.java | 79 +-- .../dto/SalesforceGetTokensDto.java | 66 ++- .../helper/MakeCompositeRequest.java | 85 ++- .../helper/SalesforceOAuthToken.java | 104 ++-- .../helper/SalesforceQueryBuilder.java | 180 ++++--- .../salesforce/helper/SalesforceRequest.java | 77 ++- .../helper/SalesforceRequestInterface.java | 4 +- .../wrappers/SalesforceGetIdentity.java | 45 +- .../wrappers/SalesforceGetNoteContent.java | 65 ++- .../SalesforceGetRefreshedAccessToken.java | 49 +- .../wrappers/SalesforceGetTokens.java | 73 ++- .../lib/validators/DateFormatValidator.java | 54 +- .../lib/validators/RedirectUriValidator.java | 12 +- .../SalesforceOauthTokenRepository.java | 79 ++- .../SalesforceOrganizationRepository.java | 80 ++- .../SalesforceUserRepository.java | 80 ++- .../CreateAccountNoteService.java | 34 +- .../DeleteAccountNoteService.java | 43 +- .../GetAccountNoteDetailsService.java | 32 +- .../GetAccountNotesListService.java | 27 +- .../accountTask/CreateTaskService.java | 39 +- .../accountTask/DeleteTaskService.java | 43 +- .../GetAccountTasksListService.java | 41 +- .../accounts/GetAccountListService.java | 49 +- .../GetCrmOrganizationUsersList.java | 75 ++- .../api/services/salesforce/AuthService.java | 507 +++++++++--------- .../salesforce/RedirectUrlService.java | 47 +- .../CrmActionsSuggestionsService.java | 20 +- .../services/users/GetCurrentUserService.java | 17 +- .../api/utility/CacheKeyGenerator.java | 50 +- .../salessparrow/api/utility/Memcached.java | 258 +++++---- .../api/functional/SalesSparrowApiTest.java | 13 +- .../functional/config/SecurityConfigTest.java | 79 ++- .../accountController/CreateNoteTest.java | 165 +++--- .../accountController/GetAccountListTest.java | 160 +++--- .../accountController/GetNoteDetailsTest.java | 174 +++--- .../accountController/GetNoteListTest.java | 212 ++++---- .../DeleteAccountNoteTest.java | 146 ++--- .../accountTaskController/CreateTaskTest.java | 159 +++--- .../DeleteAccountTaskTest.java | 167 +++--- .../GetAccountTasksListTest.java | 144 ++--- .../authController/GetRedirectUrlTest.java | 59 +- .../authController/PostLogoutTest.java | 145 ++--- .../PostSalesforceConnectTest.java | 254 ++++----- .../GetCrmOrganizationUserListTest.java | 165 +++--- .../PostCrmActionsSuggestionsTest.java | 123 +++-- .../userController/GetCurrentUserTest.java | 106 ++-- .../exception/GlobalExceptionHandlerTest.java | 57 +- .../interceptors/JsonOnlyInterceptorTest.java | 58 +- .../com/salessparrow/api/helper/Cleanup.java | 70 +-- .../com/salessparrow/api/helper/Common.java | 118 ++-- .../salessparrow/api/helper/Constants.java | 4 +- .../salessparrow/api/helper/DropTables.java | 69 +-- .../salessparrow/api/helper/FixtureData.java | 14 +- .../salessparrow/api/helper/LoadFixture.java | 186 +++---- .../com/salessparrow/api/helper/Scenario.java | 10 +- .../com/salessparrow/api/helper/Setup.java | 85 ++- .../com/salessparrow/api/lib/UtilTest.java | 39 +- .../SalesforceConstantsTest.java | 143 ++--- .../globalConstants/UserConstantsTest.java | 23 +- .../salessparrow/api/unit/lib/UtilTest.java | 45 +- .../unit/lib/openAi/OpenAiRequestTest.java | 106 ++-- .../SalesforceOauthTokenRepositoryTest.java | 213 ++++---- .../SalesforceOrganizationRepositoryTest.java | 207 +++---- .../SalesforceUserRepositoryTest.java | 216 ++++---- .../api/unit/utility/MemcachedTest.java | 106 ++-- 186 files changed, 6941 insertions(+), 6999 deletions(-) diff --git a/pom.xml b/pom.xml index 61b5ee1d..b42573c8 100644 --- a/pom.xml +++ b/pom.xml @@ -157,6 +157,12 @@ 2.20.132 + + io.spring.javaformat + spring-javaformat-maven-plugin + 0.0.39 + + @@ -166,6 +172,20 @@ spring-boot-maven-plugin + + io.spring.javaformat + spring-javaformat-maven-plugin + 0.0.39 + + + + validate + apply + + + + + org.jacoco jacoco-maven-plugin diff --git a/src/main/java/com/salessparrow/api/SalesSparrowApi.java b/src/main/java/com/salessparrow/api/SalesSparrowApi.java index 69cb9031..1fe1c6e5 100644 --- a/src/main/java/com/salessparrow/api/SalesSparrowApi.java +++ b/src/main/java/com/salessparrow/api/SalesSparrowApi.java @@ -6,8 +6,7 @@ import org.springframework.cache.annotation.EnableCaching; import org.springframework.scheduling.annotation.EnableAsync; - -@SpringBootApplication(exclude= {UserDetailsServiceAutoConfiguration.class}) +@SpringBootApplication(exclude = { UserDetailsServiceAutoConfiguration.class }) @EnableCaching // This enables caching @EnableAsync // This enables asynchronous processing in Spring public class SalesSparrowApi { @@ -15,4 +14,5 @@ public class SalesSparrowApi { public static void main(String[] args) { SpringApplication.run(SalesSparrowApi.class, args); } + } diff --git a/src/main/java/com/salessparrow/api/changelogs/DatabaseChangelog.java b/src/main/java/com/salessparrow/api/changelogs/DatabaseChangelog.java index 595aa24e..2896b5dc 100644 --- a/src/main/java/com/salessparrow/api/changelogs/DatabaseChangelog.java +++ b/src/main/java/com/salessparrow/api/changelogs/DatabaseChangelog.java @@ -15,6 +15,7 @@ @ChangeLog public class DatabaseChangelog { + Logger logger = LoggerFactory.getLogger(DatabaseChangelog.class); @ChangeSet(order = "001", id = "001", author = "testAuthor") @@ -22,14 +23,10 @@ public void createSalesforceOrganizationsTable(AmazonDynamoDB db) { String tableName = DynamoDbTableNameConstants.salesforceOrganizationsTableName(); logger.info("Creating table: " + tableName); - CreateTableRequest request = new CreateTableRequest() - .withTableName(tableName) - .withAttributeDefinitions( - new AttributeDefinition("external_organization_id", - ScalarAttributeType.S)) - .withKeySchema( - new KeySchemaElement("external_organization_id", KeyType.HASH)) - .withBillingMode("PAY_PER_REQUEST"); + CreateTableRequest request = new CreateTableRequest().withTableName(tableName) + .withAttributeDefinitions(new AttributeDefinition("external_organization_id", ScalarAttributeType.S)) + .withKeySchema(new KeySchemaElement("external_organization_id", KeyType.HASH)) + .withBillingMode("PAY_PER_REQUEST"); db.createTable(request); logger.info("Done creating table: " + tableName); @@ -40,13 +37,10 @@ public void createSalesforceOAuthTokensTable(AmazonDynamoDB db) { String tableName = DynamoDbTableNameConstants.salesforceOauthTokensTableName(); logger.info("Creating table:" + tableName); - CreateTableRequest request = new CreateTableRequest() - .withTableName(tableName) - .withAttributeDefinitions( - new AttributeDefinition("external_user_id", ScalarAttributeType.S)) - .withKeySchema( - new KeySchemaElement("external_user_id", KeyType.HASH)) - .withBillingMode("PAY_PER_REQUEST"); + CreateTableRequest request = new CreateTableRequest().withTableName(tableName) + .withAttributeDefinitions(new AttributeDefinition("external_user_id", ScalarAttributeType.S)) + .withKeySchema(new KeySchemaElement("external_user_id", KeyType.HASH)) + .withBillingMode("PAY_PER_REQUEST"); db.createTable(request); @@ -58,16 +52,14 @@ public void createSalesforceUsersTable(AmazonDynamoDB db) { String tableName = DynamoDbTableNameConstants.salesforceUsersTableName(); logger.info("Creating table:" + tableName); - CreateTableRequest request = new CreateTableRequest() - .withTableName(tableName) - .withAttributeDefinitions( - new AttributeDefinition("external_user_id", ScalarAttributeType.S)) - .withKeySchema( - new KeySchemaElement("external_user_id", KeyType.HASH)) - .withBillingMode("PAY_PER_REQUEST"); + CreateTableRequest request = new CreateTableRequest().withTableName(tableName) + .withAttributeDefinitions(new AttributeDefinition("external_user_id", ScalarAttributeType.S)) + .withKeySchema(new KeySchemaElement("external_user_id", KeyType.HASH)) + .withBillingMode("PAY_PER_REQUEST"); db.createTable(request); logger.info("Done creating table: " + tableName); } + } \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/config/AwsConfig.java b/src/main/java/com/salessparrow/api/config/AwsConfig.java index 9030f53e..ba1268fd 100644 --- a/src/main/java/com/salessparrow/api/config/AwsConfig.java +++ b/src/main/java/com/salessparrow/api/config/AwsConfig.java @@ -1,7 +1,5 @@ package com.salessparrow.api.config; -import com.amazonaws.auth.AWSStaticCredentialsProvider; -import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.client.builder.AwsClientBuilder; import com.amazonaws.services.kms.AWSKMS; import com.amazonaws.services.kms.AWSKMSClientBuilder; @@ -11,60 +9,47 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; + /** * Configuration class for AWS-related beans and settings. - * + * */ @Configuration public class AwsConfig { - /** - * Returns an instance of the AWS Key Management Service (KMS) - * client based on the environment. - * - * @implNote - Client is configured to use the local KMS endpoint for following environments - * - development - * - test - * - local-test - * For test and production environments, the client is configured to use the AWS KMS endpoint - * - * @return An instance of the AWSKMS client configured - * for the appropriate environment. - * - */ - @Bean - public AWSKMS kmsClient() { - if ( - CoreConstants.isDevEnvironment() || - CoreConstants.isTestEnvironment() || - CoreConstants.isLocalTestEnvironment() - ) { - - AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder.EndpointConfiguration( - CoreConstants.localKmsEndpoint(), - CoreConstants.awsRegion() - ); + /** + * Returns an instance of the AWS Key Management Service (KMS) client based on the + * environment. + * + * @implNote - Client is configured to use the local KMS endpoint for following + * environments - development - test - local-test For test and production + * environments, the client is configured to use the AWS KMS endpoint + * @return An instance of the AWSKMS client configured for the appropriate + * environment. + * + */ + @Bean + public AWSKMS kmsClient() { + if (CoreConstants.isDevEnvironment() || CoreConstants.isTestEnvironment() + || CoreConstants.isLocalTestEnvironment()) { + + AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder.EndpointConfiguration( + CoreConstants.localKmsEndpoint(), CoreConstants.awsRegion()); + + return AWSKMSClientBuilder.standard().withEndpointConfiguration(endpointConfiguration).build(); + } - return AWSKMSClientBuilder.standard() - .withEndpointConfiguration(endpointConfiguration) - .build(); - } - - return AWSKMSClientBuilder.standard() - .withRegion(CoreConstants.awsRegion()) - .build(); - } + return AWSKMSClientBuilder.standard().withRegion(CoreConstants.awsRegion()).build(); + } - /** - * Creates and configures an AWS SES (Simple Email Service) client. - * - * @return An instance of AmazonSimpleEmailService that allows access to AWS SES operations. - */ - @Bean - public AmazonSimpleEmailService sesClient() { - return AmazonSimpleEmailServiceClientBuilder.standard() - .withRegion(CoreConstants.awsRegion()) - .build(); - } + /** + * Creates and configures an AWS SES (Simple Email Service) client. + * @return An instance of AmazonSimpleEmailService that allows access to AWS SES + * operations. + */ + @Bean + public AmazonSimpleEmailService sesClient() { + return AmazonSimpleEmailServiceClientBuilder.standard().withRegion(CoreConstants.awsRegion()).build(); + } } \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/config/CoreConstants.java b/src/main/java/com/salessparrow/api/config/CoreConstants.java index 37b2f81c..270174d2 100644 --- a/src/main/java/com/salessparrow/api/config/CoreConstants.java +++ b/src/main/java/com/salessparrow/api/config/CoreConstants.java @@ -6,116 +6,112 @@ * Class to get the environment variables. */ public class CoreConstants { - /* Start: Env variables required before spring application context is initialized */ - - public static String environment() { - return System.getenv("ENVIRONMENT"); - } - - public static Boolean isDevEnvironment() { - return environment().equals("development"); - } - - public static Boolean isTestEnvironment() { - return environment().equals("test"); - } - - public static Boolean isLocalTestEnvironment() { - return environment().equals("local-test"); - } - - /* End: Env variables required before spring application context is initialized */ - - public static String cookieDomain(){ - return SecretConstants.cookieDomain(); - } - - public static String awsRegion() { - return SecretConstants.awsRegion(); - } - - public static String encryptionKey() { - return SecretConstants.encryptionKey(); - } - - public static String apiCookieSecret() { - return SecretConstants.apiCookieSecret(); - } - - public static String kmsKeyId() { - return SecretConstants.kmsKeyId(); - } - - public static String salesforceAuthUrl() { - return SecretConstants.salesforceAuthUrl(); - } - - public static String salesforceClientId() { - return SecretConstants.salesforceClientId(); - } - - public static String salesforceClientSecret() { - return SecretConstants.salesforceClientSecret(); - } - - public static String localKmsEndpoint() { - return SecretConstants.localKmsEndpoint(); - } - - /** - * This method returns the memcached address that is going to be used for locals - * - * @return String - */ - public static String memcachedAddress() { - return SecretConstants.memcachedHost() + ":" + SecretConstants.memcachedPort(); - } - - /** - * This method returns the list of redirect URIs that are whitelisted in - * Salesforce connected app for oAuth. - * - * @return String[] - */ - public static String[] getWhitelistedRedirectUris() { - String redirectUrisJson = SecretConstants.salesforceWhitelistedRedirectUris(); - return redirectUrisJson.split(","); - } - - /** - * This method returns api key for OpenAI. - * - * @return String - */ - public static String openAiApiKey() { - return SecretConstants.openAiApiKey(); - } - - /** - * This method returns the email address that will be used to send error emails. - * This email address or its domain must be verified in AWS SES. - * - * @return String - */ - public static String errorEmailFrom() { - return SecretConstants.errorEmailFrom(); - } - - /** - * This method returns the email address that will receive the error emails. - * - * @return String - */ - public static String errorEmailTo() { - return SecretConstants.errorEmailTo(); - } - - /** - * This method returns the dynamodb url. - * @return - */ - public static String dynamoDbUrl() { - return SecretConstants.dynamoDbUrl(); - } + + /* Start: Env variables required before spring application context is initialized */ + + public static String environment() { + return System.getenv("ENVIRONMENT"); + } + + public static Boolean isDevEnvironment() { + return environment().equals("development"); + } + + public static Boolean isTestEnvironment() { + return environment().equals("test"); + } + + public static Boolean isLocalTestEnvironment() { + return environment().equals("local-test"); + } + + /* End: Env variables required before spring application context is initialized */ + + public static String cookieDomain() { + return SecretConstants.cookieDomain(); + } + + public static String awsRegion() { + return SecretConstants.awsRegion(); + } + + public static String encryptionKey() { + return SecretConstants.encryptionKey(); + } + + public static String apiCookieSecret() { + return SecretConstants.apiCookieSecret(); + } + + public static String kmsKeyId() { + return SecretConstants.kmsKeyId(); + } + + public static String salesforceAuthUrl() { + return SecretConstants.salesforceAuthUrl(); + } + + public static String salesforceClientId() { + return SecretConstants.salesforceClientId(); + } + + public static String salesforceClientSecret() { + return SecretConstants.salesforceClientSecret(); + } + + public static String localKmsEndpoint() { + return SecretConstants.localKmsEndpoint(); + } + + /** + * This method returns the memcached address that is going to be used for locals + * @return String + */ + public static String memcachedAddress() { + return SecretConstants.memcachedHost() + ":" + SecretConstants.memcachedPort(); + } + + /** + * This method returns the list of redirect URIs that are whitelisted in Salesforce + * connected app for oAuth. + * @return String[] + */ + public static String[] getWhitelistedRedirectUris() { + String redirectUrisJson = SecretConstants.salesforceWhitelistedRedirectUris(); + return redirectUrisJson.split(","); + } + + /** + * This method returns api key for OpenAI. + * @return String + */ + public static String openAiApiKey() { + return SecretConstants.openAiApiKey(); + } + + /** + * This method returns the email address that will be used to send error emails. This + * email address or its domain must be verified in AWS SES. + * @return String + */ + public static String errorEmailFrom() { + return SecretConstants.errorEmailFrom(); + } + + /** + * This method returns the email address that will receive the error emails. + * @return String + */ + public static String errorEmailTo() { + return SecretConstants.errorEmailTo(); + } + + /** + * This method returns the dynamodb url. + * @return + */ + public static String dynamoDbUrl() { + return SecretConstants.dynamoDbUrl(); + } } diff --git a/src/main/java/com/salessparrow/api/config/CorsConfig.java b/src/main/java/com/salessparrow/api/config/CorsConfig.java index 64b4a8d9..d378d8a2 100644 --- a/src/main/java/com/salessparrow/api/config/CorsConfig.java +++ b/src/main/java/com/salessparrow/api/config/CorsConfig.java @@ -1,4 +1,5 @@ package com.salessparrow.api.config; + import org.springframework.context.annotation.Profile; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @@ -13,15 +14,16 @@ @Profile("!production") public class CorsConfig implements WebMvcConfigurer { - @Override - public void addCorsMappings(CorsRegistry registry) { - Logger logger = LoggerFactory.getLogger(CorsConfig.class); - logger.info("Add Cors config for localhost:3000"); + @Override + public void addCorsMappings(CorsRegistry registry) { + Logger logger = LoggerFactory.getLogger(CorsConfig.class); + logger.info("Add Cors config for localhost:3000"); + + registry.addMapping("/**") + .allowedOrigins("http://localhost:3000") + .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") + .allowCredentials(true) + .maxAge(3600); + } - registry.addMapping("/**") - .allowedOrigins("http://localhost:3000") - .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") - .allowCredentials(true) - .maxAge(3600); - } } diff --git a/src/main/java/com/salessparrow/api/config/DynamoBeeConfig.java b/src/main/java/com/salessparrow/api/config/DynamoBeeConfig.java index b11738e9..e1eff2aa 100644 --- a/src/main/java/com/salessparrow/api/config/DynamoBeeConfig.java +++ b/src/main/java/com/salessparrow/api/config/DynamoBeeConfig.java @@ -13,16 +13,19 @@ */ @Configuration public class DynamoBeeConfig { - @Autowired - private AmazonDynamoDB db; - @Autowired - private dynamoBeeConfigConstants dynamoBeeConfigConstants; + @Autowired + private AmazonDynamoDB db; + + @Autowired + private dynamoBeeConfigConstants dynamoBeeConfigConstants; + + @Bean + public Dynamobee dynamobee() { + Dynamobee runner = new Dynamobee(db); + runner.setChangeLogsScanPackage(dynamoBeeConfigConstants.getChangeLogScanPackage()) + .setChangelogTableName(dynamoBeeConfigConstants.getChangelogTableName()); + return runner; + } - @Bean - public Dynamobee dynamobee(){ - Dynamobee runner = new Dynamobee(db); - runner.setChangeLogsScanPackage(dynamoBeeConfigConstants.getChangeLogScanPackage()).setChangelogTableName(dynamoBeeConfigConstants.getChangelogTableName()); - return runner; - } } diff --git a/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java b/src/main/java/com/salessparrow/api/config/DynamoDBConfiguration.java index a0a442b4..8330b82b 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,60 +19,60 @@ 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) { + } + 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) { + } + 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; + 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(); + return AmazonDynamoDBClientBuilder.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/config/FilterConfig.java b/src/main/java/com/salessparrow/api/config/FilterConfig.java index d7d6e7b1..eec8b94f 100644 --- a/src/main/java/com/salessparrow/api/config/FilterConfig.java +++ b/src/main/java/com/salessparrow/api/config/FilterConfig.java @@ -8,16 +8,17 @@ @Configuration public class FilterConfig { - /** - * Register SameSiteCookieFilter - * - * @return FilterRegistrationBean - */ - @Bean - public FilterRegistrationBean sameSiteCookieFilter() { - FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); - registrationBean.setFilter(new SameSiteCookieFilter()); - registrationBean.addUrlPatterns("/*"); // or specific URL patterns - return registrationBean; - } + + /** + * Register SameSiteCookieFilter + * @return FilterRegistrationBean + */ + @Bean + public FilterRegistrationBean sameSiteCookieFilter() { + FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); + registrationBean.setFilter(new SameSiteCookieFilter()); + registrationBean.addUrlPatterns("/*"); // or specific URL patterns + return registrationBean; + } + } diff --git a/src/main/java/com/salessparrow/api/config/InterceptorConfig.java b/src/main/java/com/salessparrow/api/config/InterceptorConfig.java index af8f27a6..1aaaa015 100644 --- a/src/main/java/com/salessparrow/api/config/InterceptorConfig.java +++ b/src/main/java/com/salessparrow/api/config/InterceptorConfig.java @@ -12,40 +12,39 @@ @Configuration public class InterceptorConfig implements WebMvcConfigurer { - - @Autowired - private final LoggerInterceptor loggerInterceptor; - - @Autowired - private final JsonOnlyInterceptor jsonOnlyInterceptor; - - @Autowired - private final V1Interceptor V1Interceptor; - - @Autowired - private final UserAuthInterceptor userAuthInterceptor; - - public InterceptorConfig(UserAuthInterceptor userAuthInterceptor, JsonOnlyInterceptor jsonOnlyInterceptor, LoggerInterceptor loggerInterceptor, V1Interceptor V1Interceptor) { - this.userAuthInterceptor = userAuthInterceptor; - this.loggerInterceptor = loggerInterceptor; - this.V1Interceptor = V1Interceptor; - this.jsonOnlyInterceptor = jsonOnlyInterceptor; - } - - @Override - public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(loggerInterceptor) - .addPathPatterns("/**"); - - registry.addInterceptor(jsonOnlyInterceptor) - .addPathPatterns("/**"); - - registry.addInterceptor(V1Interceptor) - .addPathPatterns("/api/v1/**"); - - registry.addInterceptor(userAuthInterceptor) - .addPathPatterns("/**") - .excludePathPatterns("/api/v1/auth/salesforce/**") - .excludePathPatterns("/api/v1/health-check"); - } + + @Autowired + private final LoggerInterceptor loggerInterceptor; + + @Autowired + private final JsonOnlyInterceptor jsonOnlyInterceptor; + + @Autowired + private final V1Interceptor V1Interceptor; + + @Autowired + private final UserAuthInterceptor userAuthInterceptor; + + public InterceptorConfig(UserAuthInterceptor userAuthInterceptor, JsonOnlyInterceptor jsonOnlyInterceptor, + LoggerInterceptor loggerInterceptor, V1Interceptor V1Interceptor) { + this.userAuthInterceptor = userAuthInterceptor; + this.loggerInterceptor = loggerInterceptor; + this.V1Interceptor = V1Interceptor; + this.jsonOnlyInterceptor = jsonOnlyInterceptor; + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(loggerInterceptor).addPathPatterns("/**"); + + registry.addInterceptor(jsonOnlyInterceptor).addPathPatterns("/**"); + + registry.addInterceptor(V1Interceptor).addPathPatterns("/api/v1/**"); + + registry.addInterceptor(userAuthInterceptor) + .addPathPatterns("/**") + .excludePathPatterns("/api/v1/auth/salesforce/**") + .excludePathPatterns("/api/v1/health-check"); + } + } \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/config/MemcachedConfig.java b/src/main/java/com/salessparrow/api/config/MemcachedConfig.java index a4b2fc93..6d0e6ce1 100644 --- a/src/main/java/com/salessparrow/api/config/MemcachedConfig.java +++ b/src/main/java/com/salessparrow/api/config/MemcachedConfig.java @@ -33,94 +33,77 @@ @Configuration public class MemcachedConfig implements CachingConfigurer { - private MemcachedClient cache; - - private static final Logger logger = LoggerFactory.getLogger(MemcachedConfig.class); - - /** - * Cache Manager Bean to initialize the cache client. - * - * @return CacheManager - */ - @Override - @Bean - public CacheManager cacheManager() { - SimpleCacheManager cacheManager = new SimpleCacheManager(); - - setMemcachedClient(); - - cacheManager.setCaches(internalCaches(this.cache)); - return cacheManager; - } - - /** - * Internal Caches - * All caches needs to be added here along with their expiry time. - * - * @return Collection - */ - private Collection internalCaches(MemcachedClient cache) { - final Collection caches = new ArrayList<>(); - - caches.add(new Memcached( - CacheConstants.SS_SALESFORCE_USER_CACHE, - CacheConstants.SS_SALESFORCE_USER_CACHE_EXP, - cache - )); - caches.add( - new Memcached( - CacheConstants.SS_SALESFORCE_OAUTH_TOKEN_CACHE, - CacheConstants.SS_SALESFORCE_OAUTH_TOKEN_CACHE_EXP, - cache - )); - return caches; - } - - public void setMemcachedClient() { - logger.info("Memcached Client Initialized"); - try { - this.cache = new MemcachedClient( - new ConnectionFactoryBuilder() - .setTranscoder(new SerializingTranscoder()) - .setProtocol(ConnectionFactoryBuilder.Protocol.BINARY) - .build(), - AddrUtil.getAddresses(CoreConstants.memcachedAddress())); - } catch (Exception e) { - throw new CustomException( - new ErrorObject( - "a_c_mc_mc_1", - "something_went_wrong", - e.getMessage())); - } - } - - /** - * Key Generator is overriden to include a prefix that can be different for different environments. - * - * @return KeyGenerator - */ - @Override - public KeyGenerator keyGenerator() { - return new CacheKeyGenerator(); - } - - /** - * Error Handler - * - * @return CacheErrorHandler - */ - @Override - public CacheErrorHandler errorHandler() { - return new SimpleCacheErrorHandler(); - } - - /** - * Cache Resolver - * - * @return CacheResolver - */ - @Override - public CacheResolver cacheResolver() { - return null; - } + private MemcachedClient cache; + + private static final Logger logger = LoggerFactory.getLogger(MemcachedConfig.class); + + /** + * Cache Manager Bean to initialize the cache client. + * @return CacheManager + */ + @Override + @Bean + public CacheManager cacheManager() { + SimpleCacheManager cacheManager = new SimpleCacheManager(); + + setMemcachedClient(); + + cacheManager.setCaches(internalCaches(this.cache)); + return cacheManager; + } + + /** + * Internal Caches All caches needs to be added here along with their expiry time. + * @return Collection + */ + private Collection internalCaches(MemcachedClient cache) { + final Collection caches = new ArrayList<>(); + + caches.add(new Memcached(CacheConstants.SS_SALESFORCE_USER_CACHE, CacheConstants.SS_SALESFORCE_USER_CACHE_EXP, + cache)); + caches.add(new Memcached(CacheConstants.SS_SALESFORCE_OAUTH_TOKEN_CACHE, + CacheConstants.SS_SALESFORCE_OAUTH_TOKEN_CACHE_EXP, cache)); + return caches; + } + + public void setMemcachedClient() { + logger.info("Memcached Client Initialized"); + try { + this.cache = new MemcachedClient(new ConnectionFactoryBuilder().setTranscoder(new SerializingTranscoder()) + .setProtocol(ConnectionFactoryBuilder.Protocol.BINARY) + .build(), AddrUtil.getAddresses(CoreConstants.memcachedAddress())); + } + catch (Exception e) { + throw new CustomException(new ErrorObject("a_c_mc_mc_1", "something_went_wrong", e.getMessage())); + } + } + + /** + * Key Generator is overriden to include a prefix that can be different for different + * environments. + * @return KeyGenerator + */ + @Override + public KeyGenerator keyGenerator() { + return new CacheKeyGenerator(); + } + + /** + * Error Handler + * @return CacheErrorHandler + */ + @Override + public CacheErrorHandler errorHandler() { + return new SimpleCacheErrorHandler(); + } + + /** + * Cache Resolver + * @return CacheResolver + */ + @Override + public CacheResolver cacheResolver() { + return null; + } + } \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/config/SecurityConfig.java b/src/main/java/com/salessparrow/api/config/SecurityConfig.java index 02e7dfc7..dfa8750c 100644 --- a/src/main/java/com/salessparrow/api/config/SecurityConfig.java +++ b/src/main/java/com/salessparrow/api/config/SecurityConfig.java @@ -8,75 +8,77 @@ import org.springframework.security.web.header.writers.XXssProtectionHeaderWriter; import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter.ReferrerPolicy; - @Configuration @EnableWebSecurity public class SecurityConfig { - - @Bean + + @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { - http - // disable authorization for all routes - .authorizeHttpRequests(authorizeRequests ->authorizeRequests.anyRequest().permitAll()) - // Disable authentication for all routes - .httpBasic(httpBasic -> httpBasic.disable()) - // Disable form login - .formLogin(formLogin -> formLogin.disable()) - // Remove csrf in app routes - .csrf((csrf) -> csrf.ignoringRequestMatchers("/api/v1/**")) - - /** - * Cache-Control header - applied by default in spring security - * The Cache-Control header is the most important header to set as it effectively disables caching on the client side. - * - * Pragma header - applied by default in spring security - * The Pragma directive is an older directive meant for HTTP/1.0 clients where - * the Cache-Control header wasn't defined. - * - * Expires header - applied by default in spring security - * The Expires header is another older way to prevent caching, especially in HTTP/1.0. - * - * X-Content-Type-Options header - applied by default in spring security - * The X-Content-Type-Options header is a security feature that prevents pages from loading when they detect - * incorrect MIME types. - * By setting the value to "nosniff", you're instructing the browser not to override the provided Content-Type - * - * HSTS header - * The Strict-Transport-Security header is a security feature implemented by web browsers - * to ensure that websites are only accessed using HTTPS. - * - * X-Frame-Options header - * The X-Frame-Options header is a security feature that prevents your web page from being put in a frame. - * - * X-XSS-Protection header - applied by default in spring security - * The X-XSS-Protection header is a security feature that prevents pages from loading when they detect - * reflected cross-site scripting (XSS) attacks. - * - * It is not needed for rest api's as they are not rendered in the browser. But it is no harm and is a - * good practice to have it.The value "1; mode=block" instructs the browser to block the response if it - * detects an attack. - * - * Referrer-Policy header - * The Referrer-Policy header is a security feature that prevents pages from leaking information about the user's - * browsing behavior.The value "same-origin" instructs the browser to send the referrer header only when the request - * is originating from the same origin as the target resource. - */ - .headers(headers -> headers - .frameOptions(frameOptions -> frameOptions.deny()) - .httpStrictTransportSecurity(hsts -> hsts.includeSubDomains(true).preload(true).maxAgeInSeconds(31536000)) - .xssProtection(xss -> xss.headerValue(XXssProtectionHeaderWriter.HeaderValue.ENABLED_MODE_BLOCK)) - .referrerPolicy(referrer -> referrer.policy(ReferrerPolicy.SAME_ORIGIN)) - ); + http + // disable authorization for all routes + .authorizeHttpRequests(authorizeRequests -> authorizeRequests.anyRequest().permitAll()) + // Disable authentication for all routes + .httpBasic(httpBasic -> httpBasic.disable()) + // Disable form login + .formLogin(formLogin -> formLogin.disable()) + // Remove csrf in app routes + .csrf((csrf) -> csrf.ignoringRequestMatchers("/api/v1/**")) + /** + * Cache-Control header - applied by default in spring security The + * Cache-Control header is the most important header to set as it effectively + * disables caching on the client side. + * + * Pragma header - applied by default in spring security The Pragma directive + * is an older directive meant for HTTP/1.0 clients where the Cache-Control + * header wasn't defined. + * + * Expires header - applied by default in spring security The Expires header + * is another older way to prevent caching, especially in HTTP/1.0. + * + * X-Content-Type-Options header - applied by default in spring security The + * X-Content-Type-Options header is a security feature that prevents pages + * from loading when they detect incorrect MIME types. By setting the value to + * "nosniff", you're instructing the browser not to override the provided + * Content-Type + * + * HSTS header The Strict-Transport-Security header is a security feature + * implemented by web browsers to ensure that websites are only accessed using + * HTTPS. + * + * X-Frame-Options header The X-Frame-Options header is a security feature + * that prevents your web page from being put in a frame. + * + * X-XSS-Protection header - applied by default in spring security The + * X-XSS-Protection header is a security feature that prevents pages from + * loading when they detect reflected cross-site scripting (XSS) attacks. + * + * It is not needed for rest api's as they are not rendered in the browser. + * But it is no harm and is a good practice to have it.The value "1; + * mode=block" instructs the browser to block the response if it detects an + * attack. + * + * Referrer-Policy header The Referrer-Policy header is a security feature + * that prevents pages from leaking information about the user's browsing + * behavior.The value "same-origin" instructs the browser to send the referrer + * header only when the request is originating from the same origin as the + * target resource. + */ + .headers(headers -> headers.frameOptions(frameOptions -> frameOptions.deny()) + .httpStrictTransportSecurity( + hsts -> hsts.includeSubDomains(true).preload(true).maxAgeInSeconds(31536000)) + .xssProtection(xss -> xss.headerValue(XXssProtectionHeaderWriter.HeaderValue.ENABLED_MODE_BLOCK)) + .referrerPolicy(referrer -> referrer.policy(ReferrerPolicy.SAME_ORIGIN))); - // Enable for production and staging - if (!CoreConstants.isDevEnvironment() && !CoreConstants.isTestEnvironment() && - !CoreConstants.isLocalTestEnvironment()) { - // All requests must be secure - http.requiresChannel(channel -> channel.anyRequest().requiresSecure()); - } + // Enable for production and staging + if (!CoreConstants.isDevEnvironment() && !CoreConstants.isTestEnvironment() + && !CoreConstants.isLocalTestEnvironment()) { + // All requests must be secure + http.requiresChannel(channel -> channel.anyRequest().requiresSecure()); + } - return http.build(); + return http.build(); } + } diff --git a/src/main/java/com/salessparrow/api/controllers/AccountController.java b/src/main/java/com/salessparrow/api/controllers/AccountController.java index 18829e72..a9a40947 100644 --- a/src/main/java/com/salessparrow/api/controllers/AccountController.java +++ b/src/main/java/com/salessparrow/api/controllers/AccountController.java @@ -21,19 +21,19 @@ @Validated public class AccountController { - private Logger logger = org.slf4j.LoggerFactory.getLogger(AccountController.class); + private Logger logger = org.slf4j.LoggerFactory.getLogger(AccountController.class); - @Autowired - private GetAccountListService getAccountListService; + @Autowired + private GetAccountListService getAccountListService; - @GetMapping("") - public ResponseEntity getAccounts( - HttpServletRequest request, - @Valid @ModelAttribute GetAccountsDto getAccountsDto) { - logger.info("Request received"); + @GetMapping("") + public ResponseEntity getAccounts(HttpServletRequest request, + @Valid @ModelAttribute GetAccountsDto getAccountsDto) { + logger.info("Request received"); - GetAccountsFormatterDto getAccountsResponse = getAccountListService.getAccounts(request, getAccountsDto); + GetAccountsFormatterDto getAccountsResponse = getAccountListService.getAccounts(request, getAccountsDto); + + return ResponseEntity.ok().body(getAccountsResponse); + } - return ResponseEntity.ok().body(getAccountsResponse); - } } diff --git a/src/main/java/com/salessparrow/api/controllers/AccountNoteController.java b/src/main/java/com/salessparrow/api/controllers/AccountNoteController.java index 16d32670..ff6d4d6c 100644 --- a/src/main/java/com/salessparrow/api/controllers/AccountNoteController.java +++ b/src/main/java/com/salessparrow/api/controllers/AccountNoteController.java @@ -29,68 +29,58 @@ @Validated public class AccountNoteController { - private Logger logger = org.slf4j.LoggerFactory.getLogger(AccountNoteController.class); - - @Autowired - private GetAccountNotesListService getNotesListService; - - @Autowired - private GetAccountNoteDetailsService getNoteDetailsService; - - @Autowired - private CreateAccountNoteService createNoteService; - - @Autowired - private DeleteAccountNoteService deleteAccountNoteService; - - @PostMapping("") - public ResponseEntity addNoteToAccount( - HttpServletRequest request, - @PathVariable("account_id") String accountId, - @Valid @RequestBody NoteDto note - ) { - logger.info("Create Note request received"); - - CreateNoteFormatterDto createNoteFormatterDto = createNoteService.createNote(request, accountId, note); - - return ResponseEntity.ok().body(createNoteFormatterDto); - } - - @GetMapping("") - public ResponseEntity getNotesList( - HttpServletRequest request, - @PathVariable("account_id") String accountId - ) { - logger.info("Get Note List request received"); - - GetNotesListFormatterDto getNotesListResponse = getNotesListService.getNotesList(request, accountId); - - return ResponseEntity.ok().body(getNotesListResponse); - } - - @GetMapping("/{note_id}") - public ResponseEntity getNoteFromAccount( - HttpServletRequest request, - @PathVariable("account_id") String accountId, - @PathVariable("note_id") String noteId - ) { - logger.info("Get Note request received"); - - GetNoteDetailsFormatterDto getNoteDetailsResponse = getNoteDetailsService.getNoteDetails(request, noteId); - - return ResponseEntity.ok().body(getNoteDetailsResponse); - } - - @DeleteMapping("/{note_id}") - public ResponseEntity deleteNote( - HttpServletRequest request, - @PathVariable("account_id") String accountId, - @PathVariable("note_id") String noteId - ) { - logger.info("Delete Note request received"); - - deleteAccountNoteService.deleteAccountNote(request, accountId, noteId); - - return ResponseEntity.noContent().build(); - } + private Logger logger = org.slf4j.LoggerFactory.getLogger(AccountNoteController.class); + + @Autowired + private GetAccountNotesListService getNotesListService; + + @Autowired + private GetAccountNoteDetailsService getNoteDetailsService; + + @Autowired + private CreateAccountNoteService createNoteService; + + @Autowired + private DeleteAccountNoteService deleteAccountNoteService; + + @PostMapping("") + public ResponseEntity addNoteToAccount(HttpServletRequest request, + @PathVariable("account_id") String accountId, @Valid @RequestBody NoteDto note) { + logger.info("Create Note request received"); + + CreateNoteFormatterDto createNoteFormatterDto = createNoteService.createNote(request, accountId, note); + + return ResponseEntity.ok().body(createNoteFormatterDto); + } + + @GetMapping("") + public ResponseEntity getNotesList(HttpServletRequest request, + @PathVariable("account_id") String accountId) { + logger.info("Get Note List request received"); + + GetNotesListFormatterDto getNotesListResponse = getNotesListService.getNotesList(request, accountId); + + return ResponseEntity.ok().body(getNotesListResponse); + } + + @GetMapping("/{note_id}") + public ResponseEntity getNoteFromAccount(HttpServletRequest request, + @PathVariable("account_id") String accountId, @PathVariable("note_id") String noteId) { + logger.info("Get Note request received"); + + GetNoteDetailsFormatterDto getNoteDetailsResponse = getNoteDetailsService.getNoteDetails(request, noteId); + + return ResponseEntity.ok().body(getNoteDetailsResponse); + } + + @DeleteMapping("/{note_id}") + public ResponseEntity deleteNote(HttpServletRequest request, + @PathVariable("account_id") String accountId, @PathVariable("note_id") String noteId) { + logger.info("Delete Note request received"); + + deleteAccountNoteService.deleteAccountNote(request, accountId, noteId); + + return ResponseEntity.noContent().build(); + } + } diff --git a/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java b/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java index 6f6efcb8..7cab58dc 100644 --- a/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java +++ b/src/main/java/com/salessparrow/api/controllers/AccountTaskController.java @@ -24,56 +24,50 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; - @RestController @RequestMapping("/api/v1/accounts") @Validated public class AccountTaskController { - Logger logger = LoggerFactory.getLogger(AccountTaskController.class); - - @Autowired - private CreateTaskService createTaskService; - - @Autowired - private DeleteTaskService deleteTaskService; - - @Autowired - private GetAccountTasksListService getAccountTasksListService; - - @PostMapping("/{account_id}/tasks") - public ResponseEntity createTask( - HttpServletRequest request, - @PathVariable("account_id") String accountId, - @Valid @RequestBody CreateAccountTaskDto task - ){ - logger.info("Create task request received"); - - CreateTaskFormatterDto createTaskFormatterDto = createTaskService.createAccountTask(request, accountId, task); - - return ResponseEntity.status(HttpStatus.CREATED).body(createTaskFormatterDto); - } - - @GetMapping("/{account_id}/tasks") - public ResponseEntity getTasksList( - HttpServletRequest request, - @PathVariable("account_id") String accountId - ){ - logger.info("Get tasks list request received"); - - GetTasksListFormatterDto getTasksListFormatterDto = getAccountTasksListService.getAccountTasksList(request, accountId); - return ResponseEntity.status(HttpStatus.OK).body(getTasksListFormatterDto); - } - - @DeleteMapping("/{account_id}/tasks/{task_id}") - public ResponseEntity deleteTask( - HttpServletRequest request, - @PathVariable("account_id") String accountId, - @PathVariable("task_id") String taskId - ){ - logger.info("Delete task request received"); - - deleteTaskService.deleteAccountTask(request, accountId, taskId); - - return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); - } + + Logger logger = LoggerFactory.getLogger(AccountTaskController.class); + + @Autowired + private CreateTaskService createTaskService; + + @Autowired + private DeleteTaskService deleteTaskService; + + @Autowired + private GetAccountTasksListService getAccountTasksListService; + + @PostMapping("/{account_id}/tasks") + public ResponseEntity createTask(HttpServletRequest request, + @PathVariable("account_id") String accountId, @Valid @RequestBody CreateAccountTaskDto task) { + logger.info("Create task request received"); + + CreateTaskFormatterDto createTaskFormatterDto = createTaskService.createAccountTask(request, accountId, task); + + return ResponseEntity.status(HttpStatus.CREATED).body(createTaskFormatterDto); + } + + @GetMapping("/{account_id}/tasks") + public ResponseEntity getTasksList(HttpServletRequest request, + @PathVariable("account_id") String accountId) { + logger.info("Get tasks list request received"); + + GetTasksListFormatterDto getTasksListFormatterDto = getAccountTasksListService.getAccountTasksList(request, + accountId); + return ResponseEntity.status(HttpStatus.OK).body(getTasksListFormatterDto); + } + + @DeleteMapping("/{account_id}/tasks/{task_id}") + public ResponseEntity deleteTask(HttpServletRequest request, @PathVariable("account_id") String accountId, + @PathVariable("task_id") String taskId) { + logger.info("Delete task request received"); + + deleteTaskService.deleteAccountTask(request, accountId, taskId); + + return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); + } + } diff --git a/src/main/java/com/salessparrow/api/controllers/AuthController.java b/src/main/java/com/salessparrow/api/controllers/AuthController.java index 3caf84b6..6faac3ea 100644 --- a/src/main/java/com/salessparrow/api/controllers/AuthController.java +++ b/src/main/java/com/salessparrow/api/controllers/AuthController.java @@ -30,49 +30,51 @@ @Validated public class AuthController { - Logger logger = LoggerFactory.getLogger(AuthController.class); + Logger logger = LoggerFactory.getLogger(AuthController.class); - @Autowired - private RedirectUrlService redirectUrlService; + @Autowired + private RedirectUrlService redirectUrlService; - @Autowired - private AuthService authService; + @Autowired + private AuthService authService; - @Autowired - private CookieHelper cookieHelper; + @Autowired + private CookieHelper cookieHelper; - @GetMapping("/salesforce/redirect-url") - public ResponseEntity getSalesforceRedirectUrl( - @Valid @ModelAttribute SalesforceRedirectUrlDto salesforceRedirectUrlDto) { - - RedirectUrlFormatterDto redirectUrlFormatterDto = redirectUrlService.getSalesforceOauthUrl(salesforceRedirectUrlDto); - - return ResponseEntity.ok().body(redirectUrlFormatterDto); - } + @GetMapping("/salesforce/redirect-url") + public ResponseEntity getSalesforceRedirectUrl( + @Valid @ModelAttribute SalesforceRedirectUrlDto salesforceRedirectUrlDto) { - @PostMapping("/salesforce/connect") - public ResponseEntity connectToSalesforce(HttpServletRequest request, - @Valid @RequestBody SalesforceConnectDto salesforceConnectDto) { - logger.info("Salesforce connection request received"); + RedirectUrlFormatterDto redirectUrlFormatterDto = redirectUrlService + .getSalesforceOauthUrl(salesforceRedirectUrlDto); - AuthServiceDto authServiceResponse = authService.connectToSalesforce(salesforceConnectDto, request); + return ResponseEntity.ok().body(redirectUrlFormatterDto); + } - HttpHeaders headers = new HttpHeaders(); - headers = cookieHelper.setUserCookie(authServiceResponse.getCurrentUserLoginCookie(), headers); + @PostMapping("/salesforce/connect") + public ResponseEntity connectToSalesforce(HttpServletRequest request, + @Valid @RequestBody SalesforceConnectDto salesforceConnectDto) { + logger.info("Salesforce connection request received"); - SalesforceConnectFormatterDto salesforceConnectResponse = new SalesforceConnectFormatterDto(); - salesforceConnectResponse.setCurrentUser(authServiceResponse.getCurrentUser()); + AuthServiceDto authServiceResponse = authService.connectToSalesforce(salesforceConnectDto, request); - return ResponseEntity.ok().headers(headers).body(salesforceConnectResponse); - } + HttpHeaders headers = new HttpHeaders(); + headers = cookieHelper.setUserCookie(authServiceResponse.getCurrentUserLoginCookie(), headers); - @PostMapping("/logout") - public ResponseEntity logout(HttpServletRequest request) { - logger.info("User logout request received"); + SalesforceConnectFormatterDto salesforceConnectResponse = new SalesforceConnectFormatterDto(); + salesforceConnectResponse.setCurrentUser(authServiceResponse.getCurrentUser()); - HttpHeaders headers = new HttpHeaders(); - headers = cookieHelper.clearUserCookie(headers); + return ResponseEntity.ok().headers(headers).body(salesforceConnectResponse); + } + + @PostMapping("/logout") + public ResponseEntity logout(HttpServletRequest request) { + logger.info("User logout request received"); + + HttpHeaders headers = new HttpHeaders(); + headers = cookieHelper.clearUserCookie(headers); + + return ResponseEntity.ok().headers(headers).body(null); + } - return ResponseEntity.ok().headers(headers).body(null); - } } diff --git a/src/main/java/com/salessparrow/api/controllers/CrmOrganizationUserController.java b/src/main/java/com/salessparrow/api/controllers/CrmOrganizationUserController.java index 918628f3..53fce632 100644 --- a/src/main/java/com/salessparrow/api/controllers/CrmOrganizationUserController.java +++ b/src/main/java/com/salessparrow/api/controllers/CrmOrganizationUserController.java @@ -17,25 +17,24 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; - @RestController @RequestMapping("/api/v1/crm-organization-users") public class CrmOrganizationUserController { - Logger logger = LoggerFactory.getLogger(CrmOrganizationUserController.class); - - @Autowired - private GetCrmOrganizationUsersList getCrmOrganizationUsersList; - - @GetMapping("") - public ResponseEntity getCrmOrganizationUsers( - HttpServletRequest request, - @Valid @ModelAttribute GetCrmOrganizationUsersDto CrmOrganizationUsersDto - ){ - logger.info("Get list of crm organization users request received"); - - GetCrmOrganizationUsersFormatterDto getCrmOrganizationUsersFormatterDto = getCrmOrganizationUsersList.getCrmOrganizationUsers(request, CrmOrganizationUsersDto); - - return ResponseEntity.ok().body(getCrmOrganizationUsersFormatterDto); - } - + + Logger logger = LoggerFactory.getLogger(CrmOrganizationUserController.class); + + @Autowired + private GetCrmOrganizationUsersList getCrmOrganizationUsersList; + + @GetMapping("") + public ResponseEntity getCrmOrganizationUsers(HttpServletRequest request, + @Valid @ModelAttribute GetCrmOrganizationUsersDto CrmOrganizationUsersDto) { + logger.info("Get list of crm organization users request received"); + + GetCrmOrganizationUsersFormatterDto getCrmOrganizationUsersFormatterDto = getCrmOrganizationUsersList + .getCrmOrganizationUsers(request, CrmOrganizationUsersDto); + + return ResponseEntity.ok().body(getCrmOrganizationUsersFormatterDto); + } + } diff --git a/src/main/java/com/salessparrow/api/controllers/HealthCheck.java b/src/main/java/com/salessparrow/api/controllers/HealthCheck.java index e8213da9..e848c85b 100644 --- a/src/main/java/com/salessparrow/api/controllers/HealthCheck.java +++ b/src/main/java/com/salessparrow/api/controllers/HealthCheck.java @@ -8,9 +8,10 @@ @RestController @RequestMapping("/api/v1/health-check") public class HealthCheck { - - @GetMapping("") - public ResponseEntity HealthCheck() { - return ResponseEntity.ok().body("OK"); - } + + @GetMapping("") + public ResponseEntity HealthCheck() { + return ResponseEntity.ok().body("OK"); + } + } diff --git a/src/main/java/com/salessparrow/api/controllers/SuggestionsController.java b/src/main/java/com/salessparrow/api/controllers/SuggestionsController.java index aca6a157..0bef0c1e 100644 --- a/src/main/java/com/salessparrow/api/controllers/SuggestionsController.java +++ b/src/main/java/com/salessparrow/api/controllers/SuggestionsController.java @@ -19,17 +19,17 @@ @Validated public class SuggestionsController { - private Logger logger = org.slf4j.LoggerFactory.getLogger(SuggestionsController.class); + private Logger logger = org.slf4j.LoggerFactory.getLogger(SuggestionsController.class); - @Autowired - private CrmActionsSuggestionsService crmActionsSuggestionsService; + @Autowired + private CrmActionsSuggestionsService crmActionsSuggestionsService; - @PostMapping("/crm-actions") - public CrmActionSuggestionsFormatterDto getCrmActionSuggestions( - @Valid @RequestBody CrmActionsSuggestionsDto crmActionsSuggestionsDto) { - logger.info("Crm actions suggestions request received"); + @PostMapping("/crm-actions") + public CrmActionSuggestionsFormatterDto getCrmActionSuggestions( + @Valid @RequestBody CrmActionsSuggestionsDto crmActionsSuggestionsDto) { + logger.info("Crm actions suggestions request received"); - return crmActionsSuggestionsService.getSuggestions(crmActionsSuggestionsDto); - } + return crmActionsSuggestionsService.getSuggestions(crmActionsSuggestionsDto); + } } diff --git a/src/main/java/com/salessparrow/api/controllers/UserController.java b/src/main/java/com/salessparrow/api/controllers/UserController.java index cad29cdc..7d4385f1 100644 --- a/src/main/java/com/salessparrow/api/controllers/UserController.java +++ b/src/main/java/com/salessparrow/api/controllers/UserController.java @@ -15,15 +15,16 @@ @RequestMapping("/api/v1/users") public class UserController { - @Autowired - private GetCurrentUserService getCurrentUserService; + @Autowired + private GetCurrentUserService getCurrentUserService; - @GetMapping("/current") - public ResponseEntity GetCurrentUser(HttpServletRequest request) { + @GetMapping("/current") + public ResponseEntity GetCurrentUser(HttpServletRequest request) { - GetCurrentUserFormatterDto getCurrentUserFormatterDto = new GetCurrentUserFormatterDto(); - getCurrentUserFormatterDto.setCurrentUser(getCurrentUserService.getCurrentUser(request)); + GetCurrentUserFormatterDto getCurrentUserFormatterDto = new GetCurrentUserFormatterDto(); + getCurrentUserFormatterDto.setCurrentUser(getCurrentUserService.getCurrentUser(request)); + + return ResponseEntity.ok().body(getCurrentUserFormatterDto); + } - return ResponseEntity.ok().body(getCurrentUserFormatterDto); - } } diff --git a/src/main/java/com/salessparrow/api/domain/SalesforceOauthToken.java b/src/main/java/com/salessparrow/api/domain/SalesforceOauthToken.java index b130f0b0..2916fcc6 100644 --- a/src/main/java/com/salessparrow/api/domain/SalesforceOauthToken.java +++ b/src/main/java/com/salessparrow/api/domain/SalesforceOauthToken.java @@ -18,90 +18,94 @@ /** * SalesforceOauthToken model. - * + * * Cached data is serialized into bytes and stored in cache and deserialize when - * retrieved. - * Hence, the class must implement Serializable. + * retrieved. Hence, the class must implement Serializable. */ @Data @NoArgsConstructor @DynamoDBTable(tableName = "salesforce_oauth_tokens") public class SalesforceOauthToken implements Serializable { - public enum Status { - ACTIVE(1), - DELETED(2); + public enum Status { - private final int value; - private static final Map map = new HashMap<>(); + ACTIVE(1), DELETED(2); - static { - for (Status status : Status.values()) { - map.put(status.value, status); - } - } + private final int value; - Status(int value) { - this.value = value; - } + private static final Map map = new HashMap<>(); - public int getValue() { - return value; - } + static { + for (Status status : Status.values()) { + map.put(status.value, status); + } + } - public static Status valueOf(int value) { - return map.get(value); - } - } + Status(int value) { + this.value = value; + } - @DynamoDBHashKey(attributeName = "external_user_id") - private String externalUserId; + public int getValue() { + return value; + } - @DynamoDBAttribute(attributeName = "identity_url") - private String identityUrl; + public static Status valueOf(int value) { + return map.get(value); + } - @DynamoDBAttribute(attributeName = "access_token") - private String accessToken; + } - @DynamoDBAttribute(attributeName = "refresh_token") - private String refreshToken; + @DynamoDBHashKey(attributeName = "external_user_id") + private String externalUserId; - @DynamoDBAttribute(attributeName = "signature") - private String signature; + @DynamoDBAttribute(attributeName = "identity_url") + private String identityUrl; - @DynamoDBAttribute(attributeName = "id_token") - private String idToken; + @DynamoDBAttribute(attributeName = "access_token") + private String accessToken; - @DynamoDBAttribute(attributeName = "instance_url") - private String instanceUrl; + @DynamoDBAttribute(attributeName = "refresh_token") + private String refreshToken; - @DynamoDBTypeConverted(converter = StatusEnumConverter.class) - @DynamoDBAttribute(attributeName = "status") - private Status status; + @DynamoDBAttribute(attributeName = "signature") + private String signature; - @DynamoDBAttribute(attributeName = "issued_at") - private Long issuedAt; + @DynamoDBAttribute(attributeName = "id_token") + private String idToken; - @DynamoDBAutoGeneratedTimestamp(strategy = DynamoDBAutoGenerateStrategy.CREATE) - @DynamoDBAttribute(attributeName = "created_at") - private Date createdAt; + @DynamoDBAttribute(attributeName = "instance_url") + private String instanceUrl; - @DynamoDBAutoGeneratedTimestamp(strategy = DynamoDBAutoGenerateStrategy.ALWAYS) - @DynamoDBAttribute(attributeName = "updated_at") - private Date updatedAt; + @DynamoDBTypeConverted(converter = StatusEnumConverter.class) + @DynamoDBAttribute(attributeName = "status") + private Status status; - /** - * Converts Status enum to Integer and vice versa. - */ - public static class StatusEnumConverter implements DynamoDBTypeConverter { - @Override - public Integer convert(Status status) { - return status.getValue(); - } + @DynamoDBAttribute(attributeName = "issued_at") + private Long issuedAt; + + @DynamoDBAutoGeneratedTimestamp(strategy = DynamoDBAutoGenerateStrategy.CREATE) + @DynamoDBAttribute(attributeName = "created_at") + private Date createdAt; + + @DynamoDBAutoGeneratedTimestamp(strategy = DynamoDBAutoGenerateStrategy.ALWAYS) + @DynamoDBAttribute(attributeName = "updated_at") + private Date updatedAt; + + /** + * Converts Status enum to Integer and vice versa. + */ + public static class StatusEnumConverter implements DynamoDBTypeConverter { + + @Override + public Integer convert(Status status) { + return status.getValue(); + } + + @Override + public Status unconvert(Integer value) { + return Status.valueOf(value); + } + + } - @Override - public Status unconvert(Integer value) { - return Status.valueOf(value); - } - } } diff --git a/src/main/java/com/salessparrow/api/domain/SalesforceOrganization.java b/src/main/java/com/salessparrow/api/domain/SalesforceOrganization.java index f0de80ff..97297a21 100644 --- a/src/main/java/com/salessparrow/api/domain/SalesforceOrganization.java +++ b/src/main/java/com/salessparrow/api/domain/SalesforceOrganization.java @@ -21,59 +21,64 @@ @DynamoDBTable(tableName = "salesforce_organizations") public class SalesforceOrganization implements Serializable { - public enum Status { - ACTIVE(1), - DELETED(2); - - private final int value; - private static final Map map = new HashMap<>(); - - static { - for (Status status : Status.values()) { - map.put(status.value, status); - } - } - - Status(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - - public static Status valueOf(int value) { - return map.get(value); - } - } - - @DynamoDBHashKey(attributeName = "external_organization_id") - private String externalOrganizationId; - - @DynamoDBTypeConverted(converter = StatusEnumConverter.class) - @DynamoDBAttribute(attributeName = "status") - private Status status; - - @DynamoDBAutoGeneratedTimestamp(strategy = DynamoDBAutoGenerateStrategy.CREATE) - @DynamoDBAttribute(attributeName = "created_at") - private Date createdAt; - - @DynamoDBAutoGeneratedTimestamp(strategy = DynamoDBAutoGenerateStrategy.ALWAYS) - @DynamoDBAttribute(attributeName = "updated_at") - private Date updatedAt; - - /** - * Converts Status enum to Integer and vice versa. - */ - public static class StatusEnumConverter implements DynamoDBTypeConverter { - @Override - public Integer convert(Status status) { - return status.getValue(); - } - - @Override - public Status unconvert(Integer value) { - return Status.valueOf(value); - } - } + public enum Status { + + ACTIVE(1), DELETED(2); + + private final int value; + + private static final Map map = new HashMap<>(); + + static { + for (Status status : Status.values()) { + map.put(status.value, status); + } + } + + Status(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + public static Status valueOf(int value) { + return map.get(value); + } + + } + + @DynamoDBHashKey(attributeName = "external_organization_id") + private String externalOrganizationId; + + @DynamoDBTypeConverted(converter = StatusEnumConverter.class) + @DynamoDBAttribute(attributeName = "status") + private Status status; + + @DynamoDBAutoGeneratedTimestamp(strategy = DynamoDBAutoGenerateStrategy.CREATE) + @DynamoDBAttribute(attributeName = "created_at") + private Date createdAt; + + @DynamoDBAutoGeneratedTimestamp(strategy = DynamoDBAutoGenerateStrategy.ALWAYS) + @DynamoDBAttribute(attributeName = "updated_at") + private Date updatedAt; + + /** + * Converts Status enum to Integer and vice versa. + */ + public static class StatusEnumConverter implements DynamoDBTypeConverter { + + @Override + public Integer convert(Status status) { + return status.getValue(); + } + + @Override + public Status unconvert(Integer value) { + return Status.valueOf(value); + } + + } + } diff --git a/src/main/java/com/salessparrow/api/domain/SalesforceUser.java b/src/main/java/com/salessparrow/api/domain/SalesforceUser.java index 89934262..6a5f84dd 100644 --- a/src/main/java/com/salessparrow/api/domain/SalesforceUser.java +++ b/src/main/java/com/salessparrow/api/domain/SalesforceUser.java @@ -19,94 +19,98 @@ /** * SalesforceUser model. - * + * * Cached data is serialized into bytes and stored in cache and deserialize when - * retrieved. - * Hence, the class must implement Serializable. + * retrieved. Hence, the class must implement Serializable. */ @Data @NoArgsConstructor @DynamoDBTable(tableName = "salesforce_users") public class SalesforceUser implements User, Serializable { - public enum Status { - ACTIVE(1), - DELETED(2); + public enum Status { - private final int value; - private static final Map map = new HashMap<>(); + ACTIVE(1), DELETED(2); - static { - for (Status status : Status.values()) { - map.put(status.value, status); - } - } + private final int value; - Status(int value) { - this.value = value; - } + private static final Map map = new HashMap<>(); - public int getValue() { - return value; - } + static { + for (Status status : Status.values()) { + map.put(status.value, status); + } + } - public static Status valueOf(int value) { - return map.get(value); - } - } + Status(int value) { + this.value = value; + } - @DynamoDBHashKey(attributeName = "external_user_id") - private String externalUserId; + public int getValue() { + return value; + } - @DynamoDBAttribute(attributeName = "identity_url") - private String identityUrl; + public static Status valueOf(int value) { + return map.get(value); + } - @DynamoDBAttribute(attributeName = "external_organization_id") - private String externalOrganizationId; + } - @DynamoDBAttribute(attributeName = "name") - private String name; + @DynamoDBHashKey(attributeName = "external_user_id") + private String externalUserId; - @DynamoDBAttribute(attributeName = "email") - private String email; + @DynamoDBAttribute(attributeName = "identity_url") + private String identityUrl; - @DynamoDBAttribute(attributeName = "user_kind") - private String userKind; + @DynamoDBAttribute(attributeName = "external_organization_id") + private String externalOrganizationId; - @DynamoDBAttribute(attributeName = "cookie_token") - private String cookieToken; + @DynamoDBAttribute(attributeName = "name") + private String name; - @DynamoDBAttribute(attributeName = "encryption_salt") - private String encryptionSalt; + @DynamoDBAttribute(attributeName = "email") + private String email; - @DynamoDBTypeConverted(converter = StatusEnumConverter.class) - @DynamoDBAttribute(attributeName = "status") - private Status status; + @DynamoDBAttribute(attributeName = "user_kind") + private String userKind; - @DynamoDBAutoGeneratedTimestamp(strategy = DynamoDBAutoGenerateStrategy.CREATE) - @DynamoDBAttribute(attributeName = "created_at") - private Date createdAt; + @DynamoDBAttribute(attributeName = "cookie_token") + private String cookieToken; - @DynamoDBAutoGeneratedTimestamp(strategy = DynamoDBAutoGenerateStrategy.ALWAYS) - @DynamoDBAttribute(attributeName = "updated_at") - private Date updatedAt; + @DynamoDBAttribute(attributeName = "encryption_salt") + private String encryptionSalt; - /** - * Converts Status enum to Integer and vice versa. - */ - public static class StatusEnumConverter implements DynamoDBTypeConverter { - @Override - public Integer convert(Status status) { - return status.getValue(); - } + @DynamoDBTypeConverted(converter = StatusEnumConverter.class) + @DynamoDBAttribute(attributeName = "status") + private Status status; - @Override - public Status unconvert(Integer value) { - return Status.valueOf(value); - } - } + @DynamoDBAutoGeneratedTimestamp(strategy = DynamoDBAutoGenerateStrategy.CREATE) + @DynamoDBAttribute(attributeName = "created_at") + private Date createdAt; + + @DynamoDBAutoGeneratedTimestamp(strategy = DynamoDBAutoGenerateStrategy.ALWAYS) + @DynamoDBAttribute(attributeName = "updated_at") + private Date updatedAt; + + /** + * Converts Status enum to Integer and vice versa. + */ + public static class StatusEnumConverter implements DynamoDBTypeConverter { + + @Override + public Integer convert(Status status) { + return status.getValue(); + } + + @Override + public Status unconvert(Integer value) { + return Status.valueOf(value); + } + + } + + public String getId(String externalUserId) { + return UserConstants.SALESFORCE_USER_KIND + "-" + externalUserId; + } - public String getId(String externalUserId) { - return UserConstants.SALESFORCE_USER_KIND + "-" + externalUserId; - } } \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/domain/User.java b/src/main/java/com/salessparrow/api/domain/User.java index cfcfa90c..a141ea4d 100644 --- a/src/main/java/com/salessparrow/api/domain/User.java +++ b/src/main/java/com/salessparrow/api/domain/User.java @@ -5,16 +5,16 @@ */ public interface User { - String getExternalUserId(); + String getExternalUserId(); - String getEmail(); + String getEmail(); - String getName(); + String getName(); - String getUserKind(); + String getUserKind(); - String getCookieToken(); + String getCookieToken(); - String getEncryptionSalt(); + String getEncryptionSalt(); } diff --git a/src/main/java/com/salessparrow/api/dto/entities/AccountEntity.java b/src/main/java/com/salessparrow/api/dto/entities/AccountEntity.java index 49b615f9..8157b40f 100644 --- a/src/main/java/com/salessparrow/api/dto/entities/AccountEntity.java +++ b/src/main/java/com/salessparrow/api/dto/entities/AccountEntity.java @@ -4,6 +4,9 @@ @Data public class AccountEntity { - private String id; - private String name; + + private String id; + + private String name; + } \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/dto/entities/AddTaskSuggestionEntityDto.java b/src/main/java/com/salessparrow/api/dto/entities/AddTaskSuggestionEntityDto.java index 84c459d8..6f631232 100644 --- a/src/main/java/com/salessparrow/api/dto/entities/AddTaskSuggestionEntityDto.java +++ b/src/main/java/com/salessparrow/api/dto/entities/AddTaskSuggestionEntityDto.java @@ -11,6 +11,9 @@ @Data @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) public class AddTaskSuggestionEntityDto { - private String description; - private String dueDate; + + private String description; + + private String dueDate; + } diff --git a/src/main/java/com/salessparrow/api/dto/entities/CrmOrganizationUserEntity.java b/src/main/java/com/salessparrow/api/dto/entities/CrmOrganizationUserEntity.java index e9355172..bb2d65b9 100644 --- a/src/main/java/com/salessparrow/api/dto/entities/CrmOrganizationUserEntity.java +++ b/src/main/java/com/salessparrow/api/dto/entities/CrmOrganizationUserEntity.java @@ -4,6 +4,9 @@ @Data public class CrmOrganizationUserEntity { - private String id; - private String name; + + private String id; + + private String name; + } diff --git a/src/main/java/com/salessparrow/api/dto/entities/CurrentUserEntityDto.java b/src/main/java/com/salessparrow/api/dto/entities/CurrentUserEntityDto.java index a7a5aedb..77412bd5 100644 --- a/src/main/java/com/salessparrow/api/dto/entities/CurrentUserEntityDto.java +++ b/src/main/java/com/salessparrow/api/dto/entities/CurrentUserEntityDto.java @@ -2,39 +2,40 @@ /** * Salesforce connect formatter DTO. - * + * * @param current_user - * * @return SalesforceConnectFormatterDto */ public class CurrentUserEntityDto { - private String id; - private String name; - private String email; + private String id; - public String getId() { - return id; - } + private String name; - public void setId(String id) { - this.id = id; - } + private String email; - public String getName() { - return name; - } + public String getId() { + return id; + } - public void setName(String name) { - this.name = name; - } + public void setId(String id) { + this.id = id; + } - public String getEmail() { - return email; - } + public String getName() { + return name; + } - public void setEmail(String email) { - this.email = email; - } + public void setName(String name) { + this.name = name; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } } diff --git a/src/main/java/com/salessparrow/api/dto/entities/NoteDetailEntity.java b/src/main/java/com/salessparrow/api/dto/entities/NoteDetailEntity.java index 34794e18..bc327da1 100644 --- a/src/main/java/com/salessparrow/api/dto/entities/NoteDetailEntity.java +++ b/src/main/java/com/salessparrow/api/dto/entities/NoteDetailEntity.java @@ -13,18 +13,23 @@ @Data @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) public class NoteDetailEntity { - private String id; - private String creator; - private String text; - private Date lastModifiedTime; - - public NoteDetailEntity(){ - } - - public NoteDetailEntity(String id, String creator, String text, Date lastModifiedTime){ - this.id = id; - this.creator = creator; - this.text = text; - this.lastModifiedTime = lastModifiedTime; - } + + private String id; + + private String creator; + + private String text; + + private Date lastModifiedTime; + + public NoteDetailEntity() { + } + + public NoteDetailEntity(String id, String creator, String text, Date lastModifiedTime) { + this.id = id; + this.creator = creator; + this.text = text; + this.lastModifiedTime = lastModifiedTime; + } + } diff --git a/src/main/java/com/salessparrow/api/dto/entities/NoteEntity.java b/src/main/java/com/salessparrow/api/dto/entities/NoteEntity.java index 77897761..747cd761 100644 --- a/src/main/java/com/salessparrow/api/dto/entities/NoteEntity.java +++ b/src/main/java/com/salessparrow/api/dto/entities/NoteEntity.java @@ -13,19 +13,23 @@ @Data @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) public class NoteEntity { - private String id; - private String creator; - private String textPreview; - private Date lastModifiedTime; - - public NoteEntity() { - } - - public NoteEntity(String id, String creator, String text_preview, Date last_modified_time) { - this.id = id; - this.creator = creator; - this.textPreview = text_preview; - this.lastModifiedTime = last_modified_time; - } + + private String id; + + private String creator; + + private String textPreview; + + private Date lastModifiedTime; + + public NoteEntity() { + } + + public NoteEntity(String id, String creator, String text_preview, Date last_modified_time) { + this.id = id; + this.creator = creator; + this.textPreview = text_preview; + this.lastModifiedTime = last_modified_time; + } } diff --git a/src/main/java/com/salessparrow/api/dto/entities/TaskEntity.java b/src/main/java/com/salessparrow/api/dto/entities/TaskEntity.java index 958d4cd3..ba1a199e 100644 --- a/src/main/java/com/salessparrow/api/dto/entities/TaskEntity.java +++ b/src/main/java/com/salessparrow/api/dto/entities/TaskEntity.java @@ -13,10 +13,17 @@ @Data @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) public class TaskEntity { - private String id; - private String creatorName; - private String description; - private String dueDate; - private String crmOrganizationUserName; - private Date lastModifiedTime; + + private String id; + + private String creatorName; + + private String description; + + private String dueDate; + + private String crmOrganizationUserName; + + private Date lastModifiedTime; + } diff --git a/src/main/java/com/salessparrow/api/dto/formatter/CreateNoteFormatterDto.java b/src/main/java/com/salessparrow/api/dto/formatter/CreateNoteFormatterDto.java index 1cfc1cd4..7faa1ebd 100644 --- a/src/main/java/com/salessparrow/api/dto/formatter/CreateNoteFormatterDto.java +++ b/src/main/java/com/salessparrow/api/dto/formatter/CreateNoteFormatterDto.java @@ -11,5 +11,7 @@ @Data @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) public class CreateNoteFormatterDto { - private String noteId; + + private String noteId; + } \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/dto/formatter/CreateTaskFormatterDto.java b/src/main/java/com/salessparrow/api/dto/formatter/CreateTaskFormatterDto.java index 690ddabd..2dabdab6 100644 --- a/src/main/java/com/salessparrow/api/dto/formatter/CreateTaskFormatterDto.java +++ b/src/main/java/com/salessparrow/api/dto/formatter/CreateTaskFormatterDto.java @@ -8,5 +8,7 @@ @Data @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) public class CreateTaskFormatterDto { - private String taskId; + + private String taskId; + } diff --git a/src/main/java/com/salessparrow/api/dto/formatter/CrmActionSuggestionsFormatterDto.java b/src/main/java/com/salessparrow/api/dto/formatter/CrmActionSuggestionsFormatterDto.java index eaf968af..36d39ad7 100644 --- a/src/main/java/com/salessparrow/api/dto/formatter/CrmActionSuggestionsFormatterDto.java +++ b/src/main/java/com/salessparrow/api/dto/formatter/CrmActionSuggestionsFormatterDto.java @@ -9,10 +9,13 @@ import lombok.Data; /** - * CrmActionSuggestionsFormatterDto is a class for the formatter of the crm action suggestions. + * CrmActionSuggestionsFormatterDto is a class for the formatter of the crm action + * suggestions. */ @Data @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) public class CrmActionSuggestionsFormatterDto { - private List addTaskSuggestions; + + private List addTaskSuggestions; + } diff --git a/src/main/java/com/salessparrow/api/dto/formatter/GetAccountsFormatterDto.java b/src/main/java/com/salessparrow/api/dto/formatter/GetAccountsFormatterDto.java index 7a0db924..c3db2846 100644 --- a/src/main/java/com/salessparrow/api/dto/formatter/GetAccountsFormatterDto.java +++ b/src/main/java/com/salessparrow/api/dto/formatter/GetAccountsFormatterDto.java @@ -12,6 +12,9 @@ @Data @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) public class GetAccountsFormatterDto { - private List accountIds; - private Map accountMapById; + + private List accountIds; + + private Map accountMapById; + } \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/dto/formatter/GetCrmOrganizationUsersFormatterDto.java b/src/main/java/com/salessparrow/api/dto/formatter/GetCrmOrganizationUsersFormatterDto.java index 8281b132..2f5f9841 100644 --- a/src/main/java/com/salessparrow/api/dto/formatter/GetCrmOrganizationUsersFormatterDto.java +++ b/src/main/java/com/salessparrow/api/dto/formatter/GetCrmOrganizationUsersFormatterDto.java @@ -12,6 +12,9 @@ @Data @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) public class GetCrmOrganizationUsersFormatterDto { - private List crmOrganizationUserIds; - private Map crmOrganizationUserMapById; + + private List crmOrganizationUserIds; + + private Map crmOrganizationUserMapById; + } diff --git a/src/main/java/com/salessparrow/api/dto/formatter/GetCurrentUserFormatterDto.java b/src/main/java/com/salessparrow/api/dto/formatter/GetCurrentUserFormatterDto.java index bf422cfe..b135be02 100644 --- a/src/main/java/com/salessparrow/api/dto/formatter/GetCurrentUserFormatterDto.java +++ b/src/main/java/com/salessparrow/api/dto/formatter/GetCurrentUserFormatterDto.java @@ -8,13 +8,14 @@ /** * Get current user formatter DTO. - * + * * @param current_user - * * @return GetCurrentUserFormatterDto */ @Data @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) public class GetCurrentUserFormatterDto { - private CurrentUserEntityDto currentUser; + + private CurrentUserEntityDto currentUser; + } \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/dto/formatter/GetNoteDetailsFormatterDto.java b/src/main/java/com/salessparrow/api/dto/formatter/GetNoteDetailsFormatterDto.java index 92425e03..3424b6ae 100644 --- a/src/main/java/com/salessparrow/api/dto/formatter/GetNoteDetailsFormatterDto.java +++ b/src/main/java/com/salessparrow/api/dto/formatter/GetNoteDetailsFormatterDto.java @@ -10,9 +10,10 @@ @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) public class GetNoteDetailsFormatterDto { - private NoteDetailEntity noteDetail; - - public GetNoteDetailsFormatterDto(NoteDetailEntity noteDetail){ - this.noteDetail = noteDetail; - } + private NoteDetailEntity noteDetail; + + public GetNoteDetailsFormatterDto(NoteDetailEntity noteDetail) { + this.noteDetail = noteDetail; + } + } diff --git a/src/main/java/com/salessparrow/api/dto/formatter/GetNotesListFormatterDto.java b/src/main/java/com/salessparrow/api/dto/formatter/GetNotesListFormatterDto.java index e9390d75..884f1cd0 100644 --- a/src/main/java/com/salessparrow/api/dto/formatter/GetNotesListFormatterDto.java +++ b/src/main/java/com/salessparrow/api/dto/formatter/GetNotesListFormatterDto.java @@ -15,14 +15,17 @@ @Data @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) public class GetNotesListFormatterDto { - private List noteIds; - private Map noteMapById; - public GetNotesListFormatterDto(){ - } + private List noteIds; + + private Map noteMapById; + + public GetNotesListFormatterDto() { + } + + public GetNotesListFormatterDto(List noteIds, Map noteMapById) { + this.noteIds = noteIds; + this.noteMapById = noteMapById; + } - public GetNotesListFormatterDto(List noteIds, Map noteMapById){ - this.noteIds = noteIds; - this.noteMapById = noteMapById; - } } diff --git a/src/main/java/com/salessparrow/api/dto/formatter/GetTasksListFormatterDto.java b/src/main/java/com/salessparrow/api/dto/formatter/GetTasksListFormatterDto.java index 61913205..51e100e5 100644 --- a/src/main/java/com/salessparrow/api/dto/formatter/GetTasksListFormatterDto.java +++ b/src/main/java/com/salessparrow/api/dto/formatter/GetTasksListFormatterDto.java @@ -15,6 +15,9 @@ @Data @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) public class GetTasksListFormatterDto { - private List taskIds; - private Map taskMapById; + + private List taskIds; + + private Map taskMapById; + } diff --git a/src/main/java/com/salessparrow/api/dto/formatter/RedirectUrlFormatterDto.java b/src/main/java/com/salessparrow/api/dto/formatter/RedirectUrlFormatterDto.java index 42e7c4e7..f2b1db26 100644 --- a/src/main/java/com/salessparrow/api/dto/formatter/RedirectUrlFormatterDto.java +++ b/src/main/java/com/salessparrow/api/dto/formatter/RedirectUrlFormatterDto.java @@ -7,13 +7,14 @@ /** * Redirect url formatter DTO. - * + * * @param url - * * @return RedirectUrlFormatterDto */ @Data @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) public class RedirectUrlFormatterDto { - private String url; + + private String url; + } diff --git a/src/main/java/com/salessparrow/api/dto/formatter/SalesforceConnectFormatterDto.java b/src/main/java/com/salessparrow/api/dto/formatter/SalesforceConnectFormatterDto.java index bfdfb918..e25bf0a9 100644 --- a/src/main/java/com/salessparrow/api/dto/formatter/SalesforceConnectFormatterDto.java +++ b/src/main/java/com/salessparrow/api/dto/formatter/SalesforceConnectFormatterDto.java @@ -8,17 +8,17 @@ /** * Salesforce connect formatter DTO. - * + * * @param current_user - * * @return SalesforceConnectFormatterDto */ @Data @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) public class SalesforceConnectFormatterDto { - public SalesforceConnectFormatterDto() { - } - private CurrentUserEntityDto currentUser; + public SalesforceConnectFormatterDto() { + } + + private CurrentUserEntityDto currentUser; } diff --git a/src/main/java/com/salessparrow/api/dto/requestMapper/CreateAccountTaskDto.java b/src/main/java/com/salessparrow/api/dto/requestMapper/CreateAccountTaskDto.java index b1f6be7b..dc432867 100644 --- a/src/main/java/com/salessparrow/api/dto/requestMapper/CreateAccountTaskDto.java +++ b/src/main/java/com/salessparrow/api/dto/requestMapper/CreateAccountTaskDto.java @@ -12,13 +12,14 @@ @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) public class CreateAccountTaskDto { - @NotBlank(message = "missing_crm_organization_user_id") - private String crmOrganizationUserId; + @NotBlank(message = "missing_crm_organization_user_id") + private String crmOrganizationUserId; - @NotBlank(message = "missing_description") - @Size(max = 32000, message = "description_too_long") - private String description; + @NotBlank(message = "missing_description") + @Size(max = 32000, message = "description_too_long") + private String description; + + @ValidDateFormat(message = "invalid_due_date") + private String dueDate; - @ValidDateFormat(message = "invalid_due_date") - private String dueDate; } diff --git a/src/main/java/com/salessparrow/api/dto/requestMapper/CrmActionsSuggestionsDto.java b/src/main/java/com/salessparrow/api/dto/requestMapper/CrmActionsSuggestionsDto.java index 8de0553b..a38fab64 100644 --- a/src/main/java/com/salessparrow/api/dto/requestMapper/CrmActionsSuggestionsDto.java +++ b/src/main/java/com/salessparrow/api/dto/requestMapper/CrmActionsSuggestionsDto.java @@ -10,7 +10,9 @@ */ @Data public class CrmActionsSuggestionsDto { - @NotBlank(message = "missing_text") - @Length(max = 12000, message = "text_too_long") - private String text; + + @NotBlank(message = "missing_text") + @Length(max = 12000, message = "text_too_long") + private String text; + } diff --git a/src/main/java/com/salessparrow/api/dto/requestMapper/GetAccountsDto.java b/src/main/java/com/salessparrow/api/dto/requestMapper/GetAccountsDto.java index 573faf67..a9c434d3 100644 --- a/src/main/java/com/salessparrow/api/dto/requestMapper/GetAccountsDto.java +++ b/src/main/java/com/salessparrow/api/dto/requestMapper/GetAccountsDto.java @@ -5,6 +5,8 @@ @Data public class GetAccountsDto { - @Size(max = 200, message = "search_term_too_long") - private String q; + + @Size(max = 200, message = "search_term_too_long") + private String q; + } diff --git a/src/main/java/com/salessparrow/api/dto/requestMapper/GetCrmOrganizationUsersDto.java b/src/main/java/com/salessparrow/api/dto/requestMapper/GetCrmOrganizationUsersDto.java index 847394c4..7d3ee84e 100644 --- a/src/main/java/com/salessparrow/api/dto/requestMapper/GetCrmOrganizationUsersDto.java +++ b/src/main/java/com/salessparrow/api/dto/requestMapper/GetCrmOrganizationUsersDto.java @@ -5,6 +5,8 @@ @Data public class GetCrmOrganizationUsersDto { - @Size(max = 200, message = "search_term_too_long") - private String q; + + @Size(max = 200, message = "search_term_too_long") + private String q; + } diff --git a/src/main/java/com/salessparrow/api/dto/requestMapper/NoteDto.java b/src/main/java/com/salessparrow/api/dto/requestMapper/NoteDto.java index 0f3bb161..44ca28f6 100644 --- a/src/main/java/com/salessparrow/api/dto/requestMapper/NoteDto.java +++ b/src/main/java/com/salessparrow/api/dto/requestMapper/NoteDto.java @@ -7,10 +7,9 @@ @Data public class NoteDto { - @NotBlank(message = "missing_text") - @Length(max = 12000, message = "text_too_long") - private String text; -} - + @NotBlank(message = "missing_text") + @Length(max = 12000, message = "text_too_long") + private String text; +} diff --git a/src/main/java/com/salessparrow/api/dto/requestMapper/SalesforceConnectDto.java b/src/main/java/com/salessparrow/api/dto/requestMapper/SalesforceConnectDto.java index 5b5dec38..efc21d0f 100644 --- a/src/main/java/com/salessparrow/api/dto/requestMapper/SalesforceConnectDto.java +++ b/src/main/java/com/salessparrow/api/dto/requestMapper/SalesforceConnectDto.java @@ -6,40 +6,39 @@ /** * Salesforce connect DTO. - * + * * @param code * @param redirect_uri - * * @return SalesforceConnectDto */ public class SalesforceConnectDto { - @NotBlank(message = "missing_code") - private String code; + @NotBlank(message = "missing_code") + private String code; - @NotBlank(message = "missing_redirect_uri") - @ValidRedirectUri(message = "invalid_redirect_uri") - private String redirect_uri; + @NotBlank(message = "missing_redirect_uri") + @ValidRedirectUri(message = "invalid_redirect_uri") + private String redirect_uri; - public String getCode() { - return code; - } + public String getCode() { + return code; + } - public void setCode(String code) { - this.code = code; - } + public void setCode(String code) { + this.code = code; + } - public String getRedirect_uri() { - return redirect_uri; - } + public String getRedirect_uri() { + return redirect_uri; + } - public void setRedirect_uri(String redirect_uri) { - this.redirect_uri = redirect_uri; - } + public void setRedirect_uri(String redirect_uri) { + this.redirect_uri = redirect_uri; + } - @Override - public String toString() { - return "SalesforceConnectDto [code=" + code + ", redirect_uri=" + redirect_uri + "]"; - } + @Override + public String toString() { + return "SalesforceConnectDto [code=" + code + ", redirect_uri=" + redirect_uri + "]"; + } } diff --git a/src/main/java/com/salessparrow/api/dto/requestMapper/SalesforceRedirectUrlDto.java b/src/main/java/com/salessparrow/api/dto/requestMapper/SalesforceRedirectUrlDto.java index 8ddf1824..670e6890 100644 --- a/src/main/java/com/salessparrow/api/dto/requestMapper/SalesforceRedirectUrlDto.java +++ b/src/main/java/com/salessparrow/api/dto/requestMapper/SalesforceRedirectUrlDto.java @@ -7,18 +7,18 @@ /** * Redirect url DTO. - * + * * @param redirect_uri * @param state - * * @return SalesforceRedirectUrlDto */ @Data public class SalesforceRedirectUrlDto { - @NotBlank(message = "missing_redirect_uri") - @ValidRedirectUri(message = "invalid_redirect_uri") - private String redirect_uri; + @NotBlank(message = "missing_redirect_uri") + @ValidRedirectUri(message = "invalid_redirect_uri") + private String redirect_uri; + + private String state; - private String state; } diff --git a/src/main/java/com/salessparrow/api/exception/CustomException.java b/src/main/java/com/salessparrow/api/exception/CustomException.java index 928c5bdb..4ddcd91b 100644 --- a/src/main/java/com/salessparrow/api/exception/CustomException.java +++ b/src/main/java/com/salessparrow/api/exception/CustomException.java @@ -4,22 +4,25 @@ import com.salessparrow.api.lib.errorLib.ParamErrorObject; public class CustomException extends RuntimeException { - private ErrorObject errorObject; - private ParamErrorObject paramErrorObject; - public CustomException(ErrorObject errorObject) { - this.errorObject = errorObject; - } + private ErrorObject errorObject; - public CustomException(ParamErrorObject paramErrorObject) { - this.paramErrorObject = paramErrorObject; - } + private ParamErrorObject paramErrorObject; - public ParamErrorObject getParamErrorObject() { - return paramErrorObject; - } + public CustomException(ErrorObject errorObject) { + this.errorObject = errorObject; + } + + public CustomException(ParamErrorObject paramErrorObject) { + this.paramErrorObject = paramErrorObject; + } + + public ParamErrorObject getParamErrorObject() { + return paramErrorObject; + } + + public ErrorObject getErrorObject() { + return errorObject; + } - public ErrorObject getErrorObject() { - return errorObject; - } } \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/exception/ErrorResponse.java b/src/main/java/com/salessparrow/api/exception/ErrorResponse.java index f69d0ba8..b31be450 100644 --- a/src/main/java/com/salessparrow/api/exception/ErrorResponse.java +++ b/src/main/java/com/salessparrow/api/exception/ErrorResponse.java @@ -21,105 +21,97 @@ @Component public class ErrorResponse { - @Autowired - private ResourceLoader resourceLoader; - - /** - * Get error response - * - * @param apiIdentifier - * @param internalErrorIdentifier - * - * @return ErrorResponseObject - */ - protected ErrorResponseObject getErrorResponse(String apiIdentifier, String internalErrorIdentifier, String message) { - - String errorConfigPath = "classpath:config/ApiErrorConfig.json"; - Resource resource = resourceLoader.getResource(errorConfigPath); - ObjectMapper objectMapper = new ObjectMapper(); - Map errorDataMap = new HashMap<>(); - try { - errorDataMap = objectMapper.readValue(resource.getInputStream(), - new TypeReference>() { - }); - } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException("Error while reading error config file:" + e.getMessage()); - } - - ErrorConfig errorInfo = errorDataMap.get(apiIdentifier); - - if (errorInfo == null) { - errorInfo = errorDataMap.get("something_went_wrong"); - } - - - ErrorResponseObject errorResponseObject = new ErrorResponseObject( - Integer.parseInt(errorInfo.getHttpCode()), - errorInfo.getMessage(), - errorInfo.getCode(), - internalErrorIdentifier, - new ArrayList()); - - return errorResponseObject; - } - - /** - * Get error response - * - * @param internalErrorIdentifier - * @param message - * @param paramErrorIdentifiers - * - * @return ErrorResponseObject - */ - protected ErrorResponseObject getParamErrorResponse(String internalErrorIdentifier, String message, - List paramErrorIdentifiers) { - - String paramsErrorPath = "classpath:config/ParamErrorConfig.json"; - Resource resource = resourceLoader.getResource(paramsErrorPath); - ObjectMapper objectMapper = new ObjectMapper(); - Map paramErrorDataMap = new HashMap<>(); - try { - paramErrorDataMap = objectMapper.readValue(resource.getInputStream(), - new TypeReference>() { - }); - } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException("Error while reading param error config file:" + e.getMessage()); - } - - List paramErrorConfigList = new ArrayList(); - - for (String paramErrorIdentifier : paramErrorIdentifiers) { - ParamErrorConfig paramErrorConfig = null; - - Pattern pattern = Pattern.compile("^missing_(.*)$"); - Matcher matcher = pattern.matcher(paramErrorIdentifier); - - if (matcher.matches()) { - String paramName = matcher.group(1); - String messageString = paramName + " is required parameter. Please provide " + paramName + "."; - - paramErrorConfig = new ParamErrorConfig(paramName, paramErrorIdentifier, messageString); - paramErrorConfigList.add(paramErrorConfig); - } - else { - paramErrorConfig = paramErrorDataMap.get(paramErrorIdentifier); - if (paramErrorConfig != null) { - paramErrorConfigList.add(paramErrorConfig); - } - } - } - - ErrorResponseObject errorResponseObject = new ErrorResponseObject( - 400, - "At least one parameter is invalid or missing.", - "INVALID_PARAMS", - internalErrorIdentifier, - paramErrorConfigList); - - return errorResponseObject; - } + @Autowired + private ResourceLoader resourceLoader; + + /** + * Get error response + * @param apiIdentifier + * @param internalErrorIdentifier + * @return ErrorResponseObject + */ + protected ErrorResponseObject getErrorResponse(String apiIdentifier, String internalErrorIdentifier, + String message) { + + String errorConfigPath = "classpath:config/ApiErrorConfig.json"; + Resource resource = resourceLoader.getResource(errorConfigPath); + ObjectMapper objectMapper = new ObjectMapper(); + Map errorDataMap = new HashMap<>(); + try { + errorDataMap = objectMapper.readValue(resource.getInputStream(), + new TypeReference>() { + }); + } + catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("Error while reading error config file:" + e.getMessage()); + } + + ErrorConfig errorInfo = errorDataMap.get(apiIdentifier); + + if (errorInfo == null) { + errorInfo = errorDataMap.get("something_went_wrong"); + } + + ErrorResponseObject errorResponseObject = new ErrorResponseObject(Integer.parseInt(errorInfo.getHttpCode()), + errorInfo.getMessage(), errorInfo.getCode(), internalErrorIdentifier, + new ArrayList()); + + return errorResponseObject; + } + + /** + * Get error response + * @param internalErrorIdentifier + * @param message + * @param paramErrorIdentifiers + * @return ErrorResponseObject + */ + protected ErrorResponseObject getParamErrorResponse(String internalErrorIdentifier, String message, + List paramErrorIdentifiers) { + + String paramsErrorPath = "classpath:config/ParamErrorConfig.json"; + Resource resource = resourceLoader.getResource(paramsErrorPath); + ObjectMapper objectMapper = new ObjectMapper(); + Map paramErrorDataMap = new HashMap<>(); + try { + paramErrorDataMap = objectMapper.readValue(resource.getInputStream(), + new TypeReference>() { + }); + } + catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("Error while reading param error config file:" + e.getMessage()); + } + + List paramErrorConfigList = new ArrayList(); + + for (String paramErrorIdentifier : paramErrorIdentifiers) { + ParamErrorConfig paramErrorConfig = null; + + Pattern pattern = Pattern.compile("^missing_(.*)$"); + Matcher matcher = pattern.matcher(paramErrorIdentifier); + + if (matcher.matches()) { + String paramName = matcher.group(1); + String messageString = paramName + " is required parameter. Please provide " + paramName + "."; + + paramErrorConfig = new ParamErrorConfig(paramName, paramErrorIdentifier, messageString); + paramErrorConfigList.add(paramErrorConfig); + } + else { + paramErrorConfig = paramErrorDataMap.get(paramErrorIdentifier); + if (paramErrorConfig != null) { + paramErrorConfigList.add(paramErrorConfig); + } + } + } + + ErrorResponseObject errorResponseObject = new ErrorResponseObject(400, + "At least one parameter is invalid or missing.", "INVALID_PARAMS", internalErrorIdentifier, + paramErrorConfigList); + + return errorResponseObject; + } } diff --git a/src/main/java/com/salessparrow/api/exception/GlobalExceptionHandler.java b/src/main/java/com/salessparrow/api/exception/GlobalExceptionHandler.java index 9b87e84c..44382d01 100644 --- a/src/main/java/com/salessparrow/api/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/salessparrow/api/exception/GlobalExceptionHandler.java @@ -26,130 +26,108 @@ @ControllerAdvice public class GlobalExceptionHandler { - private Logger logger = org.slf4j.LoggerFactory.getLogger(GlobalExceptionHandler.class); - - @Autowired - private ErrorResponse er; - - @Autowired - private ErrorEmailService errorEmailService; - - @Autowired - private CookieHelper cookieHelper; - - /** - * Handle 404. Catches the exception for undefined endpoints - * - * @param NoHandlerFoundException - * - * @return ResponseEntity - */ - @ExceptionHandler(NoHandlerFoundException.class) - public ResponseEntity handleNoHandlerFoundException(NoHandlerFoundException ex, HttpServletRequest request) { - // Logging all headers from the request - String headerStr = Util.generateHeaderLogString(request); - logger.info("headerStr: {}", headerStr); - - ErrorResponseObject errorResponse = null; - - errorResponse = er.getErrorResponse( - "resource_not_found", - "a_e_geh_nf_1", - "handleNoHandlerFoundException"); - - return ResponseEntity.status(errorResponse.getHttpCode()) - .body(errorResponse); - } - - - /** - * Handle custom exception - * - * @param ex - * - * @return ResponseEntity> - */ - @ExceptionHandler(CustomException.class) - public ResponseEntity handleCustomException(CustomException ex) { - ErrorResponseObject errorResponse = null; - - if(ex.getParamErrorObject() != null){ - ParamErrorObject paramErrorObject = ex.getParamErrorObject(); - errorResponse = er.getParamErrorResponse( - paramErrorObject.getInternalErrorIdentifier(), - paramErrorObject.getMessage(), - paramErrorObject.getParamErrorIdentifiers()); - } else if (ex.getErrorObject() == null || ex.getErrorObject().getApiErrorIdentifier() == null) { - errorResponse = er.getErrorResponse( - "something_went_wrong", - "e_geh_hce_1", - ex.getMessage()); - } else { - ErrorObject errorObject = ex.getErrorObject(); - errorResponse = er.getErrorResponse( - errorObject.getApiErrorIdentifier(), - errorObject.getInternalErrorIdentifier(), - errorObject.getMessage()); - } - - logger.error("Error response: {}", errorResponse); - - // Send email for 500 errors only - if (errorResponse.getHttpCode() == 500) { - StackTraceElement[] stackTrace = ex.getStackTrace(); - errorEmailService.sendErrorMail("handleCustomException", errorResponse, stackTrace); - } - - // Clear user cookie for 401 errors - if (errorResponse.getHttpCode() == 401) { - HttpHeaders headers = new HttpHeaders(); - headers = cookieHelper.clearUserCookie(headers); - return ResponseEntity.status(errorResponse.getHttpCode()) - .headers(headers) - .body(errorResponse); - } - - return ResponseEntity.status(errorResponse.getHttpCode()) - .body(errorResponse); - } - - /** - * Catch-all exception handler for any unhandled runtime exception - * - * @param ex - * - * @return ResponseEntity - */ - @ExceptionHandler(RuntimeException.class) - @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) - public ResponseEntity handleRuntimeException(RuntimeException ex) { - ex.printStackTrace(); - - ErrorResponseObject errorResponse = er.getErrorResponse("something_went_wrong", - "e_geh_hre_1", ex.getMessage()); - - StackTraceElement[] stackTrace = ex.getStackTrace(); - errorEmailService.sendErrorMail("RuntimeException", errorResponse, stackTrace); - - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) - .body(errorResponse); - } - - @ExceptionHandler(MethodArgumentNotValidException.class) - @ResponseStatus(HttpStatus.BAD_REQUEST) - public ResponseEntity handleValidationException(MethodArgumentNotValidException ex) { - List paramErrorIdentifiers = new ArrayList<>(); - - for (FieldError error : ex.getBindingResult().getFieldErrors()) { - paramErrorIdentifiers.add(error.getDefaultMessage()); - } - - CustomException ce2 = new CustomException( - new ParamErrorObject( - "b_2", - paramErrorIdentifiers.toString(), - paramErrorIdentifiers)); - - return handleCustomException(ce2); - } + private Logger logger = org.slf4j.LoggerFactory.getLogger(GlobalExceptionHandler.class); + + @Autowired + private ErrorResponse er; + + @Autowired + private ErrorEmailService errorEmailService; + + @Autowired + private CookieHelper cookieHelper; + + /** + * Handle 404. Catches the exception for undefined endpoints + * @param NoHandlerFoundException + * @return ResponseEntity + */ + @ExceptionHandler(NoHandlerFoundException.class) + public ResponseEntity handleNoHandlerFoundException(NoHandlerFoundException ex, + HttpServletRequest request) { + // Logging all headers from the request + String headerStr = Util.generateHeaderLogString(request); + logger.info("headerStr: {}", headerStr); + + ErrorResponseObject errorResponse = null; + + errorResponse = er.getErrorResponse("resource_not_found", "a_e_geh_nf_1", "handleNoHandlerFoundException"); + + return ResponseEntity.status(errorResponse.getHttpCode()).body(errorResponse); + } + + /** + * Handle custom exception + * @param ex + * @return ResponseEntity> + */ + @ExceptionHandler(CustomException.class) + public ResponseEntity handleCustomException(CustomException ex) { + ErrorResponseObject errorResponse = null; + + if (ex.getParamErrorObject() != null) { + ParamErrorObject paramErrorObject = ex.getParamErrorObject(); + errorResponse = er.getParamErrorResponse(paramErrorObject.getInternalErrorIdentifier(), + paramErrorObject.getMessage(), paramErrorObject.getParamErrorIdentifiers()); + } + else if (ex.getErrorObject() == null || ex.getErrorObject().getApiErrorIdentifier() == null) { + errorResponse = er.getErrorResponse("something_went_wrong", "e_geh_hce_1", ex.getMessage()); + } + else { + ErrorObject errorObject = ex.getErrorObject(); + errorResponse = er.getErrorResponse(errorObject.getApiErrorIdentifier(), + errorObject.getInternalErrorIdentifier(), errorObject.getMessage()); + } + + logger.error("Error response: {}", errorResponse); + + // Send email for 500 errors only + if (errorResponse.getHttpCode() == 500) { + StackTraceElement[] stackTrace = ex.getStackTrace(); + errorEmailService.sendErrorMail("handleCustomException", errorResponse, stackTrace); + } + + // Clear user cookie for 401 errors + if (errorResponse.getHttpCode() == 401) { + HttpHeaders headers = new HttpHeaders(); + headers = cookieHelper.clearUserCookie(headers); + return ResponseEntity.status(errorResponse.getHttpCode()).headers(headers).body(errorResponse); + } + + return ResponseEntity.status(errorResponse.getHttpCode()).body(errorResponse); + } + + /** + * Catch-all exception handler for any unhandled runtime exception + * @param ex + * @return ResponseEntity + */ + @ExceptionHandler(RuntimeException.class) + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + public ResponseEntity handleRuntimeException(RuntimeException ex) { + ex.printStackTrace(); + + ErrorResponseObject errorResponse = er.getErrorResponse("something_went_wrong", "e_geh_hre_1", ex.getMessage()); + + StackTraceElement[] stackTrace = ex.getStackTrace(); + errorEmailService.sendErrorMail("RuntimeException", errorResponse, stackTrace); + + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse); + } + + @ExceptionHandler(MethodArgumentNotValidException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ResponseEntity handleValidationException(MethodArgumentNotValidException ex) { + List paramErrorIdentifiers = new ArrayList<>(); + + for (FieldError error : ex.getBindingResult().getFieldErrors()) { + paramErrorIdentifiers.add(error.getDefaultMessage()); + } + + CustomException ce2 = new CustomException( + new ParamErrorObject("b_2", paramErrorIdentifiers.toString(), paramErrorIdentifiers)); + + return handleCustomException(ce2); + } + } \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/filter/SameSiteCookieFilter.java b/src/main/java/com/salessparrow/api/filter/SameSiteCookieFilter.java index dd0e69a1..518ffb28 100644 --- a/src/main/java/com/salessparrow/api/filter/SameSiteCookieFilter.java +++ b/src/main/java/com/salessparrow/api/filter/SameSiteCookieFilter.java @@ -7,96 +7,90 @@ /** * Filter to set SameSite cookie attribute - * - * If you want to implement SameSite attribute setting in an interceptor, you can do it, - * but it won't be as efficient as doing it in a filter. That's because, by the time the interceptor - * is called, some part of the request processing within the Spring MVC framework has already happened. + * + * If you want to implement SameSite attribute setting in an interceptor, you can do it, + * but it won't be as efficient as doing it in a filter. That's because, by the time the + * interceptor is called, some part of the request processing within the Spring MVC + * framework has already happened. * */ public class SameSiteCookieFilter implements Filter { - @Override - public void init(FilterConfig filterConfig) { - } + @Override + public void init(FilterConfig filterConfig) { + } + + /** + * Set SameSite cookie attribute. Override the doFilter method to wrap the response + * object with a custom wrapper. + * @param request + * @param response + * @param chain + * @throws IOException + * @throws ServletException + * @return void + */ + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + + SameSiteResponseWrapper wrappedResponse = new SameSiteResponseWrapper((HttpServletResponse) response); + chain.doFilter(request, wrappedResponse); + } - /** - * Set SameSite cookie attribute. - * Override the doFilter method to wrap the response object with a custom wrapper. - * - * @param request - * @param response - * @param chain - * - * @throws IOException - * @throws ServletException - * - * @return void - */ - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) - throws IOException, ServletException { + @Override + public void destroy() { + } - SameSiteResponseWrapper wrappedResponse = new SameSiteResponseWrapper((HttpServletResponse) response); - chain.doFilter(request, wrappedResponse); - } + /** + * Custom wrapper to intercept the setHeader calls and add SameSite attribute to the + * cookie. Set SameSite=lax lax will ensure that cookies are sent only if the request + * originates from the same site. It will also send the cookie if the user is + * navigating from an external site, but only if the URL in the browser’s address bar + * matches the URL of the current site. + */ + public class SameSiteResponseWrapper extends HttpServletResponseWrapper { - @Override - public void destroy() { - } + /** + * Constructor + * @param response + * @return void + */ + public SameSiteResponseWrapper(HttpServletResponse response) { + super(response); + } - /** - * Custom wrapper to intercept the setHeader calls and add SameSite attribute to the cookie. - * Set SameSite=lax - * lax will ensure that cookies are sent only if the request originates from the same site. - * It will also send the cookie if the user is navigating from an external site, - * but only if the URL in the browser’s address bar matches the URL of the current site. - */ - public class SameSiteResponseWrapper extends HttpServletResponseWrapper { + /** + * Override the addHeader method to add SameSite attribute to the cookie + * @param name + * @param value + * @return void + * + */ + @Override + public void addHeader(String name, String value) { + if (name.equalsIgnoreCase("set-cookie") && !value.toLowerCase().contains("samesite")) { + value = String.format("%s; SameSite=lax", value); + } + super.addHeader(name, value); + } - /** - * Constructor - * - * @param response - * - * @return void - */ - public SameSiteResponseWrapper(HttpServletResponse response) { - super(response); - } + /** + * Override the setHeader method to add SameSite attribute to the cookie + * @param name + * @param value + * @return void + * + */ + @Override + public void setHeader(String name, String value) { - /** - * Override the addHeader method to add SameSite attribute to the cookie - * - * @param name - * @param value - * - * @return void - * - */ - @Override - public void addHeader(String name, String value) { - if (name.equalsIgnoreCase("set-cookie") && !value.toLowerCase().contains("samesite")) { - value = String.format("%s; SameSite=lax", value); - } - super.addHeader(name, value); - } + if (name.equalsIgnoreCase("set-cookie") && !value.toLowerCase().contains("samesite")) { + value = String.format("%s; SameSite=lax", value); + } + super.setHeader(name, value); + } - /** - * Override the setHeader method to add SameSite attribute to the cookie - * - * @param name - * @param value - * - * @return void - * - */ - @Override - public void setHeader(String name, String value) { + } - if (name.equalsIgnoreCase("set-cookie") && !value.toLowerCase().contains("samesite")) { - value = String.format("%s; SameSite=lax", value); - } - super.setHeader(name, value); - } - } } diff --git a/src/main/java/com/salessparrow/api/interceptors/JsonOnlyInterceptor.java b/src/main/java/com/salessparrow/api/interceptors/JsonOnlyInterceptor.java index 96a2fcb2..fb72023f 100644 --- a/src/main/java/com/salessparrow/api/interceptors/JsonOnlyInterceptor.java +++ b/src/main/java/com/salessparrow/api/interceptors/JsonOnlyInterceptor.java @@ -16,30 +16,24 @@ @Component public class JsonOnlyInterceptor implements HandlerInterceptor { - /** - * Intercept request and validate Content-type header - * Only application/json is allowed - * - * @param request - * @param response - * @param handler - * - * @return boolean - */ - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { - - String contentType = request.getHeader("Content-Type"); - if (contentType != null && !contentType.contains("application/json")) { - throw new CustomException( - new ErrorObject( - "i_joi_ph_1", - "unsupported_media_type", - "Content-Type header must be application/json")); - } - - return true; - } -} - + /** + * Intercept request and validate Content-type header Only application/json is allowed + * @param request + * @param response + * @param handler + * @return boolean + */ + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) + throws Exception { + + String contentType = request.getHeader("Content-Type"); + if (contentType != null && !contentType.contains("application/json")) { + throw new CustomException(new ErrorObject("i_joi_ph_1", "unsupported_media_type", + "Content-Type header must be application/json")); + } + + return true; + } +} diff --git a/src/main/java/com/salessparrow/api/interceptors/LoggerInterceptor.java b/src/main/java/com/salessparrow/api/interceptors/LoggerInterceptor.java index 37f1ccda..94233663 100644 --- a/src/main/java/com/salessparrow/api/interceptors/LoggerInterceptor.java +++ b/src/main/java/com/salessparrow/api/interceptors/LoggerInterceptor.java @@ -18,46 +18,47 @@ @Component public class LoggerInterceptor implements HandlerInterceptor { - /** - * Intercept request and log request - * - * @param request - * @param response - * @param handler - * - * @return boolean - */ - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { - String trackingId = request.getHeader("X-Tracking-Id"); - - Logger logger = LoggerFactory.getLogger(LoggerInterceptor.class); - - if (trackingId == null) { - trackingId = java.util.UUID.randomUUID().toString(); - } - - long startTime = System.currentTimeMillis(); - request.setAttribute("startTime", startTime); - - MDC.put("trackingId", trackingId); - logger.info("Request Start: {} {}", request.getMethod(), request.getRequestURI()); - - // Logging all headers from the request - String headerStr = Util.generateHeaderLogString(request); - logger.info("headerStr: {}", headerStr); - - return true; - } - - @Override - public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { - Logger logger = LoggerFactory.getLogger(LoggerInterceptor.class); - - long startTime = (Long)request.getAttribute("startTime"); - long endTime = System.currentTimeMillis(); - long executeTime = endTime - startTime; - - logger.info("Request Ended with {} in {}ms", response.getStatus(), executeTime); - } + /** + * Intercept request and log request + * @param request + * @param response + * @param handler + * @return boolean + */ + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) + throws Exception { + String trackingId = request.getHeader("X-Tracking-Id"); + + Logger logger = LoggerFactory.getLogger(LoggerInterceptor.class); + + if (trackingId == null) { + trackingId = java.util.UUID.randomUUID().toString(); + } + + long startTime = System.currentTimeMillis(); + request.setAttribute("startTime", startTime); + + MDC.put("trackingId", trackingId); + logger.info("Request Start: {} {}", request.getMethod(), request.getRequestURI()); + + // Logging all headers from the request + String headerStr = Util.generateHeaderLogString(request); + logger.info("headerStr: {}", headerStr); + + return true; + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) + throws Exception { + Logger logger = LoggerFactory.getLogger(LoggerInterceptor.class); + + long startTime = (Long) request.getAttribute("startTime"); + long endTime = System.currentTimeMillis(); + long executeTime = endTime - startTime; + + logger.info("Request Ended with {} in {}ms", response.getStatus(), executeTime); + } + } diff --git a/src/main/java/com/salessparrow/api/interceptors/UserAuthInterceptor.java b/src/main/java/com/salessparrow/api/interceptors/UserAuthInterceptor.java index 13aa70e5..e03e3ab7 100644 --- a/src/main/java/com/salessparrow/api/interceptors/UserAuthInterceptor.java +++ b/src/main/java/com/salessparrow/api/interceptors/UserAuthInterceptor.java @@ -25,63 +25,61 @@ @Component public class UserAuthInterceptor implements HandlerInterceptor { - @Autowired - private UserLoginCookieAuth userLoginCookieAuth; - - Logger logger = LoggerFactory.getLogger(UserAuthInterceptor.class); - - @Autowired - private CookieHelper cookieHelper; - - /** - * Intercept request and validate user login cookie - * - * @param request - * @param response - * @param handler - * - * @return boolean - */ - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { - String cookieValue = getCookieValue(request); - String reqApiSource = (String) request.getAttribute("api_source"); - - Map userLoginCookieAuthRes = userLoginCookieAuth.validateAndSetCookie(cookieValue, reqApiSource); - - User currentUser = (User) userLoginCookieAuthRes.get("current_user"); - request.setAttribute("current_user", currentUser); - - String userLoginCookieValue = (String) userLoginCookieAuthRes.get("userLoginCookieValue"); - - String cookieName = CookieConstants.USER_LOGIN_COOKIE_NAME; - - HttpHeaders headers = new HttpHeaders(); - headers = cookieHelper.setCookieInHeaders(cookieName, userLoginCookieValue, headers); - - response.addHeader(HttpHeaders.SET_COOKIE, headers.getFirst(HttpHeaders.SET_COOKIE)); - - return true; - } - - /** - * Get cookie value from request - * - * @param request - * @param cookieName - * - * @return String - */ - private String getCookieValue(HttpServletRequest request) { - Cookie[] cookies = request.getCookies(); - if (cookies != null) { - for (Cookie cookie : cookies) { - if (cookie.getName().equals(CookieConstants.USER_LOGIN_COOKIE_NAME)) { - return cookie.getValue(); - } - } - } - return null; - } + @Autowired + private UserLoginCookieAuth userLoginCookieAuth; + + Logger logger = LoggerFactory.getLogger(UserAuthInterceptor.class); + + @Autowired + private CookieHelper cookieHelper; + + /** + * Intercept request and validate user login cookie + * @param request + * @param response + * @param handler + * @return boolean + */ + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) + throws Exception { + String cookieValue = getCookieValue(request); + String reqApiSource = (String) request.getAttribute("api_source"); + + Map userLoginCookieAuthRes = userLoginCookieAuth.validateAndSetCookie(cookieValue, + reqApiSource); + + User currentUser = (User) userLoginCookieAuthRes.get("current_user"); + request.setAttribute("current_user", currentUser); + + String userLoginCookieValue = (String) userLoginCookieAuthRes.get("userLoginCookieValue"); + + String cookieName = CookieConstants.USER_LOGIN_COOKIE_NAME; + + HttpHeaders headers = new HttpHeaders(); + headers = cookieHelper.setCookieInHeaders(cookieName, userLoginCookieValue, headers); + + response.addHeader(HttpHeaders.SET_COOKIE, headers.getFirst(HttpHeaders.SET_COOKIE)); + + return true; + } + + /** + * Get cookie value from request + * @param request + * @param cookieName + * @return String + */ + private String getCookieValue(HttpServletRequest request) { + Cookie[] cookies = request.getCookies(); + if (cookies != null) { + for (Cookie cookie : cookies) { + if (cookie.getName().equals(CookieConstants.USER_LOGIN_COOKIE_NAME)) { + return cookie.getValue(); + } + } + } + return null; + } } diff --git a/src/main/java/com/salessparrow/api/interceptors/V1Interceptor.java b/src/main/java/com/salessparrow/api/interceptors/V1Interceptor.java index 4a6876b3..4c7940e1 100644 --- a/src/main/java/com/salessparrow/api/interceptors/V1Interceptor.java +++ b/src/main/java/com/salessparrow/api/interceptors/V1Interceptor.java @@ -14,20 +14,21 @@ @Component public class V1Interceptor implements HandlerInterceptor { - /** - * Intercept all /v1/* request and add middleware logic here - * - * @param request - * @param response - * @param handler - * - * @return boolean - */ - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + /** + * Intercept all /v1/* request and add middleware logic here + * @param request + * @param response + * @param handler + * @return boolean + */ + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) + throws Exception { + + // Set Source for app.This can be used to differentiate common web routes from app + // routes in the service. + request.setAttribute("api_source", ApiSource.APP); + return true; + } - // Set Source for app.This can be used to differentiate common web routes from app routes in the service. - request.setAttribute("api_source", ApiSource.APP); - return true; - } } diff --git a/src/main/java/com/salessparrow/api/lib/AwsKms.java b/src/main/java/com/salessparrow/api/lib/AwsKms.java index 527b4bf3..8b8b7248 100644 --- a/src/main/java/com/salessparrow/api/lib/AwsKms.java +++ b/src/main/java/com/salessparrow/api/lib/AwsKms.java @@ -16,79 +16,67 @@ import com.salessparrow.api.lib.errorLib.ErrorObject; /** - * AWS Key Management Service (KMS) component for encryption and decryption - * operations. + * AWS Key Management Service (KMS) component for encryption and decryption operations. */ @Component public class AwsKms { - @Autowired - private AWSKMS kmsClient; + @Autowired + private AWSKMS kmsClient; - /** - * Creates a new instance of AwsKms. - */ - public AwsKms() { - } + /** + * Creates a new instance of AwsKms. + */ + public AwsKms() { + } - /** - * Encrypts a token using AWS KMS. - * - * @param token - * - * @return The encrypted token. - */ - public String encryptToken(String token) { - if (token == null) { - return null; - } - EncryptRequest request = new EncryptRequest() - .withKeyId(CoreConstants.kmsKeyId()) - .withPlaintext(ByteBuffer.wrap(token.getBytes())); + /** + * Encrypts a token using AWS KMS. + * @param token + * @return The encrypted token. + */ + public String encryptToken(String token) { + if (token == null) { + return null; + } + EncryptRequest request = new EncryptRequest().withKeyId(CoreConstants.kmsKeyId()) + .withPlaintext(ByteBuffer.wrap(token.getBytes())); - EncryptResult result = null; - try { - result = kmsClient.encrypt(request); - } catch (Exception e) { - throw new CustomException( - new ErrorObject( - "l_ak_et_1", - "something_went_wrong", - e.getMessage())); - } - return Base64.getEncoder().encodeToString(result.getCiphertextBlob().array()); + EncryptResult result = null; + try { + result = kmsClient.encrypt(request); + } + catch (Exception e) { + throw new CustomException(new ErrorObject("l_ak_et_1", "something_went_wrong", e.getMessage())); + } + return Base64.getEncoder().encodeToString(result.getCiphertextBlob().array()); - } + } - /** - * Decrypts a token using AWS KMS. - * - * @param encryptedToken - * - * @return The decrypted token. - */ - public String decryptToken(String encryptedToken) { - byte[] decodedToken = Base64.getDecoder().decode(encryptedToken); + /** + * Decrypts a token using AWS KMS. + * @param encryptedToken + * @return The decrypted token. + */ + public String decryptToken(String encryptedToken) { + byte[] decodedToken = Base64.getDecoder().decode(encryptedToken); - DecryptRequest request = new DecryptRequest() - .withCiphertextBlob(ByteBuffer.wrap(decodedToken)) - .withKeyId(CoreConstants.kmsKeyId()); - DecryptResult result = null; + DecryptRequest request = new DecryptRequest().withCiphertextBlob(ByteBuffer.wrap(decodedToken)) + .withKeyId(CoreConstants.kmsKeyId()); + DecryptResult result = null; - try { - result = kmsClient.decrypt(request); - } catch (Exception e) { - throw new CustomException( - new ErrorObject( - "l_ak_dt_1", - "something_went_wrong", - e.getMessage())); - } + try { + result = kmsClient.decrypt(request); + } + catch (Exception e) { + throw new CustomException(new ErrorObject("l_ak_dt_1", "something_went_wrong", e.getMessage())); + } - if (result == null || result.getPlaintext() == null) { - return null; - } + if (result == null || result.getPlaintext() == null) { + return null; + } + + return new String(result.getPlaintext().array()); + } - return new String(result.getPlaintext().array()); - } } \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/lib/Base64Helper.java b/src/main/java/com/salessparrow/api/lib/Base64Helper.java index 945f06b2..3478a0e5 100644 --- a/src/main/java/com/salessparrow/api/lib/Base64Helper.java +++ b/src/main/java/com/salessparrow/api/lib/Base64Helper.java @@ -6,15 +6,17 @@ @Component public class Base64Helper { - public String base64Encode(String originalString) { - byte[] originalBytes = originalString.getBytes(); - byte[] encodedBytes = Base64.getEncoder().encode(originalBytes); - return new String(encodedBytes); - } - public String base64Decode(String encodedString) { - byte[] encodedBytes = encodedString.getBytes(); - byte[] decodedBytes = Base64.getDecoder().decode(encodedBytes); - return new String(decodedBytes); - } + public String base64Encode(String originalString) { + byte[] originalBytes = originalString.getBytes(); + byte[] encodedBytes = Base64.getEncoder().encode(originalBytes); + return new String(encodedBytes); + } + + public String base64Decode(String encodedString) { + byte[] encodedBytes = encodedString.getBytes(); + byte[] decodedBytes = Base64.getDecoder().decode(encodedBytes); + return new String(decodedBytes); + } + } diff --git a/src/main/java/com/salessparrow/api/lib/CookieHelper.java b/src/main/java/com/salessparrow/api/lib/CookieHelper.java index 7db1174d..06275ce8 100644 --- a/src/main/java/com/salessparrow/api/lib/CookieHelper.java +++ b/src/main/java/com/salessparrow/api/lib/CookieHelper.java @@ -15,117 +15,103 @@ @Component public class CookieHelper { - @Autowired - private LocalCipher localCipher; - - /** - * Get cookie value - * - * @param user - * @param userKind - * @param decryptedSalt - * @param apiSource - * - * @return String - */ - public String getCookieValue(User user, String userKind, String decryptedSalt, String apiSource) { - - Integer currentTimestamp = (int) (System.currentTimeMillis() / 1000); - String cookieToken = getCookieToken(user, decryptedSalt, currentTimestamp, apiSource); - - if (user.getExternalUserId() == null) { - throw new CustomException( - new ErrorObject( - "l_ch_gcv_1", - "internal_server_error", - "User is null")); - } - - return CookieConstants.LATEST_VERSION + ':' + user.getExternalUserId() + ':' + userKind + - ':' + apiSource + ':' + currentTimestamp + ':' + cookieToken; - } - - /** - * Get cookie token - * - * @param user - * @param decryptedSalt - * @param timestamp - * @param apiSource - * - * @return String - */ - public String getCookieToken(User user, String decryptedSalt, Integer timestamp, String apiSource) { - - String decryptedCookieToken = localCipher.decrypt(decryptedSalt, user.getCookieToken()); - String strSecret = CoreConstants.apiCookieSecret(); - String stringToSign = user.getExternalUserId() + ':' + timestamp + ':' + apiSource + ':' + strSecret + ':' - + decryptedCookieToken.substring(0, 16); - String salt = user.getExternalUserId() + ':' + decryptedCookieToken.substring(decryptedCookieToken.length() - 16) - + ':' - + strSecret + ':' + timestamp; - String encryptedCookieToken = localCipher.encrypt(salt, stringToSign); - - return encryptedCookieToken; - } - - /** - * Set cookie in headers - * - * @param cookieName - * @param cookieValue - * @param headers - * - * @return HttpHeaders - */ - public HttpHeaders setCookieInHeaders(String cookieName, String cookieValue, - HttpHeaders headers) { - int cookieExpiryInSecond = CookieConstants.USER_LOGIN_COOKIE_EXPIRY_IN_SEC; - - Cookie cookie = new Cookie(cookieName, cookieValue); - cookie.setHttpOnly(true); - cookie.setSecure(true); - cookie.setMaxAge(cookieExpiryInSecond); - cookie.setDomain(CoreConstants.cookieDomain()); - cookie.setPath("/"); - - headers.add(HttpHeaders.SET_COOKIE, String.format("%s=%s; Max-Age=%d; Path=/", - cookieName, cookieValue, cookieExpiryInSecond)); - - return headers; - } - - /** - * Set user cookie - * - * @param cookieValue - * @param headers - * - * @return HttpHeaders - */ - public HttpHeaders setUserCookie(String cookieValue, HttpHeaders headers) { - String cookieName = CookieConstants.USER_LOGIN_COOKIE_NAME; - - headers = setCookieInHeaders(cookieName, cookieValue, headers); - - return headers; - } - - /** - * Clear user cookie - * - * @param headers - * - * @return HttpHeaders - */ - public HttpHeaders clearUserCookie(HttpHeaders headers) { - String cookieName = CookieConstants.USER_LOGIN_COOKIE_NAME; - String cookieValue = ""; - int cookieExpiry = -1; - - headers.add(HttpHeaders.SET_COOKIE, String.format("%s=%s; Max-Age=%d; Path=/", - cookieName, cookieValue, cookieExpiry)); - - return headers; - } + @Autowired + private LocalCipher localCipher; + + /** + * Get cookie value + * @param user + * @param userKind + * @param decryptedSalt + * @param apiSource + * @return String + */ + public String getCookieValue(User user, String userKind, String decryptedSalt, String apiSource) { + + Integer currentTimestamp = (int) (System.currentTimeMillis() / 1000); + String cookieToken = getCookieToken(user, decryptedSalt, currentTimestamp, apiSource); + + if (user.getExternalUserId() == null) { + throw new CustomException(new ErrorObject("l_ch_gcv_1", "internal_server_error", "User is null")); + } + + return CookieConstants.LATEST_VERSION + ':' + user.getExternalUserId() + ':' + userKind + ':' + apiSource + ':' + + currentTimestamp + ':' + cookieToken; + } + + /** + * Get cookie token + * @param user + * @param decryptedSalt + * @param timestamp + * @param apiSource + * @return String + */ + public String getCookieToken(User user, String decryptedSalt, Integer timestamp, String apiSource) { + + String decryptedCookieToken = localCipher.decrypt(decryptedSalt, user.getCookieToken()); + String strSecret = CoreConstants.apiCookieSecret(); + String stringToSign = user.getExternalUserId() + ':' + timestamp + ':' + apiSource + ':' + strSecret + ':' + + decryptedCookieToken.substring(0, 16); + String salt = user.getExternalUserId() + ':' + + decryptedCookieToken.substring(decryptedCookieToken.length() - 16) + ':' + strSecret + ':' + + timestamp; + String encryptedCookieToken = localCipher.encrypt(salt, stringToSign); + + return encryptedCookieToken; + } + + /** + * Set cookie in headers + * @param cookieName + * @param cookieValue + * @param headers + * @return HttpHeaders + */ + public HttpHeaders setCookieInHeaders(String cookieName, String cookieValue, HttpHeaders headers) { + int cookieExpiryInSecond = CookieConstants.USER_LOGIN_COOKIE_EXPIRY_IN_SEC; + + Cookie cookie = new Cookie(cookieName, cookieValue); + cookie.setHttpOnly(true); + cookie.setSecure(true); + cookie.setMaxAge(cookieExpiryInSecond); + cookie.setDomain(CoreConstants.cookieDomain()); + cookie.setPath("/"); + + headers.add(HttpHeaders.SET_COOKIE, + String.format("%s=%s; Max-Age=%d; Path=/", cookieName, cookieValue, cookieExpiryInSecond)); + + return headers; + } + + /** + * Set user cookie + * @param cookieValue + * @param headers + * @return HttpHeaders + */ + public HttpHeaders setUserCookie(String cookieValue, HttpHeaders headers) { + String cookieName = CookieConstants.USER_LOGIN_COOKIE_NAME; + + headers = setCookieInHeaders(cookieName, cookieValue, headers); + + return headers; + } + + /** + * Clear user cookie + * @param headers + * @return HttpHeaders + */ + public HttpHeaders clearUserCookie(HttpHeaders headers) { + String cookieName = CookieConstants.USER_LOGIN_COOKIE_NAME; + String cookieValue = ""; + int cookieExpiry = -1; + + headers.add(HttpHeaders.SET_COOKIE, + String.format("%s=%s; Max-Age=%d; Path=/", cookieName, cookieValue, cookieExpiry)); + + return headers; + } + } diff --git a/src/main/java/com/salessparrow/api/lib/ErrorEmailService.java b/src/main/java/com/salessparrow/api/lib/ErrorEmailService.java index ec386105..29236e02 100644 --- a/src/main/java/com/salessparrow/api/lib/ErrorEmailService.java +++ b/src/main/java/com/salessparrow/api/lib/ErrorEmailService.java @@ -15,75 +15,74 @@ @Component public class ErrorEmailService { - Logger logger = LoggerFactory.getLogger(ErrorEmailService.class); + Logger logger = LoggerFactory.getLogger(ErrorEmailService.class); - @Autowired - private AmazonSimpleEmailService sesClient; + @Autowired + private AmazonSimpleEmailService sesClient; - /** - * Send error email - * - * @param contextString - context string for subject. helps in easy - * identification of error - * @param errorObj - error object - contains error code, message, http - * code, internal error identifier - * @param stackTraceElements - stack trace elements - * - * @return void - */ - public void sendErrorMail(String contextString, ErrorResponseObject errorObj, - StackTraceElement[] stackTraceElements) { - logger.info("Sending error email for context: " + contextString); + /** + * Send error email + * @param contextString - context string for subject. helps in easy identification of + * error + * @param errorObj - error object - contains error code, message, http code, internal + * error identifier + * @param stackTraceElements - stack trace elements + * @return void + */ + public void sendErrorMail(String contextString, ErrorResponseObject errorObj, + StackTraceElement[] stackTraceElements) { + logger.info("Sending error email for context: " + contextString); - String requestId = MDC.get("trackingId"); + String requestId = MDC.get("trackingId"); - String body = "Tracking id:" + requestId + "\n"; - body += "http_code=" + errorObj.getHttpCode() + "\n"; - body += "code=" + errorObj.getCode() + "\n"; - body += "message=" + errorObj.getMessage() + "\n"; - body += "internal_error_identifier=" + errorObj.getInternalErrorIdentifier() + "\n"; - body += "params_error=" + errorObj.getParamErrors() + "\n\n\n"; + String body = "Tracking id:" + requestId + "\n"; + body += "http_code=" + errorObj.getHttpCode() + "\n"; + body += "code=" + errorObj.getCode() + "\n"; + body += "message=" + errorObj.getMessage() + "\n"; + body += "internal_error_identifier=" + errorObj.getInternalErrorIdentifier() + "\n"; + body += "params_error=" + errorObj.getParamErrors() + "\n\n\n"; - for (StackTraceElement stackTraceElement : stackTraceElements) { - body += stackTraceElement.toString() + "\n"; - } + for (StackTraceElement stackTraceElement : stackTraceElements) { + body += stackTraceElement.toString() + "\n"; + } - String subject = "SalesSparrow::" + CoreConstants.environment() + "::Error-" + contextString - + "-" + errorObj.getMessage(); + String subject = "SalesSparrow::" + CoreConstants.environment() + "::Error-" + contextString + "-" + + errorObj.getMessage(); - // Send email only if not in dev environment - if (!CoreConstants.isDevEnvironment() && !CoreConstants.isTestEnvironment() && !CoreConstants.isLocalTestEnvironment()) { - sendEmail(CoreConstants.errorEmailFrom(), CoreConstants.errorEmailTo(), subject, body); - } else { - logger.info("Skip email for development.\n\n subject {} \n body {}", subject, body); - } + // Send email only if not in dev environment + if (!CoreConstants.isDevEnvironment() && !CoreConstants.isTestEnvironment() + && !CoreConstants.isLocalTestEnvironment()) { + sendEmail(CoreConstants.errorEmailFrom(), CoreConstants.errorEmailTo(), subject, body); + } + else { + logger.info("Skip email for development.\n\n subject {} \n body {}", subject, body); + } - } + } - /** - * Send mail async using SES. Handles exception if any - * - * @param from - source email address - * @param to - destination email address - * @param subject - subject of email - * @param body - body of email - * - * @return void - */ - @Async - public void sendEmail(String from, String to, String subject, String body) { - logger.info("send SES Email"); - try { - SendEmailRequest request = new SendEmailRequest() - .withDestination(new Destination().withToAddresses(to)) - .withMessage(new Message() - .withBody(new Body().withText(new Content().withCharset("UTF-8").withData(body))) - .withSubject(new Content().withCharset("UTF-8").withData(subject))) - .withSource(from); + /** + * Send mail async using SES. Handles exception if any + * @param from - source email address + * @param to - destination email address + * @param subject - subject of email + * @param body - body of email + * @return void + */ + @Async + public void sendEmail(String from, String to, String subject, String body) { + logger.info("send SES Email"); + try { + SendEmailRequest request = new SendEmailRequest().withDestination(new Destination().withToAddresses(to)) + .withMessage( + new Message().withBody(new Body().withText(new Content().withCharset("UTF-8").withData(body))) + .withSubject(new Content().withCharset("UTF-8").withData(subject))) + .withSource(from); + + sesClient.sendEmail(request); + } + catch (Exception e) { + logger.error("Error sending email {} subject:{} body:{}", e, subject, body); + } + } - sesClient.sendEmail(request); - } catch (Exception e) { - logger.error("Error sending email {} subject:{} body:{}", e, subject, body); - } - } } diff --git a/src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java b/src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java index 70c0fed5..85e46bc8 100644 --- a/src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java +++ b/src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java @@ -25,88 +25,91 @@ */ @Component public class GetCrmActionSuggestions { - @Autowired - private OpenAiRequest openAiRequest; - - @Autowired - private OpenAiPayloadBuilder openAiPayloadBuilder; - - private DateFormatValidator dateFormatValidator = new DateFormatValidator(); - - private Logger logger = org.slf4j.LoggerFactory.getLogger(SuggestionsController.class); - - /** - * Get the crm action suggestions. - * @param text - * @return - */ - public CrmActionSuggestionsFormatterDto getTaskSuggestions(String text) { - logger.info("Crm actions suggestions lib called"); - - String escapedText = escapeForJson(text); - String payload = openAiPayloadBuilder.payloadForCrmActionsSuggestions(escapedText); - - String response = openAiRequest.makeRequest(payload).getResponseBody(); - - return parseResponse(response); - } - - /** - * Parse the response from openai. - * @param responseBody - * @return - */ - private CrmActionSuggestionsFormatterDto parseResponse(String responseBody){ - CrmActionSuggestionsFormatterDto crmActionSuggestionsFormatterDto = new CrmActionSuggestionsFormatterDto(); - - try { - Util util = new Util(); - JsonNode rootNode = util.getJsonNode(responseBody); - JsonNode argumentsNode = rootNode.get("choices").get(0).get("message").get("function_call").get("arguments"); - - ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); - String argumentsJson = objectMapper.convertValue(argumentsNode, String.class); - - Map> arguments = objectMapper.readValue(argumentsJson, new TypeReference>>() {}); - List addTaskList = arguments.get("add_task"); - - - List formattedTaskSuggestionEntityDtos = new ArrayList<>(); - if (addTaskList != null) { - for (AddTaskSuggestionEntityDto addTask : addTaskList) { - AddTaskSuggestionEntityDto addTaskSuggestionEntityDto = new AddTaskSuggestionEntityDto(); - addTaskSuggestionEntityDto.setDescription(addTask.getDescription()); - - // Format the response check if duedate format is YYYY-MM-DD else remove duedate - String dueDate = addTask.getDueDate(); - if (dateFormatValidator.isValid(dueDate, null)) { - addTaskSuggestionEntityDto.setDueDate(dueDate); - } - - formattedTaskSuggestionEntityDtos.add(addTaskSuggestionEntityDto); - } - } - - crmActionSuggestionsFormatterDto.setAddTaskSuggestions(formattedTaskSuggestionEntityDtos); - return crmActionSuggestionsFormatterDto; - } catch (Exception e) { - throw new CustomException( - new ErrorObject( - "l_gcas_p_1", - "something_went_wrong", - e.getMessage() - ) - ); - } - } - - /** - * Escape the input string for json. - * @param input - * @return - */ - private String escapeForJson(String input) { - return input.replace("\"", "\\\"").replace("\n", "\\n"); - } + + @Autowired + private OpenAiRequest openAiRequest; + + @Autowired + private OpenAiPayloadBuilder openAiPayloadBuilder; + + private DateFormatValidator dateFormatValidator = new DateFormatValidator(); + + private Logger logger = org.slf4j.LoggerFactory.getLogger(SuggestionsController.class); + + /** + * Get the crm action suggestions. + * @param text + * @return + */ + public CrmActionSuggestionsFormatterDto getTaskSuggestions(String text) { + logger.info("Crm actions suggestions lib called"); + + String escapedText = escapeForJson(text); + String payload = openAiPayloadBuilder.payloadForCrmActionsSuggestions(escapedText); + + String response = openAiRequest.makeRequest(payload).getResponseBody(); + + return parseResponse(response); + } + + /** + * Parse the response from openai. + * @param responseBody + * @return + */ + private CrmActionSuggestionsFormatterDto parseResponse(String responseBody) { + CrmActionSuggestionsFormatterDto crmActionSuggestionsFormatterDto = new CrmActionSuggestionsFormatterDto(); + + try { + Util util = new Util(); + JsonNode rootNode = util.getJsonNode(responseBody); + JsonNode argumentsNode = rootNode.get("choices") + .get(0) + .get("message") + .get("function_call") + .get("arguments"); + + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + String argumentsJson = objectMapper.convertValue(argumentsNode, String.class); + + Map> arguments = objectMapper.readValue(argumentsJson, + new TypeReference>>() { + }); + List addTaskList = arguments.get("add_task"); + + List formattedTaskSuggestionEntityDtos = new ArrayList<>(); + if (addTaskList != null) { + for (AddTaskSuggestionEntityDto addTask : addTaskList) { + AddTaskSuggestionEntityDto addTaskSuggestionEntityDto = new AddTaskSuggestionEntityDto(); + addTaskSuggestionEntityDto.setDescription(addTask.getDescription()); + + // Format the response check if duedate format is YYYY-MM-DD else + // remove duedate + String dueDate = addTask.getDueDate(); + if (dateFormatValidator.isValid(dueDate, null)) { + addTaskSuggestionEntityDto.setDueDate(dueDate); + } + + formattedTaskSuggestionEntityDtos.add(addTaskSuggestionEntityDto); + } + } + + crmActionSuggestionsFormatterDto.setAddTaskSuggestions(formattedTaskSuggestionEntityDtos); + return crmActionSuggestionsFormatterDto; + } + catch (Exception e) { + throw new CustomException(new ErrorObject("l_gcas_p_1", "something_went_wrong", e.getMessage())); + } + } + + /** + * Escape the input string for json. + * @param input + * @return + */ + private String escapeForJson(String input) { + return input.replace("\"", "\\\"").replace("\n", "\\n"); + } + } diff --git a/src/main/java/com/salessparrow/api/lib/LocalCipher.java b/src/main/java/com/salessparrow/api/lib/LocalCipher.java index fcf6b94f..aeeaf1e5 100644 --- a/src/main/java/com/salessparrow/api/lib/LocalCipher.java +++ b/src/main/java/com/salessparrow/api/lib/LocalCipher.java @@ -20,100 +20,91 @@ @Component public class LocalCipher { - private final String algorithm = "AES"; - private final String encryptionMode = "AES/ECB/PKCS5Padding"; + private final String algorithm = "AES"; - /** - * Encrypt the input string. - * - * @param salt The salt for encryption. - * @param string The string to be encrypted. - * @return The encrypted string in hexadecimal format. - */ - public String encrypt(String salt, String string) { - byte[] encryptedBytes = null; - try { - Cipher encrypt = Cipher.getInstance(encryptionMode); - SecretKeySpec secretKey = generateSecretKey(salt); - encrypt.init(Cipher.ENCRYPT_MODE, secretKey); - encryptedBytes = encrypt.doFinal(string.getBytes(StandardCharsets.UTF_8)); - } catch (Exception e) { - throw new CustomException( - new ErrorObject( - "l_lc_e_1", - "something_went_wrong", - e.getMessage())); - } - return Base64.getEncoder().encodeToString(encryptedBytes); - } + private final String encryptionMode = "AES/ECB/PKCS5Padding"; - /** - * Decrypt the input encrypted string. - * - * @param salt The salt for decryption. - * @param encryptedString The encrypted string in hexadecimal format. - * @return The decrypted string. - */ - public String decrypt(String salt, String encryptedString) { - byte[] decryptedBytes = null; - try { - Cipher decrypt = Cipher.getInstance(encryptionMode); - SecretKeySpec secretKey = generateSecretKey(salt); - decrypt.init(Cipher.DECRYPT_MODE, secretKey); - byte[] decodedBytes = Base64.getDecoder().decode(encryptedString); - decryptedBytes = decrypt.doFinal(decodedBytes); - } catch (Exception e) { - throw new CustomException( - new ErrorObject( - "l_lc_d_1", - "something_went_wrong", - e.getMessage())); - } + /** + * Encrypt the input string. + * @param salt The salt for encryption. + * @param string The string to be encrypted. + * @return The encrypted string in hexadecimal format. + */ + public String encrypt(String salt, String string) { + byte[] encryptedBytes = null; + try { + Cipher encrypt = Cipher.getInstance(encryptionMode); + SecretKeySpec secretKey = generateSecretKey(salt); + encrypt.init(Cipher.ENCRYPT_MODE, secretKey); + encryptedBytes = encrypt.doFinal(string.getBytes(StandardCharsets.UTF_8)); + } + catch (Exception e) { + throw new CustomException(new ErrorObject("l_lc_e_1", "something_went_wrong", e.getMessage())); + } + return Base64.getEncoder().encodeToString(encryptedBytes); + } - return new String(decryptedBytes, StandardCharsets.UTF_8); - } + /** + * Decrypt the input encrypted string. + * @param salt The salt for decryption. + * @param encryptedString The encrypted string in hexadecimal format. + * @return The decrypted string. + */ + public String decrypt(String salt, String encryptedString) { + byte[] decryptedBytes = null; + try { + Cipher decrypt = Cipher.getInstance(encryptionMode); + SecretKeySpec secretKey = generateSecretKey(salt); + decrypt.init(Cipher.DECRYPT_MODE, secretKey); + byte[] decodedBytes = Base64.getDecoder().decode(encryptedString); + decryptedBytes = decrypt.doFinal(decodedBytes); + } + catch (Exception e) { + throw new CustomException(new ErrorObject("l_lc_d_1", "something_went_wrong", e.getMessage())); + } - /** - * Generate random IV. - * - * @param number The number of bytes for the IV. - * @return The random IV in hexadecimal format. - */ - public String generateRandomIv(int number) { - byte[] ivBytes = new byte[number]; - new SecureRandom().nextBytes(ivBytes); - return bytesToHex(ivBytes).substring(0, number * 2); - } + return new String(decryptedBytes, StandardCharsets.UTF_8); + } - /** - * Generate random salt. - * - * @return The random salt in hexadecimal format. - */ - public String generateRandomSalt() { - byte[] saltBytes = new byte[16]; - new SecureRandom().nextBytes(saltBytes); - return bytesToHex(saltBytes); - } + /** + * Generate random IV. + * @param number The number of bytes for the IV. + * @return The random IV in hexadecimal format. + */ + public String generateRandomIv(int number) { + byte[] ivBytes = new byte[number]; + new SecureRandom().nextBytes(ivBytes); + return bytesToHex(ivBytes).substring(0, number * 2); + } - private SecretKeySpec generateSecretKey(String salt) throws NoSuchAlgorithmException { - MessageDigest sha = MessageDigest.getInstance("SHA-256"); - byte[] keyBytes = sha.digest(salt.getBytes(StandardCharsets.UTF_8)); - byte[] key = new byte[16]; - System.arraycopy(keyBytes, 0, key, 0, 16); - return new SecretKeySpec(key, algorithm); - } + /** + * Generate random salt. + * @return The random salt in hexadecimal format. + */ + public String generateRandomSalt() { + byte[] saltBytes = new byte[16]; + new SecureRandom().nextBytes(saltBytes); + return bytesToHex(saltBytes); + } - private String bytesToHex(byte[] hash) { - StringBuilder hexString = new StringBuilder(2 * hash.length); - for (byte b : hash) { - String hex = Integer.toHexString(0xff & b); - if (hex.length() == 1) { - hexString.append('0'); - } - hexString.append(hex); - } - return hexString.toString(); - } -} + private SecretKeySpec generateSecretKey(String salt) throws NoSuchAlgorithmException { + MessageDigest sha = MessageDigest.getInstance("SHA-256"); + byte[] keyBytes = sha.digest(salt.getBytes(StandardCharsets.UTF_8)); + byte[] key = new byte[16]; + System.arraycopy(keyBytes, 0, key, 0, 16); + return new SecretKeySpec(key, algorithm); + } + + private String bytesToHex(byte[] hash) { + StringBuilder hexString = new StringBuilder(2 * hash.length); + for (byte b : hash) { + String hex = Integer.toHexString(0xff & b); + if (hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + return hexString.toString(); + } +} diff --git a/src/main/java/com/salessparrow/api/lib/UserLoginCookieAuth.java b/src/main/java/com/salessparrow/api/lib/UserLoginCookieAuth.java index 4a537faa..084785ae 100644 --- a/src/main/java/com/salessparrow/api/lib/UserLoginCookieAuth.java +++ b/src/main/java/com/salessparrow/api/lib/UserLoginCookieAuth.java @@ -20,198 +20,176 @@ @Component public class UserLoginCookieAuth { - Logger logger = LoggerFactory.getLogger(UserLoginCookieAuth.class); - - private String cookieValue; - private String reqApiSource; - - private String userId; - private String userKind; - private String cookieApiSource; - private Integer timestampInCookie; - private String token; - private User currentUser; - private String userLoginCookieValue; - private String decryptedEncryptionSalt; - - @Autowired - private LocalCipher localCipher; - - @Autowired - private CookieHelper cookieHelper; - - @Autowired - private SalesforceUserRepository salesforceUserRepository; - - /** - * Validate and set cookie - * - * @param cookieValue - * @param reqApiSource - * - * @return Map - */ - public Map validateAndSetCookie(String cookieValue, String reqApiSource) { - this.cookieValue = cookieValue; - this.reqApiSource = reqApiSource; - - logger.info("Validating cookie"); - validate(); - setParts(); - validateTimestamp(); - validateApiSource(); - fetchAndValidateUser(); - validateCookieToken(); - setCookie(); - - Map resultMap = new HashMap<>(); - resultMap.put("current_user", currentUser); - resultMap.put("userLoginCookieValue", userLoginCookieValue); - - return resultMap; - } - - /** - * Validate cookie value and expire timestamp - * - * @throws RuntimeException - */ - private void validate() { - if (cookieValue == null || cookieValue.isEmpty()) { - - throw new CustomException( - new ErrorObject( - "l_ulca_v_1", - "unauthorized_api_request", - "Invalid cookie value")); - } - - } - - /** - * Set cookie value parts - * - * @throws RuntimeException - */ - private void setParts() { - List cookieValueParts = Arrays.asList(cookieValue.split(":")); - - if (cookieValueParts.size() != 6) { - throw new CustomException( - new ErrorObject( - "l_ulca_sp_1", - "unauthorized_api_request", - "Invalid cookie value")); - } - - if (cookieValueParts.get(0).equals(CookieConstants.LATEST_VERSION)) { - userId = cookieValueParts.get(1); - userKind = cookieValueParts.get(2); - cookieApiSource = cookieValueParts.get(3); - timestampInCookie = Integer.parseInt(cookieValueParts.get(4)); - token = cookieValueParts.get(5); - } else { - throw new CustomException( - new ErrorObject( - "l_ulca_sp_2", - "unauthorized_api_request", - "Invalid cookie version")); - } - } - - /** - * Validate cookie timestamp - * - * @throws RuntimeException - */ - private void validateTimestamp() { - if (timestampInCookie + CookieConstants.USER_LOGIN_COOKIE_EXPIRY_IN_SEC < System.currentTimeMillis() / 1000) { - throw new CustomException( - new ErrorObject( - "l_ulca_vt_1", - "unauthorized_api_request", - "Cookie expired")); - - } - } - - /** - * Validate api source - * - * @throws RuntimeException - */ - private void validateApiSource() { - if (!cookieApiSource.equals(reqApiSource)) { - throw new CustomException( - new ErrorObject( - "l_ulca_vas_1", - "unauthorized_api_request", - "Cookie api source and request api source mismatch")); - - } - } - - /** - * Fetch and validate user - * - * @throws RuntimeException - */ - private void fetchAndValidateUser() { - - logger.info("Fetching and validating current user"); - if (userKind.equals(UserConstants.SALESFORCE_USER_KIND)) { - logger.info("Fetching and validating salesforce user"); - fetchAndValidateSalesforceUser(); - } else { - logger.info("Fetching another user"); - // Todo: Throw an error - } - - } - - private void fetchAndValidateSalesforceUser() { - User userObj = salesforceUserRepository.getSalesforceUserByExternalUserId(userId); - - if (userObj == null) { - throw new CustomException( - new ErrorObject( - "l_ulca_favu_1", - "unauthorized_api_request", - "User not found")); - } - - currentUser = userObj; - } - - /** - * Validate cookie token - * - * @throws RuntimeException - */ - private void validateCookieToken() { - String encryptionSalt = currentUser.getEncryptionSalt(); - decryptedEncryptionSalt = localCipher.decrypt(CoreConstants.encryptionKey(), - encryptionSalt); - - String generatedToken = cookieHelper.getCookieToken(currentUser, - decryptedEncryptionSalt, timestampInCookie, reqApiSource); - if (!generatedToken.equals(token)) { - throw new CustomException( - new ErrorObject( - "l_ulca_vct_2", - "unauthorized_api_request", - "Invalid cookie token")); - } - } - - /** - * Set cookie - * - * @throws RuntimeException - */ - private void setCookie() { - userLoginCookieValue = cookieHelper.getCookieValue(currentUser, userKind, - decryptedEncryptionSalt, reqApiSource); - } + + Logger logger = LoggerFactory.getLogger(UserLoginCookieAuth.class); + + private String cookieValue; + + private String reqApiSource; + + private String userId; + + private String userKind; + + private String cookieApiSource; + + private Integer timestampInCookie; + + private String token; + + private User currentUser; + + private String userLoginCookieValue; + + private String decryptedEncryptionSalt; + + @Autowired + private LocalCipher localCipher; + + @Autowired + private CookieHelper cookieHelper; + + @Autowired + private SalesforceUserRepository salesforceUserRepository; + + /** + * Validate and set cookie + * @param cookieValue + * @param reqApiSource + * @return Map + */ + public Map validateAndSetCookie(String cookieValue, String reqApiSource) { + this.cookieValue = cookieValue; + this.reqApiSource = reqApiSource; + + logger.info("Validating cookie"); + validate(); + setParts(); + validateTimestamp(); + validateApiSource(); + fetchAndValidateUser(); + validateCookieToken(); + setCookie(); + + Map resultMap = new HashMap<>(); + resultMap.put("current_user", currentUser); + resultMap.put("userLoginCookieValue", userLoginCookieValue); + + return resultMap; + } + + /** + * Validate cookie value and expire timestamp + * @throws RuntimeException + */ + private void validate() { + if (cookieValue == null || cookieValue.isEmpty()) { + + throw new CustomException( + new ErrorObject("l_ulca_v_1", "unauthorized_api_request", "Invalid cookie value")); + } + + } + + /** + * Set cookie value parts + * @throws RuntimeException + */ + private void setParts() { + List cookieValueParts = Arrays.asList(cookieValue.split(":")); + + if (cookieValueParts.size() != 6) { + throw new CustomException( + new ErrorObject("l_ulca_sp_1", "unauthorized_api_request", "Invalid cookie value")); + } + + if (cookieValueParts.get(0).equals(CookieConstants.LATEST_VERSION)) { + userId = cookieValueParts.get(1); + userKind = cookieValueParts.get(2); + cookieApiSource = cookieValueParts.get(3); + timestampInCookie = Integer.parseInt(cookieValueParts.get(4)); + token = cookieValueParts.get(5); + } + else { + throw new CustomException( + new ErrorObject("l_ulca_sp_2", "unauthorized_api_request", "Invalid cookie version")); + } + } + + /** + * Validate cookie timestamp + * @throws RuntimeException + */ + private void validateTimestamp() { + if (timestampInCookie + CookieConstants.USER_LOGIN_COOKIE_EXPIRY_IN_SEC < System.currentTimeMillis() / 1000) { + throw new CustomException(new ErrorObject("l_ulca_vt_1", "unauthorized_api_request", "Cookie expired")); + + } + } + + /** + * Validate api source + * @throws RuntimeException + */ + private void validateApiSource() { + if (!cookieApiSource.equals(reqApiSource)) { + throw new CustomException(new ErrorObject("l_ulca_vas_1", "unauthorized_api_request", + "Cookie api source and request api source mismatch")); + + } + } + + /** + * Fetch and validate user + * @throws RuntimeException + */ + private void fetchAndValidateUser() { + + logger.info("Fetching and validating current user"); + if (userKind.equals(UserConstants.SALESFORCE_USER_KIND)) { + logger.info("Fetching and validating salesforce user"); + fetchAndValidateSalesforceUser(); + } + else { + logger.info("Fetching another user"); + // Todo: Throw an error + } + + } + + private void fetchAndValidateSalesforceUser() { + User userObj = salesforceUserRepository.getSalesforceUserByExternalUserId(userId); + + if (userObj == null) { + throw new CustomException(new ErrorObject("l_ulca_favu_1", "unauthorized_api_request", "User not found")); + } + + currentUser = userObj; + } + + /** + * Validate cookie token + * @throws RuntimeException + */ + private void validateCookieToken() { + String encryptionSalt = currentUser.getEncryptionSalt(); + decryptedEncryptionSalt = localCipher.decrypt(CoreConstants.encryptionKey(), encryptionSalt); + + String generatedToken = cookieHelper.getCookieToken(currentUser, decryptedEncryptionSalt, timestampInCookie, + reqApiSource); + if (!generatedToken.equals(token)) { + throw new CustomException( + new ErrorObject("l_ulca_vct_2", "unauthorized_api_request", "Invalid cookie token")); + } + } + + /** + * Set cookie + * @throws RuntimeException + */ + private void setCookie() { + userLoginCookieValue = cookieHelper.getCookieValue(currentUser, userKind, decryptedEncryptionSalt, + reqApiSource); + } } diff --git a/src/main/java/com/salessparrow/api/lib/Util.java b/src/main/java/com/salessparrow/api/lib/Util.java index 2d29385d..74692bde 100644 --- a/src/main/java/com/salessparrow/api/lib/Util.java +++ b/src/main/java/com/salessparrow/api/lib/Util.java @@ -16,114 +16,100 @@ /** * Class for utility functions. - * + * */ @Component public class Util { - /** - * Get JsonNode from json string - * - * @param jsonString - * - * @return JsonNode - */ - public JsonNode getJsonNode(String jsonString) { - ObjectMapper mapper = new ObjectMapper(); - JsonNode jsonNode = null; - try { - jsonNode = mapper.readTree(jsonString); - } catch (Exception e) { - throw new CustomException( - new ErrorObject( - "l_u_gjn_1", - "something_went_wrong", - e.getMessage())); - } - return jsonNode; - } + /** + * Get JsonNode from json string + * @param jsonString + * @return JsonNode + */ + public JsonNode getJsonNode(String jsonString) { + ObjectMapper mapper = new ObjectMapper(); + JsonNode jsonNode = null; + try { + jsonNode = mapper.readTree(jsonString); + } + catch (Exception e) { + throw new CustomException(new ErrorObject("l_u_gjn_1", "something_went_wrong", e.getMessage())); + } + return jsonNode; + } + + /** + * Retrieves a string representation of all request headers. For security, the value + * of the "authorization, cookie, password" header is obfuscated. + * @param request - The HTTP request containing the headers to be logged. + * @return String - A string representation of the headers in the format + * "{headerName:headerValue, ...}". + */ + public static String generateHeaderLogString(HttpServletRequest request) { + StringBuilder headerBuilder = new StringBuilder("{"); + request.getHeaderNames().asIterator().forEachRemaining(headerName -> { + // Add any other secret headers here that you don't want logged. + if (headerName.equals("authorization") || headerName.equals("cookie") || headerName.equals("password")) { + headerBuilder.append(headerName).append(":**********, "); + } + else { + headerBuilder.append(headerName).append(":").append(request.getHeader(headerName)).append(", "); + } + }); + headerBuilder.append("}"); + + return headerBuilder.toString(); + } + + /** + * Escape special characters in a string for use in a regular expression. SOQL is + * important from security point of view. Refer + * https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql_select_quotedstringescapes.htm + * for more details. + * @param input + * @return String + */ + public static String escapeSpecialChars(String input) { + if (input == null || input == "") + return input; + + String[] specialChars = { "\\", "%", "'", "\"", "_" }; + + for (String specialChar : specialChars) { + input = input.replace(specialChar, "\\" + specialChar); + } + + return input; + } + + /** + * URL encode a string + * @param input + * @return String + */ + public static String urlEncoder(String input) { + if (input == null || input == "") + return input; + + try { + return URLEncoder.encode(input, "UTF-8"); + } + catch (UnsupportedEncodingException e) { + throw new CustomException(new ErrorObject("u_u_ue_1", "something_went_wrong", e.getMessage())); + } + } + + /** + * Get date format from datetime + * @param date + * @return String + */ + public String getDateFormatFromDatetime(Date date) { + if (date != null) { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + return dateFormat.format(date); + } + return null; + } -/** - * Retrieves a string representation of all request headers. For security, - * the value of the "authorization, cookie, password" header is obfuscated. - * - * @param request - The HTTP request containing the headers to be logged. - * @return String - A string representation of the headers in the format "{headerName:headerValue, ...}". - */ - public static String generateHeaderLogString(HttpServletRequest request) { - StringBuilder headerBuilder = new StringBuilder("{"); - request.getHeaderNames().asIterator().forEachRemaining(headerName -> { - // Add any other secret headers here that you don't want logged. - if (headerName.equals("authorization") || - headerName.equals("cookie") || - headerName.equals("password")) { - headerBuilder.append(headerName).append(":**********, "); - } else { - headerBuilder.append(headerName).append(":").append(request.getHeader(headerName)).append(", "); - } - }); - headerBuilder.append("}"); - - return headerBuilder.toString(); - } - - /** - * Escape special characters in a string for use in a regular expression. - * SOQL is important from security point of view. - * Refer https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql_select_quotedstringescapes.htm for more details. - * - * @param input - * - * @return String - */ - public static String escapeSpecialChars(String input) { - if(input == null || input == "") - return input; - - String[] specialChars = {"\\", "%", "'", "\"", "_"}; - - for (String specialChar : specialChars) { - input = input.replace(specialChar, "\\" + specialChar); - } - - return input; - } - - /** - * URL encode a string - * - * @param input - * - * @return String - */ - public static String urlEncoder(String input){ - if(input == null || input == "") - return input; - - try { - return URLEncoder.encode(input, "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new CustomException( - new ErrorObject( - "u_u_ue_1", - "something_went_wrong", - e.getMessage() - ) - ); - } - } - - /** Get date format from datetime - * - * @param date - * - * @return String - */ - public String getDateFormatFromDatetime(Date date) { - if (date != null) { - SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); - return dateFormat.format(date); - } - return null; - } } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateNoteFactory.java b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateNoteFactory.java index 86d5e17e..64eff701 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateNoteFactory.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateNoteFactory.java @@ -15,6 +15,7 @@ */ @Component public class CreateNoteFactory { + @Autowired private CreateSalesforceNote createSalesforceNote; @@ -22,20 +23,17 @@ public class CreateNoteFactory { * Create a note for a given account * @param user * @param accountId - * * @return CreateNoteFormatterDto **/ public CreateNoteFormatterDto createNote(SalesforceUser user, String accountId, NoteDto note) { - switch(user.getUserKind()) { + switch (user.getUserKind()) { case UserConstants.SALESFORCE_USER_KIND: return createSalesforceNote.createNote(user, accountId, note); default: throw new CustomException( - new ErrorObject( - "l_ca_cn_cnf_cn_1", - "something_went_wrong", - "Invalid user kind.")); + new ErrorObject("l_ca_cn_cnf_cn_1", "something_went_wrong", "Invalid user kind.")); } } + } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateNoteInterface.java b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateNoteInterface.java index 29a8301e..614274ae 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateNoteInterface.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateNoteInterface.java @@ -11,6 +11,7 @@ */ @Component public interface CreateNoteInterface { - public CreateNoteFormatterDto createNote(SalesforceUser user, String accountId, NoteDto note); -} + public CreateNoteFormatterDto createNote(SalesforceUser user, String accountId, NoteDto note); + +} diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java index c3742d16..8249b7cf 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java @@ -25,124 +25,108 @@ import com.salessparrow.api.lib.salesforce.helper.MakeCompositeRequest; /** - * CreateSalesforceNote is a class that creates a note in Salesforce and attaches it to an account. + * CreateSalesforceNote is a class that creates a note in Salesforce and attaches it to an + * account. */ @Component public class CreateSalesforceNote implements CreateNoteInterface { - - @Autowired - private SalesforceConstants salesforceConstants; - - @Autowired - private MakeCompositeRequest makeCompositeRequest; - - @Autowired - private Base64Helper base64Helper; - - /** - * Create a note for a given account. - * - * @param user - * @param accountId - * @param note - * @return CreateNoteFormatterDto - */ - public CreateNoteFormatterDto createNote(SalesforceUser user, String accountId, NoteDto note) { - String salesforceUserId = user.getExternalUserId(); - - String noteTitle = getNoteTitleFromContent(note); - String encodedNoteContent = base64Helper.base64Encode(note.getText()); - - Map createNoteBody = new HashMap(); - createNoteBody.put("Title", noteTitle); - createNoteBody.put("Content", encodedNoteContent); - - CompositeRequestDto createNoteCompositeRequestDto = new CompositeRequestDto( - "POST", - salesforceConstants.salesforceCreateNoteUrl(), - "CreateNote", - createNoteBody - ); - - Map attachNoteBody = new HashMap(); - attachNoteBody.put("ContentDocumentId", "@{CreateNote.id}"); - attachNoteBody.put("LinkedEntityId", accountId); - - CompositeRequestDto attachNoteCompositeRequestDto = new CompositeRequestDto( - "POST", - salesforceConstants.salesforceAttachNoteUrl(), - "AttachNote", - attachNoteBody - ); - - List compositeRequests = new ArrayList(); - compositeRequests.add(createNoteCompositeRequestDto); - compositeRequests.add(attachNoteCompositeRequestDto); - - HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, salesforceUserId); - - return parseResponse(response.getResponseBody()); - } - - /** - * Parse the response from Salesforce. - * - * @param createNoteFormatterDto - * @return CreateNoteFormatterDto - formatted response - */ - private CreateNoteFormatterDto parseResponse(String createNoteResponse) { - Util util = new Util(); - JsonNode rootNode = util.getJsonNode(createNoteResponse); - - JsonNode createNoteCompositeResponse = rootNode.get("compositeResponse").get(0); - String createNoteStatusCode = createNoteCompositeResponse.get("httpStatusCode").asText(); - - if (!createNoteStatusCode.equals("200") && !createNoteStatusCode.equals("201")) { - String errorBody = createNoteCompositeResponse.get("body").asText(); - - throw new CustomException( - new ErrorObject( - "l_s_fse_fscn_fcn_1", - "internal_server_error", - errorBody)); - } - - JsonNode createNoteNodeResponseBody = rootNode.get("compositeResponse").get(0).get("body"); - - ObjectMapper mapper = new ObjectMapper(); - mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); - SalesforceCreateNoteDto salesforceCreateNoteDto = mapper.convertValue(createNoteNodeResponseBody, SalesforceCreateNoteDto.class); - - JsonNode attachNoteCompositeResponse = rootNode.get("compositeResponse").get(1); - String attachNoteStatusCode = attachNoteCompositeResponse.get("httpStatusCode").asText(); - - if (!attachNoteStatusCode.equals("200") && !attachNoteStatusCode.equals("201")) { - String errorBody = attachNoteCompositeResponse.get("body").toString(); - - throw new CustomException( - new ErrorObject( - "l_s_fse_fscn_fcn_2", - "internal_server_error", - errorBody)); - } - - CreateNoteFormatterDto createNoteFormatterDto = new CreateNoteFormatterDto(); - createNoteFormatterDto.setNoteId(salesforceCreateNoteDto.getId()); - - return createNoteFormatterDto; - } - - /** - * Get the first 50 characters of the note content. - * - * @param note - note dto - * @return String - */ - private String getNoteTitleFromContent(NoteDto note) { - if (note.getText().length() < 50) { - return note.getText(); - } - - return note.getText().substring(0, 50); - } + + @Autowired + private SalesforceConstants salesforceConstants; + + @Autowired + private MakeCompositeRequest makeCompositeRequest; + + @Autowired + private Base64Helper base64Helper; + + /** + * Create a note for a given account. + * @param user + * @param accountId + * @param note + * @return CreateNoteFormatterDto + */ + public CreateNoteFormatterDto createNote(SalesforceUser user, String accountId, NoteDto note) { + String salesforceUserId = user.getExternalUserId(); + + String noteTitle = getNoteTitleFromContent(note); + String encodedNoteContent = base64Helper.base64Encode(note.getText()); + + Map createNoteBody = new HashMap(); + createNoteBody.put("Title", noteTitle); + createNoteBody.put("Content", encodedNoteContent); + + CompositeRequestDto createNoteCompositeRequestDto = new CompositeRequestDto("POST", + salesforceConstants.salesforceCreateNoteUrl(), "CreateNote", createNoteBody); + + Map attachNoteBody = new HashMap(); + attachNoteBody.put("ContentDocumentId", "@{CreateNote.id}"); + attachNoteBody.put("LinkedEntityId", accountId); + + CompositeRequestDto attachNoteCompositeRequestDto = new CompositeRequestDto("POST", + salesforceConstants.salesforceAttachNoteUrl(), "AttachNote", attachNoteBody); + + List compositeRequests = new ArrayList(); + compositeRequests.add(createNoteCompositeRequestDto); + compositeRequests.add(attachNoteCompositeRequestDto); + + HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, salesforceUserId); + + return parseResponse(response.getResponseBody()); + } + + /** + * Parse the response from Salesforce. + * @param createNoteFormatterDto + * @return CreateNoteFormatterDto - formatted response + */ + private CreateNoteFormatterDto parseResponse(String createNoteResponse) { + Util util = new Util(); + JsonNode rootNode = util.getJsonNode(createNoteResponse); + + JsonNode createNoteCompositeResponse = rootNode.get("compositeResponse").get(0); + String createNoteStatusCode = createNoteCompositeResponse.get("httpStatusCode").asText(); + + if (!createNoteStatusCode.equals("200") && !createNoteStatusCode.equals("201")) { + String errorBody = createNoteCompositeResponse.get("body").asText(); + + throw new CustomException(new ErrorObject("l_s_fse_fscn_fcn_1", "internal_server_error", errorBody)); + } + + JsonNode createNoteNodeResponseBody = rootNode.get("compositeResponse").get(0).get("body"); + + ObjectMapper mapper = new ObjectMapper(); + mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + SalesforceCreateNoteDto salesforceCreateNoteDto = mapper.convertValue(createNoteNodeResponseBody, + SalesforceCreateNoteDto.class); + + JsonNode attachNoteCompositeResponse = rootNode.get("compositeResponse").get(1); + String attachNoteStatusCode = attachNoteCompositeResponse.get("httpStatusCode").asText(); + + if (!attachNoteStatusCode.equals("200") && !attachNoteStatusCode.equals("201")) { + String errorBody = attachNoteCompositeResponse.get("body").toString(); + + throw new CustomException(new ErrorObject("l_s_fse_fscn_fcn_2", "internal_server_error", errorBody)); + } + + CreateNoteFormatterDto createNoteFormatterDto = new CreateNoteFormatterDto(); + createNoteFormatterDto.setNoteId(salesforceCreateNoteDto.getId()); + + return createNoteFormatterDto; + } + + /** + * Get the first 50 characters of the note content. + * @param note - note dto + * @return String + */ + private String getNoteTitleFromContent(NoteDto note) { + if (note.getText().length() < 50) { + return note.getText(); + } + + return note.getText().substring(0, 50); + } + } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateAccountTask.java b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateAccountTask.java index 4e7b039d..eb57e094 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateAccountTask.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateAccountTask.java @@ -11,5 +11,7 @@ */ @Component public interface CreateAccountTask { - public CreateTaskFormatterDto createAccountTask(User User,String accountId, CreateAccountTaskDto task); + + public CreateTaskFormatterDto createAccountTask(User User, String accountId, CreateAccountTaskDto task); + } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateAccountTaskFactory.java b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateAccountTaskFactory.java index 8ac55a16..bab2cac3 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateAccountTaskFactory.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateAccountTaskFactory.java @@ -18,31 +18,27 @@ @Component public class CreateAccountTaskFactory { - Logger logger = LoggerFactory.getLogger(CreateAccountTaskFactory.class); + Logger logger = LoggerFactory.getLogger(CreateAccountTaskFactory.class); - @Autowired - CreateSalesforceAccountTask createSalesforceAccountTask; + @Autowired + CreateSalesforceAccountTask createSalesforceAccountTask; + + /** + * Create a task in CRM + * @param user User object + * @param accountId CRM account id + * @param task CreateTaskDto object + * @return CreateTaskFormatterDto object + */ + public CreateTaskFormatterDto createAccountTask(User user, String accountId, CreateAccountTaskDto task) { + switch (user.getUserKind()) { + case UserConstants.SALESFORCE_USER_KIND: + logger.info("calling createTask of salesforceCreateTask"); + return createSalesforceAccountTask.createAccountTask(user, accountId, task); + default: + throw new CustomException( + new ErrorObject("l_ca_ct_ctf_1", "something_went_wrong", "Invalid user kind.")); + } + } - /** - * Create a task in CRM - * - * @param user User object - * @param accountId CRM account id - * @param task CreateTaskDto object - * - * @return CreateTaskFormatterDto object - */ - public CreateTaskFormatterDto createAccountTask(User user, String accountId, CreateAccountTaskDto task) { - switch(user.getUserKind()) { - case UserConstants.SALESFORCE_USER_KIND: - logger.info("calling createTask of salesforceCreateTask"); - return createSalesforceAccountTask.createAccountTask(user, accountId, task); - default: - throw new CustomException( - new ErrorObject( - "l_ca_ct_ctf_1", - "something_went_wrong", - "Invalid user kind.")); - } - } } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateSalesforceAccountTask.java b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateSalesforceAccountTask.java index 087bf743..d26afde7 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateSalesforceAccountTask.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateSalesforceAccountTask.java @@ -29,106 +29,93 @@ * CreateSalesforceTask class is responsible for creating a task in Salesforce */ @Component -public class CreateSalesforceAccountTask implements CreateAccountTask{ - - Logger logger = LoggerFactory.getLogger(CreateSalesforceAccountTask.class); - - @Autowired - private SalesforceConstants salesforceConstants; - - @Autowired - private MakeCompositeRequest makeCompositeRequest; - - /** - * Create a task in Salesforce - * - * @param User User object - * @param accountId Salesforce account id - * @param task CreateTaskDto object - * - * @return CreateTaskFormatterDto object - */ - public CreateTaskFormatterDto createAccountTask(User User, String accountId, CreateAccountTaskDto task) { - String salesforceUserId = User.getExternalUserId(); - - String taskSubject = getTaskSubjectFromDescription(task); - - logger.info("performing create task in salesforce"); - - Map taskBody = new HashMap(); - taskBody.put("Subject", taskSubject); - taskBody.put("Description", task.getDescription()); - taskBody.put("OwnerId", task.getCrmOrganizationUserId()); - taskBody.put("ActivityDate", task.getDueDate()); - taskBody.put("WhatId", accountId); - - CompositeRequestDto createTaskCompositeRequestDto = new CompositeRequestDto( - "POST", - salesforceConstants.salesforceCreateTaskUrl(), - "CreateTask", - taskBody - ); - - List compositeRequests = new ArrayList(); - compositeRequests.add(createTaskCompositeRequestDto); - - HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, salesforceUserId); - - return parseResponse(response.getResponseBody()); - } - - /** - * Parse the response from Salesforce - * - * @param createTaskResponse String response from Salesforce - * - * @return CreateTaskFormatterDto object - */ - private CreateTaskFormatterDto parseResponse(String createTaskResponse){ - Util util = new Util(); - JsonNode rootNode = util.getJsonNode(createTaskResponse); - - logger.info("parsing response from salesforce"); - - JsonNode createTaskCompositeResponse = rootNode.get("compositeResponse").get(0); - String createTaskStatusCode = createTaskCompositeResponse.get("httpStatusCode").asText(); - - if (!createTaskStatusCode.equals("200") && !createTaskStatusCode.equals("201")) { - String errorBody = createTaskCompositeResponse.get("body").asText(); - - throw new CustomException( - new ErrorObject( - "l_ca_ct_cst_1", - "internal_server_error", - errorBody - )); - } - - JsonNode createTaskNodeResponseBody = rootNode.get("compositeResponse").get(0).get("body"); - - ObjectMapper mapper = new ObjectMapper(); - mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); - SalesforceCreateTaskDto salesforceCreateTaskDto = mapper.convertValue(createTaskNodeResponseBody, SalesforceCreateTaskDto.class); - - CreateTaskFormatterDto createTaskFormatterDto = new CreateTaskFormatterDto(); - createTaskFormatterDto.setTaskId(salesforceCreateTaskDto.getId()); - - return createTaskFormatterDto; - } - - /** - * Get task subject from description - * - * @param task CreateTaskDto object - * - * @return String task subject - */ - private String getTaskSubjectFromDescription(CreateAccountTaskDto task) { - logger.info("getting task subject from description"); - if (task.getDescription().length() < 60) { - return task.getDescription(); - } - - return task.getDescription().substring(0, 60); - } +public class CreateSalesforceAccountTask implements CreateAccountTask { + + Logger logger = LoggerFactory.getLogger(CreateSalesforceAccountTask.class); + + @Autowired + private SalesforceConstants salesforceConstants; + + @Autowired + private MakeCompositeRequest makeCompositeRequest; + + /** + * Create a task in Salesforce + * @param User User object + * @param accountId Salesforce account id + * @param task CreateTaskDto object + * @return CreateTaskFormatterDto object + */ + public CreateTaskFormatterDto createAccountTask(User User, String accountId, CreateAccountTaskDto task) { + String salesforceUserId = User.getExternalUserId(); + + String taskSubject = getTaskSubjectFromDescription(task); + + logger.info("performing create task in salesforce"); + + Map taskBody = new HashMap(); + taskBody.put("Subject", taskSubject); + taskBody.put("Description", task.getDescription()); + taskBody.put("OwnerId", task.getCrmOrganizationUserId()); + taskBody.put("ActivityDate", task.getDueDate()); + taskBody.put("WhatId", accountId); + + CompositeRequestDto createTaskCompositeRequestDto = new CompositeRequestDto("POST", + salesforceConstants.salesforceCreateTaskUrl(), "CreateTask", taskBody); + + List compositeRequests = new ArrayList(); + compositeRequests.add(createTaskCompositeRequestDto); + + HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, salesforceUserId); + + return parseResponse(response.getResponseBody()); + } + + /** + * Parse the response from Salesforce + * @param createTaskResponse String response from Salesforce + * @return CreateTaskFormatterDto object + */ + private CreateTaskFormatterDto parseResponse(String createTaskResponse) { + Util util = new Util(); + JsonNode rootNode = util.getJsonNode(createTaskResponse); + + logger.info("parsing response from salesforce"); + + JsonNode createTaskCompositeResponse = rootNode.get("compositeResponse").get(0); + String createTaskStatusCode = createTaskCompositeResponse.get("httpStatusCode").asText(); + + if (!createTaskStatusCode.equals("200") && !createTaskStatusCode.equals("201")) { + String errorBody = createTaskCompositeResponse.get("body").asText(); + + throw new CustomException(new ErrorObject("l_ca_ct_cst_1", "internal_server_error", errorBody)); + } + + JsonNode createTaskNodeResponseBody = rootNode.get("compositeResponse").get(0).get("body"); + + ObjectMapper mapper = new ObjectMapper(); + mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + SalesforceCreateTaskDto salesforceCreateTaskDto = mapper.convertValue(createTaskNodeResponseBody, + SalesforceCreateTaskDto.class); + + CreateTaskFormatterDto createTaskFormatterDto = new CreateTaskFormatterDto(); + createTaskFormatterDto.setTaskId(salesforceCreateTaskDto.getId()); + + return createTaskFormatterDto; + } + + /** + * Get task subject from description + * @param task CreateTaskDto object + * @return String task subject + */ + private String getTaskSubjectFromDescription(CreateAccountTaskDto task) { + logger.info("getting task subject from description"); + if (task.getDescription().length() < 60) { + return task.getDescription(); + } + + return task.getDescription().substring(0, 60); + } + } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteAccountNoteFactory.java b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteAccountNoteFactory.java index 1774cb63..c3cfce49 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteAccountNoteFactory.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteAccountNoteFactory.java @@ -10,39 +10,37 @@ import com.salessparrow.api.lib.globalConstants.UserConstants; /** - * DeleteAccountNoteFactory is a factory class for the DeleteAccountNote action for the CRM. + * DeleteAccountNoteFactory is a factory class for the DeleteAccountNote action for the + * CRM. */ @Component public class DeleteAccountNoteFactory { - private Logger logger = org.slf4j.LoggerFactory.getLogger(DeleteAccountNoteFactory.class); - - @Autowired - DeleteSalesforceAccountNote getSalesforceNoteDetails; - - @Autowired - DeleteSalesforceAccountNote deleteAccountSalesforceNote; - - /** - * deleteAccountNote is a method that makes call to delete note based on user kind. - * - * @param user - * @param noteId - * - * @return void - */ - public void deleteAccountNote(User user, String noteId) { - logger.info("Delete Account Note Factory called"); - - switch(user.getUserKind()) { - case UserConstants.SALESFORCE_USER_KIND: - deleteAccountSalesforceNote.deleteAccountNote(user, noteId); - break; - default: - throw new CustomException( - new ErrorObject( - "l_ca_dan_danf_dn_1", - "something_went_wrong", - "Invalid user kind.")); - } - } + + private Logger logger = org.slf4j.LoggerFactory.getLogger(DeleteAccountNoteFactory.class); + + @Autowired + DeleteSalesforceAccountNote getSalesforceNoteDetails; + + @Autowired + DeleteSalesforceAccountNote deleteAccountSalesforceNote; + + /** + * deleteAccountNote is a method that makes call to delete note based on user kind. + * @param user + * @param noteId + * @return void + */ + public void deleteAccountNote(User user, String noteId) { + logger.info("Delete Account Note Factory called"); + + switch (user.getUserKind()) { + case UserConstants.SALESFORCE_USER_KIND: + deleteAccountSalesforceNote.deleteAccountNote(user, noteId); + break; + default: + throw new CustomException( + new ErrorObject("l_ca_dan_danf_dn_1", "something_went_wrong", "Invalid user kind.")); + } + } + } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteAccountNoteInterface.java b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteAccountNoteInterface.java index 59c43a34..83a6f669 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteAccountNoteInterface.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteAccountNoteInterface.java @@ -5,9 +5,12 @@ import com.salessparrow.api.domain.User; /** - * DeleteAccountNoteInterface is an interface for the DeleteAccountNote action for the CRM. + * DeleteAccountNoteInterface is an interface for the DeleteAccountNote action for the + * CRM. */ @Component public interface DeleteAccountNoteInterface { - public void deleteAccountNote(User user, String noteId); + + public void deleteAccountNote(User user, String noteId); + } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteSalesforceAccountNote.java b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteSalesforceAccountNote.java index 26b5c991..9ca8ca7f 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteSalesforceAccountNote.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteSalesforceAccountNote.java @@ -20,75 +20,68 @@ import com.salessparrow.api.lib.salesforce.helper.MakeCompositeRequest; /** - * DeleteAccountSalesforceNote is a class for the DeleteAccountNote service for the Salesforce CRM. + * DeleteAccountSalesforceNote is a class for the DeleteAccountNote service for the + * Salesforce CRM. **/ @Component public class DeleteSalesforceAccountNote implements DeleteAccountNoteInterface { - private Logger logger = org.slf4j.LoggerFactory.getLogger(DeleteSalesforceAccountNote.class); - - @Autowired - private SalesforceConstants salesforceConstants; - - @Autowired - private MakeCompositeRequest makeCompositeRequest; - - /** - * Deletes a note from salesforce - * - * @param user - * @param noteId - * - * @return void - **/ - public void deleteAccountNote(User user, String noteId) { - logger.info("Delete Salesforce Account Note called"); - - String salesforceUserId = user.getExternalUserId(); - - String url = salesforceConstants.salesforceDeleteNoteUrl(noteId); - - CompositeRequestDto compositeReq = new CompositeRequestDto("DELETE", url, "DeleteNote"); - - List compositeRequests = new ArrayList(); - compositeRequests.add(compositeReq); - - HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, salesforceUserId); - - parseResponse(response.getResponseBody()); - } - - /** - * Parse Response - * - * @param responseBody - * - * @return void - **/ - public void parseResponse(String responseBody) { - - Util util = new Util(); - JsonNode rootNode = util.getJsonNode(responseBody); - - JsonNode deleteNoteCompositeResponse = rootNode.get("compositeResponse").get(0); - Integer deleteNoteStatusCode = deleteNoteCompositeResponse.get("httpStatusCode").asInt(); - - if (deleteNoteStatusCode != 200 && deleteNoteStatusCode != 201 && deleteNoteStatusCode != 204) { - String errorBody = deleteNoteCompositeResponse.get("body").asText(); - - // MALFORMED_ID or NOT_FOUND - if (deleteNoteStatusCode == 400 || deleteNoteStatusCode == 404) { - throw new CustomException( - new ParamErrorObject( - "l_ca_dan_dasn_pr_1", - errorBody, - Arrays.asList("invalid_note_id"))); - } else { - throw new CustomException( - new ErrorObject( - "l_ca_dan_dasn_pr_2", - "something_went_wrong", - errorBody)); - } - } - } + + private Logger logger = org.slf4j.LoggerFactory.getLogger(DeleteSalesforceAccountNote.class); + + @Autowired + private SalesforceConstants salesforceConstants; + + @Autowired + private MakeCompositeRequest makeCompositeRequest; + + /** + * Deletes a note from salesforce + * @param user + * @param noteId + * @return void + **/ + public void deleteAccountNote(User user, String noteId) { + logger.info("Delete Salesforce Account Note called"); + + String salesforceUserId = user.getExternalUserId(); + + String url = salesforceConstants.salesforceDeleteNoteUrl(noteId); + + CompositeRequestDto compositeReq = new CompositeRequestDto("DELETE", url, "DeleteNote"); + + List compositeRequests = new ArrayList(); + compositeRequests.add(compositeReq); + + HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, salesforceUserId); + + parseResponse(response.getResponseBody()); + } + + /** + * Parse Response + * @param responseBody + * @return void + **/ + public void parseResponse(String responseBody) { + + Util util = new Util(); + JsonNode rootNode = util.getJsonNode(responseBody); + + JsonNode deleteNoteCompositeResponse = rootNode.get("compositeResponse").get(0); + Integer deleteNoteStatusCode = deleteNoteCompositeResponse.get("httpStatusCode").asInt(); + + if (deleteNoteStatusCode != 200 && deleteNoteStatusCode != 201 && deleteNoteStatusCode != 204) { + String errorBody = deleteNoteCompositeResponse.get("body").asText(); + + // MALFORMED_ID or NOT_FOUND + if (deleteNoteStatusCode == 400 || deleteNoteStatusCode == 404) { + throw new CustomException( + new ParamErrorObject("l_ca_dan_dasn_pr_1", errorBody, Arrays.asList("invalid_note_id"))); + } + else { + throw new CustomException(new ErrorObject("l_ca_dan_dasn_pr_2", "something_went_wrong", errorBody)); + } + } + } + } \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteAccountTask.java b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteAccountTask.java index 3a21e922..2c225e68 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteAccountTask.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteAccountTask.java @@ -9,5 +9,7 @@ */ @Component public interface DeleteAccountTask { - public void deleteAccountTask(User user, String accountId, String taskId); + + public void deleteAccountTask(User user, String accountId, String taskId); + } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteAccountTaskFactory.java b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteAccountTaskFactory.java index 8419cf7d..7da8282e 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteAccountTaskFactory.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteAccountTaskFactory.java @@ -11,38 +11,34 @@ import com.salessparrow.api.lib.globalConstants.UserConstants; /** - * DeleteAccountTaskFactory is a factory class that handles the deleting a task in an account. + * DeleteAccountTaskFactory is a factory class that handles the deleting a task in an + * account. */ @Component public class DeleteAccountTaskFactory { - Logger logger = LoggerFactory.getLogger(DeleteAccountTaskFactory.class); + Logger logger = LoggerFactory.getLogger(DeleteAccountTaskFactory.class); + + @Autowired + DeleteSalesforceAccountTask deleteSalesforceAccountTask; + + /** + * Deletes a task in an account. + * @param user + * @param accountId + * @param taskId + * @return void + */ + public void deleteAccountTask(User user, String accountId, String taskId) { + logger.info("Delete Account Task Factory called"); + switch (user.getUserKind()) { + case UserConstants.SALESFORCE_USER_KIND: + deleteSalesforceAccountTask.deleteAccountTask(user, accountId, taskId); + break; + default: + throw new CustomException( + new ErrorObject("l_ca_dat_datf_1", "something_went_wrong", "Invalid user kind.")); + } + } - @Autowired - DeleteSalesforceAccountTask deleteSalesforceAccountTask; - - /** - * Deletes a task in an account. - * - * @param user - * @param accountId - * @param taskId - * - * @return void - */ - public void deleteAccountTask(User user, String accountId, String taskId) { - logger.info("Delete Account Task Factory called"); - switch(user.getUserKind()) { - case UserConstants.SALESFORCE_USER_KIND: - deleteSalesforceAccountTask.deleteAccountTask(user, accountId, taskId); - break; - default: - throw new CustomException( - new ErrorObject( - "l_ca_dat_datf_1", - "something_went_wrong", - "Invalid user kind.") - ); - } - } } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteSalesforceAccountTask.java b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteSalesforceAccountTask.java index 835451c2..cb9f866a 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteSalesforceAccountTask.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteSalesforceAccountTask.java @@ -21,78 +21,71 @@ import com.salessparrow.api.lib.salesforce.helper.MakeCompositeRequest; /** - * DeleteSalesforceAccountTask is a class that handles the deleting a task in an account for salesforce. + * DeleteSalesforceAccountTask is a class that handles the deleting a task in an account + * for salesforce. */ @Component -public class DeleteSalesforceAccountTask implements DeleteAccountTask{ - Logger logger = LoggerFactory.getLogger(DeleteSalesforceAccountTask.class); - - @Autowired - private SalesforceConstants salesforceConstants; - - @Autowired - private MakeCompositeRequest makeCompositeRequest; - - /** - * Deletes a task in an account for salesforce. - * - * @param user - * @param accountId - * @param taskId - * - * @return void - */ - public void deleteAccountTask(User user, String accountId, String taskId) { - logger.info("Delete Salesforce Account Task called"); - - String salesforceUserId = user.getExternalUserId(); - - String url = salesforceConstants.salesforceDeleteAccountTaskUrl(taskId); - - CompositeRequestDto compositeReq = new CompositeRequestDto("DELETE", url, "DeleteTask"); - - List compositeRequests = new ArrayList(); - compositeRequests.add(compositeReq); - - HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, salesforceUserId); - - parseResponse(response.getResponseBody()); - - } - - /** - * Parses the response from salesforce. - * - * @param responseBody - * - * @return void - */ - private void parseResponse(String responseBody) { - logger.info("Parsing response body"); - Util util = new Util(); - JsonNode rootNode = util.getJsonNode(responseBody); - - JsonNode deleteNoteCompositeResponse = rootNode.get("compositeResponse").get(0); - Integer deleteNoteStatusCode = deleteNoteCompositeResponse.get("httpStatusCode").asInt(); - - if (deleteNoteStatusCode != 200 && deleteNoteStatusCode != 201 && deleteNoteStatusCode != 204) { - String errorBody = deleteNoteCompositeResponse.get("body").asText(); - - // MALFORMED_ID or NOT_FOUND - if (deleteNoteStatusCode == 400 || deleteNoteStatusCode == 404) { - - throw new CustomException( - new ParamErrorObject( - "l_ca_dan_dasn_pr_1", - errorBody, - Arrays.asList("invalid_task_id"))); - }else{ - throw new CustomException( - new ErrorObject( - "l_ca_dan_dasn_pr_2", - "something_went_wrong", - errorBody)); - } - } - } +public class DeleteSalesforceAccountTask implements DeleteAccountTask { + + Logger logger = LoggerFactory.getLogger(DeleteSalesforceAccountTask.class); + + @Autowired + private SalesforceConstants salesforceConstants; + + @Autowired + private MakeCompositeRequest makeCompositeRequest; + + /** + * Deletes a task in an account for salesforce. + * @param user + * @param accountId + * @param taskId + * @return void + */ + public void deleteAccountTask(User user, String accountId, String taskId) { + logger.info("Delete Salesforce Account Task called"); + + String salesforceUserId = user.getExternalUserId(); + + String url = salesforceConstants.salesforceDeleteAccountTaskUrl(taskId); + + CompositeRequestDto compositeReq = new CompositeRequestDto("DELETE", url, "DeleteTask"); + + List compositeRequests = new ArrayList(); + compositeRequests.add(compositeReq); + + HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, salesforceUserId); + + parseResponse(response.getResponseBody()); + + } + + /** + * Parses the response from salesforce. + * @param responseBody + * @return void + */ + private void parseResponse(String responseBody) { + logger.info("Parsing response body"); + Util util = new Util(); + JsonNode rootNode = util.getJsonNode(responseBody); + + JsonNode deleteNoteCompositeResponse = rootNode.get("compositeResponse").get(0); + Integer deleteNoteStatusCode = deleteNoteCompositeResponse.get("httpStatusCode").asInt(); + + if (deleteNoteStatusCode != 200 && deleteNoteStatusCode != 201 && deleteNoteStatusCode != 204) { + String errorBody = deleteNoteCompositeResponse.get("body").asText(); + + // MALFORMED_ID or NOT_FOUND + if (deleteNoteStatusCode == 400 || deleteNoteStatusCode == 404) { + + throw new CustomException( + new ParamErrorObject("l_ca_dan_dasn_pr_1", errorBody, Arrays.asList("invalid_task_id"))); + } + else { + throw new CustomException(new ErrorObject("l_ca_dan_dasn_pr_2", "something_went_wrong", errorBody)); + } + } + } + } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNoteDetails/GetAccountNoteDetails.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNoteDetails/GetAccountNoteDetails.java index a8a0677a..ea06b893 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNoteDetails/GetAccountNoteDetails.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNoteDetails/GetAccountNoteDetails.java @@ -10,5 +10,7 @@ */ @Component public interface GetAccountNoteDetails { - public GetNoteDetailsFormatterDto getNoteDetails(User user, String noteId); + + public GetNoteDetailsFormatterDto getNoteDetails(User user, String noteId); + } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNoteDetails/GetAccountNoteDetailsFactory.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNoteDetails/GetAccountNoteDetailsFactory.java index fa9b715b..cee21300 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNoteDetails/GetAccountNoteDetailsFactory.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNoteDetails/GetAccountNoteDetailsFactory.java @@ -14,28 +14,25 @@ */ @Component public class GetAccountNoteDetailsFactory { - @Autowired - GetSalesforceAccountNoteDetails getSalesforceNoteDetails; - /** - * getNoteDetails is a method that returns the details of a note. - * - * @param user - * @param noteId - * - * @return GetNoteDetailsFormatterDto - */ - public GetNoteDetailsFormatterDto getNoteDetails(User user, String noteId) { + @Autowired + GetSalesforceAccountNoteDetails getSalesforceNoteDetails; + + /** + * getNoteDetails is a method that returns the details of a note. + * @param user + * @param noteId + * @return GetNoteDetailsFormatterDto + */ + public GetNoteDetailsFormatterDto getNoteDetails(User user, String noteId) { + + switch (user.getUserKind()) { + case UserConstants.SALESFORCE_USER_KIND: + return getSalesforceNoteDetails.getNoteDetails(user, noteId); + default: + throw new CustomException( + new ErrorObject("l_ca_gnd_gndf_gnd_1", "something_went_wrong", "Invalid user kind.")); + } + } - switch(user.getUserKind()) { - case UserConstants.SALESFORCE_USER_KIND: - return getSalesforceNoteDetails.getNoteDetails(user, noteId); - default: - throw new CustomException( - new ErrorObject( - "l_ca_gnd_gndf_gnd_1", - "something_went_wrong", - "Invalid user kind.")); - } - } } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNoteDetails/GetSalesforceAccountNoteDetails.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNoteDetails/GetSalesforceAccountNoteDetails.java index 183ae279..94fec882 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNoteDetails/GetSalesforceAccountNoteDetails.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNoteDetails/GetSalesforceAccountNoteDetails.java @@ -26,107 +26,90 @@ @Component public class GetSalesforceAccountNoteDetails implements GetAccountNoteDetails { - @Autowired - private SalesforceConstants salesforceConstants; - - @Autowired - private MakeCompositeRequest makeCompositeRequest; - - @Autowired - private SalesforceGetNoteContent salesforceGetNoteContent; - - /** - * Get the details of a note - * - * @param user - * @param noteId - * - * @return GetNoteDetailsFormatterDto - **/ - public GetNoteDetailsFormatterDto getNoteDetails(User user, String noteId) { - - String salesforceUserId = user.getExternalUserId(); - - HttpClient.HttpResponse noteDetailsResponse = notesResponse(noteId, salesforceUserId); - - HttpClient.HttpResponse noteContentResponse = salesforceGetNoteContent.getNoteContent(noteId, salesforceUserId); - - GetNoteDetailsFormatterDto noteDetailsFormatterDto = parseResponse(noteDetailsResponse.getResponseBody(), noteContentResponse.getResponseBody()); - - return noteDetailsFormatterDto; - - } - - /** - * Get the list of notes for a given account - * - * @param documentIds - * @param salesforceUserId - * - * @return HttpResponse - **/ - private HttpClient.HttpResponse notesResponse(String noteId, String salesforceUserId) { - SalesforceQueryBuilder salesforceLib = new SalesforceQueryBuilder(); - String notesQuery = salesforceLib.getNoteDetailsUrl(noteId); - - String notesUrl = salesforceConstants.queryUrlPath() + notesQuery; - - CompositeRequestDto noteCompositeRequest = new CompositeRequestDto("GET", notesUrl, "GetNotesList"); - - List compositeRequests = new ArrayList(); - compositeRequests.add(noteCompositeRequest); - - HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, salesforceUserId); - - return response; - } - - /** - * Format the response of the note details - * - * @param noteDetailsResponse - * @param noteContentResponse - * - * @return GetNoteDetailsFormatterDto - */ - private GetNoteDetailsFormatterDto parseResponse(String noteDetailsResponse, String noteContentResponse) { - NoteDetailEntity noteDetailEntity = new NoteDetailEntity(); - try { - Util util = new Util(); - JsonNode rootNode = util.getJsonNode(noteDetailsResponse); - JsonNode recordsNode = rootNode.get("compositeResponse").get(0).get("body").get("records"); - - for (JsonNode recordNode : recordsNode) { - ObjectMapper mapper = new ObjectMapper(); - mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); - SalesforceGetNoteDetailsDto salesforceGetNotesList = mapper.convertValue(recordNode, SalesforceGetNoteDetailsDto.class); - noteDetailEntity = salesforceGetNotesList.noteDetailEntity(noteContentResponse); - } - if(recordsNode.size() == 0) { - throw new CustomException( - new ErrorObject( - "l_c_gnd_gsnd_1", - "something_went_wrong", - "Note not found" - ) - ); - } - } catch (Exception e) { - throw new CustomException( - new ErrorObject( - "l_c_gnd_gsnd_2", - "something_went_wrong", - e.getMessage() - ) - ); - } - - GetNoteDetailsFormatterDto getNoteDetailsFormatterDto = new GetNoteDetailsFormatterDto( - noteDetailEntity - ); - - return getNoteDetailsFormatterDto; - - } + @Autowired + private SalesforceConstants salesforceConstants; + + @Autowired + private MakeCompositeRequest makeCompositeRequest; + + @Autowired + private SalesforceGetNoteContent salesforceGetNoteContent; + + /** + * Get the details of a note + * @param user + * @param noteId + * @return GetNoteDetailsFormatterDto + **/ + public GetNoteDetailsFormatterDto getNoteDetails(User user, String noteId) { + + String salesforceUserId = user.getExternalUserId(); + + HttpClient.HttpResponse noteDetailsResponse = notesResponse(noteId, salesforceUserId); + + HttpClient.HttpResponse noteContentResponse = salesforceGetNoteContent.getNoteContent(noteId, salesforceUserId); + + GetNoteDetailsFormatterDto noteDetailsFormatterDto = parseResponse(noteDetailsResponse.getResponseBody(), + noteContentResponse.getResponseBody()); + + return noteDetailsFormatterDto; + + } + + /** + * Get the list of notes for a given account + * @param documentIds + * @param salesforceUserId + * @return HttpResponse + **/ + private HttpClient.HttpResponse notesResponse(String noteId, String salesforceUserId) { + SalesforceQueryBuilder salesforceLib = new SalesforceQueryBuilder(); + String notesQuery = salesforceLib.getNoteDetailsUrl(noteId); + + String notesUrl = salesforceConstants.queryUrlPath() + notesQuery; + + CompositeRequestDto noteCompositeRequest = new CompositeRequestDto("GET", notesUrl, "GetNotesList"); + + List compositeRequests = new ArrayList(); + compositeRequests.add(noteCompositeRequest); + + HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, salesforceUserId); + + return response; + } + + /** + * Format the response of the note details + * @param noteDetailsResponse + * @param noteContentResponse + * @return GetNoteDetailsFormatterDto + */ + private GetNoteDetailsFormatterDto parseResponse(String noteDetailsResponse, String noteContentResponse) { + NoteDetailEntity noteDetailEntity = new NoteDetailEntity(); + try { + Util util = new Util(); + JsonNode rootNode = util.getJsonNode(noteDetailsResponse); + JsonNode recordsNode = rootNode.get("compositeResponse").get(0).get("body").get("records"); + + for (JsonNode recordNode : recordsNode) { + ObjectMapper mapper = new ObjectMapper(); + mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + SalesforceGetNoteDetailsDto salesforceGetNotesList = mapper.convertValue(recordNode, + SalesforceGetNoteDetailsDto.class); + noteDetailEntity = salesforceGetNotesList.noteDetailEntity(noteContentResponse); + } + if (recordsNode.size() == 0) { + throw new CustomException(new ErrorObject("l_c_gnd_gsnd_1", "something_went_wrong", "Note not found")); + } + } + catch (Exception e) { + throw new CustomException(new ErrorObject("l_c_gnd_gsnd_2", "something_went_wrong", e.getMessage())); + } + + GetNoteDetailsFormatterDto getNoteDetailsFormatterDto = new GetNoteDetailsFormatterDto(noteDetailEntity); + + return getNoteDetailsFormatterDto; + + } } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNotesList/GetAccountNoteListFactory.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNotesList/GetAccountNoteListFactory.java index 462d11ca..11f8e882 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNotesList/GetAccountNoteListFactory.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNotesList/GetAccountNoteListFactory.java @@ -10,33 +10,29 @@ import com.salessparrow.api.lib.globalConstants.UserConstants; /** - * GetNotesListFactory is a factory class for the GetNotesList action for the - * CRM. + * GetNotesListFactory is a factory class for the GetNotesList action for the CRM. */ @Component public class GetAccountNoteListFactory { - @Autowired - private GetSalesforceAccountNotesList getSalesforceNotesList; - /** - * Get the list of notes for a given account. - * - * @param user - * @param accountId - * - * @return GetNotesListFormatterDto - **/ - public GetNotesListFormatterDto getNotesList(User user, String accountId) { + @Autowired + private GetSalesforceAccountNotesList getSalesforceNotesList; + + /** + * Get the list of notes for a given account. + * @param user + * @param accountId + * @return GetNotesListFormatterDto + **/ + public GetNotesListFormatterDto getNotesList(User user, String accountId) { + + switch (user.getUserKind()) { + case UserConstants.SALESFORCE_USER_KIND: + return getSalesforceNotesList.getNotesList(user, accountId); + default: + throw new CustomException( + new ErrorObject("l_ca_gnl_gnlf_gnl_1", "something_went_wrong", "Invalid user kind.")); + } + } - switch(user.getUserKind()) { - case UserConstants.SALESFORCE_USER_KIND: - return getSalesforceNotesList.getNotesList(user, accountId); - default: - throw new CustomException( - new ErrorObject( - "l_ca_gnl_gnlf_gnl_1", - "something_went_wrong", - "Invalid user kind.")); - } - } } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNotesList/GetAccountNotesList.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNotesList/GetAccountNotesList.java index 1bc60ac7..99155a8b 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNotesList/GetAccountNotesList.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNotesList/GetAccountNotesList.java @@ -10,6 +10,7 @@ */ @Component public interface GetAccountNotesList { - public GetNotesListFormatterDto getNotesList(User user, String accountId); -} + public GetNotesListFormatterDto getNotesList(User user, String accountId); + +} diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNotesList/GetSalesforceAccountNotesList.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNotesList/GetSalesforceAccountNotesList.java index 0618e186..f8765dbb 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNotesList/GetSalesforceAccountNotesList.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountNotesList/GetSalesforceAccountNotesList.java @@ -29,162 +29,144 @@ * GetSalesforceNotesList is a class for the GetNotesList service for the Salesforce CRM. */ @Component -public class GetSalesforceAccountNotesList implements GetAccountNotesList{ - @Autowired - private SalesforceConstants salesforceConstants; - - @Autowired - private MakeCompositeRequest makeCompositeRequest; - - /** - * Get the list of notes for a given account - * @param user - * @param accountId - * - * @return GetNotesListFormatterDto - **/ - public GetNotesListFormatterDto getNotesList(User user,String accountId) { - - String salesforceUserId = user.getExternalUserId(); - - HttpClient.HttpResponse response = notesListIdResponse(accountId, salesforceUserId); - - List ContentDocumentIds = parseNotesId(response.getResponseBody()); - - if(ContentDocumentIds.size() == 0) { - return new GetNotesListFormatterDto( - new ArrayList(), - new HashMap() - ); - } - - HttpClient.HttpResponse getNotesResponse = notesListByIdResponse(ContentDocumentIds, salesforceUserId); - - GetNotesListFormatterDto getNotesListFormatterDto = parseResponse(getNotesResponse.getResponseBody()); - - return getNotesListFormatterDto; - } - - /** - * Get the list of notes id for a given account - * @param accountId - * @param salesforceUserId - * - * @return HttpResponse - **/ - private HttpClient.HttpResponse notesListIdResponse(String accountId, String salesforceUserId) { - SalesforceQueryBuilder salesforceLib = new SalesforceQueryBuilder(); - String documentIdsQuery = salesforceLib.getContentDocumentIdUrl(accountId); - - String documentIdsUrl = salesforceConstants.queryUrlPath() + documentIdsQuery; - - CompositeRequestDto documentIdsCompositeReq = new CompositeRequestDto("GET", documentIdsUrl, "GetContentDocumentId"); - - List compositeRequests = new ArrayList(); - compositeRequests.add(documentIdsCompositeReq); - - HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, salesforceUserId ); - - return response; - } - - /** - * Get the list of notes for a given account - * @param documentIds - * @param salesforceUserId - * - * @return HttpResponse - **/ - private HttpClient.HttpResponse notesListByIdResponse(List documentIds, String salesforceUserId) { - SalesforceQueryBuilder salesforceLib = new SalesforceQueryBuilder(); - String notesQuery = salesforceLib.getNoteListIdUrl(documentIds); - - String notesUrl = salesforceConstants.queryUrlPath() + notesQuery; - - CompositeRequestDto noteCompositeRequest = new CompositeRequestDto("GET", notesUrl, "GetNotesList"); - - List compositeRequests = new ArrayList(); - compositeRequests.add(noteCompositeRequest); - - HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, salesforceUserId ); - - return response; - } - - - - /** - * Get the list of notes for a given account - * - * @param responseBody - * - * @return List - */ - private List parseNotesId(String responseBody) { - List notesIds = new ArrayList(); - - try { - Util util = new Util(); - JsonNode rootNode = util.getJsonNode(responseBody); - JsonNode recordsNode = rootNode.get("compositeResponse").get(0).get("body").get("records"); - for (JsonNode recordNode : recordsNode) { - ObjectMapper mapper = new ObjectMapper(); - mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); - SalesforceGetNoteIdDto salesforceGetNoteId = mapper.convertValue(recordNode, SalesforceGetNoteIdDto.class); - notesIds.add(salesforceGetNoteId.getContentDocumentId()); - } - } catch (Exception e) { - throw new CustomException( - new ErrorObject( - "l_c_gnl_gsnl_1", - "something_went_wrong", - e.getMessage() - ) - ); - } - - return notesIds; - } - - /** - * Get the list of notes for a given account - * - * @param responseBody - * - * @return GetNotesListFormatterDto - */ - private GetNotesListFormatterDto parseResponse(String responseBody){ - List noteIds = new ArrayList(); - Map noteIdToEntityMap = new HashMap<>(); - - try { - Util util = new Util(); - JsonNode rootNode = util.getJsonNode(responseBody); - JsonNode recordsNode = rootNode.get("compositeResponse").get(0).get("body").get("records"); - for (JsonNode recordNode : recordsNode) { - ObjectMapper mapper = new ObjectMapper(); - mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); - SalesforceGetNotesListDto salesforceGetNotesList = mapper.convertValue(recordNode, SalesforceGetNotesListDto.class); - NoteEntity noteEntity = salesforceGetNotesList.noteEntity(); - - noteIds.add(noteEntity.getId()); - noteIdToEntityMap.put(noteEntity.getId(), noteEntity); - } - } catch (Exception e) { - throw new CustomException( - new ErrorObject( - "l_c_gnl_gsnl_2", - "something_went_wrong", - e.getMessage() - ) - ); - } - - GetNotesListFormatterDto getNotesListFormatterDto = new GetNotesListFormatterDto(); - getNotesListFormatterDto.setNoteIds(noteIds); - getNotesListFormatterDto.setNoteMapById(noteIdToEntityMap); - - return getNotesListFormatterDto; - } +public class GetSalesforceAccountNotesList implements GetAccountNotesList { + + @Autowired + private SalesforceConstants salesforceConstants; + + @Autowired + private MakeCompositeRequest makeCompositeRequest; + + /** + * Get the list of notes for a given account + * @param user + * @param accountId + * @return GetNotesListFormatterDto + **/ + public GetNotesListFormatterDto getNotesList(User user, String accountId) { + + String salesforceUserId = user.getExternalUserId(); + + HttpClient.HttpResponse response = notesListIdResponse(accountId, salesforceUserId); + + List ContentDocumentIds = parseNotesId(response.getResponseBody()); + + if (ContentDocumentIds.size() == 0) { + return new GetNotesListFormatterDto(new ArrayList(), new HashMap()); + } + + HttpClient.HttpResponse getNotesResponse = notesListByIdResponse(ContentDocumentIds, salesforceUserId); + + GetNotesListFormatterDto getNotesListFormatterDto = parseResponse(getNotesResponse.getResponseBody()); + + return getNotesListFormatterDto; + } + + /** + * Get the list of notes id for a given account + * @param accountId + * @param salesforceUserId + * @return HttpResponse + **/ + private HttpClient.HttpResponse notesListIdResponse(String accountId, String salesforceUserId) { + SalesforceQueryBuilder salesforceLib = new SalesforceQueryBuilder(); + String documentIdsQuery = salesforceLib.getContentDocumentIdUrl(accountId); + + String documentIdsUrl = salesforceConstants.queryUrlPath() + documentIdsQuery; + + CompositeRequestDto documentIdsCompositeReq = new CompositeRequestDto("GET", documentIdsUrl, + "GetContentDocumentId"); + + List compositeRequests = new ArrayList(); + compositeRequests.add(documentIdsCompositeReq); + + HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, salesforceUserId); + + return response; + } + + /** + * Get the list of notes for a given account + * @param documentIds + * @param salesforceUserId + * @return HttpResponse + **/ + private HttpClient.HttpResponse notesListByIdResponse(List documentIds, String salesforceUserId) { + SalesforceQueryBuilder salesforceLib = new SalesforceQueryBuilder(); + String notesQuery = salesforceLib.getNoteListIdUrl(documentIds); + + String notesUrl = salesforceConstants.queryUrlPath() + notesQuery; + + CompositeRequestDto noteCompositeRequest = new CompositeRequestDto("GET", notesUrl, "GetNotesList"); + + List compositeRequests = new ArrayList(); + compositeRequests.add(noteCompositeRequest); + + HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, salesforceUserId); + + return response; + } + + /** + * Get the list of notes for a given account + * @param responseBody + * @return List + */ + private List parseNotesId(String responseBody) { + List notesIds = new ArrayList(); + + try { + Util util = new Util(); + JsonNode rootNode = util.getJsonNode(responseBody); + JsonNode recordsNode = rootNode.get("compositeResponse").get(0).get("body").get("records"); + for (JsonNode recordNode : recordsNode) { + ObjectMapper mapper = new ObjectMapper(); + mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + SalesforceGetNoteIdDto salesforceGetNoteId = mapper.convertValue(recordNode, + SalesforceGetNoteIdDto.class); + notesIds.add(salesforceGetNoteId.getContentDocumentId()); + } + } + catch (Exception e) { + throw new CustomException(new ErrorObject("l_c_gnl_gsnl_1", "something_went_wrong", e.getMessage())); + } + + return notesIds; + } + + /** + * Get the list of notes for a given account + * @param responseBody + * @return GetNotesListFormatterDto + */ + private GetNotesListFormatterDto parseResponse(String responseBody) { + List noteIds = new ArrayList(); + Map noteIdToEntityMap = new HashMap<>(); + + try { + Util util = new Util(); + JsonNode rootNode = util.getJsonNode(responseBody); + JsonNode recordsNode = rootNode.get("compositeResponse").get(0).get("body").get("records"); + for (JsonNode recordNode : recordsNode) { + ObjectMapper mapper = new ObjectMapper(); + mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + SalesforceGetNotesListDto salesforceGetNotesList = mapper.convertValue(recordNode, + SalesforceGetNotesListDto.class); + NoteEntity noteEntity = salesforceGetNotesList.noteEntity(); + + noteIds.add(noteEntity.getId()); + noteIdToEntityMap.put(noteEntity.getId(), noteEntity); + } + } + catch (Exception e) { + throw new CustomException(new ErrorObject("l_c_gnl_gsnl_2", "something_went_wrong", e.getMessage())); + } + + GetNotesListFormatterDto getNotesListFormatterDto = new GetNotesListFormatterDto(); + getNotesListFormatterDto.setNoteIds(noteIds); + getNotesListFormatterDto.setNoteMapById(noteIdToEntityMap); + + return getNotesListFormatterDto; + } } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetAccountTasksListFactory.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetAccountTasksListFactory.java index a18185f8..d388c065 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetAccountTasksListFactory.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetAccountTasksListFactory.java @@ -12,35 +12,33 @@ import com.salessparrow.api.lib.globalConstants.UserConstants; /** - * GetAccountTasksListFactory is a factory class for the GetAccountTasksList action for the CRM. + * GetAccountTasksListFactory is a factory class for the GetAccountTasksList action for + * the CRM. */ @Component public class GetAccountTasksListFactory { - Logger logger = LoggerFactory.getLogger(GetAccountTasksListFactory.class); - - @Autowired - private GetSalesforceAccountTasksList getSalesforceAccountTasksList; - - /** - * Get the list of tasks for a given account. - * - * @param user - * @param accountId - * - * @return GetTasksListFormatterDto - **/ - public GetTasksListFormatterDto getAccountTasksList(User user, String accountId) { - logger.info("factory for getAccountTasksList action"); - - switch(user.getUserKind()) { - case UserConstants.SALESFORCE_USER_KIND: - return getSalesforceAccountTasksList.getAccountTasksList(user, accountId); - default: - throw new CustomException( - new ErrorObject( - "l_ca_gatl_gatlf_gtl_1", - "something_went_wrong", - "Invalid user kind.")); - } - } + + Logger logger = LoggerFactory.getLogger(GetAccountTasksListFactory.class); + + @Autowired + private GetSalesforceAccountTasksList getSalesforceAccountTasksList; + + /** + * Get the list of tasks for a given account. + * @param user + * @param accountId + * @return GetTasksListFormatterDto + **/ + public GetTasksListFormatterDto getAccountTasksList(User user, String accountId) { + logger.info("factory for getAccountTasksList action"); + + switch (user.getUserKind()) { + case UserConstants.SALESFORCE_USER_KIND: + return getSalesforceAccountTasksList.getAccountTasksList(user, accountId); + default: + throw new CustomException( + new ErrorObject("l_ca_gatl_gatlf_gtl_1", "something_went_wrong", "Invalid user kind.")); + } + } + } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetAccountTasksListInterface.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetAccountTasksListInterface.java index c42796f1..5fd7c2b3 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetAccountTasksListInterface.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetAccountTasksListInterface.java @@ -6,9 +6,12 @@ import com.salessparrow.api.dto.formatter.GetTasksListFormatterDto; /** - * GetAccountTasksListInterface is an interface for the GetAccountTasksList action for the CRM. + * GetAccountTasksListInterface is an interface for the GetAccountTasksList action for the + * CRM. */ @Component public interface GetAccountTasksListInterface { - public GetTasksListFormatterDto getTasksList(User user, String accountId); + + public GetTasksListFormatterDto getTasksList(User user, String accountId); + } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetSalesforceAccountTasksList.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetSalesforceAccountTasksList.java index 71a7b6e3..5d29e90d 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetSalesforceAccountTasksList.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccountTasksList/GetSalesforceAccountTasksList.java @@ -29,98 +29,93 @@ import com.salessparrow.api.lib.salesforce.helper.SalesforceQueryBuilder; /** - * GetSalesforceAccountTasksList is a class for the GetAccountTasksList service for the Salesforce CRM. + * GetSalesforceAccountTasksList is a class for the GetAccountTasksList service for the + * Salesforce CRM. */ @Component public class GetSalesforceAccountTasksList { - Logger logger = LoggerFactory.getLogger(GetSalesforceAccountTasksList.class); - - @Autowired - private SalesforceConstants salesforceConstants; - - @Autowired - private MakeCompositeRequest makeCompositeRequest; - - /** - * Get the list of tasks for a given account in salesforce - * - * @param user - * @param accountId - * - * @return GetTasksListFormatterDto - **/ - public GetTasksListFormatterDto getAccountTasksList(User user, String accountId) { - logger.info("Salesforce getAccountTasksList action called"); - - String salesforceUserId = user.getExternalUserId(); - - SalesforceQueryBuilder salesforceQuery = new SalesforceQueryBuilder(); - String query = salesforceQuery.getAccountTasksQuery(accountId); - - String url = salesforceConstants.queryUrlPath() + query; - - CompositeRequestDto compositeReq = new CompositeRequestDto("GET", url, "GetTasksList"); - - List compositeRequests = new ArrayList(); - compositeRequests.add(compositeReq); - - HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, salesforceUserId); - - return parseResponse(response.getResponseBody()); - } - - /** - * Parse Response - * - * @param responseBody - * - * @return GetTasksListFormatterDto - **/ - public GetTasksListFormatterDto parseResponse(String responseBody) { - - List taskIds = new ArrayList(); - Map taskIdToEntityMap = new HashMap<>(); - - Util util = new Util(); - JsonNode rootNode = util.getJsonNode(responseBody); - - JsonNode getTasksCompositeResponse = rootNode.get("compositeResponse").get(0); - Integer getTasksStatusCode = getTasksCompositeResponse.get("httpStatusCode").asInt(); - - if (getTasksStatusCode != 200 && getTasksStatusCode != 201) { - String errorBody = getTasksCompositeResponse.get("body").asText(); - - if (getTasksStatusCode == 400) { - throw new CustomException( - new ParamErrorObject( - "l_ca_gatl_gsatl_pr_1", - errorBody, - Arrays.asList("invalid_account_id"))); - } else { - throw new CustomException( - new ErrorObject( - "l_ca_gatl_gsatl_pr_2", - "something_went_wrong", - errorBody)); - } - } - - JsonNode recordsNode = rootNode.get("compositeResponse").get(0).get("body").get("records");; - - for (JsonNode recordNode : recordsNode) { - ObjectMapper mapper = new ObjectMapper(); - mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); - SalesforceGetTasksListDto salesforceGetTasksListDto = mapper.convertValue(recordNode, SalesforceGetTasksListDto.class); - TaskEntity taskEntity = salesforceGetTasksListDto.taskEntity(); - - taskIds.add(taskEntity.getId()); - taskIdToEntityMap.put(taskEntity.getId(), taskEntity); - } - - GetTasksListFormatterDto getTasksListFormatterDto = new GetTasksListFormatterDto(); - getTasksListFormatterDto.setTaskMapById(taskIdToEntityMap); - getTasksListFormatterDto.setTaskIds(taskIds); - - return getTasksListFormatterDto; - } + + Logger logger = LoggerFactory.getLogger(GetSalesforceAccountTasksList.class); + + @Autowired + private SalesforceConstants salesforceConstants; + + @Autowired + private MakeCompositeRequest makeCompositeRequest; + + /** + * Get the list of tasks for a given account in salesforce + * @param user + * @param accountId + * @return GetTasksListFormatterDto + **/ + public GetTasksListFormatterDto getAccountTasksList(User user, String accountId) { + logger.info("Salesforce getAccountTasksList action called"); + + String salesforceUserId = user.getExternalUserId(); + + SalesforceQueryBuilder salesforceQuery = new SalesforceQueryBuilder(); + String query = salesforceQuery.getAccountTasksQuery(accountId); + + String url = salesforceConstants.queryUrlPath() + query; + + CompositeRequestDto compositeReq = new CompositeRequestDto("GET", url, "GetTasksList"); + + List compositeRequests = new ArrayList(); + compositeRequests.add(compositeReq); + + HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, salesforceUserId); + + return parseResponse(response.getResponseBody()); + } + + /** + * Parse Response + * @param responseBody + * @return GetTasksListFormatterDto + **/ + public GetTasksListFormatterDto parseResponse(String responseBody) { + + List taskIds = new ArrayList(); + Map taskIdToEntityMap = new HashMap<>(); + + Util util = new Util(); + JsonNode rootNode = util.getJsonNode(responseBody); + + JsonNode getTasksCompositeResponse = rootNode.get("compositeResponse").get(0); + Integer getTasksStatusCode = getTasksCompositeResponse.get("httpStatusCode").asInt(); + + if (getTasksStatusCode != 200 && getTasksStatusCode != 201) { + String errorBody = getTasksCompositeResponse.get("body").asText(); + + if (getTasksStatusCode == 400) { + throw new CustomException( + new ParamErrorObject("l_ca_gatl_gsatl_pr_1", errorBody, Arrays.asList("invalid_account_id"))); + } + else { + throw new CustomException(new ErrorObject("l_ca_gatl_gsatl_pr_2", "something_went_wrong", errorBody)); + } + } + + JsonNode recordsNode = rootNode.get("compositeResponse").get(0).get("body").get("records"); + ; + + for (JsonNode recordNode : recordsNode) { + ObjectMapper mapper = new ObjectMapper(); + mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + SalesforceGetTasksListDto salesforceGetTasksListDto = mapper.convertValue(recordNode, + SalesforceGetTasksListDto.class); + TaskEntity taskEntity = salesforceGetTasksListDto.taskEntity(); + + taskIds.add(taskEntity.getId()); + taskIdToEntityMap.put(taskEntity.getId(), taskEntity); + } + + GetTasksListFormatterDto getTasksListFormatterDto = new GetTasksListFormatterDto(); + getTasksListFormatterDto.setTaskMapById(taskIdToEntityMap); + getTasksListFormatterDto.setTaskIds(taskIds); + + return getTasksListFormatterDto; + } + } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetAccounts.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetAccounts.java index b6a44704..438ee12b 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetAccounts.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetAccounts.java @@ -11,5 +11,6 @@ @Component public interface GetAccounts { - public GetAccountsFormatterDto getAccounts(User user, String searchTerm); + public GetAccountsFormatterDto getAccounts(User user, String searchTerm); + } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetAccountsFactory.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetAccountsFactory.java index 4c29d58f..24837ae9 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetAccountsFactory.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetAccountsFactory.java @@ -14,28 +14,25 @@ */ @Component public class GetAccountsFactory { - @Autowired - private GetSalesforceAccounts getSalesforceAccounts; - /** - * Get the list of accounts for a given searchterm. - * - * @param user - * @param searchTerm - * - * @return GetAccountsFormatterDto - **/ - public GetAccountsFormatterDto getAccounts(User user, String searchTerm) { + @Autowired + private GetSalesforceAccounts getSalesforceAccounts; + + /** + * Get the list of accounts for a given searchterm. + * @param user + * @param searchTerm + * @return GetAccountsFormatterDto + **/ + public GetAccountsFormatterDto getAccounts(User user, String searchTerm) { + + switch (user.getUserKind()) { + case UserConstants.SALESFORCE_USER_KIND: + return getSalesforceAccounts.getAccounts(user, searchTerm); + default: + throw new CustomException( + new ErrorObject("l_ca_ga_gaf_ga_1", "something_went_wrong", "Invalid user kind.")); + } + } - switch(user.getUserKind()) { - case UserConstants.SALESFORCE_USER_KIND: - return getSalesforceAccounts.getAccounts(user, searchTerm); - default: - throw new CustomException( - new ErrorObject( - "l_ca_ga_gaf_ga_1", - "something_went_wrong", - "Invalid user kind.")); - } - } } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java index 6827b06b..4e222f4a 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java @@ -28,80 +28,75 @@ * GetSalesforceAccounts is a class for the GetAccounts service for the Salesforce CRM. **/ @Component -public class GetSalesforceAccounts implements GetAccounts{ - @Autowired - private SalesforceConstants salesforceConstants; - - @Autowired - private MakeCompositeRequest makeCompositeRequest; - - /** - * Get the list of accounts for a given search term - * - * @param user - * @param searchTerm - * - * @return GetAccountsFormatterDto - **/ - public GetAccountsFormatterDto getAccounts(User user, String searchTerm) { - String salesforceUserId = user.getExternalUserId(); - - SalesforceQueryBuilder salesforceQuery = new SalesforceQueryBuilder(); - String query = salesforceQuery.getAccountsQuery(searchTerm); - - String url = salesforceConstants.queryUrlPath() + query; - - CompositeRequestDto compositeReq = new CompositeRequestDto("GET", url, "getAccounts"); - - List compositeRequests = new ArrayList(); - compositeRequests.add(compositeReq); - - HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, salesforceUserId); - - return parseResponse(response.getResponseBody()); - } - - /** - * Parse Response - * - * @param responseBody - * - * @return GetAccountsFormatterDto - **/ - public GetAccountsFormatterDto parseResponse(String responseBody) { - - List accountIds = new ArrayList(); - Map accountIdToEntityMap = new HashMap<>(); - - Util util = new Util(); - JsonNode rootNode = util.getJsonNode(responseBody); - - JsonNode httpStatusCodeNode = rootNode.get("compositeResponse").get(0).get("httpStatusCode"); - - if (httpStatusCodeNode.asInt() != 200 && httpStatusCodeNode.asInt() != 201) { - throw new CustomException( - new ErrorObject( - "l_ca_ga_gsa_pr_1", - "something_went_wrong", - "Error in fetching accounts from salesforce")); - } - - JsonNode recordsNode = rootNode.get("compositeResponse").get(0).get("body").get("records"); - - for (JsonNode recordNode : recordsNode) { - ObjectMapper mapper = new ObjectMapper(); - mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); - SalesforceAccountDto salesforceAccount = mapper.convertValue(recordNode, SalesforceAccountDto.class); - AccountEntity accountEntity = salesforceAccount.getAccountEntity(); - - accountIds.add(accountEntity.getId()); - accountIdToEntityMap.put(accountEntity.getId(), accountEntity); - } - - GetAccountsFormatterDto getAccountsResponse = new GetAccountsFormatterDto(); - getAccountsResponse.setAccountMapById(accountIdToEntityMap); - getAccountsResponse.setAccountIds(accountIds); - - return getAccountsResponse; - } +public class GetSalesforceAccounts implements GetAccounts { + + @Autowired + private SalesforceConstants salesforceConstants; + + @Autowired + private MakeCompositeRequest makeCompositeRequest; + + /** + * Get the list of accounts for a given search term + * @param user + * @param searchTerm + * @return GetAccountsFormatterDto + **/ + public GetAccountsFormatterDto getAccounts(User user, String searchTerm) { + String salesforceUserId = user.getExternalUserId(); + + SalesforceQueryBuilder salesforceQuery = new SalesforceQueryBuilder(); + String query = salesforceQuery.getAccountsQuery(searchTerm); + + String url = salesforceConstants.queryUrlPath() + query; + + CompositeRequestDto compositeReq = new CompositeRequestDto("GET", url, "getAccounts"); + + List compositeRequests = new ArrayList(); + compositeRequests.add(compositeReq); + + HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, salesforceUserId); + + return parseResponse(response.getResponseBody()); + } + + /** + * Parse Response + * @param responseBody + * @return GetAccountsFormatterDto + **/ + public GetAccountsFormatterDto parseResponse(String responseBody) { + + List accountIds = new ArrayList(); + Map accountIdToEntityMap = new HashMap<>(); + + Util util = new Util(); + JsonNode rootNode = util.getJsonNode(responseBody); + + JsonNode httpStatusCodeNode = rootNode.get("compositeResponse").get(0).get("httpStatusCode"); + + if (httpStatusCodeNode.asInt() != 200 && httpStatusCodeNode.asInt() != 201) { + throw new CustomException(new ErrorObject("l_ca_ga_gsa_pr_1", "something_went_wrong", + "Error in fetching accounts from salesforce")); + } + + JsonNode recordsNode = rootNode.get("compositeResponse").get(0).get("body").get("records"); + + for (JsonNode recordNode : recordsNode) { + ObjectMapper mapper = new ObjectMapper(); + mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + SalesforceAccountDto salesforceAccount = mapper.convertValue(recordNode, SalesforceAccountDto.class); + AccountEntity accountEntity = salesforceAccount.getAccountEntity(); + + accountIds.add(accountEntity.getId()); + accountIdToEntityMap.put(accountEntity.getId(), accountEntity); + } + + GetAccountsFormatterDto getAccountsResponse = new GetAccountsFormatterDto(); + getAccountsResponse.setAccountMapById(accountIdToEntityMap); + getAccountsResponse.setAccountIds(accountIds); + + return getAccountsResponse; + } + } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getCrmOrganizationUsers/GetCrmOrganizationUsers.java b/src/main/java/com/salessparrow/api/lib/crmActions/getCrmOrganizationUsers/GetCrmOrganizationUsers.java index 283236ae..4263a9b5 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getCrmOrganizationUsers/GetCrmOrganizationUsers.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getCrmOrganizationUsers/GetCrmOrganizationUsers.java @@ -7,10 +7,11 @@ /** * GetCrmOrganizationUsers interface for the getCrmOrganizationUsers action. - * + * */ @Component public interface GetCrmOrganizationUsers { - - public GetCrmOrganizationUsersFormatterDto getCrmOrganizationUsers(User user, String searchTerm); + + public GetCrmOrganizationUsersFormatterDto getCrmOrganizationUsers(User user, String searchTerm); + } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getCrmOrganizationUsers/GetCrmOrganizationUsersFactory.java b/src/main/java/com/salessparrow/api/lib/crmActions/getCrmOrganizationUsers/GetCrmOrganizationUsersFactory.java index 31bc34b6..bf819926 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getCrmOrganizationUsers/GetCrmOrganizationUsersFactory.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getCrmOrganizationUsers/GetCrmOrganizationUsersFactory.java @@ -13,34 +13,31 @@ /** * GetCrmOrganizationUsersFactory class for the getCrmOrganizationUsers action. - * + * */ @Component public class GetCrmOrganizationUsersFactory { - Logger logger = LoggerFactory.getLogger(GetCrmOrganizationUsersFactory.class); - - @Autowired - private GetSalesforceCrmOrganizationUsers getSalesforceCrmOrganizationUsers; + Logger logger = LoggerFactory.getLogger(GetCrmOrganizationUsersFactory.class); + + @Autowired + private GetSalesforceCrmOrganizationUsers getSalesforceCrmOrganizationUsers; + + /** + * getCrmOrganizationUsers method for the getCrmOrganizationUsers action. + * @param user + * @param searchTerm + * @return GetCrmOrganizationUsersFormatterDto + */ + public GetCrmOrganizationUsersFormatterDto getCrmOrganizationUsers(User user, String searchTerm) { + switch (user.getUserKind()) { + case UserConstants.SALESFORCE_USER_KIND: + logger.info("Executing salesforce get CrmOrganizationUser Service"); + return getSalesforceCrmOrganizationUsers.getCrmOrganizationUsers(user, searchTerm); + default: + throw new CustomException( + new ErrorObject("l_ca_gcou_gcouf_gcou_1", "something_went_wrong", "Invalid user kind.")); + } + } - /** - * getCrmOrganizationUsers method for the getCrmOrganizationUsers action. - * - * @param user - * @param searchTerm - * @return GetCrmOrganizationUsersFormatterDto - */ - public GetCrmOrganizationUsersFormatterDto getCrmOrganizationUsers(User user, String searchTerm){ - switch(user.getUserKind()) { - case UserConstants.SALESFORCE_USER_KIND: - logger.info("Executing salesforce get CrmOrganizationUser Service"); - return getSalesforceCrmOrganizationUsers.getCrmOrganizationUsers(user, searchTerm); - default: - throw new CustomException( - new ErrorObject( - "l_ca_gcou_gcouf_gcou_1", - "something_went_wrong", - "Invalid user kind.")); - } - } } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getCrmOrganizationUsers/GetSalesforceCrmOrganizationUsers.java b/src/main/java/com/salessparrow/api/lib/crmActions/getCrmOrganizationUsers/GetSalesforceCrmOrganizationUsers.java index d14c48c8..b911a6fa 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getCrmOrganizationUsers/GetSalesforceCrmOrganizationUsers.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getCrmOrganizationUsers/GetSalesforceCrmOrganizationUsers.java @@ -28,87 +28,83 @@ /** * GetCrmOrganizationUsersFactory class for the getCrmOrganizationUsers action. - * + * */ @Component -public class GetSalesforceCrmOrganizationUsers implements GetCrmOrganizationUsers{ - - Logger logger = LoggerFactory.getLogger(GetSalesforceCrmOrganizationUsers.class); - - @Autowired - private SalesforceConstants salesforceConstants; - - @Autowired - private MakeCompositeRequest makeCompositeRequest; - - /** - * getCrmOrganizationUsers method for the getCrmOrganizationUsers action. - * - * @param user - * @param searchTerm - * - * @return GetCrmOrganizationUsersFormatterDto - */ - public GetCrmOrganizationUsersFormatterDto getCrmOrganizationUsers(User user, String searchTerm) { - String salesforceUserId = user.getExternalUserId(); - - SalesforceQueryBuilder salesforceQuery = new SalesforceQueryBuilder(); - String query = salesforceQuery.getCrmOrganizationUsersQuery(searchTerm); - - String url = salesforceConstants.queryUrlPath() + query; - - CompositeRequestDto compositeReq = new CompositeRequestDto("GET", url, "getCrmOrganizationUsers"); - - List compositeRequests = new ArrayList(); - compositeRequests.add(compositeReq); - - HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, salesforceUserId); - - return parseResponse(response.getResponseBody()); - } - - /** - * parseResponse method for the getCrmOrganizationUsers action. - * - * @param responseBody - * - * @return GetCrmOrganizationUsersFormatterDto - */ - private GetCrmOrganizationUsersFormatterDto parseResponse(String responseBody){ - List crmOrganizationUserIds = new ArrayList(); - Map crmOrganizationUserMap = new HashMap(); - - logger.info("Parsing response from salesforce"); - - Util util = new Util(); - JsonNode rootNode = util.getJsonNode(responseBody); - - JsonNode httpStatusCodeNode = rootNode.get("compositeResponse").get(0).get("httpStatusCode"); - - if (httpStatusCodeNode.asInt() != 200 && httpStatusCodeNode.asInt() != 201) { - throw new CustomException( - new ErrorObject( - "l_ca_ga_gsa_pr_1", - "bad_request", - "Error in fetching accounts from salesforce")); - } - - JsonNode recordsNode = rootNode.get("compositeResponse").get(0).get("body").get("records"); - - for (JsonNode recordNode : recordsNode) { - ObjectMapper mapper = new ObjectMapper(); - mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); - SalesforceCrmOrganizationUserDto salesforceCrmOrganization = mapper.convertValue(recordNode, SalesforceCrmOrganizationUserDto.class); - CrmOrganizationUserEntity accountCrmOrganizationUser = salesforceCrmOrganization.getCrmOrganizationUserEntity(); - - crmOrganizationUserIds.add(accountCrmOrganizationUser.getId()); - crmOrganizationUserMap.put(accountCrmOrganizationUser.getId(), accountCrmOrganizationUser); - } - - GetCrmOrganizationUsersFormatterDto getCrmOrganizationUsersResponse = new GetCrmOrganizationUsersFormatterDto(); - getCrmOrganizationUsersResponse.setCrmOrganizationUserIds(crmOrganizationUserIds); - getCrmOrganizationUsersResponse.setCrmOrganizationUserMapById(crmOrganizationUserMap); - - return getCrmOrganizationUsersResponse; - } +public class GetSalesforceCrmOrganizationUsers implements GetCrmOrganizationUsers { + + Logger logger = LoggerFactory.getLogger(GetSalesforceCrmOrganizationUsers.class); + + @Autowired + private SalesforceConstants salesforceConstants; + + @Autowired + private MakeCompositeRequest makeCompositeRequest; + + /** + * getCrmOrganizationUsers method for the getCrmOrganizationUsers action. + * @param user + * @param searchTerm + * @return GetCrmOrganizationUsersFormatterDto + */ + public GetCrmOrganizationUsersFormatterDto getCrmOrganizationUsers(User user, String searchTerm) { + String salesforceUserId = user.getExternalUserId(); + + SalesforceQueryBuilder salesforceQuery = new SalesforceQueryBuilder(); + String query = salesforceQuery.getCrmOrganizationUsersQuery(searchTerm); + + String url = salesforceConstants.queryUrlPath() + query; + + CompositeRequestDto compositeReq = new CompositeRequestDto("GET", url, "getCrmOrganizationUsers"); + + List compositeRequests = new ArrayList(); + compositeRequests.add(compositeReq); + + HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, salesforceUserId); + + return parseResponse(response.getResponseBody()); + } + + /** + * parseResponse method for the getCrmOrganizationUsers action. + * @param responseBody + * @return GetCrmOrganizationUsersFormatterDto + */ + private GetCrmOrganizationUsersFormatterDto parseResponse(String responseBody) { + List crmOrganizationUserIds = new ArrayList(); + Map crmOrganizationUserMap = new HashMap(); + + logger.info("Parsing response from salesforce"); + + Util util = new Util(); + JsonNode rootNode = util.getJsonNode(responseBody); + + JsonNode httpStatusCodeNode = rootNode.get("compositeResponse").get(0).get("httpStatusCode"); + + if (httpStatusCodeNode.asInt() != 200 && httpStatusCodeNode.asInt() != 201) { + throw new CustomException( + new ErrorObject("l_ca_ga_gsa_pr_1", "bad_request", "Error in fetching accounts from salesforce")); + } + + JsonNode recordsNode = rootNode.get("compositeResponse").get(0).get("body").get("records"); + + for (JsonNode recordNode : recordsNode) { + ObjectMapper mapper = new ObjectMapper(); + mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + SalesforceCrmOrganizationUserDto salesforceCrmOrganization = mapper.convertValue(recordNode, + SalesforceCrmOrganizationUserDto.class); + CrmOrganizationUserEntity accountCrmOrganizationUser = salesforceCrmOrganization + .getCrmOrganizationUserEntity(); + + crmOrganizationUserIds.add(accountCrmOrganizationUser.getId()); + crmOrganizationUserMap.put(accountCrmOrganizationUser.getId(), accountCrmOrganizationUser); + } + + GetCrmOrganizationUsersFormatterDto getCrmOrganizationUsersResponse = new GetCrmOrganizationUsersFormatterDto(); + getCrmOrganizationUsersResponse.setCrmOrganizationUserIds(crmOrganizationUserIds); + getCrmOrganizationUsersResponse.setCrmOrganizationUserMapById(crmOrganizationUserMap); + + return getCrmOrganizationUsersResponse; + } + } diff --git a/src/main/java/com/salessparrow/api/lib/customAnnotations/ValidDateFormat.java b/src/main/java/com/salessparrow/api/lib/customAnnotations/ValidDateFormat.java index c0965df6..298ed763 100644 --- a/src/main/java/com/salessparrow/api/lib/customAnnotations/ValidDateFormat.java +++ b/src/main/java/com/salessparrow/api/lib/customAnnotations/ValidDateFormat.java @@ -10,9 +10,11 @@ @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = DateFormatValidator.class) public @interface ValidDateFormat { - String message() default "Invalid Date Format"; - Class[] groups() default {}; + String message() default "Invalid Date Format"; + + Class[] groups() default {}; + + Class[] payload() default {}; - Class[] payload() default {}; } \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/lib/customAnnotations/ValidRedirectUri.java b/src/main/java/com/salessparrow/api/lib/customAnnotations/ValidRedirectUri.java index fe671480..c6dd0201 100644 --- a/src/main/java/com/salessparrow/api/lib/customAnnotations/ValidRedirectUri.java +++ b/src/main/java/com/salessparrow/api/lib/customAnnotations/ValidRedirectUri.java @@ -10,9 +10,11 @@ @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = RedirectUriValidator.class) public @interface ValidRedirectUri { - String message() default "Invalid redirect URI"; - Class[] groups() default {}; + String message() default "Invalid redirect URI"; + + Class[] groups() default {}; + + Class[] payload() default {}; - Class[] payload() default {}; } \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/lib/errorLib/ErrorConfig.java b/src/main/java/com/salessparrow/api/lib/errorLib/ErrorConfig.java index 998610ec..60a78859 100644 --- a/src/main/java/com/salessparrow/api/lib/errorLib/ErrorConfig.java +++ b/src/main/java/com/salessparrow/api/lib/errorLib/ErrorConfig.java @@ -4,16 +4,17 @@ @Data public class ErrorConfig { - private String httpCode; - private String code; - private String message; - @Override - public String toString() { - return "ErrorInfo{" + - "http_code='" + httpCode + '\'' + - ", code='" + code + '\'' + - ", message='" + message + '\'' + - '}'; - } + private String httpCode; + + private String code; + + private String message; + + @Override + public String toString() { + return "ErrorInfo{" + "http_code='" + httpCode + '\'' + ", code='" + code + '\'' + ", message='" + message + + '\'' + '}'; + } + } \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/lib/errorLib/ErrorObject.java b/src/main/java/com/salessparrow/api/lib/errorLib/ErrorObject.java index a6e26c77..d6ae1d83 100644 --- a/src/main/java/com/salessparrow/api/lib/errorLib/ErrorObject.java +++ b/src/main/java/com/salessparrow/api/lib/errorLib/ErrorObject.java @@ -5,17 +5,19 @@ @Data public class ErrorObject { - private String internalErrorIdentifier; - private String apiErrorIdentifier; - private String message; - - public ErrorObject() { - } - - public ErrorObject(String internalErrorIdentifier, String apiErrorIdentifier, String message) { - this.internalErrorIdentifier = internalErrorIdentifier; - this.apiErrorIdentifier = apiErrorIdentifier; - this.message = message; - } + private String internalErrorIdentifier; + + private String apiErrorIdentifier; + + private String message; + + public ErrorObject() { + } + + public ErrorObject(String internalErrorIdentifier, String apiErrorIdentifier, String message) { + this.internalErrorIdentifier = internalErrorIdentifier; + this.apiErrorIdentifier = apiErrorIdentifier; + this.message = message; + } } diff --git a/src/main/java/com/salessparrow/api/lib/errorLib/ErrorResponseObject.java b/src/main/java/com/salessparrow/api/lib/errorLib/ErrorResponseObject.java index c0a9ce35..4fb6e8ed 100644 --- a/src/main/java/com/salessparrow/api/lib/errorLib/ErrorResponseObject.java +++ b/src/main/java/com/salessparrow/api/lib/errorLib/ErrorResponseObject.java @@ -10,27 +10,33 @@ @Data @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) public class ErrorResponseObject { - int httpCode; - String message; - String code; - String internalErrorIdentifier; - List paramErrors; - - public ErrorResponseObject() { - } - - public ErrorResponseObject(int httpCode, String message, String code, String internalErrorIdentifier, - List paramErrors) { - this.httpCode = httpCode; - this.message = message; - this.code = code; - this.internalErrorIdentifier = internalErrorIdentifier; - this.paramErrors = paramErrors; - } - - @Override - public String toString() { - return "ErrorResponseObject [code=" + code + ", paramErrors=" + paramErrors + ", httpCode=" + httpCode - + ", internalErrorIdentifier=" + internalErrorIdentifier + ", message=" + message + "]"; - } + + int httpCode; + + String message; + + String code; + + String internalErrorIdentifier; + + List paramErrors; + + public ErrorResponseObject() { + } + + public ErrorResponseObject(int httpCode, String message, String code, String internalErrorIdentifier, + List paramErrors) { + this.httpCode = httpCode; + this.message = message; + this.code = code; + this.internalErrorIdentifier = internalErrorIdentifier; + this.paramErrors = paramErrors; + } + + @Override + public String toString() { + return "ErrorResponseObject [code=" + code + ", paramErrors=" + paramErrors + ", httpCode=" + httpCode + + ", internalErrorIdentifier=" + internalErrorIdentifier + ", message=" + message + "]"; + } + } diff --git a/src/main/java/com/salessparrow/api/lib/errorLib/ParamErrorConfig.java b/src/main/java/com/salessparrow/api/lib/errorLib/ParamErrorConfig.java index 31ce85f5..92587a72 100644 --- a/src/main/java/com/salessparrow/api/lib/errorLib/ParamErrorConfig.java +++ b/src/main/java/com/salessparrow/api/lib/errorLib/ParamErrorConfig.java @@ -8,25 +8,26 @@ @Data @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) public class ParamErrorConfig { - private String parameter; - private String paramErrorIdentifier; - private String message; - - public ParamErrorConfig() { - } - - public ParamErrorConfig(String parameter, String paramErrorIdentifier, String message) { - this.parameter = parameter; - this.paramErrorIdentifier = paramErrorIdentifier; - this.message = message; - } - - @Override - public String toString() { - return "{" + - "parameter='" + parameter + '\'' + - ", paramErrorIdentifier='" + paramErrorIdentifier + '\'' + - ", message='" + message + '\'' + - '}'; - } + + private String parameter; + + private String paramErrorIdentifier; + + private String message; + + public ParamErrorConfig() { + } + + public ParamErrorConfig(String parameter, String paramErrorIdentifier, String message) { + this.parameter = parameter; + this.paramErrorIdentifier = paramErrorIdentifier; + this.message = message; + } + + @Override + public String toString() { + return "{" + "parameter='" + parameter + '\'' + ", paramErrorIdentifier='" + paramErrorIdentifier + '\'' + + ", message='" + message + '\'' + '}'; + } + } diff --git a/src/main/java/com/salessparrow/api/lib/errorLib/ParamErrorObject.java b/src/main/java/com/salessparrow/api/lib/errorLib/ParamErrorObject.java index 758f2b40..3ca7457c 100644 --- a/src/main/java/com/salessparrow/api/lib/errorLib/ParamErrorObject.java +++ b/src/main/java/com/salessparrow/api/lib/errorLib/ParamErrorObject.java @@ -6,17 +6,20 @@ @Data public class ParamErrorObject { - - private String internalErrorIdentifier; - private String message; - private List paramErrorIdentifiers; - - public ParamErrorObject() { - } - - public ParamErrorObject(String internalErrorIdentifier, String message, List paramErrorIdentifiers) { - this.internalErrorIdentifier = internalErrorIdentifier; - this.message = message; - this.paramErrorIdentifiers = paramErrorIdentifiers; - } + + private String internalErrorIdentifier; + + private String message; + + private List paramErrorIdentifiers; + + public ParamErrorObject() { + } + + public ParamErrorObject(String internalErrorIdentifier, String message, List paramErrorIdentifiers) { + this.internalErrorIdentifier = internalErrorIdentifier; + this.message = message; + this.paramErrorIdentifiers = paramErrorIdentifiers; + } + } diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/ApiSource.java b/src/main/java/com/salessparrow/api/lib/globalConstants/ApiSource.java index ce517936..41ebb34f 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/ApiSource.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/ApiSource.java @@ -5,5 +5,6 @@ @Component public class ApiSource { - public static final String APP = "app"; + public static final String APP = "app"; + } diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/CacheConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/CacheConstants.java index 42d56a54..c2863d9e 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/CacheConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/CacheConstants.java @@ -5,11 +5,16 @@ @Component public class CacheConstants { - public static final String SalesSparrowPrefix = "ss_"; + public static final String SalesSparrowPrefix = "ss_"; - public static final String SS_SALESFORCE_USER_CACHE = SalesSparrowPrefix + "sf_user"; - public static final Integer SS_SALESFORCE_USER_CACHE_EXP = 30 * 24 * 60 * 60; // 30 days + public static final String SS_SALESFORCE_USER_CACHE = SalesSparrowPrefix + "sf_user"; + + public static final Integer SS_SALESFORCE_USER_CACHE_EXP = 30 * 24 * 60 * 60; // 30 + // days + + public static final String SS_SALESFORCE_OAUTH_TOKEN_CACHE = SalesSparrowPrefix + "sf_oauth_token"; + + public static final Integer SS_SALESFORCE_OAUTH_TOKEN_CACHE_EXP = 30 * 24 * 60 * 60; // 30 + // days - public static final String SS_SALESFORCE_OAUTH_TOKEN_CACHE = SalesSparrowPrefix + "sf_oauth_token"; - public static final Integer SS_SALESFORCE_OAUTH_TOKEN_CACHE_EXP = 30 * 24 * 60 * 60; // 30 days } diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/CookieConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/CookieConstants.java index 193e3170..e1d870a2 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/CookieConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/CookieConstants.java @@ -5,9 +5,10 @@ @Component public class CookieConstants { - public static final String LATEST_VERSION = "1"; + public static final String LATEST_VERSION = "1"; - public static final String USER_LOGIN_COOKIE_NAME = "ulcn"; + public static final String USER_LOGIN_COOKIE_NAME = "ulcn"; + + public static final Integer USER_LOGIN_COOKIE_EXPIRY_IN_SEC = 30 * 60 * 60 * 24; - public static final Integer USER_LOGIN_COOKIE_EXPIRY_IN_SEC = 30 * 60 * 60 * 24; } diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/DynamoDbTableNameConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/DynamoDbTableNameConstants.java index 51f9013e..9e0f3774 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/DynamoDbTableNameConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/DynamoDbTableNameConstants.java @@ -7,27 +7,28 @@ */ public class DynamoDbTableNameConstants { - /** - * Returns the name of the table that contains the Salesforce organizations. - * @return - */ - public static String salesforceOrganizationsTableName() { - return CoreConstants.environment() + "_salesforce_organizations"; - } + /** + * Returns the name of the table that contains the Salesforce organizations. + * @return + */ + public static String salesforceOrganizationsTableName() { + return CoreConstants.environment() + "_salesforce_organizations"; + } - /** - * Returns the name of the table that contains the Salesforce OAuth tokens. - * @return - */ - public static String salesforceOauthTokensTableName() { - return CoreConstants.environment() + "_salesforce_oauth_tokens"; - } + /** + * Returns the name of the table that contains the Salesforce OAuth tokens. + * @return + */ + public static String salesforceOauthTokensTableName() { + return CoreConstants.environment() + "_salesforce_oauth_tokens"; + } + + /** + * Returns the name of the table that contains the Salesforce users. + * @return + */ + public static String salesforceUsersTableName() { + return CoreConstants.environment() + "_salesforce_users"; + } - /** - * Returns the name of the table that contains the Salesforce users. - * @return - */ - public static String salesforceUsersTableName() { - return CoreConstants.environment() + "_salesforce_users"; - } } diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/OpenAiConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/OpenAiConstants.java index f07f41ca..2c2c0035 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/OpenAiConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/OpenAiConstants.java @@ -5,11 +5,12 @@ @Component public class OpenAiConstants { - public String chatCompletionUrl() { - return "https://api.openai.com/v1/chat/completions"; - } + public String chatCompletionUrl() { + return "https://api.openai.com/v1/chat/completions"; + } + + public Integer timeoutMillis() { + return 20000; + } - public Integer timeoutMillis() { - return 20000; - } } diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/SalesforceConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/SalesforceConstants.java index 35eee8c9..d9f6a07d 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/SalesforceConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/SalesforceConstants.java @@ -6,67 +6,68 @@ @Component public class SalesforceConstants { - public String compositeUrlPath() { - return "/services/data/v58.0/composite"; - } + public String compositeUrlPath() { + return "/services/data/v58.0/composite"; + } - public String queryUrlPath() { - return "/services/data/v58.0/query/?q="; - } + public String queryUrlPath() { + return "/services/data/v58.0/query/?q="; + } - public String sObjectsPath() { - return "/services/data/v58.0/sobjects"; - } + public String sObjectsPath() { + return "/services/data/v58.0/sobjects"; + } - public String salesforceCompositeUrl(String urlPrefix) { - return urlPrefix + compositeUrlPath(); - } + public String salesforceCompositeUrl(String urlPrefix) { + return urlPrefix + compositeUrlPath(); + } - public String oauth2AuthorizeUrl() { - return CoreConstants.salesforceAuthUrl() + "/services/oauth2/authorize"; - } + public String oauth2AuthorizeUrl() { + return CoreConstants.salesforceAuthUrl() + "/services/oauth2/authorize"; + } - public String oauth2Url() { - return CoreConstants.salesforceAuthUrl() + "/services/oauth2/token"; - } + public String oauth2Url() { + return CoreConstants.salesforceAuthUrl() + "/services/oauth2/token"; + } - public String salesforceCreateNoteUrl() { - return sObjectsPath() + "/ContentNote"; - } + public String salesforceCreateNoteUrl() { + return sObjectsPath() + "/ContentNote"; + } - public String salesforceDeleteNoteUrl(String noteId) { - return sObjectsPath() + "/ContentNote/" + noteId; - } + public String salesforceDeleteNoteUrl(String noteId) { + return sObjectsPath() + "/ContentNote/" + noteId; + } - public String salesforceAttachNoteUrl() { - return sObjectsPath() + "/ContentDocumentLink"; - } + public String salesforceAttachNoteUrl() { + return sObjectsPath() + "/ContentDocumentLink"; + } - public String identityUrl() { - return "/services/oauth2/userinfo"; - } + public String identityUrl() { + return "/services/oauth2/userinfo"; + } - public String authorizationCodeGrantType() { - return "authorization_code"; - } + public String authorizationCodeGrantType() { + return "authorization_code"; + } - public String refreshTokenGrantType() { - return "refresh_token"; - } + public String refreshTokenGrantType() { + return "refresh_token"; + } - public Integer timeoutMillis() { - return 10000; - } + public Integer timeoutMillis() { + return 10000; + } - public String salesforceNotesContentUrl(String urlPrefix, String noteId){ - return urlPrefix + "/services/data/v58.0/sobjects/ContentNote/" + noteId + "/Content"; - } + public String salesforceNotesContentUrl(String urlPrefix, String noteId) { + return urlPrefix + "/services/data/v58.0/sobjects/ContentNote/" + noteId + "/Content"; + } - public String salesforceCreateTaskUrl(){ - return sObjectsPath() + "/Task"; - } + public String salesforceCreateTaskUrl() { + return sObjectsPath() + "/Task"; + } + + public String salesforceDeleteAccountTaskUrl(String taskId) { + return sObjectsPath() + "/Task/" + taskId; + } - public String salesforceDeleteAccountTaskUrl(String taskId){ - return sObjectsPath() + "/Task/" + taskId; - } } diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java index 3ec93ed2..63d50a78 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java @@ -21,156 +21,148 @@ */ public class SecretConstants { - /* Secret manager configuration start */ - - /** - * This is the builder that is going to be used to access the secrets manager. - */ - public static SecretsManagerClientBuilder secretsManagerClientBuilder = SecretsManagerClient.builder(); - - /** - * This method returns the secrets from the secrets manager. - * @return - * @throws JsonProcessingException - * @throws JsonMappingException - */ - public static String getSecret(String key) { - String secretJson = ""; - - if (CoreConstants.isDevEnvironment()) { - secretJson = getLocalEnvVars("secrets.json"); - } else if (CoreConstants.isLocalTestEnvironment()) { - secretJson = getLocalEnvVars("test.secrets.json"); - } else { - SecretCache cache = new SecretCache(secretsManagerClientBuilder); - String secretId = getSecretId(); - secretJson = cache.getSecretString(secretId); - cache.close(); - } - - ObjectMapper objectMapper = new ObjectMapper(); - String specificValue = ""; - try { - JsonNode jsonNode = objectMapper.readTree(secretJson); - specificValue = jsonNode.get(key).asText(); - } catch (Exception e) { - throw new CustomException( - new ErrorObject( - "l_gc_s_gs_1", - "something_went_wrong", - e.getMessage())); - } - - return specificValue; - } - - /** - * This method returns the secret id that is going to be - * used to access the secrets manager. - * - * @return - */ - private static String getSecretId() { - return "ai-sales-sparrow-api-" + CoreConstants.environment(); - } - - /* Secret manager configuration function end */ - - /* Secrets start */ - - public static String cookieDomain() { - return getSecret("COOKIE_DOMAIN"); - } - - public static String awsRegion() { - return getSecret("AWS_IAM_REGION"); - } - - public static String encryptionKey() { - return getSecret("ENCRYPTION_KEY"); - } - - public static String apiCookieSecret() { - return getSecret("API_COOKIE_SECRET"); - } - - public static String kmsKeyId() { - return getSecret("KMS_KEY_ID"); - } - - public static String salesforceAuthUrl() { - return getSecret("SALESFORCE_AUTH_URL"); - } - - public static String salesforceClientId() { - return getSecret("SALESFORCE_CLIENT_ID"); - } - - public static String salesforceClientSecret() { - return getSecret("SALESFORCE_CLIENT_SECRET"); - } - - public static String memcachedHost() { - return getSecret("MEMCACHED_CACHE_HOST"); - } - - public static String memcachedPort() { - return getSecret("MEMCACHED_CACHE_PORT"); - } - - public static String salesforceWhitelistedRedirectUris() { - return getSecret("SALESFORCE_WHITELISTED_REDIRECT_URIS"); - } - - public static String openAiApiKey() { - return getSecret("OPENAI_API_KEY"); - } - - public static String errorEmailFrom() { - return getSecret("ERROR_EMAIL_FROM"); - } - - public static String errorEmailTo() { - return getSecret("ERROR_EMAIL_TO"); - } - - public static String dynamoDbUrl() { - return getSecret("DYNAMO_DB_URL"); - } - - public static String localKmsEndpoint() { - return getSecret("LOCAL_KMS_ENDPOINT"); - } - - /* Secrets end */ - - /** - * This method returns the local environment variables. - * - * @return String - */ - private static String getLocalEnvVars(String filename) { - try (FileReader fileReader = new FileReader(filename)) { - int ch; - StringBuilder secretJsonBuilder = new StringBuilder(); - - while ((ch = fileReader.read()) != -1) { - secretJsonBuilder.append((char) ch); - } - - return secretJsonBuilder.toString(); - } catch (FileNotFoundException e) { - throw new CustomException( - new ErrorObject( - "l_gc_s_glev_1", - "something_went_wrong", - e.getMessage())); - } catch (IOException e) { - throw new CustomException( - new ErrorObject( - "l_gc_s_glev_2", - "something_went_wrong", - e.getMessage())); - } - } + /* Secret manager configuration start */ + + /** + * This is the builder that is going to be used to access the secrets manager. + */ + public static SecretsManagerClientBuilder secretsManagerClientBuilder = SecretsManagerClient.builder(); + + /** + * This method returns the secrets from the secrets manager. + * @return + * @throws JsonProcessingException + * @throws JsonMappingException + */ + public static String getSecret(String key) { + String secretJson = ""; + + if (CoreConstants.isDevEnvironment()) { + secretJson = getLocalEnvVars("secrets.json"); + } + else if (CoreConstants.isLocalTestEnvironment()) { + secretJson = getLocalEnvVars("test.secrets.json"); + } + else { + SecretCache cache = new SecretCache(secretsManagerClientBuilder); + String secretId = getSecretId(); + secretJson = cache.getSecretString(secretId); + cache.close(); + } + + ObjectMapper objectMapper = new ObjectMapper(); + String specificValue = ""; + try { + JsonNode jsonNode = objectMapper.readTree(secretJson); + specificValue = jsonNode.get(key).asText(); + } + catch (Exception e) { + throw new CustomException(new ErrorObject("l_gc_s_gs_1", "something_went_wrong", e.getMessage())); + } + + return specificValue; + } + + /** + * This method returns the secret id that is going to be used to access the secrets + * manager. + * @return + */ + private static String getSecretId() { + return "ai-sales-sparrow-api-" + CoreConstants.environment(); + } + + /* Secret manager configuration function end */ + + /* Secrets start */ + + public static String cookieDomain() { + return getSecret("COOKIE_DOMAIN"); + } + + public static String awsRegion() { + return getSecret("AWS_IAM_REGION"); + } + + public static String encryptionKey() { + return getSecret("ENCRYPTION_KEY"); + } + + public static String apiCookieSecret() { + return getSecret("API_COOKIE_SECRET"); + } + + public static String kmsKeyId() { + return getSecret("KMS_KEY_ID"); + } + + public static String salesforceAuthUrl() { + return getSecret("SALESFORCE_AUTH_URL"); + } + + public static String salesforceClientId() { + return getSecret("SALESFORCE_CLIENT_ID"); + } + + public static String salesforceClientSecret() { + return getSecret("SALESFORCE_CLIENT_SECRET"); + } + + public static String memcachedHost() { + return getSecret("MEMCACHED_CACHE_HOST"); + } + + public static String memcachedPort() { + return getSecret("MEMCACHED_CACHE_PORT"); + } + + public static String salesforceWhitelistedRedirectUris() { + return getSecret("SALESFORCE_WHITELISTED_REDIRECT_URIS"); + } + + public static String openAiApiKey() { + return getSecret("OPENAI_API_KEY"); + } + + public static String errorEmailFrom() { + return getSecret("ERROR_EMAIL_FROM"); + } + + public static String errorEmailTo() { + return getSecret("ERROR_EMAIL_TO"); + } + + public static String dynamoDbUrl() { + return getSecret("DYNAMO_DB_URL"); + } + + public static String localKmsEndpoint() { + return getSecret("LOCAL_KMS_ENDPOINT"); + } + + /* Secrets end */ + + /** + * This method returns the local environment variables. + * @return String + */ + private static String getLocalEnvVars(String filename) { + try (FileReader fileReader = new FileReader(filename)) { + int ch; + StringBuilder secretJsonBuilder = new StringBuilder(); + + while ((ch = fileReader.read()) != -1) { + secretJsonBuilder.append((char) ch); + } + + return secretJsonBuilder.toString(); + } + catch (FileNotFoundException e) { + throw new CustomException(new ErrorObject("l_gc_s_glev_1", "something_went_wrong", e.getMessage())); + } + catch (IOException e) { + throw new CustomException(new ErrorObject("l_gc_s_glev_2", "something_went_wrong", e.getMessage())); + } + } + } diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/UserConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/UserConstants.java index e6d4cb08..43fb1c8a 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/UserConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/UserConstants.java @@ -4,10 +4,12 @@ * User constants. */ public class UserConstants { - public static final String SALESFORCE_USER_KIND = "SALESFORCE"; - - // Private constructor to prevent instantiation - private UserConstants() { - throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); - } + + public static final String SALESFORCE_USER_KIND = "SALESFORCE"; + + // Private constructor to prevent instantiation + private UserConstants() { + throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); + } + } diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/config/dynamoBeeConfigConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/config/dynamoBeeConfigConstants.java index 33dd75b9..99ca5863 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/config/dynamoBeeConfigConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/config/dynamoBeeConfigConstants.java @@ -6,15 +6,16 @@ @Component public class dynamoBeeConfigConstants { - public String getChangeLogScanPackage() { - return "com.salessparrow.api.changelogs"; - } + public String getChangeLogScanPackage() { + return "com.salessparrow.api.changelogs"; + } - public String getChangelogTableName() { - return CoreConstants.environment() + "_changelog"; - } + public String getChangelogTableName() { + return CoreConstants.environment() + "_changelog"; + } + + public String authorName() { + return CoreConstants.environment() + "_salessparrow_api"; + } - public String authorName() { - return CoreConstants.environment() + "_salessparrow_api"; - } } diff --git a/src/main/java/com/salessparrow/api/lib/httpLib/HttpClient.java b/src/main/java/com/salessparrow/api/lib/httpLib/HttpClient.java index dfc00415..6b15a81b 100644 --- a/src/main/java/com/salessparrow/api/lib/httpLib/HttpClient.java +++ b/src/main/java/com/salessparrow/api/lib/httpLib/HttpClient.java @@ -13,97 +13,98 @@ public class HttpClient { - public static class HttpResponse { - private int statusCode; - private String responseBody; - private Map> headers; - private String contentType; + public static class HttpResponse { - public HttpResponse(int statusCode, String responseBody, Map> headers, String contentType) { - this.statusCode = statusCode; - this.responseBody = responseBody; - this.headers = headers; - this.contentType = contentType; - } + private int statusCode; - public HttpResponse() { - } + private String responseBody; - public int getStatusCode() { - return statusCode; - } + private Map> headers; - public String getResponseBody() { - return responseBody; - } + private String contentType; - public Map> getHeaders() { - return headers; - } + public HttpResponse(int statusCode, String responseBody, Map> headers, + String contentType) { + this.statusCode = statusCode; + this.responseBody = responseBody; + this.headers = headers; + this.contentType = contentType; + } - public String getContentType() { - return contentType; - } + public HttpResponse() { + } - public void setResponseBody(String responseBody) { - this.responseBody = responseBody; - } + public int getStatusCode() { + return statusCode; + } - } + public String getResponseBody() { + return responseBody; + } - public static HttpResponse makeGetRequest(String url, Map headers, int timeoutMillis) { + public Map> getHeaders() { + return headers; + } - WebClient webClient = WebClient.builder().build(); + public String getContentType() { + return contentType; + } - WebClient.RequestHeadersSpec request = webClient.get() - .uri(url); + public void setResponseBody(String responseBody) { + this.responseBody = responseBody; + } - if (headers != null) { - request.headers(httpHeaders -> { - headers.forEach(httpHeaders::set); - }); - } + } - Mono> responseMono = request - .retrieve() - .toEntity(String.class); + public static HttpResponse makeGetRequest(String url, Map headers, int timeoutMillis) { - ResponseEntity responseEntity = responseMono.block(Duration.ofMillis(timeoutMillis)); + WebClient webClient = WebClient.builder().build(); - int statusCode = responseEntity.getStatusCode().value(); - String responseBody = responseEntity.getBody(); - Map> responseHeaders = new HashMap<>(responseEntity.getHeaders()); - String contentType = responseEntity.getHeaders().getContentType().toString(); + WebClient.RequestHeadersSpec request = webClient.get().uri(url); - return new HttpResponse(statusCode, responseBody, responseHeaders, contentType); - } + if (headers != null) { + request.headers(httpHeaders -> { + headers.forEach(httpHeaders::set); + }); + } - public static HttpResponse makePostRequest(String url, Map headers, Object requestBody, - int timeoutMillis) { - WebClient webClient = WebClient.builder().build(); + Mono> responseMono = request.retrieve().toEntity(String.class); - WebClient.RequestHeadersSpec request = webClient.post() - .uri(url) - .contentType(MediaType.APPLICATION_JSON) - .bodyValue(requestBody); + ResponseEntity responseEntity = responseMono.block(Duration.ofMillis(timeoutMillis)); - if (headers != null) { - request.headers(httpHeaders -> { - headers.forEach(httpHeaders::set); - }); - } + int statusCode = responseEntity.getStatusCode().value(); + String responseBody = responseEntity.getBody(); + Map> responseHeaders = new HashMap<>(responseEntity.getHeaders()); + String contentType = responseEntity.getHeaders().getContentType().toString(); - Mono> responseMono = request - .retrieve() - .toEntity(String.class); + return new HttpResponse(statusCode, responseBody, responseHeaders, contentType); + } - ResponseEntity responseEntity = responseMono.block(Duration.ofMillis(timeoutMillis)); + public static HttpResponse makePostRequest(String url, Map headers, Object requestBody, + int timeoutMillis) { + WebClient webClient = WebClient.builder().build(); - int statusCode = responseEntity.getStatusCode().value(); - String responseBody = responseEntity.getBody(); - Map> responseHeaders = new HashMap<>(responseEntity.getHeaders()); - String contentType = responseEntity.getHeaders().getContentType().toString(); + WebClient.RequestHeadersSpec request = webClient.post() + .uri(url) + .contentType(MediaType.APPLICATION_JSON) + .bodyValue(requestBody); + + if (headers != null) { + request.headers(httpHeaders -> { + headers.forEach(httpHeaders::set); + }); + } + + Mono> responseMono = request.retrieve().toEntity(String.class); + + ResponseEntity responseEntity = responseMono.block(Duration.ofMillis(timeoutMillis)); + + int statusCode = responseEntity.getStatusCode().value(); + String responseBody = responseEntity.getBody(); + Map> responseHeaders = new HashMap<>(responseEntity.getHeaders()); + String contentType = responseEntity.getHeaders().getContentType().toString(); + + return new HttpResponse(statusCode, responseBody, responseHeaders, contentType); + } - return new HttpResponse(statusCode, responseBody, responseHeaders, contentType); - } } diff --git a/src/main/java/com/salessparrow/api/lib/openAi/OpenAiPayloadBuilder.java b/src/main/java/com/salessparrow/api/lib/openAi/OpenAiPayloadBuilder.java index 2ca2744c..9fc56960 100644 --- a/src/main/java/com/salessparrow/api/lib/openAi/OpenAiPayloadBuilder.java +++ b/src/main/java/com/salessparrow/api/lib/openAi/OpenAiPayloadBuilder.java @@ -11,60 +11,41 @@ @Component public class OpenAiPayloadBuilder { - /** - * Payload for crm actions suggestions. - * @param text - * @return - */ - public String payloadForCrmActionsSuggestions(String text) { - - return "{\n" + - " \"model\": \"gpt-3.5-turbo-0613\",\n" + - " \"messages\": [\n" + - " {\n" + - " \"role\": \"user\",\n" + - " \"content\": \"You are an AI assistant which gives suggestion on creating task in crm using the input message.Only use the functions you have been provided with. \\nInput message: \\n" + text + "\\n\"\n" + - " }\n" + - " ],\n" + - " \"functions\": [\n" + - " {\n" + - " \"name\": \"suggest_actions\",\n" + - " \"description\": \"This is function for suggesting actions in crm(example salesforce, freshsales) based on input message.\",\n" + - " \"parameters\": {\n" + - " \"type\": \"object\",\n" + - " \"properties\": {\n" + - " \"add_task\": {\n" + - " \"name\": \"add_task\",\n" + - " \"description\": \"Tasks using input message.\",\n" + - " \"type\": \"array\",\n" + - " \"items\": {\n" + - " \"type\": \"object\",\n" + - " \"properties\": {\n" + - " \"description\": {\n" + - " \"type\": \"string\",\n" + - " \"description\": \"Description for task to add. This is mandatory\"\n" + - " },\n" + - " \"due_date\": {\n" + - " \"type\": \"string\",\n" + - " \"description\": \"Due date for task in YYYY-MM-DD format. Today's date is " + getTodaysDate() + ". This is mandatory\"\n" + - " }\n" + - " },\n" + - " \"required\": [\"description\", \"due_date\"]\n" + - " }\n" + - " }\n" + - " }\n" + - " }\n" + - " }\n" + - " ]\n" + - "}"; - } + /** + * Payload for crm actions suggestions. + * @param text + * @return + */ + public String payloadForCrmActionsSuggestions(String text) { + + return "{\n" + " \"model\": \"gpt-3.5-turbo-0613\",\n" + " \"messages\": [\n" + " {\n" + + " \"role\": \"user\",\n" + + " \"content\": \"You are an AI assistant which gives suggestion on creating task in crm using the input message.Only use the functions you have been provided with. \\nInput message: \\n" + + text + "\\n\"\n" + " }\n" + " ],\n" + " \"functions\": [\n" + " {\n" + + " \"name\": \"suggest_actions\",\n" + + " \"description\": \"This is function for suggesting actions in crm(example salesforce, freshsales) based on input message.\",\n" + + " \"parameters\": {\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + + " \"add_task\": {\n" + " \"name\": \"add_task\",\n" + + " \"description\": \"Tasks using input message.\",\n" + + " \"type\": \"array\",\n" + " \"items\": {\n" + + " \"type\": \"object\",\n" + " \"properties\": {\n" + + " \"description\": {\n" + " \"type\": \"string\",\n" + + " \"description\": \"Description for task to add. This is mandatory\"\n" + + " },\n" + " \"due_date\": {\n" + + " \"type\": \"string\",\n" + + " \"description\": \"Due date for task in YYYY-MM-DD format. Today's date is " + + getTodaysDate() + ". This is mandatory\"\n" + " }\n" + " },\n" + + " \"required\": [\"description\", \"due_date\"]\n" + " }\n" + " }\n" + + " }\n" + " }\n" + " }\n" + " ]\n" + "}"; + } + + /** + * Todays date in yyyy-MM-dd format. + * @return + */ + public String getTodaysDate() { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + return sdf.format(new Date()); + } - /** - * Todays date in yyyy-MM-dd format. - * @return - */ - public String getTodaysDate() { - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); - return sdf.format(new Date()); - } } diff --git a/src/main/java/com/salessparrow/api/lib/openAi/OpenAiRequest.java b/src/main/java/com/salessparrow/api/lib/openAi/OpenAiRequest.java index 757cd635..08bfd163 100644 --- a/src/main/java/com/salessparrow/api/lib/openAi/OpenAiRequest.java +++ b/src/main/java/com/salessparrow/api/lib/openAi/OpenAiRequest.java @@ -20,52 +20,42 @@ **/ @Component public class OpenAiRequest { - @Autowired - private OpenAiConstants openAiConstants; - private Logger logger = org.slf4j.LoggerFactory.getLogger(SuggestionsController.class); - - /** - * Make a request to the OpenAI API. - * @param payload - * @return - */ - public HttpClient.HttpResponse makeRequest(Object payload) { - String httpReqUrl = openAiConstants.chatCompletionUrl(); + @Autowired + private OpenAiConstants openAiConstants; + + private Logger logger = org.slf4j.LoggerFactory.getLogger(SuggestionsController.class); + + /** + * Make a request to the OpenAI API. + * @param payload + * @return + */ + public HttpClient.HttpResponse makeRequest(Object payload) { + String httpReqUrl = openAiConstants.chatCompletionUrl(); + + Map headers = new HashMap<>(); + headers.put("Authorization", "Bearer " + CoreConstants.openAiApiKey()); + + Integer timeoutMillis = openAiConstants.timeoutMillis(); + try { + logger.info("Making request to OpenAI API"); + HttpClient.HttpResponse response = HttpClient.makePostRequest(httpReqUrl, headers, payload, timeoutMillis); + + return response; + } + catch (WebClientResponseException e) { + if (e.getStatusCode().value() == 401) { + throw new CustomException( + new ErrorObject("l_o_a_oar_mr_1", "something_went_wrong", "Invalid OpenAI API key")); + } + else if (e.getStatusCode().value() == 400) { + throw new CustomException( + new ErrorObject("l_o_a_oar_mr_2", "something_went_wrong", "Invalid request payload")); + } + + throw new CustomException(new ErrorObject("l_o_a_oar_mr_3", "something_went_wrong", e.getMessage())); + } + } - Map headers = new HashMap<>(); - headers.put("Authorization", "Bearer " + CoreConstants.openAiApiKey()); - - Integer timeoutMillis = openAiConstants.timeoutMillis(); - try { - logger.info("Making request to OpenAI API"); - HttpClient.HttpResponse response = HttpClient.makePostRequest( - httpReqUrl, - headers, - payload, - timeoutMillis); - - return response; - } catch (WebClientResponseException e) { - if(e.getStatusCode().value() == 401) { - throw new CustomException( - new ErrorObject( - "l_o_a_oar_mr_1", - "something_went_wrong", - "Invalid OpenAI API key")); - } else if(e.getStatusCode().value() == 400) { - throw new CustomException( - new ErrorObject( - "l_o_a_oar_mr_2", - "something_went_wrong", - "Invalid request payload")); - } - - throw new CustomException( - new ErrorObject( - "l_o_a_oar_mr_3", - "something_went_wrong", - e.getMessage())); - } - } } diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/dto/CompositeRequestDto.java b/src/main/java/com/salessparrow/api/lib/salesforce/dto/CompositeRequestDto.java index 29d9f93f..f931f093 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/dto/CompositeRequestDto.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/dto/CompositeRequestDto.java @@ -4,22 +4,26 @@ @Data public class CompositeRequestDto { - - private String method; - private String url; - private String referenceId; - private Object body; - - public CompositeRequestDto(String method, String url, String referenceId) { - this.method = method; - this.url = url; - this.referenceId = referenceId; - } - - public CompositeRequestDto(String method, String url, String referenceId, Object body) { - this.method = method; - this.url = url; - this.referenceId = referenceId; - this.body = body; - } + + private String method; + + private String url; + + private String referenceId; + + private Object body; + + public CompositeRequestDto(String method, String url, String referenceId) { + this.method = method; + this.url = url; + this.referenceId = referenceId; + } + + public CompositeRequestDto(String method, String url, String referenceId, Object body) { + this.method = method; + this.url = url; + this.referenceId = referenceId; + this.body = body; + } + } diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceAccountDto.java b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceAccountDto.java index 647e8b73..c56db55a 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceAccountDto.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceAccountDto.java @@ -9,14 +9,17 @@ @Data @JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) public class SalesforceAccountDto { - private String id; - private String name; - public AccountEntity getAccountEntity() { - AccountEntity accountEntity = new AccountEntity(); - accountEntity.setId(this.id); - accountEntity.setName(this.name); + private String id; + + private String name; + + public AccountEntity getAccountEntity() { + AccountEntity accountEntity = new AccountEntity(); + accountEntity.setId(this.id); + accountEntity.setName(this.name); + + return accountEntity; + } - return accountEntity; - } } diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceCreateNoteDto.java b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceCreateNoteDto.java index f9c4445f..cee8a169 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceCreateNoteDto.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceCreateNoteDto.java @@ -7,9 +7,11 @@ */ @Data public class SalesforceCreateNoteDto { - String id; - String success; - - String[] errors; + String id; + + String success; + + String[] errors; + } diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceCreateTaskDto.java b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceCreateTaskDto.java index a3b476e4..a8053476 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceCreateTaskDto.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceCreateTaskDto.java @@ -4,5 +4,7 @@ @Data public class SalesforceCreateTaskDto { - String id; + + String id; + } diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceCrmOrganizationUserDto.java b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceCrmOrganizationUserDto.java index 2494a585..bb3b69ab 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceCrmOrganizationUserDto.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceCrmOrganizationUserDto.java @@ -9,17 +9,20 @@ @Data @JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) public class SalesforceCrmOrganizationUserDto { - private String id; - private String name; - - /** - * convert SalesforceCrmOrganizationUserDto into CrmOrganizationUserEntity - */ - public CrmOrganizationUserEntity getCrmOrganizationUserEntity() { - CrmOrganizationUserEntity crmOrganizationUserEntity = new CrmOrganizationUserEntity(); - crmOrganizationUserEntity.setId(this.id); - crmOrganizationUserEntity.setName(this.name); - - return crmOrganizationUserEntity; - } + + private String id; + + private String name; + + /** + * convert SalesforceCrmOrganizationUserDto into CrmOrganizationUserEntity + */ + public CrmOrganizationUserEntity getCrmOrganizationUserEntity() { + CrmOrganizationUserEntity crmOrganizationUserEntity = new CrmOrganizationUserEntity(); + crmOrganizationUserEntity.setId(this.id); + crmOrganizationUserEntity.setName(this.name); + + return crmOrganizationUserEntity; + } + } diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetIdentityDto.java b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetIdentityDto.java index 84a00108..87d007c7 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetIdentityDto.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetIdentityDto.java @@ -8,9 +8,15 @@ @Data @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) public class SalesforceGetIdentityDto { - private String sub; - private String userId; - private String organizationId; - private String name; - private String email; + + private String sub; + + private String userId; + + private String organizationId; + + private String name; + + private String email; + } diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetNoteDetailsDto.java b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetNoteDetailsDto.java index ae5bdc4b..bb8422d2 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetNoteDetailsDto.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetNoteDetailsDto.java @@ -11,23 +11,25 @@ @Data @JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) public class SalesforceGetNoteDetailsDto { - private String id; - private CreatedBy createdBy; - private Date lastModifiedDate; - - @Data - @JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) - private class CreatedBy{ - private String name; - } - - public NoteDetailEntity noteDetailEntity(String noteContentResponse){ - NoteDetailEntity noteDetailEntity = new NoteDetailEntity( - this.id, - this.createdBy.name, - noteContentResponse, - this.lastModifiedDate - ); - return noteDetailEntity; - } + + private String id; + + private CreatedBy createdBy; + + private Date lastModifiedDate; + + @Data + @JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) + private class CreatedBy { + + private String name; + + } + + public NoteDetailEntity noteDetailEntity(String noteContentResponse) { + NoteDetailEntity noteDetailEntity = new NoteDetailEntity(this.id, this.createdBy.name, noteContentResponse, + this.lastModifiedDate); + return noteDetailEntity; + } + } diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetNoteIdDto.java b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetNoteIdDto.java index d81d79d3..8666b20e 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetNoteIdDto.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetNoteIdDto.java @@ -8,5 +8,7 @@ @Data @JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) public class SalesforceGetNoteIdDto { - private String contentDocumentId; + + private String contentDocumentId; + } diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetNotesListDto.java b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetNotesListDto.java index 736562a1..6dab2276 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetNotesListDto.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetNotesListDto.java @@ -11,24 +11,26 @@ @Data @JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) public class SalesforceGetNotesListDto { - private String id; - private String textPreview; - private CreatedBy createdBy; - private Date lastModifiedDate; - - @Data - @JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) - private class CreatedBy{ - private String name; - } - - public NoteEntity noteEntity(){ - NoteEntity noteEntity = new NoteEntity( - this.id, - this.createdBy.name, - this.textPreview, - this.lastModifiedDate - ); - return noteEntity; - } + + private String id; + + private String textPreview; + + private CreatedBy createdBy; + + private Date lastModifiedDate; + + @Data + @JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) + private class CreatedBy { + + private String name; + + } + + public NoteEntity noteEntity() { + NoteEntity noteEntity = new NoteEntity(this.id, this.createdBy.name, this.textPreview, this.lastModifiedDate); + return noteEntity; + } + } diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetTasksListDto.java b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetTasksListDto.java index 66a9071a..f8bfe670 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetTasksListDto.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetTasksListDto.java @@ -12,38 +12,49 @@ @Data @JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) public class SalesforceGetTasksListDto { - private String id; - private String description; - private Date activityDate; - private CreatedBy createdBy; - private Owner owner; - private Date lastModifiedDate; - - @Data - @JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) - private class CreatedBy{ - private String name; - } - - @Data - @JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) - private class Owner{ - private String name; - } - - public TaskEntity taskEntity(){ - Util util = new Util(); - - TaskEntity taskEntity = new TaskEntity(); - taskEntity.setId(this.id); - taskEntity.setCreatorName(this.createdBy.name); - taskEntity.setDescription(this.description); - taskEntity.setCrmOrganizationUserName(this.owner.name); - taskEntity.setLastModifiedTime(this.lastModifiedDate); - - String dueDate = util.getDateFormatFromDatetime(this.activityDate); - - taskEntity.setDueDate(dueDate); - return taskEntity; - } + + private String id; + + private String description; + + private Date activityDate; + + private CreatedBy createdBy; + + private Owner owner; + + private Date lastModifiedDate; + + @Data + @JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) + private class CreatedBy { + + private String name; + + } + + @Data + @JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) + private class Owner { + + private String name; + + } + + public TaskEntity taskEntity() { + Util util = new Util(); + + TaskEntity taskEntity = new TaskEntity(); + taskEntity.setId(this.id); + taskEntity.setCreatorName(this.createdBy.name); + taskEntity.setDescription(this.description); + taskEntity.setCrmOrganizationUserName(this.owner.name); + taskEntity.setLastModifiedTime(this.lastModifiedDate); + + String dueDate = util.getDateFormatFromDatetime(this.activityDate); + + taskEntity.setDueDate(dueDate); + return taskEntity; + } + } diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetTokensDto.java b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetTokensDto.java index 40365b23..3848b8cd 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetTokensDto.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceGetTokensDto.java @@ -8,33 +8,41 @@ @Data @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) public class SalesforceGetTokensDto { - private String accessToken; - private String refreshToken; - private String signature; - private String scope; - private String idToken; - private String instanceUrl; - private String id; - private String tokenType; - private String issuedAt; - - /** - * Get Salesforce organization id from id - * - * @return String - */ - public String getSalesforceOrganizationId() { - String[] idParts = id.split("/"); - return idParts[4]; - } - - /** - * Get Salesforce user id from id - * - * @return String - */ - public String getSalesforceUserId() { - String[] idParts = id.split("/"); - return idParts[5]; - } + + private String accessToken; + + private String refreshToken; + + private String signature; + + private String scope; + + private String idToken; + + private String instanceUrl; + + private String id; + + private String tokenType; + + private String issuedAt; + + /** + * Get Salesforce organization id from id + * @return String + */ + public String getSalesforceOrganizationId() { + String[] idParts = id.split("/"); + return idParts[4]; + } + + /** + * Get Salesforce user id from id + * @return String + */ + public String getSalesforceUserId() { + String[] idParts = id.split("/"); + return idParts[5]; + } + } diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/helper/MakeCompositeRequest.java b/src/main/java/com/salessparrow/api/lib/salesforce/helper/MakeCompositeRequest.java index d16a2dcb..ac3ebe49 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/helper/MakeCompositeRequest.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/helper/MakeCompositeRequest.java @@ -19,49 +19,44 @@ @Component public class MakeCompositeRequest { - Logger logger = LoggerFactory.getLogger(MakeCompositeRequest.class); - - @Autowired - private SalesforceRequest salesforceOauthRequest; - - @Autowired - private SalesforceConstants salesforceConstants; - - /** - * Make composite post request to the Salesforce API. - * - * @param compositeRequests - * @param salesforceUserId - * - * @return HttpClient.HttpResponse - **/ - public HttpClient.HttpResponse makePostRequest( - List compositeRequests, - String salesforceUserId) { - Map> compositeRequestsMap = new HashMap<>(); - compositeRequestsMap.put("compositeRequest", compositeRequests); - - Integer timeoutMillis = salesforceConstants.timeoutMillis(); - - SalesforceRequestInterface request = (token, instanceUrl) -> { - String httpReqUrl = salesforceConstants.salesforceCompositeUrl(instanceUrl); - - Map headers = new HashMap<>(); - headers.put("Authorization", "Bearer " + token); - - HttpClient.HttpResponse response = HttpClient.makePostRequest( - httpReqUrl, - headers, - compositeRequestsMap, - timeoutMillis); - return response; - }; - - HttpClient.HttpResponse response = null; - - logger.info("making composite request to salesforce"); - - response = salesforceOauthRequest.makeRequest(salesforceUserId, request); - return response; - } + Logger logger = LoggerFactory.getLogger(MakeCompositeRequest.class); + + @Autowired + private SalesforceRequest salesforceOauthRequest; + + @Autowired + private SalesforceConstants salesforceConstants; + + /** + * Make composite post request to the Salesforce API. + * @param compositeRequests + * @param salesforceUserId + * @return HttpClient.HttpResponse + **/ + public HttpClient.HttpResponse makePostRequest(List compositeRequests, + String salesforceUserId) { + Map> compositeRequestsMap = new HashMap<>(); + compositeRequestsMap.put("compositeRequest", compositeRequests); + + Integer timeoutMillis = salesforceConstants.timeoutMillis(); + + SalesforceRequestInterface request = (token, instanceUrl) -> { + String httpReqUrl = salesforceConstants.salesforceCompositeUrl(instanceUrl); + + Map headers = new HashMap<>(); + headers.put("Authorization", "Bearer " + token); + + HttpClient.HttpResponse response = HttpClient.makePostRequest(httpReqUrl, headers, compositeRequestsMap, + timeoutMillis); + return response; + }; + + HttpClient.HttpResponse response = null; + + logger.info("making composite request to salesforce"); + + response = salesforceOauthRequest.makeRequest(salesforceUserId, request); + return response; + } + } diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceOAuthToken.java b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceOAuthToken.java index dba11f8e7..bbb39595 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceOAuthToken.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceOAuthToken.java @@ -17,57 +17,55 @@ @Service public class SalesforceOAuthToken { - @Autowired - private AwsKms awsKms; - - @Autowired - private SalesforceOauthTokenRepository salesforceOauthTokenRepository; - - @Autowired - private SalesforceGetRefreshedAccessToken salesforceGetRefreshedAccessToken; - - @Autowired - private Util util; - - /** - * Fetch the access token from the database and decrypt it. - * - * @param sfOAuthToken - * - * @return String - */ - public String fetchAccessToken(SalesforceOauthToken sfOAuthToken) { - String decryptedAccessToken = awsKms.decryptToken(sfOAuthToken.getAccessToken()); - return decryptedAccessToken; - } - - public String updateAndGetRefreshedAccessToken(SalesforceOauthToken sfOAuthToken) { - String encryptedRefreshToken = sfOAuthToken.getRefreshToken(); - String decryptedRefreshToken = awsKms.decryptToken(encryptedRefreshToken); - - HttpClient.HttpResponse response = salesforceGetRefreshedAccessToken.getRefreshedAccessToken(decryptedRefreshToken); - String decryptedAccessToken = updateAccessTokenInDatabase(response.getResponseBody(), sfOAuthToken); - - return decryptedAccessToken; - } - - /** - * Update the access token in the database and return the decrypted access token. - * - * @param responseBody - * @param sfOAuthToken - * - * @return String - */ - private String updateAccessTokenInDatabase(String responseBody, SalesforceOauthToken sfOAuthToken) { - JsonNode rootNode = util.getJsonNode(responseBody); - String decryptedAccessToken = rootNode.get("access_token").asText(); - - String encryptedAccessToken = awsKms.encryptToken(decryptedAccessToken); - - sfOAuthToken.setAccessToken(encryptedAccessToken); - salesforceOauthTokenRepository.saveSalesforceOauthToken(sfOAuthToken); - - return decryptedAccessToken; - } + @Autowired + private AwsKms awsKms; + + @Autowired + private SalesforceOauthTokenRepository salesforceOauthTokenRepository; + + @Autowired + private SalesforceGetRefreshedAccessToken salesforceGetRefreshedAccessToken; + + @Autowired + private Util util; + + /** + * Fetch the access token from the database and decrypt it. + * @param sfOAuthToken + * @return String + */ + public String fetchAccessToken(SalesforceOauthToken sfOAuthToken) { + String decryptedAccessToken = awsKms.decryptToken(sfOAuthToken.getAccessToken()); + return decryptedAccessToken; + } + + public String updateAndGetRefreshedAccessToken(SalesforceOauthToken sfOAuthToken) { + String encryptedRefreshToken = sfOAuthToken.getRefreshToken(); + String decryptedRefreshToken = awsKms.decryptToken(encryptedRefreshToken); + + HttpClient.HttpResponse response = salesforceGetRefreshedAccessToken + .getRefreshedAccessToken(decryptedRefreshToken); + String decryptedAccessToken = updateAccessTokenInDatabase(response.getResponseBody(), sfOAuthToken); + + return decryptedAccessToken; + } + + /** + * Update the access token in the database and return the decrypted access token. + * @param responseBody + * @param sfOAuthToken + * @return String + */ + private String updateAccessTokenInDatabase(String responseBody, SalesforceOauthToken sfOAuthToken) { + JsonNode rootNode = util.getJsonNode(responseBody); + String decryptedAccessToken = rootNode.get("access_token").asText(); + + String encryptedAccessToken = awsKms.encryptToken(decryptedAccessToken); + + sfOAuthToken.setAccessToken(encryptedAccessToken); + salesforceOauthTokenRepository.saveSalesforceOauthToken(sfOAuthToken); + + return decryptedAccessToken; + } + } diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java index 6de69b2b..6797965f 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java @@ -11,93 +11,95 @@ */ @Component public class SalesforceQueryBuilder { - - /** - * Get the list of accounts for a given searchTerm - * - * @param searchTerm - * - * @return String - */ - public String getAccountsQuery(String searchTerm) { - searchTerm = Util.escapeSpecialChars(searchTerm); - - String query = ""; - if (searchTerm == "") { - query = "SELECT Id, Name FROM Account ORDER BY LastModifiedDate DESC LIMIT 20"; - } else { - query = "SELECT Id, Name FROM Account WHERE Name LIKE '%"+searchTerm+"%' ORDER BY LastModifiedDate DESC LIMIT 20"; - } - - return Util.urlEncoder(query); - } - - /** - * Get the list of tasks for a given account - * - * @param accountId - * - * @return String - */ - public String getAccountTasksQuery(String accountId) { - accountId = Util.escapeSpecialChars(accountId); - - return Util.urlEncoder("SELECT Id, Description, ActivityDate, CreatedBy.Name, Owner.Name, LastModifiedDate FROM Task WHERE WhatId='" - + accountId + "' ORDER BY LastModifiedDate DESC LIMIT 5"); - } - - /** - * Get the list of notes for a given account - * - * @param accountId - * @return String - */ - public String getContentDocumentIdUrl(String accountId) { - accountId = Util.escapeSpecialChars(accountId); - - return Util.urlEncoder("SELECT ContentDocumentId FROM ContentDocumentLink WHERE LinkedEntityId = '" - + accountId + "'"); - } - - /** - * Get the list of notes for a given account - * - * @param documentIds - * @return String - */ - public String getNoteListIdUrl(List documentIds) { - StringBuilder queryBuilder = new StringBuilder( - "SELECT Id, Title, TextPreview, CreatedBy.Name, LastModifiedDate FROM ContentNote WHERE Id IN ("); - - for (int i = 0; i < documentIds.size(); i++) { - if (i > 0) { - queryBuilder.append(", "); - } - - String documentId = Util.escapeSpecialChars(documentIds.get(i)); - queryBuilder.append("'").append(documentId).append("'"); - } - queryBuilder.append(") ORDER BY LastModifiedDate DESC LIMIT 5"); - - return Util.urlEncoder(queryBuilder.toString()); - } - - public String getNoteDetailsUrl(String noteId){ - noteId = Util.escapeSpecialChars(noteId); - - return Util.urlEncoder("SELECT Id, Title, TextPreview, CreatedBy.Name, LastModifiedDate FROM ContentNote WHERE Id = '" + noteId + "'"); - } - - public String getCrmOrganizationUsersQuery(String searchTerm) { - searchTerm = Util.escapeSpecialChars(searchTerm); - String query = ""; - - if (searchTerm == "") { - query = "SELECT Id, Name FROM User ORDER BY LastModifiedDate DESC LIMIT 20"; - } else { - query = "SELECT Id, Name FROM User WHERE Name LIKE '%"+searchTerm+"%' ORDER BY LastModifiedDate DESC LIMIT 20"; - } - - return Util.urlEncoder(query); - } + + /** + * Get the list of accounts for a given searchTerm + * @param searchTerm + * @return String + */ + public String getAccountsQuery(String searchTerm) { + searchTerm = Util.escapeSpecialChars(searchTerm); + + String query = ""; + if (searchTerm == "") { + query = "SELECT Id, Name FROM Account ORDER BY LastModifiedDate DESC LIMIT 20"; + } + else { + query = "SELECT Id, Name FROM Account WHERE Name LIKE '%" + searchTerm + + "%' ORDER BY LastModifiedDate DESC LIMIT 20"; + } + + return Util.urlEncoder(query); + } + + /** + * Get the list of tasks for a given account + * @param accountId + * @return String + */ + public String getAccountTasksQuery(String accountId) { + accountId = Util.escapeSpecialChars(accountId); + + return Util.urlEncoder( + "SELECT Id, Description, ActivityDate, CreatedBy.Name, Owner.Name, LastModifiedDate FROM Task WHERE WhatId='" + + accountId + "' ORDER BY LastModifiedDate DESC LIMIT 5"); + } + + /** + * Get the list of notes for a given account + * @param accountId + * @return String + */ + public String getContentDocumentIdUrl(String accountId) { + accountId = Util.escapeSpecialChars(accountId); + + return Util + .urlEncoder("SELECT ContentDocumentId FROM ContentDocumentLink WHERE LinkedEntityId = '" + accountId + "'"); + } + + /** + * Get the list of notes for a given account + * @param documentIds + * @return String + */ + public String getNoteListIdUrl(List documentIds) { + StringBuilder queryBuilder = new StringBuilder( + "SELECT Id, Title, TextPreview, CreatedBy.Name, LastModifiedDate FROM ContentNote WHERE Id IN ("); + + for (int i = 0; i < documentIds.size(); i++) { + if (i > 0) { + queryBuilder.append(", "); + } + + String documentId = Util.escapeSpecialChars(documentIds.get(i)); + queryBuilder.append("'").append(documentId).append("'"); + } + queryBuilder.append(") ORDER BY LastModifiedDate DESC LIMIT 5"); + + return Util.urlEncoder(queryBuilder.toString()); + } + + public String getNoteDetailsUrl(String noteId) { + noteId = Util.escapeSpecialChars(noteId); + + return Util + .urlEncoder("SELECT Id, Title, TextPreview, CreatedBy.Name, LastModifiedDate FROM ContentNote WHERE Id = '" + + noteId + "'"); + } + + public String getCrmOrganizationUsersQuery(String searchTerm) { + searchTerm = Util.escapeSpecialChars(searchTerm); + String query = ""; + + if (searchTerm == "") { + query = "SELECT Id, Name FROM User ORDER BY LastModifiedDate DESC LIMIT 20"; + } + else { + query = "SELECT Id, Name FROM User WHERE Name LIKE '%" + searchTerm + + "%' ORDER BY LastModifiedDate DESC LIMIT 20"; + } + + return Util.urlEncoder(query); + } + } diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceRequest.java b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceRequest.java index 9f999e5d..bc1039a0 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceRequest.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceRequest.java @@ -15,46 +15,39 @@ @Component public class SalesforceRequest { - @Autowired - private SalesforceOAuthToken getAccessTokenService; - - @Autowired - private SalesforceOauthTokenRepository salesforceOauthTokenRepository; - - /** - * Make a request to the Salesforce API. - * - * @param salesforceUserId - * @param request - * - * @return T - */ - public T makeRequest(String salesforceUserId, SalesforceRequestInterface request) { - SalesforceOauthToken sfOAuthToken = salesforceOauthTokenRepository - .getSalesforceOauthTokenByExternalUserId(salesforceUserId); - - String decryptedAccessToken = getAccessTokenService.fetchAccessToken(sfOAuthToken); - - try { - return request.execute(decryptedAccessToken, sfOAuthToken.getInstanceUrl()); - } catch (WebClientResponseException e) { - if(e.getStatusCode().value() == 401) { - try { - decryptedAccessToken = getAccessTokenService.updateAndGetRefreshedAccessToken(sfOAuthToken); - return request.execute(decryptedAccessToken, sfOAuthToken.getInstanceUrl()); - } catch (Exception e1) { - throw new CustomException( - new ErrorObject( - "l_s_h_sr_mr_1", - "something_went_wrong", - e.getMessage())); - } - } - throw new CustomException( - new ErrorObject( - "l_s_h_sr_mr_2", - "something_went_wrong", - e.getMessage())); - } - } + @Autowired + private SalesforceOAuthToken getAccessTokenService; + + @Autowired + private SalesforceOauthTokenRepository salesforceOauthTokenRepository; + + /** + * Make a request to the Salesforce API. + * @param salesforceUserId + * @param request + * @return T + */ + public T makeRequest(String salesforceUserId, SalesforceRequestInterface request) { + SalesforceOauthToken sfOAuthToken = salesforceOauthTokenRepository + .getSalesforceOauthTokenByExternalUserId(salesforceUserId); + + String decryptedAccessToken = getAccessTokenService.fetchAccessToken(sfOAuthToken); + + try { + return request.execute(decryptedAccessToken, sfOAuthToken.getInstanceUrl()); + } + catch (WebClientResponseException e) { + if (e.getStatusCode().value() == 401) { + try { + decryptedAccessToken = getAccessTokenService.updateAndGetRefreshedAccessToken(sfOAuthToken); + return request.execute(decryptedAccessToken, sfOAuthToken.getInstanceUrl()); + } + catch (Exception e1) { + throw new CustomException(new ErrorObject("l_s_h_sr_mr_1", "something_went_wrong", e.getMessage())); + } + } + throw new CustomException(new ErrorObject("l_s_h_sr_mr_2", "something_went_wrong", e.getMessage())); + } + } + } diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceRequestInterface.java b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceRequestInterface.java index ab9352be..bca6d324 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceRequestInterface.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceRequestInterface.java @@ -5,5 +5,7 @@ */ @FunctionalInterface public interface SalesforceRequestInterface { - T execute(String token, String instanceUrl); + + T execute(String token, String instanceUrl); + } diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceGetIdentity.java b/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceGetIdentity.java index d7f7d088..d05b06d7 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceGetIdentity.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceGetIdentity.java @@ -16,29 +16,24 @@ public class SalesforceGetIdentity { - @Autowired - private SalesforceConstants salesforceConstants; - - public HttpResponse getUserIdentity(String instanceUrl, String accessToken) { - String salesforceIdentityEndpoint = instanceUrl + salesforceConstants.identityUrl(); - - Map headers = new HashMap<>(); - headers.put("Authorization", "Bearer " + accessToken); - - HttpResponse response = null; - try { - response = HttpClient.makeGetRequest( - salesforceIdentityEndpoint, - headers, - 10000); - } catch (Exception e) { - throw new CustomException( - new ErrorObject( - "l_s_w_sgi_gui_1", - "bad_request", - e.getMessage())); - } - - return response; - } + @Autowired + private SalesforceConstants salesforceConstants; + + public HttpResponse getUserIdentity(String instanceUrl, String accessToken) { + String salesforceIdentityEndpoint = instanceUrl + salesforceConstants.identityUrl(); + + Map headers = new HashMap<>(); + headers.put("Authorization", "Bearer " + accessToken); + + HttpResponse response = null; + try { + response = HttpClient.makeGetRequest(salesforceIdentityEndpoint, headers, 10000); + } + catch (Exception e) { + throw new CustomException(new ErrorObject("l_s_w_sgi_gui_1", "bad_request", e.getMessage())); + } + + return response; + } + } diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceGetNoteContent.java b/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceGetNoteContent.java index 79d29ec5..d1a89884 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceGetNoteContent.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceGetNoteContent.java @@ -16,38 +16,35 @@ */ @Component public class SalesforceGetNoteContent { - @Autowired - private SalesforceConstants salesforceConstants; - - @Autowired - private SalesforceRequest salesforceOauthRequest; - - /** - * Get the content of a note - * - * @param noteId - * @param salesforceUserId - * - * @return HttpResponse - */ - public HttpClient.HttpResponse getNoteContent(String noteId, String salesforceUserId){ - Integer timeoutMillis = salesforceConstants.timeoutMillis(); - - SalesforceRequestInterface request = (token, instanceUrl) -> { - String noteContentQuery = salesforceConstants.salesforceNotesContentUrl(instanceUrl, noteId); - - Map headers = new HashMap<>(); - headers.put("Authorization", "Bearer " + token); - - HttpClient.HttpResponse response = HttpClient.makeGetRequest( - noteContentQuery, - headers, - timeoutMillis); - - return response; - }; - - HttpClient.HttpResponse response = salesforceOauthRequest.makeRequest(salesforceUserId, request); - return response; - } + + @Autowired + private SalesforceConstants salesforceConstants; + + @Autowired + private SalesforceRequest salesforceOauthRequest; + + /** + * Get the content of a note + * @param noteId + * @param salesforceUserId + * @return HttpResponse + */ + public HttpClient.HttpResponse getNoteContent(String noteId, String salesforceUserId) { + Integer timeoutMillis = salesforceConstants.timeoutMillis(); + + SalesforceRequestInterface request = (token, instanceUrl) -> { + String noteContentQuery = salesforceConstants.salesforceNotesContentUrl(instanceUrl, noteId); + + Map headers = new HashMap<>(); + headers.put("Authorization", "Bearer " + token); + + HttpClient.HttpResponse response = HttpClient.makeGetRequest(noteContentQuery, headers, timeoutMillis); + + return response; + }; + + HttpClient.HttpResponse response = salesforceOauthRequest.makeRequest(salesforceUserId, request); + return response; + } + } diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceGetRefreshedAccessToken.java b/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceGetRefreshedAccessToken.java index 62caf9f6..fd3f94bc 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceGetRefreshedAccessToken.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceGetRefreshedAccessToken.java @@ -16,30 +16,27 @@ @Component public class SalesforceGetRefreshedAccessToken { - @Autowired - SalesforceConstants salesforceConstants; - - /** - * Get tokens from Salesforce - * - * @param decryptedRefreshToken - * - * @return HttpResponse - */ - public HttpClient.HttpResponse getRefreshedAccessToken(String decryptedRefreshToken) { - String url = salesforceConstants.oauth2Url(); - - String requestBody = "grant_type=" + salesforceConstants.refreshTokenGrantType() + "&client_id=" - + CoreConstants.salesforceClientId() - + "&client_secret=" - + CoreConstants.salesforceClientSecret() + - "&refresh_token=" + decryptedRefreshToken; - - Map headers = new HashMap<>(); - headers.put("content-type", "application/x-www-form-urlencoded"); - - HttpClient.HttpResponse response = HttpClient.makePostRequest(url, headers, requestBody, 5000); - - return response; - } + @Autowired + SalesforceConstants salesforceConstants; + + /** + * Get tokens from Salesforce + * @param decryptedRefreshToken + * @return HttpResponse + */ + public HttpClient.HttpResponse getRefreshedAccessToken(String decryptedRefreshToken) { + String url = salesforceConstants.oauth2Url(); + + String requestBody = "grant_type=" + salesforceConstants.refreshTokenGrantType() + "&client_id=" + + CoreConstants.salesforceClientId() + "&client_secret=" + CoreConstants.salesforceClientSecret() + + "&refresh_token=" + decryptedRefreshToken; + + Map headers = new HashMap<>(); + headers.put("content-type", "application/x-www-form-urlencoded"); + + HttpClient.HttpResponse response = HttpClient.makePostRequest(url, headers, requestBody, 5000); + + return response; + } + } diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceGetTokens.java b/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceGetTokens.java index 22e79738..a9a036d3 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceGetTokens.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/wrappers/SalesforceGetTokens.java @@ -21,46 +21,37 @@ @Component public class SalesforceGetTokens { - @Autowired - private SalesforceConstants salesforceConstants; + @Autowired + private SalesforceConstants salesforceConstants; + + /** + * Get tokens from Salesforce + * @param code + * @param redirectUri + * @return HttpResponse + */ + public HttpResponse getTokens(String code, String redirectUri) { + + String salesforceOAuthEndpoint = salesforceConstants.oauth2Url(); + + String requestBody = "grant_type=" + salesforceConstants.authorizationCodeGrantType() + "&client_id=" + + CoreConstants.salesforceClientId() + "&client_secret=" + CoreConstants.salesforceClientSecret() + + "&code=" + code + "&redirect_uri=" + redirectUri; + + Map headers = new HashMap<>(); + headers.put("content-type", "application/x-www-form-urlencoded"); + + HttpResponse response = null; + try { + response = HttpClient.makePostRequest(salesforceOAuthEndpoint, 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)); + } + return response; + } - /** - * Get tokens from Salesforce - * - * @param code - * @param redirectUri - * - * @return HttpResponse - */ - public HttpResponse getTokens(String code, String redirectUri) { - - String salesforceOAuthEndpoint = salesforceConstants.oauth2Url(); - - String requestBody = "grant_type=" + salesforceConstants.authorizationCodeGrantType() + "&client_id=" - + CoreConstants.salesforceClientId() - + "&client_secret=" - + CoreConstants.salesforceClientSecret() + - "&code=" + code + "&redirect_uri=" + redirectUri; - - Map headers = new HashMap<>(); - headers.put("content-type", "application/x-www-form-urlencoded"); - - HttpResponse response = null; - try { - response = HttpClient.makePostRequest( - salesforceOAuthEndpoint, - 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)); - } - return response; - } } diff --git a/src/main/java/com/salessparrow/api/lib/validators/DateFormatValidator.java b/src/main/java/com/salessparrow/api/lib/validators/DateFormatValidator.java index 9f2a9d3b..0e42b15d 100644 --- a/src/main/java/com/salessparrow/api/lib/validators/DateFormatValidator.java +++ b/src/main/java/com/salessparrow/api/lib/validators/DateFormatValidator.java @@ -10,34 +10,34 @@ /** * Validate date format with regular expression - * + * */ public class DateFormatValidator implements ConstraintValidator { - private static final String DATE_FORMAT = "yyyy-MM-dd"; - - /** - * Validate date format with regular expression - * - * @param date date address for validation - * - * @return true valid date format, false invalid date format - */ - @Override - public boolean isValid(String value, ConstraintValidatorContext context) { - if(value == null) { - return false; - } - - SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT); - sdf.setLenient(false); - - try { - Date parsedDate = sdf.parse(value); - String dateString = sdf.format(parsedDate); - return dateString.equals(value.toString()); - } catch (Exception ex) { - return false; - } - } + private static final String DATE_FORMAT = "yyyy-MM-dd"; + + /** + * Validate date format with regular expression + * @param date date address for validation + * @return true valid date format, false invalid date format + */ + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + if (value == null) { + return false; + } + + SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT); + sdf.setLenient(false); + + try { + Date parsedDate = sdf.parse(value); + String dateString = sdf.format(parsedDate); + return dateString.equals(value.toString()); + } + catch (Exception ex) { + return false; + } + } + } \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/lib/validators/RedirectUriValidator.java b/src/main/java/com/salessparrow/api/lib/validators/RedirectUriValidator.java index 7e8fd95e..cbd2dc2e 100644 --- a/src/main/java/com/salessparrow/api/lib/validators/RedirectUriValidator.java +++ b/src/main/java/com/salessparrow/api/lib/validators/RedirectUriValidator.java @@ -13,11 +13,11 @@ public class RedirectUriValidator implements ConstraintValidator { - private List ALLOWED_URIS = new ArrayList<>( - Arrays.asList(CoreConstants.getWhitelistedRedirectUris())); + private List ALLOWED_URIS = new ArrayList<>(Arrays.asList(CoreConstants.getWhitelistedRedirectUris())); + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + return value != null && ALLOWED_URIS.contains(value); + } - @Override - public boolean isValid(String value, ConstraintValidatorContext context) { - return value != null && ALLOWED_URIS.contains(value); - } } \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/repositories/SalesforceOauthTokenRepository.java b/src/main/java/com/salessparrow/api/repositories/SalesforceOauthTokenRepository.java index a04a1001..f2a12e2a 100644 --- a/src/main/java/com/salessparrow/api/repositories/SalesforceOauthTokenRepository.java +++ b/src/main/java/com/salessparrow/api/repositories/SalesforceOauthTokenRepository.java @@ -16,51 +16,42 @@ @Repository public class SalesforceOauthTokenRepository { - private final DynamoDBMapper dynamoDBMapper; + private final DynamoDBMapper dynamoDBMapper; - public SalesforceOauthTokenRepository(DynamoDBMapper dynamoDBMapper) { - this.dynamoDBMapper = dynamoDBMapper; - } + public SalesforceOauthTokenRepository(DynamoDBMapper dynamoDBMapper) { + this.dynamoDBMapper = dynamoDBMapper; + } - /** - * Saves a SalesforceOauthToken to the salesforce_oauth_tokens table. - * - * @param salesforceOauthToken - * - * @return SalesforceOauthToken - */ - @CachePut(value = CacheConstants.SS_SALESFORCE_OAUTH_TOKEN_CACHE, key = "#salesforceOauthToken.externalUserId") - public SalesforceOauthToken saveSalesforceOauthToken(SalesforceOauthToken salesforceOauthToken) { - try { - dynamoDBMapper.save(salesforceOauthToken); - } catch (Exception e) { - throw new CustomException(new ErrorObject( - "r_sotr_ssot_1", - "something_went_wrong", - e.getMessage())); - } - return salesforceOauthToken; - } + /** + * Saves a SalesforceOauthToken to the salesforce_oauth_tokens table. + * @param salesforceOauthToken + * @return SalesforceOauthToken + */ + @CachePut(value = CacheConstants.SS_SALESFORCE_OAUTH_TOKEN_CACHE, key = "#salesforceOauthToken.externalUserId") + public SalesforceOauthToken saveSalesforceOauthToken(SalesforceOauthToken salesforceOauthToken) { + try { + dynamoDBMapper.save(salesforceOauthToken); + } + catch (Exception e) { + throw new CustomException(new ErrorObject("r_sotr_ssot_1", "something_went_wrong", e.getMessage())); + } + return salesforceOauthToken; + } + + /** + * Retrieves a SalesforceOauthToken from the salesforce_oauth_tokens table based on + * the provided externalUserId. + * @param externalUserId + * @return SalesforceOauthToken + */ + @Cacheable(value = CacheConstants.SS_SALESFORCE_OAUTH_TOKEN_CACHE, key = "#externalUserId") + public SalesforceOauthToken getSalesforceOauthTokenByExternalUserId(String externalUserId) { + try { + return dynamoDBMapper.load(SalesforceOauthToken.class, externalUserId); + } + catch (Exception e) { + throw new CustomException(new ErrorObject("r_sotr_gsotbsfui_1", "something_went_wrong", e.getMessage())); + } + } - /** - * Retrieves a SalesforceOauthToken from the salesforce_oauth_tokens table based - * on the - * provided externalUserId. - * - * @param externalUserId - * - * @return SalesforceOauthToken - */ - @Cacheable(value = CacheConstants.SS_SALESFORCE_OAUTH_TOKEN_CACHE, key = "#externalUserId") - public SalesforceOauthToken getSalesforceOauthTokenByExternalUserId(String externalUserId) { - try { - return dynamoDBMapper.load(SalesforceOauthToken.class, externalUserId); - } catch (Exception e) { - throw new CustomException( - new ErrorObject( - "r_sotr_gsotbsfui_1", - "something_went_wrong", - e.getMessage())); - } - } } diff --git a/src/main/java/com/salessparrow/api/repositories/SalesforceOrganizationRepository.java b/src/main/java/com/salessparrow/api/repositories/SalesforceOrganizationRepository.java index 24bb0561..33496b80 100644 --- a/src/main/java/com/salessparrow/api/repositories/SalesforceOrganizationRepository.java +++ b/src/main/java/com/salessparrow/api/repositories/SalesforceOrganizationRepository.java @@ -13,48 +13,40 @@ @Repository public class SalesforceOrganizationRepository { - private final DynamoDBMapper dynamoDBMapper; - - public SalesforceOrganizationRepository(DynamoDBMapper dynamoDBMapper) { - this.dynamoDBMapper = dynamoDBMapper; - } - - /** - * Saves a SalesforceOrganization to the salesforce_organizations table. - * - * @param sfo - * - * @return SalesforceOrganization - */ - public SalesforceOrganization saveSalesforceOrganization(SalesforceOrganization sfo) { - try { - dynamoDBMapper.save(sfo); - } catch (Exception e) { - throw new CustomException(new ErrorObject( - "r_sor_sso_1", - "something_went_wrong", - e.getMessage())); - } - return sfo; - } - - /** - * Gets a SalesforceOrganization from the salesforce_organizations table by - * externalOrganizationId. - * - * @param externalOrganizationId - * - * @return SalesforceOrganization - */ - public SalesforceOrganization getSalesforceOrganizationByExternalOrganizationId(String externalOrganizationId) { - try { - return dynamoDBMapper.load(SalesforceOrganization.class, externalOrganizationId); - } catch (Exception e) { - throw new CustomException( - new ErrorObject( - "r_sor_gsobeoi_1", - "something_went_wrong", - e.getMessage())); - } - } + private final DynamoDBMapper dynamoDBMapper; + + public SalesforceOrganizationRepository(DynamoDBMapper dynamoDBMapper) { + this.dynamoDBMapper = dynamoDBMapper; + } + + /** + * Saves a SalesforceOrganization to the salesforce_organizations table. + * @param sfo + * @return SalesforceOrganization + */ + public SalesforceOrganization saveSalesforceOrganization(SalesforceOrganization sfo) { + try { + dynamoDBMapper.save(sfo); + } + catch (Exception e) { + throw new CustomException(new ErrorObject("r_sor_sso_1", "something_went_wrong", e.getMessage())); + } + return sfo; + } + + /** + * Gets a SalesforceOrganization from the salesforce_organizations table by + * externalOrganizationId. + * @param externalOrganizationId + * @return SalesforceOrganization + */ + public SalesforceOrganization getSalesforceOrganizationByExternalOrganizationId(String externalOrganizationId) { + try { + return dynamoDBMapper.load(SalesforceOrganization.class, externalOrganizationId); + } + catch (Exception e) { + throw new CustomException(new ErrorObject("r_sor_gsobeoi_1", "something_went_wrong", e.getMessage())); + } + } + } diff --git a/src/main/java/com/salessparrow/api/repositories/SalesforceUserRepository.java b/src/main/java/com/salessparrow/api/repositories/SalesforceUserRepository.java index f7e1d878..5cd5d55d 100644 --- a/src/main/java/com/salessparrow/api/repositories/SalesforceUserRepository.java +++ b/src/main/java/com/salessparrow/api/repositories/SalesforceUserRepository.java @@ -16,50 +16,42 @@ @Repository public class SalesforceUserRepository { - private final DynamoDBMapper dynamoDBMapper; + private final DynamoDBMapper dynamoDBMapper; - public SalesforceUserRepository(DynamoDBMapper dynamoDBMapper) { - this.dynamoDBMapper = dynamoDBMapper; - } - /** - * Saves a SalesforceUser to the salesforce_users table. - * - * @param salesforceUser - * - * @return SalesforceUser - */ - @CachePut(value=CacheConstants.SS_SALESFORCE_USER_CACHE, key="#salesforceUser.externalUserId") - public SalesforceUser saveSalesforceUser(SalesforceUser salesforceUser) { - try { - dynamoDBMapper.save(salesforceUser); - } catch (Exception e) { - throw new CustomException( - new ErrorObject( - "r_sur_ssu_1", - "something_went_wrong", - e.getMessage())); - } - return salesforceUser; - } + public SalesforceUserRepository(DynamoDBMapper dynamoDBMapper) { + this.dynamoDBMapper = dynamoDBMapper; + } + + /** + * Saves a SalesforceUser to the salesforce_users table. + * @param salesforceUser + * @return SalesforceUser + */ + @CachePut(value = CacheConstants.SS_SALESFORCE_USER_CACHE, key = "#salesforceUser.externalUserId") + public SalesforceUser saveSalesforceUser(SalesforceUser salesforceUser) { + try { + dynamoDBMapper.save(salesforceUser); + } + catch (Exception e) { + throw new CustomException(new ErrorObject("r_sur_ssu_1", "something_went_wrong", e.getMessage())); + } + return salesforceUser; + } + + /** + * Retrieves a SalesforceUser from the salesforce_users table based on the provided + * id. + * @param id + * @return SalesforceUser + */ + @Cacheable(value = CacheConstants.SS_SALESFORCE_USER_CACHE, key = "#externalUserId") + public SalesforceUser getSalesforceUserByExternalUserId(String externalUserId) { + try { + return dynamoDBMapper.load(SalesforceUser.class, externalUserId); + } + catch (Exception e) { + throw new CustomException(new ErrorObject("r_sur_gsubi_1", "something_went_wrong", e.getMessage())); + } + } - /** - * Retrieves a SalesforceUser from the salesforce_users table based on the - * provided id. - * - * @param id - * - * @return SalesforceUser - */ - @Cacheable(value=CacheConstants.SS_SALESFORCE_USER_CACHE, key="#externalUserId") - public SalesforceUser getSalesforceUserByExternalUserId(String externalUserId) { - try { - return dynamoDBMapper.load(SalesforceUser.class, externalUserId); - } catch (Exception e) { - throw new CustomException( - new ErrorObject( - "r_sur_gsubi_1", - "something_went_wrong", - e.getMessage())); - } - } } diff --git a/src/main/java/com/salessparrow/api/services/accountNotes/CreateAccountNoteService.java b/src/main/java/com/salessparrow/api/services/accountNotes/CreateAccountNoteService.java index 0105fe9c..c7ab77aa 100644 --- a/src/main/java/com/salessparrow/api/services/accountNotes/CreateAccountNoteService.java +++ b/src/main/java/com/salessparrow/api/services/accountNotes/CreateAccountNoteService.java @@ -15,21 +15,21 @@ */ @Service public class CreateAccountNoteService { - - @Autowired - private CreateNoteFactory createNoteFactory; - - /** - * Create a note for a specific account. - * - * @param request - * @param accountId - * @return CreateNoteFormatterDto - */ - public CreateNoteFormatterDto createNote(HttpServletRequest request, String accountId, NoteDto note) { - - SalesforceUser currentUser = (SalesforceUser) request.getAttribute("current_user"); - - return createNoteFactory.createNote(currentUser, accountId, note); - } + + @Autowired + private CreateNoteFactory createNoteFactory; + + /** + * Create a note for a specific account. + * @param request + * @param accountId + * @return CreateNoteFormatterDto + */ + public CreateNoteFormatterDto createNote(HttpServletRequest request, String accountId, NoteDto note) { + + SalesforceUser currentUser = (SalesforceUser) request.getAttribute("current_user"); + + return createNoteFactory.createNote(currentUser, accountId, note); + } + } diff --git a/src/main/java/com/salessparrow/api/services/accountNotes/DeleteAccountNoteService.java b/src/main/java/com/salessparrow/api/services/accountNotes/DeleteAccountNoteService.java index 3ed5ea2f..2c5843b9 100644 --- a/src/main/java/com/salessparrow/api/services/accountNotes/DeleteAccountNoteService.java +++ b/src/main/java/com/salessparrow/api/services/accountNotes/DeleteAccountNoteService.java @@ -10,28 +10,29 @@ import jakarta.servlet.http.HttpServletRequest; /** - * DeleteAccountNoteService is a service class for the DeleteAccountNote action for the CRM. + * DeleteAccountNoteService is a service class for the DeleteAccountNote action for the + * CRM. */ @Service public class DeleteAccountNoteService { - private Logger logger = org.slf4j.LoggerFactory.getLogger(DeleteAccountNoteService.class); - - @Autowired - private DeleteAccountNoteFactory deleteAccountNoteFactory; - - /** - * Delete note for the given note id - * - * @param accountId - * @param noteId - * - * @return void - */ - public void deleteAccountNote(HttpServletRequest request, String accountId, String noteId) { - logger.info("Delete Account Note Service called"); - - User currentUser = (User) request.getAttribute("current_user"); - - deleteAccountNoteFactory.deleteAccountNote(currentUser, noteId); - } + + private Logger logger = org.slf4j.LoggerFactory.getLogger(DeleteAccountNoteService.class); + + @Autowired + private DeleteAccountNoteFactory deleteAccountNoteFactory; + + /** + * Delete note for the given note id + * @param accountId + * @param noteId + * @return void + */ + public void deleteAccountNote(HttpServletRequest request, String accountId, String noteId) { + logger.info("Delete Account Note Service called"); + + User currentUser = (User) request.getAttribute("current_user"); + + deleteAccountNoteFactory.deleteAccountNote(currentUser, noteId); + } + } diff --git a/src/main/java/com/salessparrow/api/services/accountNotes/GetAccountNoteDetailsService.java b/src/main/java/com/salessparrow/api/services/accountNotes/GetAccountNoteDetailsService.java index 342328d7..90c2ddb6 100644 --- a/src/main/java/com/salessparrow/api/services/accountNotes/GetAccountNoteDetailsService.java +++ b/src/main/java/com/salessparrow/api/services/accountNotes/GetAccountNoteDetailsService.java @@ -14,20 +14,20 @@ */ @Service public class GetAccountNoteDetailsService { - @Autowired - private GetAccountNoteDetailsFactory getNoteDetailsFactory; - - /** - * Get the details of a note - * - * @param accountId - * @param noteId - * - * @return GetNoteDetailsFormatterDto - */ - public GetNoteDetailsFormatterDto getNoteDetails(HttpServletRequest request, String noteId) { - User currentUser = (User) request.getAttribute("current_user"); - - return getNoteDetailsFactory.getNoteDetails(currentUser, noteId); - } + + @Autowired + private GetAccountNoteDetailsFactory getNoteDetailsFactory; + + /** + * Get the details of a note + * @param accountId + * @param noteId + * @return GetNoteDetailsFormatterDto + */ + public GetNoteDetailsFormatterDto getNoteDetails(HttpServletRequest request, String noteId) { + User currentUser = (User) request.getAttribute("current_user"); + + return getNoteDetailsFactory.getNoteDetails(currentUser, noteId); + } + } diff --git a/src/main/java/com/salessparrow/api/services/accountNotes/GetAccountNotesListService.java b/src/main/java/com/salessparrow/api/services/accountNotes/GetAccountNotesListService.java index 16da0d23..3b6458ae 100644 --- a/src/main/java/com/salessparrow/api/services/accountNotes/GetAccountNotesListService.java +++ b/src/main/java/com/salessparrow/api/services/accountNotes/GetAccountNotesListService.java @@ -14,22 +14,21 @@ */ @Service public class GetAccountNotesListService { - @Autowired - private GetAccountNoteListFactory getNotesListFactory; - /** - * Get the list of notes for a given account - * @param accountId - * @param request - * - * @return GetNotesListFormatterDto - **/ - public GetNotesListFormatterDto getNotesList(HttpServletRequest request, String accountId) { + @Autowired + private GetAccountNoteListFactory getNotesListFactory; - User currentUser = (User) request.getAttribute("current_user"); + /** + * Get the list of notes for a given account + * @param accountId + * @param request + * @return GetNotesListFormatterDto + **/ + public GetNotesListFormatterDto getNotesList(HttpServletRequest request, String accountId) { - return getNotesListFactory.getNotesList(currentUser, accountId); - } + User currentUser = (User) request.getAttribute("current_user"); + + return getNotesListFactory.getNotesList(currentUser, accountId); + } - } diff --git a/src/main/java/com/salessparrow/api/services/accountTask/CreateTaskService.java b/src/main/java/com/salessparrow/api/services/accountTask/CreateTaskService.java index eb86bdf7..d30cb0ab 100644 --- a/src/main/java/com/salessparrow/api/services/accountTask/CreateTaskService.java +++ b/src/main/java/com/salessparrow/api/services/accountTask/CreateTaskService.java @@ -17,23 +17,24 @@ */ @Service public class CreateTaskService { - Logger logger = LoggerFactory.getLogger(CreateTaskService.class); - - @Autowired - private CreateAccountTaskFactory createAccountTaskFactory; - - /** - * Create a task in CRM - * - * @param request HttpServletRequest object - * @param accountId CRM account id - * @param task CreateTaskDto object - * - * @return CreateTaskFormatterDto object - */ - public CreateTaskFormatterDto createAccountTask(HttpServletRequest request, String accountId, CreateAccountTaskDto task) { - logger.info("inside createTask Service"); - User currentUser = (User) request.getAttribute("current_user"); - return createAccountTaskFactory.createAccountTask(currentUser, accountId, task); - } + + Logger logger = LoggerFactory.getLogger(CreateTaskService.class); + + @Autowired + private CreateAccountTaskFactory createAccountTaskFactory; + + /** + * Create a task in CRM + * @param request HttpServletRequest object + * @param accountId CRM account id + * @param task CreateTaskDto object + * @return CreateTaskFormatterDto object + */ + public CreateTaskFormatterDto createAccountTask(HttpServletRequest request, String accountId, + CreateAccountTaskDto task) { + logger.info("inside createTask Service"); + User currentUser = (User) request.getAttribute("current_user"); + return createAccountTaskFactory.createAccountTask(currentUser, accountId, task); + } + } diff --git a/src/main/java/com/salessparrow/api/services/accountTask/DeleteTaskService.java b/src/main/java/com/salessparrow/api/services/accountTask/DeleteTaskService.java index 73506f4f..4cd7c5f7 100644 --- a/src/main/java/com/salessparrow/api/services/accountTask/DeleteTaskService.java +++ b/src/main/java/com/salessparrow/api/services/accountTask/DeleteTaskService.java @@ -15,26 +15,25 @@ */ @Service public class DeleteTaskService { - - Logger logger = LoggerFactory.getLogger(DeleteTaskService.class); - - @Autowired - private DeleteAccountTaskFactory deleteAccountTaskFactory; - - /** - * Deletes a task in an account. - * - * @param request - * @param accountId - * @param taskId - * - * @return void - */ - public void deleteAccountTask(HttpServletRequest request, String accountId, String taskId) { - logger.info("Delete task in account service called"); - - User currentUser = (User) request.getAttribute("current_user"); - - deleteAccountTaskFactory.deleteAccountTask(currentUser, accountId, taskId); - } + + Logger logger = LoggerFactory.getLogger(DeleteTaskService.class); + + @Autowired + private DeleteAccountTaskFactory deleteAccountTaskFactory; + + /** + * Deletes a task in an account. + * @param request + * @param accountId + * @param taskId + * @return void + */ + public void deleteAccountTask(HttpServletRequest request, String accountId, String taskId) { + logger.info("Delete task in account service called"); + + User currentUser = (User) request.getAttribute("current_user"); + + deleteAccountTaskFactory.deleteAccountTask(currentUser, accountId, taskId); + } + } diff --git a/src/main/java/com/salessparrow/api/services/accountTask/GetAccountTasksListService.java b/src/main/java/com/salessparrow/api/services/accountTask/GetAccountTasksListService.java index cc4b2254..162f5496 100644 --- a/src/main/java/com/salessparrow/api/services/accountTask/GetAccountTasksListService.java +++ b/src/main/java/com/salessparrow/api/services/accountTask/GetAccountTasksListService.java @@ -12,27 +12,28 @@ import jakarta.servlet.http.HttpServletRequest; /** - * GetAccountTasksListService class is responsible for getting list of account tasks in CRM + * GetAccountTasksListService class is responsible for getting list of account tasks in + * CRM */ @Service public class GetAccountTasksListService { - Logger logger = LoggerFactory.getLogger(GetAccountTasksListService.class); - - @Autowired - private GetAccountTasksListFactory getAccountTasksListFactory; - - /** - * Get list of account tasks from CRM - * - * @param request HttpServletRequest object - * @param accountId CRM account id - * - * @return GetTasksListFormatterDto object - */ - public GetTasksListFormatterDto getAccountTasksList(HttpServletRequest request, String accountId) { - logger.info("getAccountTasksList Service called"); - - User currentUser = (User) request.getAttribute("current_user"); - return getAccountTasksListFactory.getAccountTasksList(currentUser, accountId); - } + + Logger logger = LoggerFactory.getLogger(GetAccountTasksListService.class); + + @Autowired + private GetAccountTasksListFactory getAccountTasksListFactory; + + /** + * Get list of account tasks from CRM + * @param request HttpServletRequest object + * @param accountId CRM account id + * @return GetTasksListFormatterDto object + */ + public GetTasksListFormatterDto getAccountTasksList(HttpServletRequest request, String accountId) { + logger.info("getAccountTasksList Service called"); + + User currentUser = (User) request.getAttribute("current_user"); + return getAccountTasksListFactory.getAccountTasksList(currentUser, accountId); + } + } diff --git a/src/main/java/com/salessparrow/api/services/accounts/GetAccountListService.java b/src/main/java/com/salessparrow/api/services/accounts/GetAccountListService.java index dcf775df..3fbb27ec 100644 --- a/src/main/java/com/salessparrow/api/services/accounts/GetAccountListService.java +++ b/src/main/java/com/salessparrow/api/services/accounts/GetAccountListService.java @@ -15,28 +15,29 @@ */ @Service public class GetAccountListService { - @Autowired - private GetAccountsFactory getAccountsFactory; - - /** - * Get the list of accounts for a given search term - * @param request - * @param getAccountsDto - * - * @return GetAccountsFormatterDto - **/ - public GetAccountsFormatterDto getAccounts(HttpServletRequest request, GetAccountsDto getAccountsDto) { - User currentUser = (User) request.getAttribute("current_user"); - - String formattedSearchString = ""; - if(getAccountsDto.getQ() != null){ - formattedSearchString = formatSearchString(getAccountsDto.getQ()); - } - return getAccountsFactory.getAccounts(currentUser, formattedSearchString); - } - - private String formatSearchString(String q) { - q = q.trim(); - return q; - } + + @Autowired + private GetAccountsFactory getAccountsFactory; + + /** + * Get the list of accounts for a given search term + * @param request + * @param getAccountsDto + * @return GetAccountsFormatterDto + **/ + public GetAccountsFormatterDto getAccounts(HttpServletRequest request, GetAccountsDto getAccountsDto) { + User currentUser = (User) request.getAttribute("current_user"); + + String formattedSearchString = ""; + if (getAccountsDto.getQ() != null) { + formattedSearchString = formatSearchString(getAccountsDto.getQ()); + } + return getAccountsFactory.getAccounts(currentUser, formattedSearchString); + } + + private String formatSearchString(String q) { + q = q.trim(); + return q; + } + } diff --git a/src/main/java/com/salessparrow/api/services/crmOrganizationUsers/GetCrmOrganizationUsersList.java b/src/main/java/com/salessparrow/api/services/crmOrganizationUsers/GetCrmOrganizationUsersList.java index a873f2d5..618d3f9f 100644 --- a/src/main/java/com/salessparrow/api/services/crmOrganizationUsers/GetCrmOrganizationUsersList.java +++ b/src/main/java/com/salessparrow/api/services/crmOrganizationUsers/GetCrmOrganizationUsersList.java @@ -13,48 +13,45 @@ /** * GetCrmOrganizationUsersList class for the getCrmOrganizationUsers action. - * - * + * + * */ @Service public class GetCrmOrganizationUsersList { - Logger logger = LoggerFactory.getLogger(GetCrmOrganizationUsersList.class); - - @Autowired - private GetCrmOrganizationUsersFactory getCrmOrganizationUsersFactory; - - /** - * getCrmOrganizationUsers method for the getCrmOrganizationUsers action. - * - * @param request - * @param crmOrganizationUsersDto - * - * @return GetCrmOrganizationUsersFormatterDto - */ - public GetCrmOrganizationUsersFormatterDto getCrmOrganizationUsers(HttpServletRequest request ,GetCrmOrganizationUsersDto crmOrganizationUsersDto) { - logger.info("Inside Search crm organization user service"); - User currentUser = (User) request.getAttribute("current_user"); - String formattedSearchString = ""; - if(crmOrganizationUsersDto.getQ() != null){ - formattedSearchString = formatSearchString(crmOrganizationUsersDto.getQ()); - } - - return getCrmOrganizationUsersFactory.getCrmOrganizationUsers(currentUser, formattedSearchString); - } - - /** - * formatSearchString method for the getCrmOrganizationUsers action. - * - * @param searchTerm - * - * @return String - */ - private String formatSearchString(String searchTerm) { - logger.info("format and sanitize search term"); - searchTerm = searchTerm.trim(); - - return searchTerm; - } + Logger logger = LoggerFactory.getLogger(GetCrmOrganizationUsersList.class); + + @Autowired + private GetCrmOrganizationUsersFactory getCrmOrganizationUsersFactory; + + /** + * getCrmOrganizationUsers method for the getCrmOrganizationUsers action. + * @param request + * @param crmOrganizationUsersDto + * @return GetCrmOrganizationUsersFormatterDto + */ + public GetCrmOrganizationUsersFormatterDto getCrmOrganizationUsers(HttpServletRequest request, + GetCrmOrganizationUsersDto crmOrganizationUsersDto) { + logger.info("Inside Search crm organization user service"); + User currentUser = (User) request.getAttribute("current_user"); + String formattedSearchString = ""; + if (crmOrganizationUsersDto.getQ() != null) { + formattedSearchString = formatSearchString(crmOrganizationUsersDto.getQ()); + } + + return getCrmOrganizationUsersFactory.getCrmOrganizationUsers(currentUser, formattedSearchString); + } + + /** + * formatSearchString method for the getCrmOrganizationUsers action. + * @param searchTerm + * @return String + */ + private String formatSearchString(String searchTerm) { + logger.info("format and sanitize search term"); + searchTerm = searchTerm.trim(); + + return searchTerm; + } } 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 45de9a62..9010670d 100644 --- a/src/main/java/com/salessparrow/api/services/salesforce/AuthService.java +++ b/src/main/java/com/salessparrow/api/services/salesforce/AuthService.java @@ -31,284 +31,277 @@ import com.salessparrow.api.repositories.SalesforceUserRepository; import jakarta.servlet.http.HttpServletRequest; - @Service public class AuthService { - private String reqApiSource; - private String code; - private String redirectUri; + private String reqApiSource; + + private String code; + + private String redirectUri; + + private SalesforceGetTokensDto tokensData; + + private SalesforceGetIdentityDto userData; + + private SalesforceOauthToken salesforceOauthToken; + + private SalesforceUser salesforceUser; + + private String decryptedSalt; + + private Boolean isNewUser; + + Logger logger = LoggerFactory.getLogger(AuthService.class); + + @Autowired + private AwsKms awsKms; + + @Autowired + private Util util; + + @Autowired + private SalesforceUserRepository salesforceUserRepository; + + @Autowired + private SalesforceOauthTokenRepository salesforceOauthTokenRepository; + + @Autowired + private SalesforceOrganizationRepository salesforceOrganizationRepository; + + @Autowired + private LocalCipher localCipher; + + @Autowired + private CookieHelper cookieHelper; + + @Autowired + private SalesforceGetTokens salesforceGetTokens; + + @Autowired + private SalesforceGetIdentity salesforceGetIdentity; - private SalesforceGetTokensDto tokensData; - private SalesforceGetIdentityDto userData; - private SalesforceOauthToken salesforceOauthToken; - private SalesforceUser salesforceUser; - private String decryptedSalt; - private Boolean isNewUser; + /** + * Connect to Salesforce and create user if not exists. + * @param params + * @param request + * @return AuthServiceDto + */ + public AuthServiceDto connectToSalesforce(SalesforceConnectDto params, HttpServletRequest request) { + this.reqApiSource = (String) request.getAttribute("api_source"); - Logger logger = LoggerFactory.getLogger(AuthService.class); + this.isNewUser = true; // setting default value true to this variable, this will + // be updated based on conditions in further processing - @Autowired - private AwsKms awsKms; + code = params.getCode(); + redirectUri = params.getRedirect_uri(); - @Autowired - private Util util; + fetchOauthTokensFromSalesforce(); - @Autowired - private SalesforceUserRepository salesforceUserRepository; + validateAndUpsertSalesforceOrganization(); - @Autowired - private SalesforceOauthTokenRepository salesforceOauthTokenRepository; - - @Autowired - private SalesforceOrganizationRepository salesforceOrganizationRepository; + upsertSalesforceOAuthTokens(); - @Autowired - private LocalCipher localCipher; + verifyExistingSalesforceUser(); - @Autowired - private CookieHelper cookieHelper; + if (this.isNewUser) { + fetchUserInfoFromSalesforce(); + createSalesforceUser(); + } - @Autowired - private SalesforceGetTokens salesforceGetTokens; + return prepareResponse(); + } - @Autowired - private SalesforceGetIdentity salesforceGetIdentity; + /** + * Call Salesforce oauth token endpoint and fetch tokens. + * @return void + */ + private void fetchOauthTokensFromSalesforce() { + logger.info("Fetching OAuth Tokens from Salesforce"); - /** - * Connect to Salesforce and create user if not exists. - * - * @param params - * @param request - * - * @return AuthServiceDto - */ - public AuthServiceDto connectToSalesforce(SalesforceConnectDto params, HttpServletRequest request) { - this.reqApiSource = (String) request.getAttribute("api_source"); + HttpResponse response = salesforceGetTokens.getTokens(this.code, this.redirectUri); - this.isNewUser = true; // setting default value true to this variable, this will be updated based on conditions in further processing + JsonNode jsonNode = util.getJsonNode(response.getResponseBody()); + ObjectMapper mapper = new ObjectMapper(); + mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + SalesforceGetTokensDto salesforceGetTokensDto = mapper.convertValue(jsonNode, SalesforceGetTokensDto.class); - code = params.getCode(); - redirectUri = params.getRedirect_uri(); + this.tokensData = salesforceGetTokensDto; + } - fetchOauthTokensFromSalesforce(); + /** + * Validate and upsert Salesforce Organization in DB. + * @return void + */ + private void validateAndUpsertSalesforceOrganization() { + logger.info("Validating Salesforce Organization"); - validateAndUpsertSalesforceOrganization(); + String salesforceOrganizationId = this.tokensData.getSalesforceOrganizationId(); - upsertSalesforceOAuthTokens(); + SalesforceOrganization existingOrganizationData = salesforceOrganizationRepository + .getSalesforceOrganizationByExternalOrganizationId(salesforceOrganizationId); - verifyExistingSalesforceUser(); + if (existingOrganizationData != null) { + logger.info("Salesforce Organization already exists"); - if (this.isNewUser) { - fetchUserInfoFromSalesforce(); - createSalesforceUser(); - } + if (existingOrganizationData.getStatus() != SalesforceOrganization.Status.ACTIVE) { + logger.info("Salesforce Organization is not active."); + throw new CustomException(new ErrorObject("s_s_as_vauso_1", "forbidden_api_request", + "Salesforce Organization is not active.")); + } + } + + logger.info("Upserting Salesforce Organization in DB"); + SalesforceOrganization salesforceOrganization = new SalesforceOrganization(); + salesforceOrganization.setExternalOrganizationId(salesforceOrganizationId); + salesforceOrganization.setStatus(SalesforceOrganization.Status.ACTIVE); + + salesforceOrganizationRepository.saveSalesforceOrganization(salesforceOrganization); + } + + /** + * Upsert Salesforce Oauth Token in DB. + * @return void + */ + private void upsertSalesforceOAuthTokens() { + + logger.info("Upserting Salesforce OAuth Tokens in DB"); + + long currentTime = System.currentTimeMillis(); + String encryptedAccessToken = awsKms.encryptToken(this.tokensData.getAccessToken()); + + logger.info("Time in ms for encryption : " + (System.currentTimeMillis() - currentTime)); + + String encryptedRefreshToken = awsKms.encryptToken(this.tokensData.getRefreshToken()); + String salesforceUserId = this.tokensData.getSalesforceUserId(); + + SalesforceOauthToken salesforceOauthToken = new SalesforceOauthToken(); + // Todo: use salesforceconnect res entity object + salesforceOauthToken.setExternalUserId(salesforceUserId); + salesforceOauthToken.setIdentityUrl(this.tokensData.getId()); + salesforceOauthToken.setAccessToken(encryptedAccessToken); + salesforceOauthToken.setRefreshToken(encryptedRefreshToken); + salesforceOauthToken.setSignature(this.tokensData.getSignature()); + salesforceOauthToken.setIdToken(this.tokensData.getIdToken()); + salesforceOauthToken.setInstanceUrl(this.tokensData.getInstanceUrl()); + salesforceOauthToken.setStatus(SalesforceOauthToken.Status.ACTIVE); + salesforceOauthToken.setIssuedAt(Long.parseLong(this.tokensData.getIssuedAt())); + + this.salesforceOauthToken = salesforceOauthTokenRepository.saveSalesforceOauthToken(salesforceOauthToken); + } + + /** + * Verify if Salesforce User already exists. + * @return void + */ + private void verifyExistingSalesforceUser() { + String salesforceUserId = this.tokensData.getSalesforceUserId(); + SalesforceUser salesforceUser = salesforceUserRepository.getSalesforceUserByExternalUserId(salesforceUserId); + + if (salesforceUser != null) { + logger.info("Salesforce User already exists"); + this.salesforceUser = salesforceUser; + this.isNewUser = false; + this.decryptedSalt = localCipher.decrypt(CoreConstants.encryptionKey(), salesforceUser.getEncryptionSalt()); + } + } + + /** + * Fetch user info from Salesforce Identity API. + * @return void + */ + private void fetchUserInfoFromSalesforce() { + + logger.info("Calling Salesforce Identity API"); + + HttpResponse response = salesforceGetIdentity.getUserIdentity(salesforceOauthToken.getInstanceUrl(), + this.tokensData.getAccessToken()); + JsonNode jsonNode = util.getJsonNode(response.getResponseBody()); + ObjectMapper mapper = new ObjectMapper(); + mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + SalesforceGetIdentityDto salesforceGetIdentityDto = mapper.convertValue(jsonNode, + SalesforceGetIdentityDto.class); + + this.userData = salesforceGetIdentityDto; + } + + /** + * Create Salesforce User in DB. + * @return void + */ + private void createSalesforceUser() { + logger.info("Creating Salesforce User"); + + String decryptedSalt = localCipher.generateRandomSalt(); + String cookieToken = localCipher.generateRandomIv(32); + + String encryptedSalt = localCipher.encrypt(CoreConstants.encryptionKey(), decryptedSalt); + String encryptedCookieToken = localCipher.encrypt(decryptedSalt, cookieToken); + + SalesforceUser salesforceUser = new SalesforceUser(); + salesforceUser.setExternalUserId(this.userData.getUserId()); + salesforceUser.setIdentityUrl(this.userData.getSub()); + salesforceUser.setExternalOrganizationId(this.userData.getOrganizationId()); + salesforceUser.setName(this.userData.getName()); + salesforceUser.setEmail(this.userData.getEmail()); + salesforceUser.setUserKind(UserConstants.SALESFORCE_USER_KIND); + salesforceUser.setCookieToken(encryptedCookieToken); + salesforceUser.setEncryptionSalt(encryptedSalt); + salesforceUser.setStatus(SalesforceUser.Status.ACTIVE); + + this.salesforceUser = salesforceUserRepository.saveSalesforceUser(salesforceUser); + this.decryptedSalt = decryptedSalt; + } + + /** + * Prepare service response. + * @return AuthServiceDto + */ + private AuthServiceDto prepareResponse() { + logger.info("Preparing response"); + AuthServiceDto authServiceDto = new AuthServiceDto(); + + CurrentUserEntityDto currentUserEntityDto = new CurrentUserEntityDto(); + currentUserEntityDto.setId(this.salesforceUser.getId(this.salesforceUser.getExternalUserId())); + currentUserEntityDto.setName(this.salesforceUser.getName()); + currentUserEntityDto.setEmail(this.salesforceUser.getEmail()); + + String userLoginCookieValue = cookieHelper.getCookieValue(this.salesforceUser, + UserConstants.SALESFORCE_USER_KIND, this.decryptedSalt, reqApiSource); + + authServiceDto.setCurrentUser(currentUserEntityDto); + authServiceDto.setCurrentUserLoginCookie(userLoginCookieValue); + return authServiceDto; + } + + /** + * DTO for AuthService. + * + * @return AuthServiceDto + */ + public class AuthServiceDto { + + private CurrentUserEntityDto currentUser; + + private String currentUserLoginCookie; + + public CurrentUserEntityDto getCurrentUser() { + return currentUser; + } + + public void setCurrentUser(CurrentUserEntityDto currentUser) { + this.currentUser = currentUser; + } + + public String getCurrentUserLoginCookie() { + return currentUserLoginCookie; + } + + public void setCurrentUserLoginCookie(String currentUserLoginCookie) { + this.currentUserLoginCookie = currentUserLoginCookie; + } + + } - return prepareResponse(); - } - - /** - * Call Salesforce oauth token endpoint and fetch tokens. - * - * @return void - */ - private void fetchOauthTokensFromSalesforce() { - logger.info("Fetching OAuth Tokens from Salesforce"); - - HttpResponse response = salesforceGetTokens.getTokens(this.code, this.redirectUri); - - JsonNode jsonNode = util.getJsonNode(response.getResponseBody()); - - ObjectMapper mapper = new ObjectMapper(); - mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); - SalesforceGetTokensDto salesforceGetTokensDto = mapper.convertValue(jsonNode, - SalesforceGetTokensDto.class); - - this.tokensData = salesforceGetTokensDto; - } - - /** - * Validate and upsert Salesforce Organization in DB. - * - * @return void - */ - private void validateAndUpsertSalesforceOrganization() { - logger.info("Validating Salesforce Organization"); - - String salesforceOrganizationId = this.tokensData.getSalesforceOrganizationId(); - - SalesforceOrganization existingOrganizationData = salesforceOrganizationRepository - .getSalesforceOrganizationByExternalOrganizationId(salesforceOrganizationId); - - if (existingOrganizationData != null) { - logger.info("Salesforce Organization already exists"); - - if (existingOrganizationData.getStatus() != SalesforceOrganization.Status.ACTIVE) { - logger.info("Salesforce Organization is not active."); - throw new CustomException( - new ErrorObject( - "s_s_as_vauso_1", - "forbidden_api_request", - "Salesforce Organization is not active.")); - } - } - - logger.info("Upserting Salesforce Organization in DB"); - SalesforceOrganization salesforceOrganization = new SalesforceOrganization(); - salesforceOrganization.setExternalOrganizationId(salesforceOrganizationId); - salesforceOrganization.setStatus(SalesforceOrganization.Status.ACTIVE); - - salesforceOrganizationRepository.saveSalesforceOrganization(salesforceOrganization); - } - - /** - * Upsert Salesforce Oauth Token in DB. - * - * @return void - */ - private void upsertSalesforceOAuthTokens() { - - logger.info("Upserting Salesforce OAuth Tokens in DB"); - - long currentTime = System.currentTimeMillis(); - String encryptedAccessToken = awsKms.encryptToken(this.tokensData.getAccessToken()); - - logger.info("Time in ms for encryption : " + (System.currentTimeMillis() - currentTime)); - - String encryptedRefreshToken = awsKms.encryptToken(this.tokensData.getRefreshToken()); - String salesforceUserId = this.tokensData.getSalesforceUserId(); - - SalesforceOauthToken salesforceOauthToken = new SalesforceOauthToken(); - // Todo: use salesforceconnect res entity object - salesforceOauthToken.setExternalUserId(salesforceUserId); - salesforceOauthToken.setIdentityUrl(this.tokensData.getId()); - salesforceOauthToken.setAccessToken(encryptedAccessToken); - salesforceOauthToken.setRefreshToken(encryptedRefreshToken); - salesforceOauthToken.setSignature(this.tokensData.getSignature()); - salesforceOauthToken.setIdToken(this.tokensData.getIdToken()); - salesforceOauthToken.setInstanceUrl(this.tokensData.getInstanceUrl()); - salesforceOauthToken.setStatus(SalesforceOauthToken.Status.ACTIVE); - salesforceOauthToken.setIssuedAt(Long.parseLong(this.tokensData.getIssuedAt())); - - this.salesforceOauthToken = salesforceOauthTokenRepository - .saveSalesforceOauthToken(salesforceOauthToken); - } - - /** - * Verify if Salesforce User already exists. - * - * @return void - */ - private void verifyExistingSalesforceUser() { - String salesforceUserId = this.tokensData.getSalesforceUserId(); - SalesforceUser salesforceUser = salesforceUserRepository.getSalesforceUserByExternalUserId(salesforceUserId); - - if (salesforceUser != null) { - logger.info("Salesforce User already exists"); - this.salesforceUser = salesforceUser; - this.isNewUser = false; - this.decryptedSalt = localCipher.decrypt(CoreConstants.encryptionKey(), salesforceUser.getEncryptionSalt()); - } - } - - /** - * Fetch user info from Salesforce Identity API. - * - * @return void - */ - private void fetchUserInfoFromSalesforce() { - - logger.info("Calling Salesforce Identity API"); - - HttpResponse response = salesforceGetIdentity.getUserIdentity(salesforceOauthToken.getInstanceUrl(), - this.tokensData.getAccessToken()); - JsonNode jsonNode = util.getJsonNode(response.getResponseBody()); - ObjectMapper mapper = new ObjectMapper(); - mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); - SalesforceGetIdentityDto salesforceGetIdentityDto = mapper.convertValue(jsonNode, - SalesforceGetIdentityDto.class); - - this.userData = salesforceGetIdentityDto; - } - - /** - * Create Salesforce User in DB. - * - * @return void - */ - private void createSalesforceUser() { - logger.info("Creating Salesforce User"); - - String decryptedSalt = localCipher.generateRandomSalt(); - String cookieToken = localCipher.generateRandomIv(32); - - String encryptedSalt = localCipher.encrypt(CoreConstants.encryptionKey(), decryptedSalt); - String encryptedCookieToken = localCipher.encrypt(decryptedSalt, cookieToken); - - SalesforceUser salesforceUser = new SalesforceUser(); - salesforceUser.setExternalUserId(this.userData.getUserId()); - salesforceUser.setIdentityUrl(this.userData.getSub()); - salesforceUser.setExternalOrganizationId(this.userData.getOrganizationId()); - salesforceUser.setName(this.userData.getName()); - salesforceUser.setEmail(this.userData.getEmail()); - salesforceUser.setUserKind(UserConstants.SALESFORCE_USER_KIND); - salesforceUser.setCookieToken(encryptedCookieToken); - salesforceUser.setEncryptionSalt(encryptedSalt); - salesforceUser.setStatus(SalesforceUser.Status.ACTIVE); - - this.salesforceUser = salesforceUserRepository.saveSalesforceUser(salesforceUser); - this.decryptedSalt = decryptedSalt; - } - - /** - * Prepare service response. - * - * @return AuthServiceDto - */ - private AuthServiceDto prepareResponse() { - logger.info("Preparing response"); - AuthServiceDto authServiceDto = new AuthServiceDto(); - - CurrentUserEntityDto currentUserEntityDto = new CurrentUserEntityDto(); - currentUserEntityDto.setId(this.salesforceUser.getId(this.salesforceUser.getExternalUserId())); - currentUserEntityDto.setName(this.salesforceUser.getName()); - currentUserEntityDto.setEmail(this.salesforceUser.getEmail()); - - String userLoginCookieValue = cookieHelper.getCookieValue(this.salesforceUser, - UserConstants.SALESFORCE_USER_KIND, - this.decryptedSalt, reqApiSource); - - authServiceDto.setCurrentUser(currentUserEntityDto); - authServiceDto.setCurrentUserLoginCookie(userLoginCookieValue); - return authServiceDto; - } - - /** - * DTO for AuthService. - * - * @return AuthServiceDto - */ - public class AuthServiceDto { - - private CurrentUserEntityDto currentUser; - private String currentUserLoginCookie; - - public CurrentUserEntityDto getCurrentUser() { - return currentUser; - } - - public void setCurrentUser(CurrentUserEntityDto currentUser) { - this.currentUser = currentUser; - } - - public String getCurrentUserLoginCookie() { - return currentUserLoginCookie; - } - - public void setCurrentUserLoginCookie(String currentUserLoginCookie) { - this.currentUserLoginCookie = currentUserLoginCookie; - } - - } } \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/services/salesforce/RedirectUrlService.java b/src/main/java/com/salessparrow/api/services/salesforce/RedirectUrlService.java index 8866f743..844dc89e 100644 --- a/src/main/java/com/salessparrow/api/services/salesforce/RedirectUrlService.java +++ b/src/main/java/com/salessparrow/api/services/salesforce/RedirectUrlService.java @@ -16,36 +16,35 @@ @Service public class RedirectUrlService { - @Autowired - private SalesforceConstants salesforceConstants; + @Autowired + private SalesforceConstants salesforceConstants; - Logger logger = LoggerFactory.getLogger(RedirectUrlService.class); + Logger logger = LoggerFactory.getLogger(RedirectUrlService.class); - /** - * Get the redirect url for the oauth2 flow - * @param salesforceRedirectUrlDto - * - * @return RedirectUrlFormatterDto - **/ - public RedirectUrlFormatterDto getSalesforceOauthUrl(SalesforceRedirectUrlDto salesforceRedirectUrlDto) { + /** + * Get the redirect url for the oauth2 flow + * @param salesforceRedirectUrlDto + * @return RedirectUrlFormatterDto + **/ + public RedirectUrlFormatterDto getSalesforceOauthUrl(SalesforceRedirectUrlDto salesforceRedirectUrlDto) { - String redirectUri = salesforceRedirectUrlDto.getRedirect_uri(); - String state = salesforceRedirectUrlDto.getState(); + String redirectUri = salesforceRedirectUrlDto.getRedirect_uri(); + String state = salesforceRedirectUrlDto.getState(); - String salesforceLoginUrl = salesforceConstants.oauth2AuthorizeUrl(); - String salesforceClientId = CoreConstants.salesforceClientId(); + String salesforceLoginUrl = salesforceConstants.oauth2AuthorizeUrl(); + String salesforceClientId = CoreConstants.salesforceClientId(); - String salesforceOauthUrl = salesforceLoginUrl + "?response_type=code" + - "&client_id=" + salesforceClientId + - "&redirect_uri=" + redirectUri; + String salesforceOauthUrl = salesforceLoginUrl + "?response_type=code" + "&client_id=" + salesforceClientId + + "&redirect_uri=" + redirectUri; - if (state != null && !state.isEmpty()) { - salesforceOauthUrl += "&state=" + state; - } + if (state != null && !state.isEmpty()) { + salesforceOauthUrl += "&state=" + state; + } - RedirectUrlFormatterDto redirectUrlFormatterDto = new RedirectUrlFormatterDto(); - redirectUrlFormatterDto.setUrl(salesforceOauthUrl); + RedirectUrlFormatterDto redirectUrlFormatterDto = new RedirectUrlFormatterDto(); + redirectUrlFormatterDto.setUrl(salesforceOauthUrl); + + return redirectUrlFormatterDto; + } - return redirectUrlFormatterDto; - } } \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/services/suggestions/CrmActionsSuggestionsService.java b/src/main/java/com/salessparrow/api/services/suggestions/CrmActionsSuggestionsService.java index d377c4be..2923e2e2 100644 --- a/src/main/java/com/salessparrow/api/services/suggestions/CrmActionsSuggestionsService.java +++ b/src/main/java/com/salessparrow/api/services/suggestions/CrmActionsSuggestionsService.java @@ -14,15 +14,17 @@ */ @Service public class CrmActionsSuggestionsService { - @Autowired - private GetCrmActionSuggestions getCrmActionSuggestions; - private Logger logger = org.slf4j.LoggerFactory.getLogger(SuggestionsController.class); - - public CrmActionSuggestionsFormatterDto getSuggestions(CrmActionsSuggestionsDto crmActionsSuggestionsDto) { - logger.info("Crm actions service called"); - String text = crmActionsSuggestionsDto.getText(); + @Autowired + private GetCrmActionSuggestions getCrmActionSuggestions; + + private Logger logger = org.slf4j.LoggerFactory.getLogger(SuggestionsController.class); + + public CrmActionSuggestionsFormatterDto getSuggestions(CrmActionsSuggestionsDto crmActionsSuggestionsDto) { + logger.info("Crm actions service called"); + String text = crmActionsSuggestionsDto.getText(); + + return getCrmActionSuggestions.getTaskSuggestions(text); + } - return getCrmActionSuggestions.getTaskSuggestions(text); - } } diff --git a/src/main/java/com/salessparrow/api/services/users/GetCurrentUserService.java b/src/main/java/com/salessparrow/api/services/users/GetCurrentUserService.java index 3b4bf580..6245d3cc 100644 --- a/src/main/java/com/salessparrow/api/services/users/GetCurrentUserService.java +++ b/src/main/java/com/salessparrow/api/services/users/GetCurrentUserService.java @@ -13,14 +13,15 @@ @Service public class GetCurrentUserService { - public CurrentUserEntityDto getCurrentUser(HttpServletRequest request) { - User currentUser = (User) request.getAttribute("current_user"); + public CurrentUserEntityDto getCurrentUser(HttpServletRequest request) { + User currentUser = (User) request.getAttribute("current_user"); - CurrentUserEntityDto currentUserEntityDto = new CurrentUserEntityDto(); - currentUserEntityDto.setId(currentUser.getExternalUserId()); - currentUserEntityDto.setName(currentUser.getName()); - currentUserEntityDto.setEmail(currentUser.getEmail()); + CurrentUserEntityDto currentUserEntityDto = new CurrentUserEntityDto(); + currentUserEntityDto.setId(currentUser.getExternalUserId()); + currentUserEntityDto.setName(currentUser.getName()); + currentUserEntityDto.setEmail(currentUser.getEmail()); + + return currentUserEntityDto; + } - return currentUserEntityDto; - } } \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/utility/CacheKeyGenerator.java b/src/main/java/com/salessparrow/api/utility/CacheKeyGenerator.java index fd706592..73426574 100644 --- a/src/main/java/com/salessparrow/api/utility/CacheKeyGenerator.java +++ b/src/main/java/com/salessparrow/api/utility/CacheKeyGenerator.java @@ -4,33 +4,33 @@ import org.springframework.cache.interceptor.KeyGenerator; import java.lang.reflect.Method; - /** * Cache Key Generator */ public class CacheKeyGenerator implements KeyGenerator { - /** - * Generate the key based on the method name and the parameters. Append the environment name to the key. - * - * @param target - * @param method - * @param params - * - * @return String - */ - @Override - public Object generate(Object target, Method method, Object... params) { - String prefix = CoreConstants.environment(); - StringBuilder key = new StringBuilder(); - key.append(prefix); - key.append(":"); - key.append(target.getClass().getSimpleName()); - key.append(":"); - key.append(method.getName()); - for (Object param : params) { - key.append(":"); - key.append(param.toString()); - } - return key.toString(); - }; + + /** + * Generate the key based on the method name and the parameters. Append the + * environment name to the key. + * @param target + * @param method + * @param params + * @return String + */ + @Override + public Object generate(Object target, Method method, Object... params) { + String prefix = CoreConstants.environment(); + StringBuilder key = new StringBuilder(); + key.append(prefix); + key.append(":"); + key.append(target.getClass().getSimpleName()); + key.append(":"); + key.append(method.getName()); + for (Object param : params) { + key.append(":"); + key.append(param.toString()); + } + return key.toString(); + }; + } diff --git a/src/main/java/com/salessparrow/api/utility/Memcached.java b/src/main/java/com/salessparrow/api/utility/Memcached.java index bede6bec..eb3ee843 100644 --- a/src/main/java/com/salessparrow/api/utility/Memcached.java +++ b/src/main/java/com/salessparrow/api/utility/Memcached.java @@ -12,137 +12,129 @@ */ public class Memcached implements Cache { - private static final Logger logger = LoggerFactory.getLogger(Memcached.class); - - private String name; - - private MemcachedClient cache; - - private int expiration; - - /** - * Constructor - * - * @param name - * @param expiration - */ - public Memcached(String name, int expiration, MemcachedClient memcachedClient) { - this.name = name; - this.expiration = expiration; - this.cache = memcachedClient; - } - - /** - * Returns the name of the cache. - * - * @param name - */ - @Override - public String getName() { - return name; - } - - /** - * Returns the native cache. - * - * @param name - */ - @Override - public Object getNativeCache() { - return cache; - } - - /** - * Returns the value associated with the key. - * - * @param key - */ - @Override - public ValueWrapper get(final Object key) { - String keyString = name + "_" + key.toString(); - Object value = null; - try { - value = cache.get(keyString); - } catch (final Exception e) { - logger.warn(e.getMessage()); - } - if (value == null) { - logger.debug("cache miss for key: " + keyString); - return null; - } - logger.debug("cache hit for key: " + keyString); - - return new SimpleValueWrapper(value); - } - - /** - * Associates the value with the key. - * - * @param key - * @param value - */ - @Override - public void put(final Object key, final Object value) { - String keyString = name + "_" + key.toString(); - if (value != null) { - cache.set(keyString, expiration, value); - logger.debug("cache put for key: " + keyString); - } - } - - /** - * Removes the key and its associated value. - * - * @param key - */ - @Override - public void evict(final Object key) { - String keyString = name + "_" + key.toString(); - this.cache.delete(keyString); - logger.debug("cache delete for key: " + keyString); - } - - /** - * Clears the cache. - * - * @param key - */ - @Override - public void clear() { - cache.flush(); - logger.debug("cache clear completed"); - } - - /** - * Returns the value associated with the key. - * - * @param key - * @param aClass - */ - @Override - public T get(Object o, Class aClass) { - return null; - } - - /** - * Returns the value associated with the key. - * - * @param key - * @param callable - */ - @Override - public T get(Object o, Callable callable) { - return null; - } - - /** - * Associates the value with the key if absent. - * - * @param key - * @param value - */ - @Override - public ValueWrapper putIfAbsent(Object o, Object o1) { - return null; - } + private static final Logger logger = LoggerFactory.getLogger(Memcached.class); + + private String name; + + private MemcachedClient cache; + + private int expiration; + + /** + * Constructor + * @param name + * @param expiration + */ + public Memcached(String name, int expiration, MemcachedClient memcachedClient) { + this.name = name; + this.expiration = expiration; + this.cache = memcachedClient; + } + + /** + * Returns the name of the cache. + * @param name + */ + @Override + public String getName() { + return name; + } + + /** + * Returns the native cache. + * @param name + */ + @Override + public Object getNativeCache() { + return cache; + } + + /** + * Returns the value associated with the key. + * @param key + */ + @Override + public ValueWrapper get(final Object key) { + String keyString = name + "_" + key.toString(); + Object value = null; + try { + value = cache.get(keyString); + } + catch (final Exception e) { + logger.warn(e.getMessage()); + } + if (value == null) { + logger.debug("cache miss for key: " + keyString); + return null; + } + logger.debug("cache hit for key: " + keyString); + + return new SimpleValueWrapper(value); + } + + /** + * Associates the value with the key. + * @param key + * @param value + */ + @Override + public void put(final Object key, final Object value) { + String keyString = name + "_" + key.toString(); + if (value != null) { + cache.set(keyString, expiration, value); + logger.debug("cache put for key: " + keyString); + } + } + + /** + * Removes the key and its associated value. + * @param key + */ + @Override + public void evict(final Object key) { + String keyString = name + "_" + key.toString(); + this.cache.delete(keyString); + logger.debug("cache delete for key: " + keyString); + } + + /** + * Clears the cache. + * @param key + */ + @Override + public void clear() { + cache.flush(); + logger.debug("cache clear completed"); + } + + /** + * Returns the value associated with the key. + * @param key + * @param aClass + */ + @Override + public T get(Object o, Class aClass) { + return null; + } + + /** + * Returns the value associated with the key. + * @param key + * @param callable + */ + @Override + public T get(Object o, Callable callable) { + return null; + } + + /** + * Associates the value with the key if absent. + * @param key + * @param value + */ + @Override + public ValueWrapper putIfAbsent(Object o, Object o1) { + return null; + } + } \ No newline at end of file diff --git a/src/test/java/com/salessparrow/api/functional/SalesSparrowApiTest.java b/src/test/java/com/salessparrow/api/functional/SalesSparrowApiTest.java index 82b7dea1..13014bca 100644 --- a/src/test/java/com/salessparrow/api/functional/SalesSparrowApiTest.java +++ b/src/test/java/com/salessparrow/api/functional/SalesSparrowApiTest.java @@ -10,11 +10,12 @@ @SpringBootTest public class SalesSparrowApiTest { - @Autowired - private ApplicationContext ctx; + @Autowired + private ApplicationContext ctx; + + @Test + public void contextLoads() { + assertThat(ctx).isNotNull(); + } - @Test - public void contextLoads() { - assertThat(ctx).isNotNull(); - } } diff --git a/src/test/java/com/salessparrow/api/functional/config/SecurityConfigTest.java b/src/test/java/com/salessparrow/api/functional/config/SecurityConfigTest.java index 677d78a0..701a2bcd 100644 --- a/src/test/java/com/salessparrow/api/functional/config/SecurityConfigTest.java +++ b/src/test/java/com/salessparrow/api/functional/config/SecurityConfigTest.java @@ -16,63 +16,62 @@ import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; - import com.github.dynamobee.exception.DynamobeeException; import com.salessparrow.api.helper.Cleanup; import com.salessparrow.api.helper.Common; import com.salessparrow.api.helper.LoadFixture; import com.salessparrow.api.helper.Setup; - @SpringBootTest @AutoConfigureMockMvc @WebAppConfiguration @Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) public class SecurityConfigTest { - @Autowired - private MockMvc mockMvc; - @Autowired - private Setup setup; + @Autowired + private MockMvc mockMvc; - @Autowired - private Cleanup cleanup; + @Autowired + private Setup setup; - @Autowired - private Common common; + @Autowired + private Cleanup cleanup; - @BeforeEach - public void setUp() throws DynamobeeException, IOException { - setup.perform(); - } + @Autowired + private Common common; - @AfterEach - public void tearDown() { - cleanup.perform(); - } + @BeforeEach + public void setUp() throws DynamobeeException, IOException { + setup.perform(); + } - @Test - public void allRoutesShouldBeAccessibleWithoutAuthenticationAndAuthorization() throws Exception{ - ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/auth/salesforce/redirect-url") - .param("redirect_uri", "http://localhost:3000") - .contentType(MediaType.APPLICATION_JSON)); - assertEquals(resultActions.andReturn().getResponse().getStatus(), 200); - } + @AfterEach + public void tearDown() { + cleanup.perform(); + } - @Test - public void securityHeadersShouldBeSet() throws Exception{ - mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/auth/salesforce/redirect-url") - .param("redirect_uri", "http://localhost:3000") - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(header().string("X-Content-Type-Options", "nosniff")) - .andExpect(header().string("X-XSS-Protection", "1; mode=block")) - .andExpect(header().string("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate")) - .andExpect(header().string("Pragma", "no-cache")) - .andExpect(header().string("Expires", "0")) - .andExpect(header().string("X-Frame-Options", "DENY")) - .andExpect(header().string("Referrer-Policy", "same-origin")) - .andExpect(header().string("Content-Type", "application/json")); - } + @Test + public void allRoutesShouldBeAccessibleWithoutAuthenticationAndAuthorization() throws Exception { + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/auth/salesforce/redirect-url") + .param("redirect_uri", "http://localhost:3000") + .contentType(MediaType.APPLICATION_JSON)); + assertEquals(resultActions.andReturn().getResponse().getStatus(), 200); + } -} + @Test + public void securityHeadersShouldBeSet() throws Exception { + mockMvc + .perform(MockMvcRequestBuilders.get("/api/v1/auth/salesforce/redirect-url") + .param("redirect_uri", "http://localhost:3000") + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(header().string("X-Content-Type-Options", "nosniff")) + .andExpect(header().string("X-XSS-Protection", "1; mode=block")) + .andExpect(header().string("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate")) + .andExpect(header().string("Pragma", "no-cache")) + .andExpect(header().string("Expires", "0")) + .andExpect(header().string("X-Frame-Options", "DENY")) + .andExpect(header().string("Referrer-Policy", "same-origin")) + .andExpect(header().string("Content-Type", "application/json")); + } +} diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/CreateNoteTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/CreateNoteTest.java index 50582928..43d6e7af 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/CreateNoteTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/CreateNoteTest.java @@ -48,81 +48,92 @@ @Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) public class CreateNoteTest { - @Autowired - private MockMvc mockMvc; - @Autowired - private Common common; - @Autowired - private LoadFixture loadFixture; - @Autowired - private Setup setup; - @Autowired - private Cleanup cleanup; - - @MockBean - private MakeCompositeRequest makeCompositeRequestMock; - - @BeforeEach - public void setUp() throws DynamobeeException { - setup.perform(); - } - - @AfterEach - public void tearDown() { - cleanup.perform(); - } - - @ParameterizedTest - @MethodSource("testScenariosProvider") - public void createNote(Scenario testScenario) throws Exception { - - // Load fixture data - String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/functional/controllers/accountController/createNote.fixtures.json", currentFunctionName); - loadFixture.perform(fixtureData); - - // Read data from the scenario - ObjectMapper objectMapper = new ObjectMapper(); - String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; - String accountId = (String) testScenario.getInput().get("accountId"); - - // Prepare mock responses - HttpResponse createNoteMockResponse = new HttpResponse(); - createNoteMockResponse.setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest"))); - when(makeCompositeRequestMock.makePostRequest(any(), any())).thenReturn(createNoteMockResponse); - - // Perform the request - String requestBody = objectMapper.writeValueAsString(testScenario.getInput().get("body")); - String url = "/api/v1/accounts/" + accountId + "/notes"; - - ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.post(url) - .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) - .content(requestBody) - .contentType(MediaType.APPLICATION_JSON)); - - // Check the response - String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); - String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); - - if(resultActions.andReturn().getResponse().getStatus() == 200) { - assertEquals(expectedOutput, actualOutput); - } else { - common.compareErrors(testScenario, actualOutput); - } - } - - static Stream testScenariosProvider() throws IOException { - List testScenarios = loadScenarios(); - return testScenarios.stream(); - } - - private static List loadScenarios() throws IOException { - String scenariosPath = "classpath:data/functional/controllers/accountController/createNote.scenarios.json"; - Resource resource = new DefaultResourceLoader().getResource(scenariosPath); - ObjectMapper objectMapper = new ObjectMapper(); - - try (InputStream inputStream = resource.getInputStream()) { - return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); - } - } + @Autowired + private MockMvc mockMvc; + + @Autowired + private Common common; + + @Autowired + private LoadFixture loadFixture; + + @Autowired + private Setup setup; + + @Autowired + private Cleanup cleanup; + + @MockBean + private MakeCompositeRequest makeCompositeRequestMock; + + @BeforeEach + public void setUp() throws DynamobeeException { + setup.perform(); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + @ParameterizedTest + @MethodSource("testScenariosProvider") + public void createNote(Scenario testScenario) throws Exception { + + // Load fixture data + String currentFunctionName = new Object() { + }.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture( + "classpath:fixtures/functional/controllers/accountController/createNote.fixtures.json", + currentFunctionName); + loadFixture.perform(fixtureData); + + // Read data from the scenario + ObjectMapper objectMapper = new ObjectMapper(); + String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; + String accountId = (String) testScenario.getInput().get("accountId"); + + // Prepare mock responses + HttpResponse createNoteMockResponse = new HttpResponse(); + createNoteMockResponse + .setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest"))); + when(makeCompositeRequestMock.makePostRequest(any(), any())).thenReturn(createNoteMockResponse); + + // Perform the request + String requestBody = objectMapper.writeValueAsString(testScenario.getInput().get("body")); + String url = "/api/v1/accounts/" + accountId + "/notes"; + + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.post(url) + .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) + .content(requestBody) + .contentType(MediaType.APPLICATION_JSON)); + + // Check the response + String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); + String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); + + if (resultActions.andReturn().getResponse().getStatus() == 200) { + assertEquals(expectedOutput, actualOutput); + } + else { + common.compareErrors(testScenario, actualOutput); + } + } + + static Stream testScenariosProvider() throws IOException { + List testScenarios = loadScenarios(); + return testScenarios.stream(); + } + + private static List loadScenarios() throws IOException { + String scenariosPath = "classpath:data/functional/controllers/accountController/createNote.scenarios.json"; + Resource resource = new DefaultResourceLoader().getResource(scenariosPath); + ObjectMapper objectMapper = new ObjectMapper(); + + try (InputStream inputStream = resource.getInputStream()) { + return objectMapper.readValue(resource.getInputStream(), new TypeReference>() { + }); + } + } + } diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java index 5ba39578..2d20c89d 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountListTest.java @@ -48,79 +48,89 @@ @WebAppConfiguration @Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) public class GetAccountListTest { - @Autowired - private MockMvc mockMvc; - @Autowired - private Common common; - @Autowired - private LoadFixture loadFixture; - @Autowired - private Setup setup; - @Autowired - private Cleanup cleanup; - - @MockBean - private MakeCompositeRequest makeCompositeRequestMock; - - @BeforeEach - public void setUp() throws DynamobeeException { - setup.perform(); - } - - @AfterEach - public void tearDown() { - cleanup.perform(); - } - - @ParameterizedTest - @MethodSource("testScenariosProvider") - public void getAccountList(Scenario testScenario) throws Exception { - // Load fixture data - String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/functional/controllers/accountController/getAccountList.fixtures.json", currentFunctionName); - loadFixture.perform(fixtureData); - - // Read data from the scenario - ObjectMapper objectMapper = new ObjectMapper(); - String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; - - // Prepare mock responses - HttpResponse getAccountMockResponse = new HttpResponse(); - getAccountMockResponse.setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest"))); - when(makeCompositeRequestMock.makePostRequest(any(), any())).thenReturn(getAccountMockResponse); - - // Perform the request - String url = "/api/v1/accounts"; - String q = objectMapper.writeValueAsString(testScenario.getInput().get("q")); - - ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get(url) - .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) - .param("q", q) - .contentType(MediaType.APPLICATION_JSON)); - - - // Check the response - String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); - String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); - - JsonNode expectedOutputJson = objectMapper.readTree(expectedOutput); - JsonNode actualOutputJson = objectMapper.readTree(actualOutput); - - assertEquals(expectedOutputJson, actualOutputJson); - } - - static Stream testScenariosProvider() throws IOException { - List testScenarios = loadScenarios(); - return testScenarios.stream(); - } - - private static List loadScenarios() throws IOException { - String scenariosPath = "classpath:data/functional/controllers/accountController/getAccountList.scenarios.json"; - Resource resource = new DefaultResourceLoader().getResource(scenariosPath); - ObjectMapper objectMapper = new ObjectMapper(); - - try (InputStream inputStream = resource.getInputStream()) { - return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); - } - } + + @Autowired + private MockMvc mockMvc; + + @Autowired + private Common common; + + @Autowired + private LoadFixture loadFixture; + + @Autowired + private Setup setup; + + @Autowired + private Cleanup cleanup; + + @MockBean + private MakeCompositeRequest makeCompositeRequestMock; + + @BeforeEach + public void setUp() throws DynamobeeException { + setup.perform(); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + @ParameterizedTest + @MethodSource("testScenariosProvider") + public void getAccountList(Scenario testScenario) throws Exception { + // Load fixture data + String currentFunctionName = new Object() { + }.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture( + "classpath:fixtures/functional/controllers/accountController/getAccountList.fixtures.json", + currentFunctionName); + loadFixture.perform(fixtureData); + + // Read data from the scenario + ObjectMapper objectMapper = new ObjectMapper(); + String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; + + // Prepare mock responses + HttpResponse getAccountMockResponse = new HttpResponse(); + getAccountMockResponse + .setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest"))); + when(makeCompositeRequestMock.makePostRequest(any(), any())).thenReturn(getAccountMockResponse); + + // Perform the request + String url = "/api/v1/accounts"; + String q = objectMapper.writeValueAsString(testScenario.getInput().get("q")); + + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get(url) + .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) + .param("q", q) + .contentType(MediaType.APPLICATION_JSON)); + + // Check the response + String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); + String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); + + JsonNode expectedOutputJson = objectMapper.readTree(expectedOutput); + JsonNode actualOutputJson = objectMapper.readTree(actualOutput); + + assertEquals(expectedOutputJson, actualOutputJson); + } + + static Stream testScenariosProvider() throws IOException { + List testScenarios = loadScenarios(); + return testScenarios.stream(); + } + + private static List loadScenarios() throws IOException { + String scenariosPath = "classpath:data/functional/controllers/accountController/getAccountList.scenarios.json"; + Resource resource = new DefaultResourceLoader().getResource(scenariosPath); + ObjectMapper objectMapper = new ObjectMapper(); + + try (InputStream inputStream = resource.getInputStream()) { + return objectMapper.readValue(resource.getInputStream(), new TypeReference>() { + }); + } + } + } diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java index be28e02d..84e90a28 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteDetailsTest.java @@ -50,85 +50,97 @@ @Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) public class GetNoteDetailsTest { - @Autowired - private MockMvc mockMvc; - @Autowired - private Common common; - @Autowired - private LoadFixture loadFixture; - @Autowired - private Setup setup; - @Autowired - private Cleanup cleanup; - @MockBean - private SalesforceGetNoteContent salesforceGetNoteContentMock; - - @MockBean - private MakeCompositeRequest makeCompositeRequestMock; - - @BeforeEach - public void setUp() throws DynamobeeException, IOException { - setup.perform(); - } - - @AfterEach - public void tearDown() { - cleanup.perform(); - } - - @ParameterizedTest - @MethodSource("testScenariosProvider") - public void getNoteDetails(Scenario testScenario) throws Exception { - String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/functional/controllers/accountController/getNoteDetails.fixtures.json", currentFunctionName); - loadFixture.perform(fixtureData); - - ObjectMapper objectMapper = new ObjectMapper(); - - String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; - String accountId = (String) testScenario.getInput().get("accountId"); - String noteId = (String) testScenario.getInput().get("noteId"); - - HttpResponse getNoteDetailsMockResponse = new HttpResponse(); - - getNoteDetailsMockResponse.setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest"))); - - when(makeCompositeRequestMock.makePostRequest(any(), any())).thenReturn(getNoteDetailsMockResponse); - - - HttpResponse getNoteContentMockResponse = new HttpResponse(); - getNoteContentMockResponse.setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeWrapperRequest"))); - - when(salesforceGetNoteContentMock.getNoteContent(any(), any())).thenReturn(getNoteContentMockResponse); - - String url = "/api/v1/accounts/" + accountId + "/notes/" + noteId; - ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get(url) - .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) - .contentType(MediaType.APPLICATION_JSON)); - - String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); - String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); - - if(resultActions.andReturn().getResponse().getStatus() == 200) { - assertEquals(expectedOutput, actualOutput); - } else { - common.compareErrors(testScenario, actualOutput); - } - - } - - static Stream testScenariosProvider() throws IOException { - List testScenarios = loadScenarios(); - return testScenarios.stream(); - } - - private static List loadScenarios() throws IOException { - String scenariosPath = "classpath:data/functional/controllers/accountController/getNoteDetails.scenarios.json"; - Resource resource = new DefaultResourceLoader().getResource(scenariosPath); - ObjectMapper objectMapper = new ObjectMapper(); - - try (InputStream inputStream = resource.getInputStream()) { - return objectMapper.readValue(inputStream, new TypeReference>() {}); - } - } + @Autowired + private MockMvc mockMvc; + + @Autowired + private Common common; + + @Autowired + private LoadFixture loadFixture; + + @Autowired + private Setup setup; + + @Autowired + private Cleanup cleanup; + + @MockBean + private SalesforceGetNoteContent salesforceGetNoteContentMock; + + @MockBean + private MakeCompositeRequest makeCompositeRequestMock; + + @BeforeEach + public void setUp() throws DynamobeeException, IOException { + setup.perform(); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + @ParameterizedTest + @MethodSource("testScenariosProvider") + public void getNoteDetails(Scenario testScenario) throws Exception { + String currentFunctionName = new Object() { + }.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture( + "classpath:fixtures/functional/controllers/accountController/getNoteDetails.fixtures.json", + currentFunctionName); + loadFixture.perform(fixtureData); + + ObjectMapper objectMapper = new ObjectMapper(); + + String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; + String accountId = (String) testScenario.getInput().get("accountId"); + String noteId = (String) testScenario.getInput().get("noteId"); + + HttpResponse getNoteDetailsMockResponse = new HttpResponse(); + + getNoteDetailsMockResponse + .setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest"))); + + when(makeCompositeRequestMock.makePostRequest(any(), any())).thenReturn(getNoteDetailsMockResponse); + + HttpResponse getNoteContentMockResponse = new HttpResponse(); + getNoteContentMockResponse + .setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeWrapperRequest"))); + + when(salesforceGetNoteContentMock.getNoteContent(any(), any())).thenReturn(getNoteContentMockResponse); + + String url = "/api/v1/accounts/" + accountId + "/notes/" + noteId; + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get(url) + .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) + .contentType(MediaType.APPLICATION_JSON)); + + String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); + String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); + + if (resultActions.andReturn().getResponse().getStatus() == 200) { + assertEquals(expectedOutput, actualOutput); + } + else { + common.compareErrors(testScenario, actualOutput); + } + + } + + static Stream testScenariosProvider() throws IOException { + List testScenarios = loadScenarios(); + return testScenarios.stream(); + } + + private static List loadScenarios() throws IOException { + String scenariosPath = "classpath:data/functional/controllers/accountController/getNoteDetails.scenarios.json"; + Resource resource = new DefaultResourceLoader().getResource(scenariosPath); + ObjectMapper objectMapper = new ObjectMapper(); + + try (InputStream inputStream = resource.getInputStream()) { + return objectMapper.readValue(inputStream, new TypeReference>() { + }); + } + } + } diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteListTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteListTest.java index d87993c0..6e798a92 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteListTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetNoteListTest.java @@ -55,107 +55,113 @@ @WebAppConfiguration @Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) public class GetNoteListTest { - @Autowired - private MockMvc mockMvc; - - @Autowired - private Setup setup; - - @Autowired - private Cleanup cleanup; - - @Autowired - private Common common; - - @Autowired - private LoadFixture loadFixture; - - @MockBean - private MakeCompositeRequest makeCompositeRequestMock; - - @MockBean - private SalesforceRequest salesforceOauthRequestMock; - - @BeforeEach - public void setUp() throws DynamobeeException, IOException { - setup.perform(); - } - - @AfterEach - public void tearDown() { - cleanup.perform(); - } - - @ParameterizedTest - @MethodSource("testScenariosProvider") - public void getNoteList(Scenario testScenario) throws Exception{ - String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture( - "classpath:fixtures/functional/controllers/accountController/getNotesList.fixtures.json", - currentFunctionName - ); - loadFixture.perform(fixtureData); - - ObjectMapper objectMapper = new ObjectMapper(); - - String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; - String accountId = (String) testScenario.getInput().get("accountId"); - List documentIds = (List) testScenario.getInput().get("documentId"); - - if(documentIds == null) { - documentIds = new ArrayList(); - } - - // Mocking the CompositeRequests of the salesforce oauth request - SalesforceQueryBuilder salesforceLib = new SalesforceQueryBuilder(); - String documentIdsQuery = salesforceLib.getContentDocumentIdUrl(accountId); - String documentIdsUrl = new SalesforceConstants().queryUrlPath() + documentIdsQuery; - CompositeRequestDto documentIdsCompositeReq = new CompositeRequestDto("GET", documentIdsUrl, "GetContentDocumentId"); - List compositeRequests = new ArrayList(); - compositeRequests.add(documentIdsCompositeReq); - - - HttpResponse getNotesListIdMockResponse = new HttpResponse(); - getNotesListIdMockResponse.setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest1"))); - - when(makeCompositeRequestMock.makePostRequest(eq(compositeRequests), any())).thenReturn(getNotesListIdMockResponse); - - // Mocking the CompositeRequests of the salesforce notes list request - String notesQuery = salesforceLib.getNoteListIdUrl(documentIds); - String notesUrl = new SalesforceConstants().queryUrlPath() + notesQuery; - CompositeRequestDto noteCompositeRequest = new CompositeRequestDto("GET", notesUrl, "GetNotesList"); - List noteCompositeRequests = new ArrayList(); - noteCompositeRequests.add(noteCompositeRequest); - - - HttpResponse getNotesListMockResponse = new HttpResponse(); - getNotesListMockResponse.setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest2"))); - - when(makeCompositeRequestMock.makePostRequest(eq(noteCompositeRequests), any())).thenReturn(getNotesListMockResponse); - - String url = "/api/v1/accounts/" + accountId + "/notes"; - ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get(url) - .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) - .contentType(MediaType.APPLICATION_JSON)); - - String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); - - String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); - assertEquals(expectedOutput, actualOutput); - } - - static Stream testScenariosProvider() throws IOException { - List testScenarios = loadScenarios(); - return testScenarios.stream(); - } - - private static List loadScenarios() throws IOException { - String scenariosPath = "classpath:data/functional/controllers/accountController/getNotesList.scenarios.json"; - Resource resource = new DefaultResourceLoader().getResource(scenariosPath); - ObjectMapper objectMapper = new ObjectMapper(); - - try (InputStream inputStream = resource.getInputStream()) { - return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); - } - } + + @Autowired + private MockMvc mockMvc; + + @Autowired + private Setup setup; + + @Autowired + private Cleanup cleanup; + + @Autowired + private Common common; + + @Autowired + private LoadFixture loadFixture; + + @MockBean + private MakeCompositeRequest makeCompositeRequestMock; + + @MockBean + private SalesforceRequest salesforceOauthRequestMock; + + @BeforeEach + public void setUp() throws DynamobeeException, IOException { + setup.perform(); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + @ParameterizedTest + @MethodSource("testScenariosProvider") + public void getNoteList(Scenario testScenario) throws Exception { + String currentFunctionName = new Object() { + }.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture( + "classpath:fixtures/functional/controllers/accountController/getNotesList.fixtures.json", + currentFunctionName); + loadFixture.perform(fixtureData); + + ObjectMapper objectMapper = new ObjectMapper(); + + String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; + String accountId = (String) testScenario.getInput().get("accountId"); + List documentIds = (List) testScenario.getInput().get("documentId"); + + if (documentIds == null) { + documentIds = new ArrayList(); + } + + // Mocking the CompositeRequests of the salesforce oauth request + SalesforceQueryBuilder salesforceLib = new SalesforceQueryBuilder(); + String documentIdsQuery = salesforceLib.getContentDocumentIdUrl(accountId); + String documentIdsUrl = new SalesforceConstants().queryUrlPath() + documentIdsQuery; + CompositeRequestDto documentIdsCompositeReq = new CompositeRequestDto("GET", documentIdsUrl, + "GetContentDocumentId"); + List compositeRequests = new ArrayList(); + compositeRequests.add(documentIdsCompositeReq); + + HttpResponse getNotesListIdMockResponse = new HttpResponse(); + getNotesListIdMockResponse + .setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest1"))); + + when(makeCompositeRequestMock.makePostRequest(eq(compositeRequests), any())) + .thenReturn(getNotesListIdMockResponse); + + // Mocking the CompositeRequests of the salesforce notes list request + String notesQuery = salesforceLib.getNoteListIdUrl(documentIds); + String notesUrl = new SalesforceConstants().queryUrlPath() + notesQuery; + CompositeRequestDto noteCompositeRequest = new CompositeRequestDto("GET", notesUrl, "GetNotesList"); + List noteCompositeRequests = new ArrayList(); + noteCompositeRequests.add(noteCompositeRequest); + + HttpResponse getNotesListMockResponse = new HttpResponse(); + getNotesListMockResponse + .setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest2"))); + + when(makeCompositeRequestMock.makePostRequest(eq(noteCompositeRequests), any())) + .thenReturn(getNotesListMockResponse); + + String url = "/api/v1/accounts/" + accountId + "/notes"; + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get(url) + .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) + .contentType(MediaType.APPLICATION_JSON)); + + String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); + + String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); + assertEquals(expectedOutput, actualOutput); + } + + static Stream testScenariosProvider() throws IOException { + List testScenarios = loadScenarios(); + return testScenarios.stream(); + } + + private static List loadScenarios() throws IOException { + String scenariosPath = "classpath:data/functional/controllers/accountController/getNotesList.scenarios.json"; + Resource resource = new DefaultResourceLoader().getResource(scenariosPath); + ObjectMapper objectMapper = new ObjectMapper(); + + try (InputStream inputStream = resource.getInputStream()) { + return objectMapper.readValue(resource.getInputStream(), new TypeReference>() { + }); + } + } + } diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountNoteController/DeleteAccountNoteTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountNoteController/DeleteAccountNoteTest.java index c2c8e98f..2c5d5cee 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountNoteController/DeleteAccountNoteTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountNoteController/DeleteAccountNoteTest.java @@ -47,72 +47,82 @@ @Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) public class DeleteAccountNoteTest { - @Autowired - private MockMvc mockMvc; - @Autowired - private Common common; - @Autowired - private LoadFixture loadFixture; - @Autowired - private Setup setup; - @Autowired - private Cleanup cleanup; - - @MockBean - private MakeCompositeRequest makeCompositeRequestMock; - - @BeforeEach - public void setUp() throws DynamobeeException { - setup.perform(); - } - - @AfterEach - public void tearDown() { - cleanup.perform(); - } - - @ParameterizedTest - @MethodSource("testScenariosProvider") - public void deleteAccountNote(Scenario testScenario) throws Exception { - - // Load fixture data - String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/functional/controllers/accountNoteController/deleteAccountNote.fixtures.json", currentFunctionName); - loadFixture.perform(fixtureData); - - // Read data from the scenario - ObjectMapper objectMapper = new ObjectMapper(); - String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; - String accountId = (String) testScenario.getInput().get("accountId"); - String noteId = (String) testScenario.getInput().get("noteId"); - - // Prepare mock responses - HttpResponse deleteNoteMockResponse = new HttpResponse(); - deleteNoteMockResponse.setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest"))); - when(makeCompositeRequestMock.makePostRequest(any(), any())).thenReturn(deleteNoteMockResponse); - - // Perform the request - String url = "/api/v1/accounts/" + accountId + "/notes/" + noteId ; - - ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.delete(url) - .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) - .contentType(MediaType.APPLICATION_JSON)); - - // Check the response - String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); - String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); - common.assertCustomEquals(expectedOutput, actualOutput); - } - - static Stream testScenariosProvider() throws IOException { - List testScenarios = loadScenarios(); - return testScenarios.stream(); - } - - private static List loadScenarios() throws IOException { - String scenariosPath = "classpath:data/functional/controllers/accountNoteController/deleteAccountNote.scenarios.json"; - Resource resource = new DefaultResourceLoader().getResource(scenariosPath); - ObjectMapper objectMapper = new ObjectMapper(); - return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); - } + @Autowired + private MockMvc mockMvc; + + @Autowired + private Common common; + + @Autowired + private LoadFixture loadFixture; + + @Autowired + private Setup setup; + + @Autowired + private Cleanup cleanup; + + @MockBean + private MakeCompositeRequest makeCompositeRequestMock; + + @BeforeEach + public void setUp() throws DynamobeeException { + setup.perform(); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + @ParameterizedTest + @MethodSource("testScenariosProvider") + public void deleteAccountNote(Scenario testScenario) throws Exception { + + // Load fixture data + String currentFunctionName = new Object() { + }.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture( + "classpath:fixtures/functional/controllers/accountNoteController/deleteAccountNote.fixtures.json", + currentFunctionName); + loadFixture.perform(fixtureData); + + // Read data from the scenario + ObjectMapper objectMapper = new ObjectMapper(); + String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; + String accountId = (String) testScenario.getInput().get("accountId"); + String noteId = (String) testScenario.getInput().get("noteId"); + + // Prepare mock responses + HttpResponse deleteNoteMockResponse = new HttpResponse(); + deleteNoteMockResponse + .setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest"))); + when(makeCompositeRequestMock.makePostRequest(any(), any())).thenReturn(deleteNoteMockResponse); + + // Perform the request + String url = "/api/v1/accounts/" + accountId + "/notes/" + noteId; + + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.delete(url) + .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) + .contentType(MediaType.APPLICATION_JSON)); + + // Check the response + String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); + String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); + common.assertCustomEquals(expectedOutput, actualOutput); + } + + static Stream testScenariosProvider() throws IOException { + List testScenarios = loadScenarios(); + return testScenarios.stream(); + } + + private static List loadScenarios() throws IOException { + String scenariosPath = "classpath:data/functional/controllers/accountNoteController/deleteAccountNote.scenarios.json"; + Resource resource = new DefaultResourceLoader().getResource(scenariosPath); + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.readValue(resource.getInputStream(), new TypeReference>() { + }); + } + } diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/CreateTaskTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/CreateTaskTest.java index 68e7a8f6..307edeb1 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/CreateTaskTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/CreateTaskTest.java @@ -47,78 +47,89 @@ @Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) public class CreateTaskTest { - @Autowired - private MockMvc mockMvc; - @Autowired - private Common common; - @Autowired - private LoadFixture loadFixture; - @Autowired - private Setup setup; - @Autowired - private Cleanup cleanup; - - @MockBean - private MakeCompositeRequest makeCompositeRequestMock; - - @BeforeEach - public void setUp() throws DynamobeeException { - setup.perform(); - } - - @AfterEach - public void tearDown() { - cleanup.perform(); - } - - @ParameterizedTest - @MethodSource("testScenariosProvider") - public void createTask(Scenario testScenario) throws Exception { - - // Load fixture data - String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/functional/controllers/accountTaskController/createTask.fixtures.json", currentFunctionName); - loadFixture.perform(fixtureData); - - // Read data from the scenario - ObjectMapper objectMapper = new ObjectMapper(); - String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; - String accountId = (String) testScenario.getInput().get("accountId"); - - // Prepare mock responses - HttpResponse createNoteMockResponse = new HttpResponse(); - createNoteMockResponse.setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest"))); - when(makeCompositeRequestMock.makePostRequest(any(), any())).thenReturn(createNoteMockResponse); - - // Perform the request - String requestBody = objectMapper.writeValueAsString(testScenario.getInput().get("body")); - String url = "/api/v1/accounts/" + accountId + "/tasks"; - - ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.post(url) - .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) - .content(requestBody) - .contentType(MediaType.APPLICATION_JSON)); - - // Check the response - String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); - String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); - - if(resultActions.andReturn().getResponse().getStatus() == 201) { - assertEquals(expectedOutput, actualOutput); - } else { - common.compareErrors(testScenario, actualOutput); - } - } - - static Stream testScenariosProvider() throws IOException { - List testScenarios = loadScenarios(); - return testScenarios.stream(); - } - - private static List loadScenarios() throws IOException { - String scenariosPath = "classpath:data/functional/controllers/accountTaskController/createTask.scenarios.json"; - Resource resource = new DefaultResourceLoader().getResource(scenariosPath); - ObjectMapper objectMapper = new ObjectMapper(); - return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); - } + @Autowired + private MockMvc mockMvc; + + @Autowired + private Common common; + + @Autowired + private LoadFixture loadFixture; + + @Autowired + private Setup setup; + + @Autowired + private Cleanup cleanup; + + @MockBean + private MakeCompositeRequest makeCompositeRequestMock; + + @BeforeEach + public void setUp() throws DynamobeeException { + setup.perform(); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + @ParameterizedTest + @MethodSource("testScenariosProvider") + public void createTask(Scenario testScenario) throws Exception { + + // Load fixture data + String currentFunctionName = new Object() { + }.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture( + "classpath:fixtures/functional/controllers/accountTaskController/createTask.fixtures.json", + currentFunctionName); + loadFixture.perform(fixtureData); + + // Read data from the scenario + ObjectMapper objectMapper = new ObjectMapper(); + String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; + String accountId = (String) testScenario.getInput().get("accountId"); + + // Prepare mock responses + HttpResponse createNoteMockResponse = new HttpResponse(); + createNoteMockResponse + .setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest"))); + when(makeCompositeRequestMock.makePostRequest(any(), any())).thenReturn(createNoteMockResponse); + + // Perform the request + String requestBody = objectMapper.writeValueAsString(testScenario.getInput().get("body")); + String url = "/api/v1/accounts/" + accountId + "/tasks"; + + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.post(url) + .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) + .content(requestBody) + .contentType(MediaType.APPLICATION_JSON)); + + // Check the response + String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); + String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); + + if (resultActions.andReturn().getResponse().getStatus() == 201) { + assertEquals(expectedOutput, actualOutput); + } + else { + common.compareErrors(testScenario, actualOutput); + } + } + + static Stream testScenariosProvider() throws IOException { + List testScenarios = loadScenarios(); + return testScenarios.stream(); + } + + private static List loadScenarios() throws IOException { + String scenariosPath = "classpath:data/functional/controllers/accountTaskController/createTask.scenarios.json"; + Resource resource = new DefaultResourceLoader().getResource(scenariosPath); + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.readValue(resource.getInputStream(), new TypeReference>() { + }); + } + } diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/DeleteAccountTaskTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/DeleteAccountTaskTest.java index 4cdd31f8..538beecd 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/DeleteAccountTaskTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/DeleteAccountTaskTest.java @@ -47,82 +47,93 @@ @Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) public class DeleteAccountTaskTest { - @Autowired - private MockMvc mockMvc; - @Autowired - private Common common; - @Autowired - private LoadFixture loadFixture; - @Autowired - private Setup setup; - @Autowired - private Cleanup cleanup; - - @MockBean - private MakeCompositeRequest makeCompositeRequestMock; - - @BeforeEach - public void setUp() throws DynamobeeException { - setup.perform(); - } - - @AfterEach - public void tearDown() { - cleanup.perform(); - } - - @ParameterizedTest - @MethodSource("testScenariosProvider") - public void deleteAccountTask(Scenario testScenario) throws Exception { - - // Load fixture data - String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/functional/controllers/accountTaskController/deleteAccountTask.fixtures.json", currentFunctionName); - loadFixture.perform(fixtureData); - - // Read data from the scenario - ObjectMapper objectMapper = new ObjectMapper(); - String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; - String accountId = (String) testScenario.getInput().get("accountId"); - String taskId = (String) testScenario.getInput().get("taskId"); - - // Prepare mock responses - HttpResponse createNoteMockResponse = new HttpResponse(); - createNoteMockResponse.setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest"))); - when(makeCompositeRequestMock.makePostRequest(any(), any())).thenReturn(createNoteMockResponse); - - // Perform the request - String requestBody = objectMapper.writeValueAsString(testScenario.getInput().get("body")); - String url = "/api/v1/accounts/" + accountId + "/tasks/" + taskId; - - ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.delete(url) - .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) - .content(requestBody) - .contentType(MediaType.APPLICATION_JSON)); - - // Check the response - String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); - String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); - - if(resultActions.andReturn().getResponse().getStatus() == 204) { - if (expectedOutput.equals("{}")) { - expectedOutput = ""; - } - assertEquals(expectedOutput, actualOutput); - } else { - common.compareErrors(testScenario, actualOutput); - } - } - - static Stream testScenariosProvider() throws IOException { - List testScenarios = loadScenarios(); - return testScenarios.stream(); - } - - private static List loadScenarios() throws IOException { - String scenariosPath = "classpath:data/functional/controllers/accountTaskController/deleteAccountTask.scenarios.json"; - Resource resource = new DefaultResourceLoader().getResource(scenariosPath); - ObjectMapper objectMapper = new ObjectMapper(); - return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); - } + @Autowired + private MockMvc mockMvc; + + @Autowired + private Common common; + + @Autowired + private LoadFixture loadFixture; + + @Autowired + private Setup setup; + + @Autowired + private Cleanup cleanup; + + @MockBean + private MakeCompositeRequest makeCompositeRequestMock; + + @BeforeEach + public void setUp() throws DynamobeeException { + setup.perform(); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + @ParameterizedTest + @MethodSource("testScenariosProvider") + public void deleteAccountTask(Scenario testScenario) throws Exception { + + // Load fixture data + String currentFunctionName = new Object() { + }.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture( + "classpath:fixtures/functional/controllers/accountTaskController/deleteAccountTask.fixtures.json", + currentFunctionName); + loadFixture.perform(fixtureData); + + // Read data from the scenario + ObjectMapper objectMapper = new ObjectMapper(); + String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; + String accountId = (String) testScenario.getInput().get("accountId"); + String taskId = (String) testScenario.getInput().get("taskId"); + + // Prepare mock responses + HttpResponse createNoteMockResponse = new HttpResponse(); + createNoteMockResponse + .setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest"))); + when(makeCompositeRequestMock.makePostRequest(any(), any())).thenReturn(createNoteMockResponse); + + // Perform the request + String requestBody = objectMapper.writeValueAsString(testScenario.getInput().get("body")); + String url = "/api/v1/accounts/" + accountId + "/tasks/" + taskId; + + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.delete(url) + .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) + .content(requestBody) + .contentType(MediaType.APPLICATION_JSON)); + + // Check the response + String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); + String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); + + if (resultActions.andReturn().getResponse().getStatus() == 204) { + if (expectedOutput.equals("{}")) { + expectedOutput = ""; + } + assertEquals(expectedOutput, actualOutput); + } + else { + common.compareErrors(testScenario, actualOutput); + } + } + + static Stream testScenariosProvider() throws IOException { + List testScenarios = loadScenarios(); + return testScenarios.stream(); + } + + private static List loadScenarios() throws IOException { + String scenariosPath = "classpath:data/functional/controllers/accountTaskController/deleteAccountTask.scenarios.json"; + Resource resource = new DefaultResourceLoader().getResource(scenariosPath); + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.readValue(resource.getInputStream(), new TypeReference>() { + }); + } + } diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/GetAccountTasksListTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/GetAccountTasksListTest.java index a9ee431b..3914c29f 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/GetAccountTasksListTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountTaskController/GetAccountTasksListTest.java @@ -47,71 +47,81 @@ @Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) public class GetAccountTasksListTest { - @Autowired - private MockMvc mockMvc; - @Autowired - private Common common; - @Autowired - private LoadFixture loadFixture; - @Autowired - private Setup setup; - @Autowired - private Cleanup cleanup; - - @MockBean - private MakeCompositeRequest makeCompositeRequestMock; - - @BeforeEach - public void setUp() throws DynamobeeException { - setup.perform(); - } - - @AfterEach - public void tearDown() { - cleanup.perform(); - } - - @ParameterizedTest - @MethodSource("testScenariosProvider") - public void getAccountTasksList(Scenario testScenario) throws Exception { - - // Load fixture data - String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/functional/controllers/accountTaskController/getAccountTasksList.fixtures.json", currentFunctionName); - loadFixture.perform(fixtureData); - - // Read data from the scenario - ObjectMapper objectMapper = new ObjectMapper(); - String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; - String accountId = (String) testScenario.getInput().get("accountId"); - - // Prepare mock responses - HttpResponse getTasksListMockResponse = new HttpResponse(); - getTasksListMockResponse.setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest"))); - when(makeCompositeRequestMock.makePostRequest(any(), any())).thenReturn(getTasksListMockResponse); - - // Perform the request - String url = "/api/v1/accounts/" + accountId + "/tasks"; - - ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get(url) - .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) - .contentType(MediaType.APPLICATION_JSON)); - - // Check the response - String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); - String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); - assertEquals(expectedOutput, actualOutput); - } - - static Stream testScenariosProvider() throws IOException { - List testScenarios = loadScenarios(); - return testScenarios.stream(); - } - - private static List loadScenarios() throws IOException { - String scenariosPath = "classpath:data/functional/controllers/accountTaskController/getAccountTasksList.scenarios.json"; - Resource resource = new DefaultResourceLoader().getResource(scenariosPath); - ObjectMapper objectMapper = new ObjectMapper(); - return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); - } + @Autowired + private MockMvc mockMvc; + + @Autowired + private Common common; + + @Autowired + private LoadFixture loadFixture; + + @Autowired + private Setup setup; + + @Autowired + private Cleanup cleanup; + + @MockBean + private MakeCompositeRequest makeCompositeRequestMock; + + @BeforeEach + public void setUp() throws DynamobeeException { + setup.perform(); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + @ParameterizedTest + @MethodSource("testScenariosProvider") + public void getAccountTasksList(Scenario testScenario) throws Exception { + + // Load fixture data + String currentFunctionName = new Object() { + }.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture( + "classpath:fixtures/functional/controllers/accountTaskController/getAccountTasksList.fixtures.json", + currentFunctionName); + loadFixture.perform(fixtureData); + + // Read data from the scenario + ObjectMapper objectMapper = new ObjectMapper(); + String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; + String accountId = (String) testScenario.getInput().get("accountId"); + + // Prepare mock responses + HttpResponse getTasksListMockResponse = new HttpResponse(); + getTasksListMockResponse + .setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest"))); + when(makeCompositeRequestMock.makePostRequest(any(), any())).thenReturn(getTasksListMockResponse); + + // Perform the request + String url = "/api/v1/accounts/" + accountId + "/tasks"; + + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get(url) + .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) + .contentType(MediaType.APPLICATION_JSON)); + + // Check the response + String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); + String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); + assertEquals(expectedOutput, actualOutput); + } + + static Stream testScenariosProvider() throws IOException { + List testScenarios = loadScenarios(); + return testScenarios.stream(); + } + + private static List loadScenarios() throws IOException { + String scenariosPath = "classpath:data/functional/controllers/accountTaskController/getAccountTasksList.scenarios.json"; + Resource resource = new DefaultResourceLoader().getResource(scenariosPath); + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.readValue(resource.getInputStream(), new TypeReference>() { + }); + } + } diff --git a/src/test/java/com/salessparrow/api/functional/controllers/authController/GetRedirectUrlTest.java b/src/test/java/com/salessparrow/api/functional/controllers/authController/GetRedirectUrlTest.java index e6e33786..535cb06f 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/authController/GetRedirectUrlTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/authController/GetRedirectUrlTest.java @@ -24,31 +24,36 @@ @WebAppConfiguration @Import({ Setup.class, Cleanup.class, Common.class }) public class GetRedirectUrlTest { - @Autowired - private MockMvc mockMvc; - - @Autowired - private Common common; - - @Test - public void getRedirectUrl() throws Exception{ - List testDataItems = common.loadScenariosData("classpath:data/functional/controllers/authController/redirectUrl.scenarios.json"); - - for (Scenario testDataItem : testDataItems) { - ObjectMapper objectMapper = new ObjectMapper(); - String expectedOutput = objectMapper.writeValueAsString(testDataItem.getOutput()); - - ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/auth/salesforce/redirect-url") - .param("redirect_uri", (String) testDataItem.getInput().get("redirect_uri")) - .param("state", (String) testDataItem.getInput().get("state")) - .contentType(MediaType.APPLICATION_JSON)); - - String contentAsString = resultActions.andReturn().getResponse().getContentAsString(); - if(resultActions.andReturn().getResponse().getStatus() == 200) { - assertEquals(expectedOutput, contentAsString); - } else { - common.compareErrors(testDataItem, contentAsString); - } - } - } + + @Autowired + private MockMvc mockMvc; + + @Autowired + private Common common; + + @Test + public void getRedirectUrl() throws Exception { + List testDataItems = common + .loadScenariosData("classpath:data/functional/controllers/authController/redirectUrl.scenarios.json"); + + for (Scenario testDataItem : testDataItems) { + ObjectMapper objectMapper = new ObjectMapper(); + String expectedOutput = objectMapper.writeValueAsString(testDataItem.getOutput()); + + ResultActions resultActions = mockMvc + .perform(MockMvcRequestBuilders.get("/api/v1/auth/salesforce/redirect-url") + .param("redirect_uri", (String) testDataItem.getInput().get("redirect_uri")) + .param("state", (String) testDataItem.getInput().get("state")) + .contentType(MediaType.APPLICATION_JSON)); + + String contentAsString = resultActions.andReturn().getResponse().getContentAsString(); + if (resultActions.andReturn().getResponse().getStatus() == 200) { + assertEquals(expectedOutput, contentAsString); + } + else { + common.compareErrors(testDataItem, contentAsString); + } + } + } + } 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..03ca555f 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 @@ -39,76 +39,77 @@ @WebAppConfiguration @Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) public class PostLogoutTest { - @Autowired - private ResourceLoader resourceLoader; - - @Autowired - private MockMvc mockMvc; - - @Autowired - private Setup setup; - - @Autowired - private Cleanup cleanup; - - @Autowired - private Common common; - - @Autowired - private LoadFixture loadFixture; - - @BeforeEach - public void setUp() throws DynamobeeException, IOException { - setup.perform(); - } - - @AfterEach - public void tearDown() { - cleanup.perform(); - } - - @Test - public void testPostLogout() throws Exception { - String currentFunctionName = new Object() { - }.getClass().getEnclosingMethod().getName(); - - FixtureData fixtureData = common.loadFixture( - "classpath:fixtures/functional/controllers/authController/PostLogoutFixture.json", - currentFunctionName); - loadFixture.perform(fixtureData); - - List testDataItems = loadTestData(currentFunctionName); - - for (Scenario testDataItem : testDataItems) { - System.out.println("Test description: " + testDataItem.getDescription()); - ObjectMapper objectMapper = new ObjectMapper(); - String expectedOutput = objectMapper.writeValueAsString(testDataItem.getOutput()); - String cookieValue = (String) testDataItem.getInput().get("cookie"); - - ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.post("/api/v1/auth/logout") - .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); - } - } - } - - 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); - } + + @Autowired + private ResourceLoader resourceLoader; + + @Autowired + private MockMvc mockMvc; + + @Autowired + private Setup setup; + + @Autowired + private Cleanup cleanup; + + @Autowired + private Common common; + + @Autowired + private LoadFixture loadFixture; + + @BeforeEach + public void setUp() throws DynamobeeException, IOException { + setup.perform(); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + @Test + public void testPostLogout() throws Exception { + String currentFunctionName = new Object() { + }.getClass().getEnclosingMethod().getName(); + + FixtureData fixtureData = common.loadFixture( + "classpath:fixtures/functional/controllers/authController/PostLogoutFixture.json", currentFunctionName); + loadFixture.perform(fixtureData); + + List testDataItems = loadTestData(currentFunctionName); + + for (Scenario testDataItem : testDataItems) { + System.out.println("Test description: " + testDataItem.getDescription()); + ObjectMapper objectMapper = new ObjectMapper(); + String expectedOutput = objectMapper.writeValueAsString(testDataItem.getOutput()); + String cookieValue = (String) testDataItem.getInput().get("cookie"); + + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.post("/api/v1/auth/logout") + .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); + } + } + } + + 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 dafdf4c0..d918ffbd 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 @@ -50,136 +50,146 @@ @WebAppConfiguration @Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) public class PostSalesforceConnectTest { - @Autowired - private ResourceLoader resourceLoader; - @Autowired - private MockMvc mockMvc; + @Autowired + private ResourceLoader resourceLoader; - @Autowired - private Setup setup; + @Autowired + private MockMvc mockMvc; - @Autowired - private Cleanup cleanup; + @Autowired + private Setup setup; - @Autowired - private Common common; + @Autowired + private Cleanup cleanup; - @Autowired - private LoadFixture loadFixture; + @Autowired + private Common common; - @MockBean - private SalesforceGetTokens mockGetTokens; + @Autowired + private LoadFixture loadFixture; - @MockBean - private SalesforceGetIdentity mockGetIdentity; + @MockBean + private SalesforceGetTokens mockGetTokens; - @Mock - private HttpResponse getTokensHttpMockResponse; + @MockBean + private SalesforceGetIdentity mockGetIdentity; + + @Mock + private HttpResponse getTokensHttpMockResponse; + + @InjectMocks + private AuthService authService; - @InjectMocks - private AuthService authService; - - @BeforeEach - public void setUp() throws DynamobeeException, IOException { - MockitoAnnotations.openMocks(this); - setup.perform(); - } - - @AfterEach - public void tearDown() { - cleanup.perform(); - } - - @Test - public void testPostSalesforceConnectSignup() throws Exception { - String currentFunctionName = new Object() { - }.getClass().getEnclosingMethod().getName(); - - List testDataItems = loadTestData(currentFunctionName); - - for (Scenario testDataItem : testDataItems) { - System.out.println("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); - - 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()); - } - } - } - - @Test - public void testPostSalesforceConnectLogin() 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 = loadTestData(currentFunctionName); - - for (Scenario testDataItem : testDataItems) { - System.out.println("Test description: " + testDataItem.getDescription()); - ObjectMapper objectMapper = new ObjectMapper(); - - HttpResponse getTokensMockRes = new HttpResponse(); - getTokensMockRes.setResponseBody(objectMapper.writeValueAsString(testDataItem.getMocks().get("getTokens"))); - - 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"))) - .accept(MediaType.APPLICATION_JSON).characterEncoding("UTF-8") - .contentType(MediaType.APPLICATION_JSON)); - - String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); - - if (resultActions.andReturn().getResponse().getStatus() == 200) { - 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()); - } - } - - } - - 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(); - - Map> scenariosMap = new HashMap<>(); - scenariosMap = objectMapper.readValue(resource.getInputStream(), - new TypeReference>>() { - }); - return scenariosMap.get(key); - } + @BeforeEach + public void setUp() throws DynamobeeException, IOException { + MockitoAnnotations.openMocks(this); + setup.perform(); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + @Test + public void testPostSalesforceConnectSignup() throws Exception { + String currentFunctionName = new Object() { + }.getClass().getEnclosingMethod().getName(); + + List testDataItems = loadTestData(currentFunctionName); + + for (Scenario testDataItem : testDataItems) { + System.out.println("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); + + 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()); + } + } + } + + @Test + public void testPostSalesforceConnectLogin() 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 = loadTestData(currentFunctionName); + + for (Scenario testDataItem : testDataItems) { + System.out.println("Test description: " + testDataItem.getDescription()); + ObjectMapper objectMapper = new ObjectMapper(); + + HttpResponse getTokensMockRes = new HttpResponse(); + getTokensMockRes.setResponseBody(objectMapper.writeValueAsString(testDataItem.getMocks().get("getTokens"))); + + 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"))) + .accept(MediaType.APPLICATION_JSON) + .characterEncoding("UTF-8") + .contentType(MediaType.APPLICATION_JSON)); + + String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); + + if (resultActions.andReturn().getResponse().getStatus() == 200) { + 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()); + } + } + + } + + 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(); + + 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/crmOrganizationUserController/GetCrmOrganizationUserListTest.java b/src/test/java/com/salessparrow/api/functional/controllers/crmOrganizationUserController/GetCrmOrganizationUserListTest.java index af3bbc42..4c439e11 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/crmOrganizationUserController/GetCrmOrganizationUserListTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/crmOrganizationUserController/GetCrmOrganizationUserListTest.java @@ -47,81 +47,92 @@ @WebAppConfiguration @Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) public class GetCrmOrganizationUserListTest { - @Autowired - private MockMvc mockMvc; - @Autowired - private Common common; - @Autowired - private LoadFixture loadFixture; - @Autowired - private Setup setup; - @Autowired - private Cleanup cleanup; - - @MockBean - private MakeCompositeRequest makeCompositeRequestMock; - - @BeforeEach - public void setUp() throws DynamobeeException { - setup.perform(); - } - - @AfterEach - public void tearDown() { - cleanup.perform(); - } - - @ParameterizedTest - @MethodSource("testScenariosProvider") - public void getCrmOrganizationUserList(Scenario testScenario) throws Exception { - // Load fixture data - String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/functional/controllers/crmOrganizationUserController/getCrmOrganizationUserList.fixtures.json", currentFunctionName); - loadFixture.perform(fixtureData); - - // Read data from the scenario - ObjectMapper objectMapper = new ObjectMapper(); - - String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; - String q = (String) testScenario.getInput().get("q"); - - // Prepare mock responses - HttpResponse getAccountMockResponse = new HttpResponse(); - getAccountMockResponse.setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest"))); - when(makeCompositeRequestMock.makePostRequest(any(), any())).thenReturn(getAccountMockResponse); - - // Perform the request - String url = "/api/v1/crm-organization-users"; - - ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get(url) - .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) - .param("q", q) - .contentType(MediaType.APPLICATION_JSON)); - - - // Check the response - String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); - String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); - - JsonNode expectedOutputJson = objectMapper.readTree(expectedOutput); - JsonNode actualOutputJson = objectMapper.readTree(actualOutput); - - if(resultActions.andReturn().getResponse().getStatus() == 200) { - assertEquals(expectedOutputJson, actualOutputJson); - } else { - common.compareErrors(testScenario, actualOutput); - } - } - - static Stream testScenariosProvider() throws IOException { - List testScenarios = loadScenarios(); - return testScenarios.stream(); - } - - private static List loadScenarios() throws IOException { - String scenariosPath = "classpath:data/functional/controllers/crmOrganizationUserController/getCrmOrganizationUserList.scenarios.json"; - Resource resource = new DefaultResourceLoader().getResource(scenariosPath); - ObjectMapper objectMapper = new ObjectMapper(); - return objectMapper.readValue(resource.getInputStream(), new TypeReference>() {}); - } + + @Autowired + private MockMvc mockMvc; + + @Autowired + private Common common; + + @Autowired + private LoadFixture loadFixture; + + @Autowired + private Setup setup; + + @Autowired + private Cleanup cleanup; + + @MockBean + private MakeCompositeRequest makeCompositeRequestMock; + + @BeforeEach + public void setUp() throws DynamobeeException { + setup.perform(); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + @ParameterizedTest + @MethodSource("testScenariosProvider") + public void getCrmOrganizationUserList(Scenario testScenario) throws Exception { + // Load fixture data + String currentFunctionName = new Object() { + }.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture( + "classpath:fixtures/functional/controllers/crmOrganizationUserController/getCrmOrganizationUserList.fixtures.json", + currentFunctionName); + loadFixture.perform(fixtureData); + + // Read data from the scenario + ObjectMapper objectMapper = new ObjectMapper(); + + String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; + String q = (String) testScenario.getInput().get("q"); + + // Prepare mock responses + HttpResponse getAccountMockResponse = new HttpResponse(); + getAccountMockResponse + .setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest"))); + when(makeCompositeRequestMock.makePostRequest(any(), any())).thenReturn(getAccountMockResponse); + + // Perform the request + String url = "/api/v1/crm-organization-users"; + + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get(url) + .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) + .param("q", q) + .contentType(MediaType.APPLICATION_JSON)); + + // Check the response + String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); + String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); + + JsonNode expectedOutputJson = objectMapper.readTree(expectedOutput); + JsonNode actualOutputJson = objectMapper.readTree(actualOutput); + + if (resultActions.andReturn().getResponse().getStatus() == 200) { + assertEquals(expectedOutputJson, actualOutputJson); + } + else { + common.compareErrors(testScenario, actualOutput); + } + } + + static Stream testScenariosProvider() throws IOException { + List testScenarios = loadScenarios(); + return testScenarios.stream(); + } + + private static List loadScenarios() throws IOException { + String scenariosPath = "classpath:data/functional/controllers/crmOrganizationUserController/getCrmOrganizationUserList.scenarios.json"; + Resource resource = new DefaultResourceLoader().getResource(scenariosPath); + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.readValue(resource.getInputStream(), new TypeReference>() { + }); + } + } diff --git a/src/test/java/com/salessparrow/api/functional/controllers/suggestionsController/PostCrmActionsSuggestionsTest.java b/src/test/java/com/salessparrow/api/functional/controllers/suggestionsController/PostCrmActionsSuggestionsTest.java index 4c31f70e..73abe853 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/suggestionsController/PostCrmActionsSuggestionsTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/suggestionsController/PostCrmActionsSuggestionsTest.java @@ -41,62 +41,69 @@ @WebAppConfiguration @Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) public class PostCrmActionsSuggestionsTest { - @Autowired - private MockMvc mockMvc; - - @Autowired - private Setup setup; - - @Autowired - private Cleanup cleanup; - - @Autowired - private Common common; - - @Autowired - private LoadFixture loadFixture; - - @MockBean - private OpenAiRequest openAiRequestMock; - - @BeforeEach - public void setUp() throws DynamobeeException, IOException { - setup.perform(); - } - - @AfterEach - public void tearDown() { - cleanup.perform(); - } - - @Test - public void testPostCrmActionsSuggestions() throws Exception { - String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/functional/controllers/suggestionsController/postCrmActionsSuggestions.fixtures.json", - currentFunctionName); - loadFixture.perform(fixtureData); - - List testDataItems = common.loadScenariosData("classpath:data/functional/controllers/suggestionsController/crmActionsSuggestions.scenarios.json"); - for (Scenario testDataItem : testDataItems) { - ObjectMapper objectMapper = new ObjectMapper(); - HttpResponse getAccountMockResponse = new HttpResponse(); - getAccountMockResponse.setResponseBody(objectMapper.writeValueAsString(testDataItem.getMocks().get("makeRequest"))); - when(openAiRequestMock.makeRequest(any())).thenReturn(getAccountMockResponse); - - String expectedOutput = objectMapper.writeValueAsString(testDataItem.getOutput()); - String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; - - ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.post("/api/v1/suggestions/crm-actions") - .content(objectMapper.writeValueAsString(testDataItem.getInput())) - .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) { - assertEquals(expectedOutput, actualOutput); - } else { - common.compareErrors(testDataItem, actualOutput); - } - } - } + + @Autowired + private MockMvc mockMvc; + + @Autowired + private Setup setup; + + @Autowired + private Cleanup cleanup; + + @Autowired + private Common common; + + @Autowired + private LoadFixture loadFixture; + + @MockBean + private OpenAiRequest openAiRequestMock; + + @BeforeEach + public void setUp() throws DynamobeeException, IOException { + setup.perform(); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + @Test + public void testPostCrmActionsSuggestions() throws Exception { + String currentFunctionName = new Object() { + }.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture( + "classpath:fixtures/functional/controllers/suggestionsController/postCrmActionsSuggestions.fixtures.json", + currentFunctionName); + loadFixture.perform(fixtureData); + + List testDataItems = common.loadScenariosData( + "classpath:data/functional/controllers/suggestionsController/crmActionsSuggestions.scenarios.json"); + for (Scenario testDataItem : testDataItems) { + ObjectMapper objectMapper = new ObjectMapper(); + HttpResponse getAccountMockResponse = new HttpResponse(); + getAccountMockResponse + .setResponseBody(objectMapper.writeValueAsString(testDataItem.getMocks().get("makeRequest"))); + when(openAiRequestMock.makeRequest(any())).thenReturn(getAccountMockResponse); + + String expectedOutput = objectMapper.writeValueAsString(testDataItem.getOutput()); + String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; + + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.post("/api/v1/suggestions/crm-actions") + .content(objectMapper.writeValueAsString(testDataItem.getInput())) + .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) { + assertEquals(expectedOutput, actualOutput); + } + else { + common.compareErrors(testDataItem, actualOutput); + } + } + } + } diff --git a/src/test/java/com/salessparrow/api/functional/controllers/userController/GetCurrentUserTest.java b/src/test/java/com/salessparrow/api/functional/controllers/userController/GetCurrentUserTest.java index 0d11b37d..9d022e18 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/userController/GetCurrentUserTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/userController/GetCurrentUserTest.java @@ -33,54 +33,60 @@ @WebAppConfiguration @Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) public class GetCurrentUserTest { - @Autowired - private MockMvc mockMvc; - - @Autowired - private Setup setup; - - @Autowired - private Cleanup cleanup; - - @Autowired - private Common common; - - @Autowired - private LoadFixture loadFixture; - - @BeforeEach - public void setUp() throws DynamobeeException, IOException { - setup.perform(); - } - - @AfterEach - public void tearDown() { - cleanup.perform(); - } - - @Test - public void getCurrentUser() throws Exception{ - String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/functional/controllers/userController/getCurrentUser.fixtures.json", - currentFunctionName); - loadFixture.perform(fixtureData); - - List testDataItems = common.loadScenariosData("classpath:data/functional/controllers/userController/getCurrentUser.scenarios.json"); - for (Scenario testDataItem : testDataItems) { - ObjectMapper objectMapper = new ObjectMapper(); - String expectedOutput = objectMapper.writeValueAsString(testDataItem.getOutput()); - String cookieValue = (String) testDataItem.getInput().get("cookie"); - - ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/users/current") - .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) { - assertEquals(expectedOutput, actualOutput); - } else { - common.compareErrors(testDataItem, actualOutput); - } - } - } + + @Autowired + private MockMvc mockMvc; + + @Autowired + private Setup setup; + + @Autowired + private Cleanup cleanup; + + @Autowired + private Common common; + + @Autowired + private LoadFixture loadFixture; + + @BeforeEach + public void setUp() throws DynamobeeException, IOException { + setup.perform(); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + @Test + public void getCurrentUser() throws Exception { + String currentFunctionName = new Object() { + }.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture( + "classpath:fixtures/functional/controllers/userController/getCurrentUser.fixtures.json", + currentFunctionName); + loadFixture.perform(fixtureData); + + List testDataItems = common + .loadScenariosData("classpath:data/functional/controllers/userController/getCurrentUser.scenarios.json"); + for (Scenario testDataItem : testDataItems) { + ObjectMapper objectMapper = new ObjectMapper(); + String expectedOutput = objectMapper.writeValueAsString(testDataItem.getOutput()); + String cookieValue = (String) testDataItem.getInput().get("cookie"); + + ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/users/current") + .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) { + assertEquals(expectedOutput, actualOutput); + } + else { + common.compareErrors(testDataItem, actualOutput); + } + } + } + } diff --git a/src/test/java/com/salessparrow/api/functional/exception/GlobalExceptionHandlerTest.java b/src/test/java/com/salessparrow/api/functional/exception/GlobalExceptionHandlerTest.java index 221d47e4..a1f759f0 100644 --- a/src/test/java/com/salessparrow/api/functional/exception/GlobalExceptionHandlerTest.java +++ b/src/test/java/com/salessparrow/api/functional/exception/GlobalExceptionHandlerTest.java @@ -25,46 +25,47 @@ import com.salessparrow.api.helper.Scenario; import com.salessparrow.api.helper.Setup; - @SpringBootTest @AutoConfigureMockMvc @WebAppConfiguration @Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) public class GlobalExceptionHandlerTest { - @Autowired - private MockMvc mockMvc; - @Autowired - private Setup setup; + @Autowired + private MockMvc mockMvc; - @Autowired - private Cleanup cleanup; + @Autowired + private Setup setup; - @Autowired - private Common common; + @Autowired + private Cleanup cleanup; - @BeforeEach - public void setUp() throws DynamobeeException, IOException { - setup.perform(); - } + @Autowired + private Common common; - @AfterEach - public void tearDown() { - cleanup.perform(); - } + @BeforeEach + public void setUp() throws DynamobeeException, IOException { + setup.perform(); + } - @Test - public void handleNoHandlerFoundException() throws Exception{ - List testDataItems = common.loadScenariosData("classpath:data/functional/exceptions/globalExceptionHandler.scenarios.json"); - for (Scenario testDataItem : testDataItems) { + @AfterEach + public void tearDown() { + cleanup.perform(); + } - ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/unknown-route") - .contentType(MediaType.APPLICATION_JSON)); + @Test + public void handleNoHandlerFoundException() throws Exception { + List testDataItems = common + .loadScenariosData("classpath:data/functional/exceptions/globalExceptionHandler.scenarios.json"); + for (Scenario testDataItem : testDataItems) { - String contentAsString = resultActions.andReturn().getResponse().getContentAsString(); - common.compareErrors(testDataItem, contentAsString); - } + ResultActions resultActions = mockMvc + .perform(MockMvcRequestBuilders.get("/api/v1/unknown-route").contentType(MediaType.APPLICATION_JSON)); - } -} + String contentAsString = resultActions.andReturn().getResponse().getContentAsString(); + common.compareErrors(testDataItem, contentAsString); + } + } + +} diff --git a/src/test/java/com/salessparrow/api/functional/interceptors/JsonOnlyInterceptorTest.java b/src/test/java/com/salessparrow/api/functional/interceptors/JsonOnlyInterceptorTest.java index c34fc2e9..94d090fe 100644 --- a/src/test/java/com/salessparrow/api/functional/interceptors/JsonOnlyInterceptorTest.java +++ b/src/test/java/com/salessparrow/api/functional/interceptors/JsonOnlyInterceptorTest.java @@ -25,45 +25,47 @@ import com.salessparrow.api.helper.Scenario; import com.salessparrow.api.helper.Setup; - @SpringBootTest @AutoConfigureMockMvc @WebAppConfiguration @Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) public class JsonOnlyInterceptorTest { - @Autowired - private MockMvc mockMvc; - @Autowired - private Setup setup; + @Autowired + private MockMvc mockMvc; - @Autowired - private Cleanup cleanup; + @Autowired + private Setup setup; - @Autowired - private Common common; + @Autowired + private Cleanup cleanup; - @BeforeEach - public void setUp() throws DynamobeeException, IOException { - setup.perform(); - } + @Autowired + private Common common; - @AfterEach - public void tearDown() { - cleanup.perform(); - } + @BeforeEach + public void setUp() throws DynamobeeException, IOException { + setup.perform(); + } - @Test - public void preHandle() throws Exception{ - List testDataItems = common.loadScenariosData("classpath:data/functional/interceptors/jsonOnlyInterceptor.scenarios.json"); - for (Scenario testDataItem : testDataItems) { - ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/auth/salesforce/redirect-url") - .contentType(MediaType.ALL_VALUE)); + @AfterEach + public void tearDown() { + cleanup.perform(); + } - String contentAsString = resultActions.andReturn().getResponse().getContentAsString(); - common.compareErrors(testDataItem, contentAsString); - } + @Test + public void preHandle() throws Exception { + List testDataItems = common + .loadScenariosData("classpath:data/functional/interceptors/jsonOnlyInterceptor.scenarios.json"); + for (Scenario testDataItem : testDataItems) { + ResultActions resultActions = mockMvc + .perform(MockMvcRequestBuilders.get("/api/v1/auth/salesforce/redirect-url") + .contentType(MediaType.ALL_VALUE)); - } -} + String contentAsString = resultActions.andReturn().getResponse().getContentAsString(); + common.compareErrors(testDataItem, contentAsString); + } + } + +} diff --git a/src/test/java/com/salessparrow/api/helper/Cleanup.java b/src/test/java/com/salessparrow/api/helper/Cleanup.java index 8f8fa4aa..156c0b40 100644 --- a/src/test/java/com/salessparrow/api/helper/Cleanup.java +++ b/src/test/java/com/salessparrow/api/helper/Cleanup.java @@ -12,39 +12,39 @@ @TestConfiguration public class Cleanup { - Logger logger = LoggerFactory.getLogger(Cleanup.class); - - @Autowired - private DropTables dropTables; - - @Autowired - private CacheManager cacheManager; - - /** - * Clean the setup after each test. - * - Flush the cache - * - Drop dynamodb tables - */ - public void perform() { - logger.info("Cleaning setup"); - - flushCache(); - dropTables(); - } - - /** - * Flush the cache. - */ - private void flushCache(){ - logger.info("Setup: Flushing cache"); - cacheManager.getCacheNames().stream().forEach(cacheName -> { - cacheManager.getCache(cacheName).clear(); - }); } - - /** - * Drop the tables. - */ - private void dropTables() { - dropTables.perform(); - } + Logger logger = LoggerFactory.getLogger(Cleanup.class); + + @Autowired + private DropTables dropTables; + + @Autowired + private CacheManager cacheManager; + + /** + * Clean the setup after each test. - Flush the cache - Drop dynamodb tables + */ + public void perform() { + logger.info("Cleaning setup"); + + flushCache(); + dropTables(); + } + + /** + * Flush the cache. + */ + private void flushCache() { + logger.info("Setup: Flushing cache"); + cacheManager.getCacheNames().stream().forEach(cacheName -> { + cacheManager.getCache(cacheName).clear(); + }); + } + + /** + * Drop the tables. + */ + private void dropTables() { + dropTables.perform(); + } + } diff --git a/src/test/java/com/salessparrow/api/helper/Common.java b/src/test/java/com/salessparrow/api/helper/Common.java index 45ff3eda..8ec4596d 100644 --- a/src/test/java/com/salessparrow/api/helper/Common.java +++ b/src/test/java/com/salessparrow/api/helper/Common.java @@ -21,71 +21,71 @@ */ @TestConfiguration public class Common { - @Autowired - private ResourceLoader resourceLoader; - /** - * Load the fixture data from the given location. - * - * @param location - * @param key - * @return FixtureData - * @throws IOException - */ - public FixtureData loadFixture(String location, String key) throws IOException { - Resource resource = resourceLoader.getResource(location); - ObjectMapper objectMapper = new ObjectMapper(); - Map fixtureMap = new HashMap<>(); - fixtureMap = objectMapper.readValue(resource.getInputStream(), new TypeReference>() { - }); - return fixtureMap.get(key); - } + @Autowired + private ResourceLoader resourceLoader; - /** - * Load the test scenario data from the given location. - * - * @param location - * @return List - * @throws IOException - */ - public List loadScenariosData(String location) throws IOException { - Resource resource = resourceLoader.getResource(location); - ObjectMapper objectMapper = new ObjectMapper(); - return objectMapper.readValue(resource.getInputStream(), new TypeReference>() { - }); - } + /** + * Load the fixture data from the given location. + * @param location + * @param key + * @return FixtureData + * @throws IOException + */ + public FixtureData loadFixture(String location, String key) throws IOException { + Resource resource = resourceLoader.getResource(location); + ObjectMapper objectMapper = new ObjectMapper(); + Map fixtureMap = new HashMap<>(); + fixtureMap = objectMapper.readValue(resource.getInputStream(), + new TypeReference>() { + }); + return fixtureMap.get(key); + } - /** - * Compare the errors from the test data with the actual errors. - * - * @param testDataItem - * @param contentAsString - */ - public void compareErrors(Scenario testDataItem, String contentAsString) throws Exception { - ObjectMapper objectMapper = new ObjectMapper(); - JsonNode resJsonNode = objectMapper.readTree(contentAsString); - Integer httpCode = resJsonNode.get("http_code").asInt(); - assertEquals(testDataItem.getOutput().get("http_code"), httpCode); + /** + * Load the test scenario data from the given location. + * @param location + * @return List + * @throws IOException + */ + public List loadScenariosData(String location) throws IOException { + Resource resource = resourceLoader.getResource(location); + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.readValue(resource.getInputStream(), new TypeReference>() { + }); + } - String code = resJsonNode.get("code").asText(); - assertEquals(testDataItem.getOutput().get("code"), code); + /** + * Compare the errors from the test data with the actual errors. + * @param testDataItem + * @param contentAsString + */ + public void compareErrors(Scenario testDataItem, String contentAsString) throws Exception { + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode resJsonNode = objectMapper.readTree(contentAsString); + Integer httpCode = resJsonNode.get("http_code").asInt(); + assertEquals(testDataItem.getOutput().get("http_code"), httpCode); - List paramErrors = (List) testDataItem.getOutput().get("param_errors"); - if (paramErrors != null) { - for (int i = 0; i < paramErrors.size(); i++) { - String actualError = resJsonNode.get("param_errors").get(i).get("param_error_identifier").asText(); - assertEquals(paramErrors.contains(actualError), true); - } - } - } + String code = resJsonNode.get("code").asText(); + assertEquals(testDataItem.getOutput().get("code"), code); - // Custom assertion method that treats {} and "" as the same - public void assertCustomEquals(String expected, String actual) { + List paramErrors = (List) testDataItem.getOutput().get("param_errors"); + if (paramErrors != null) { + for (int i = 0; i < paramErrors.size(); i++) { + String actualError = resJsonNode.get("param_errors").get(i).get("param_error_identifier").asText(); + assertEquals(paramErrors.contains(actualError), true); + } + } + } - if (expected.equals("{}")) { - expected = ""; - } + // Custom assertion method that treats {} and "" as the same + public void assertCustomEquals(String expected, String actual) { + + if (expected.equals("{}")) { + expected = ""; + } + + assertEquals(expected, actual); + } - assertEquals(expected, actual); - } } diff --git a/src/test/java/com/salessparrow/api/helper/Constants.java b/src/test/java/com/salessparrow/api/helper/Constants.java index 41822d84..0ad4b468 100644 --- a/src/test/java/com/salessparrow/api/helper/Constants.java +++ b/src/test/java/com/salessparrow/api/helper/Constants.java @@ -4,5 +4,7 @@ * Constants is a helper class for the tests. */ public class Constants { - public static final String SALESFORCE_ACTIVE_USER_COOKIE_VALUE = "1:0055i00000AUxQHAA1:SALESFORCE:app:1692878227:a2xOxjcPChK/YsKCWRuY50J3gH21/tqcGlv7sWU/aPw3/UFVFPbvWn2LLzY5B5kVPXjj1gELRqa4B4ds6uuqIw=="; + + public static final String SALESFORCE_ACTIVE_USER_COOKIE_VALUE = "1:0055i00000AUxQHAA1:SALESFORCE:app:1692878227:a2xOxjcPChK/YsKCWRuY50J3gH21/tqcGlv7sWU/aPw3/UFVFPbvWn2LLzY5B5kVPXjj1gELRqa4B4ds6uuqIw=="; + } diff --git a/src/test/java/com/salessparrow/api/helper/DropTables.java b/src/test/java/com/salessparrow/api/helper/DropTables.java index 573b55b4..4b7da5e3 100644 --- a/src/test/java/com/salessparrow/api/helper/DropTables.java +++ b/src/test/java/com/salessparrow/api/helper/DropTables.java @@ -17,38 +17,39 @@ */ @TestConfiguration public class DropTables { - Logger logger = LoggerFactory.getLogger(DropTables.class); - - @Autowired - private AmazonDynamoDB dynamoDB; - - /** - * This method is used to drop the tables. - */ - public void perform() { - if (!CoreConstants.isTestEnvironment() && !CoreConstants.isLocalTestEnvironment()) { - throw new RuntimeException("Cannot drop tables in non test environment"); - } - - List tableList = getAllTableList(); - String envPrefix = CoreConstants.environment() + "_"; - - for (String tableName : tableList) { - if (tableName.startsWith(envPrefix)) { - dynamoDB.deleteTable(tableName); - } - } - } - - /** - * This method is used to get all the table list. - * - * @return List of table names - */ - private List getAllTableList() { - ListTablesRequest listTablesRequest = new ListTablesRequest(); - ListTablesResult listTablesResult = dynamoDB.listTables(listTablesRequest); - - return listTablesResult.getTableNames(); - } + + Logger logger = LoggerFactory.getLogger(DropTables.class); + + @Autowired + private AmazonDynamoDB dynamoDB; + + /** + * This method is used to drop the tables. + */ + public void perform() { + if (!CoreConstants.isTestEnvironment() && !CoreConstants.isLocalTestEnvironment()) { + throw new RuntimeException("Cannot drop tables in non test environment"); + } + + List tableList = getAllTableList(); + String envPrefix = CoreConstants.environment() + "_"; + + for (String tableName : tableList) { + if (tableName.startsWith(envPrefix)) { + dynamoDB.deleteTable(tableName); + } + } + } + + /** + * This method is used to get all the table list. + * @return List of table names + */ + private List getAllTableList() { + ListTablesRequest listTablesRequest = new ListTablesRequest(); + ListTablesResult listTablesResult = dynamoDB.listTables(listTablesRequest); + + return listTablesResult.getTableNames(); + } + } diff --git a/src/test/java/com/salessparrow/api/helper/FixtureData.java b/src/test/java/com/salessparrow/api/helper/FixtureData.java index d65283f4..f82bcfc8 100644 --- a/src/test/java/com/salessparrow/api/helper/FixtureData.java +++ b/src/test/java/com/salessparrow/api/helper/FixtureData.java @@ -6,12 +6,18 @@ @Data public class FixtureData { - List salesforce_users; - List salesforce_oauth_tokens; - List salesforce_organizations; + + List salesforce_users; + + List salesforce_oauth_tokens; + + List salesforce_organizations; + } @Data class FilePathData { - String filepath; + + String filepath; + } \ No newline at end of file diff --git a/src/test/java/com/salessparrow/api/helper/LoadFixture.java b/src/test/java/com/salessparrow/api/helper/LoadFixture.java index 59851447..ba2a7e75 100644 --- a/src/test/java/com/salessparrow/api/helper/LoadFixture.java +++ b/src/test/java/com/salessparrow/api/helper/LoadFixture.java @@ -20,97 +20,97 @@ * LoadFixture is a helper class for the tests. */ public class LoadFixture { - @Autowired - private ResourceLoader resourceLoader; - - @Autowired - private SalesforceUserRepository salesforceUserRepository; - - - @Autowired - private SalesforceOauthTokenRepository salesforceOauthTokenRepository; - - - @Autowired - private SalesforceOrganizationRepository salesforceOrganizationRepository; - - /** - * Load the fixture data. - * - * @param location - * @return FixtureData - * @throws IOException - */ - public void perform(FixtureData fixtureData) throws IOException { - - if (fixtureData.getSalesforce_users() != null) { - for (FilePathData filePathData : fixtureData.getSalesforce_users()) { - SalesforceUser salesforceUser = loadSalesForceUserFixture(filePathData.getFilepath()); - salesforceUserRepository.saveSalesforceUser(salesforceUser); - } - } - - if (fixtureData.getSalesforce_oauth_tokens() != null) { - for (FilePathData filePathData : fixtureData.getSalesforce_oauth_tokens()) { - SalesforceOauthToken salesforceOauth = loadSalesForceOAuthTokenFixture(filePathData.getFilepath()); - salesforceOauthTokenRepository.saveSalesforceOauthToken(salesforceOauth); - } - } - - if (fixtureData.getSalesforce_organizations() != null) { - for (FilePathData filePathData : fixtureData.getSalesforce_organizations()) { - SalesforceOrganization salesforceOrganization = loadSalesForceOrganizationFixture(filePathData.getFilepath()); - salesforceOrganizationRepository.saveSalesforceOrganization(salesforceOrganization); - } - } - - } - - /** - * Load the SalesforceUser fixture data from the given location. - * - * @param location - * @return FixtureData - * @throws IOException - */ - public SalesforceUser loadSalesForceUserFixture(String location) throws IOException { - Resource resource = resourceLoader.getResource(location); - ObjectMapper objectMapper = new ObjectMapper(); - - try (InputStream inputStream = resource.getInputStream()) { - return objectMapper.readValue(resource.getInputStream(), new TypeReference() {}); - } - } - - /** - * Load the SalesforceOauthToken fixture data from the given location. - * - * @param location - * @return FixtureData - * @throws IOException - */ - public SalesforceOauthToken loadSalesForceOAuthTokenFixture(String location) throws IOException { - Resource resource = resourceLoader.getResource(location); - ObjectMapper objectMapper = new ObjectMapper(); - - try (InputStream inputStream = resource.getInputStream()) { - return objectMapper.readValue(resource.getInputStream(), new TypeReference() {}); - } - } - - /** - * Load the SalesforceOrganization fixture data from the given location. - * - * @param location - * @return FixtureData - * @throws IOException - */ - public SalesforceOrganization loadSalesForceOrganizationFixture(String location) throws IOException { - Resource resource = resourceLoader.getResource(location); - ObjectMapper objectMapper = new ObjectMapper(); - - try (InputStream inputStream = resource.getInputStream()) { - return objectMapper.readValue(resource.getInputStream(), new TypeReference() {}); - } - } + + @Autowired + private ResourceLoader resourceLoader; + + @Autowired + private SalesforceUserRepository salesforceUserRepository; + + @Autowired + private SalesforceOauthTokenRepository salesforceOauthTokenRepository; + + @Autowired + private SalesforceOrganizationRepository salesforceOrganizationRepository; + + /** + * Load the fixture data. + * @param location + * @return FixtureData + * @throws IOException + */ + public void perform(FixtureData fixtureData) throws IOException { + + if (fixtureData.getSalesforce_users() != null) { + for (FilePathData filePathData : fixtureData.getSalesforce_users()) { + SalesforceUser salesforceUser = loadSalesForceUserFixture(filePathData.getFilepath()); + salesforceUserRepository.saveSalesforceUser(salesforceUser); + } + } + + if (fixtureData.getSalesforce_oauth_tokens() != null) { + for (FilePathData filePathData : fixtureData.getSalesforce_oauth_tokens()) { + SalesforceOauthToken salesforceOauth = loadSalesForceOAuthTokenFixture(filePathData.getFilepath()); + salesforceOauthTokenRepository.saveSalesforceOauthToken(salesforceOauth); + } + } + + if (fixtureData.getSalesforce_organizations() != null) { + for (FilePathData filePathData : fixtureData.getSalesforce_organizations()) { + SalesforceOrganization salesforceOrganization = loadSalesForceOrganizationFixture( + filePathData.getFilepath()); + salesforceOrganizationRepository.saveSalesforceOrganization(salesforceOrganization); + } + } + + } + + /** + * Load the SalesforceUser fixture data from the given location. + * @param location + * @return FixtureData + * @throws IOException + */ + public SalesforceUser loadSalesForceUserFixture(String location) throws IOException { + Resource resource = resourceLoader.getResource(location); + ObjectMapper objectMapper = new ObjectMapper(); + + try (InputStream inputStream = resource.getInputStream()) { + return objectMapper.readValue(resource.getInputStream(), new TypeReference() { + }); + } + } + + /** + * Load the SalesforceOauthToken fixture data from the given location. + * @param location + * @return FixtureData + * @throws IOException + */ + public SalesforceOauthToken loadSalesForceOAuthTokenFixture(String location) throws IOException { + Resource resource = resourceLoader.getResource(location); + ObjectMapper objectMapper = new ObjectMapper(); + + try (InputStream inputStream = resource.getInputStream()) { + return objectMapper.readValue(resource.getInputStream(), new TypeReference() { + }); + } + } + + /** + * Load the SalesforceOrganization fixture data from the given location. + * @param location + * @return FixtureData + * @throws IOException + */ + public SalesforceOrganization loadSalesForceOrganizationFixture(String location) throws IOException { + Resource resource = resourceLoader.getResource(location); + ObjectMapper objectMapper = new ObjectMapper(); + + try (InputStream inputStream = resource.getInputStream()) { + return objectMapper.readValue(resource.getInputStream(), new TypeReference() { + }); + } + } + } diff --git a/src/test/java/com/salessparrow/api/helper/Scenario.java b/src/test/java/com/salessparrow/api/helper/Scenario.java index f7264683..f00d367d 100644 --- a/src/test/java/com/salessparrow/api/helper/Scenario.java +++ b/src/test/java/com/salessparrow/api/helper/Scenario.java @@ -6,11 +6,13 @@ @Data public class Scenario { - String description; - Map input; + String description; - Map mocks; + Map input; + + Map mocks; + + Map output; - Map output; } diff --git a/src/test/java/com/salessparrow/api/helper/Setup.java b/src/test/java/com/salessparrow/api/helper/Setup.java index c5d4049b..cdaad0d5 100644 --- a/src/test/java/com/salessparrow/api/helper/Setup.java +++ b/src/test/java/com/salessparrow/api/helper/Setup.java @@ -17,53 +17,52 @@ @Import({ DropTables.class }) public class Setup { - Logger logger = LoggerFactory.getLogger(Setup.class); + Logger logger = LoggerFactory.getLogger(Setup.class); - @Autowired - private DropTables dropTables; - - @Autowired - private Dynamobee dynamobee; - - @Autowired - private CacheManager cacheManager; + @Autowired + private DropTables dropTables; - /** - * Create the setup. - * - Flush the cache - * - Drop dynamodb tables - * - Run migrations - * @throws DynamobeeException - */ - public void perform() throws DynamobeeException { - logger.info("Creating setup"); + @Autowired + private Dynamobee dynamobee; - flushCache(); - dropTables(); - runMigrations(); - } + @Autowired + private CacheManager cacheManager; - /** - * Flush the cache. - */ - private void flushCache(){ - logger.info("Setup: Flushing cache"); - cacheManager.getCacheNames().stream().forEach(cacheName -> { - cacheManager.getCache(cacheName).clear(); - }); } + /** + * Create the setup. - Flush the cache - Drop dynamodb tables - Run migrations + * @throws DynamobeeException + */ + public void perform() throws DynamobeeException { + logger.info("Creating setup"); - /** - * Drop dynamodb tables. - */ - private void dropTables() { - dropTables.perform(); - } + flushCache(); + dropTables(); + runMigrations(); + } + + /** + * Flush the cache. + */ + private void flushCache() { + logger.info("Setup: Flushing cache"); + cacheManager.getCacheNames().stream().forEach(cacheName -> { + cacheManager.getCache(cacheName).clear(); + }); + } + + /** + * Drop dynamodb tables. + */ + private void dropTables() { + dropTables.perform(); + } + + /** + * Run migrations. + * @throws DynamobeeException + */ + public void runMigrations() throws DynamobeeException { + dynamobee.execute(); + } - /** - * Run migrations. - * @throws DynamobeeException - */ - public void runMigrations() throws DynamobeeException { - dynamobee.execute(); - } } diff --git a/src/test/java/com/salessparrow/api/lib/UtilTest.java b/src/test/java/com/salessparrow/api/lib/UtilTest.java index d819f9ed..2c735d10 100644 --- a/src/test/java/com/salessparrow/api/lib/UtilTest.java +++ b/src/test/java/com/salessparrow/api/lib/UtilTest.java @@ -15,30 +15,31 @@ public class UtilTest { - @Mock - private ObjectMapper objectMapper; + @Mock + private ObjectMapper objectMapper; - @InjectMocks - private Util util; + @InjectMocks + private Util util; - @BeforeEach - public void setup() { - MockitoAnnotations.openMocks(this); - } + @BeforeEach + public void setup() { + MockitoAnnotations.openMocks(this); + } - @Test - public void testGetJsonNode_ValidJson() throws Exception { - String jsonString = "{\"key\": \"value\"}"; + @Test + public void testGetJsonNode_ValidJson() throws Exception { + String jsonString = "{\"key\": \"value\"}"; - JsonNode resultJsonNode = util.getJsonNode(jsonString); + JsonNode resultJsonNode = util.getJsonNode(jsonString); - assertEquals("value", resultJsonNode.get("key").asText()); - } + assertEquals("value", resultJsonNode.get("key").asText()); + } - @Test - public void testGetJsonNode_InvalidJson() throws Exception { - String invalidJsonString = "invalid json"; + @Test + public void testGetJsonNode_InvalidJson() throws Exception { + String invalidJsonString = "invalid json"; + + assertThrows(CustomException.class, () -> util.getJsonNode(invalidJsonString)); + } - assertThrows(CustomException.class, () -> util.getJsonNode(invalidJsonString)); - } } diff --git a/src/test/java/com/salessparrow/api/unit/globalConstants/SalesforceConstantsTest.java b/src/test/java/com/salessparrow/api/unit/globalConstants/SalesforceConstantsTest.java index 6a88b400..36f1a00a 100644 --- a/src/test/java/com/salessparrow/api/unit/globalConstants/SalesforceConstantsTest.java +++ b/src/test/java/com/salessparrow/api/unit/globalConstants/SalesforceConstantsTest.java @@ -8,73 +8,78 @@ @SpringBootTest public class SalesforceConstantsTest { - @Test - void testCompositeUrlPath() { - assertEquals("/services/data/v58.0/composite", new SalesforceConstants().compositeUrlPath()); - } - - @Test - void testQueryUrlPath() { - assertEquals("/services/data/v58.0/query/?q=", new SalesforceConstants().queryUrlPath()); - } - - @Test - void testSObjectsPath() { - assertEquals("/services/data/v58.0/sobjects", new SalesforceConstants().sObjectsPath()); - } - - @Test - void testSalesforceCompositeUrl() { - assertEquals("https://test.salesforce.com/services/data/v58.0/composite", new SalesforceConstants().salesforceCompositeUrl("https://test.salesforce.com")); - } - - @Test - void testOauth2AuthorizeUrl() { - assertEquals("https://test.salesforce.com/services/oauth2/authorize", new SalesforceConstants().oauth2AuthorizeUrl()); - } - - @Test - void testOauth2Url() { - assertEquals("https://test.salesforce.com/services/oauth2/token", new SalesforceConstants().oauth2Url()); - } - - @Test - void testSalesforceCreateNoteUrl() { - assertEquals("/services/data/v58.0/sobjects/ContentNote", new SalesforceConstants().salesforceCreateNoteUrl()); - } - - @Test - void testSalesforceAttachNoteUrl() { - assertEquals("/services/data/v58.0/sobjects/ContentDocumentLink", new SalesforceConstants().salesforceAttachNoteUrl()); - } - - @Test - void testIdentityUrl() { - assertEquals("/services/oauth2/userinfo", new SalesforceConstants().identityUrl()); - } - - @Test - void testAuthorizationCodeGrantType() { - assertEquals("authorization_code", new SalesforceConstants().authorizationCodeGrantType()); - } - - @Test - void testRefreshTokenGrantType() { - assertEquals("refresh_token", new SalesforceConstants().refreshTokenGrantType()); - } - - @Test - void testTimeoutMillis() { - assertEquals(10000, new SalesforceConstants().timeoutMillis()); - } - - @Test - void testSalesforceNotesContentUrl() { - assertEquals("https://test.salesforce.com/services/data/v58.0/sobjects/ContentNote/123/Content", new SalesforceConstants().salesforceNotesContentUrl("https://test.salesforce.com", "123")); - } - - @Test - void testSalesforceCreateTaskUrl() { - assertEquals("/services/data/v58.0/sobjects/Task", new SalesforceConstants().salesforceCreateTaskUrl()); - } + @Test + void testCompositeUrlPath() { + assertEquals("/services/data/v58.0/composite", new SalesforceConstants().compositeUrlPath()); + } + + @Test + void testQueryUrlPath() { + assertEquals("/services/data/v58.0/query/?q=", new SalesforceConstants().queryUrlPath()); + } + + @Test + void testSObjectsPath() { + assertEquals("/services/data/v58.0/sobjects", new SalesforceConstants().sObjectsPath()); + } + + @Test + void testSalesforceCompositeUrl() { + assertEquals("https://test.salesforce.com/services/data/v58.0/composite", + new SalesforceConstants().salesforceCompositeUrl("https://test.salesforce.com")); + } + + @Test + void testOauth2AuthorizeUrl() { + assertEquals("https://test.salesforce.com/services/oauth2/authorize", + new SalesforceConstants().oauth2AuthorizeUrl()); + } + + @Test + void testOauth2Url() { + assertEquals("https://test.salesforce.com/services/oauth2/token", new SalesforceConstants().oauth2Url()); + } + + @Test + void testSalesforceCreateNoteUrl() { + assertEquals("/services/data/v58.0/sobjects/ContentNote", new SalesforceConstants().salesforceCreateNoteUrl()); + } + + @Test + void testSalesforceAttachNoteUrl() { + assertEquals("/services/data/v58.0/sobjects/ContentDocumentLink", + new SalesforceConstants().salesforceAttachNoteUrl()); + } + + @Test + void testIdentityUrl() { + assertEquals("/services/oauth2/userinfo", new SalesforceConstants().identityUrl()); + } + + @Test + void testAuthorizationCodeGrantType() { + assertEquals("authorization_code", new SalesforceConstants().authorizationCodeGrantType()); + } + + @Test + void testRefreshTokenGrantType() { + assertEquals("refresh_token", new SalesforceConstants().refreshTokenGrantType()); + } + + @Test + void testTimeoutMillis() { + assertEquals(10000, new SalesforceConstants().timeoutMillis()); + } + + @Test + void testSalesforceNotesContentUrl() { + assertEquals("https://test.salesforce.com/services/data/v58.0/sobjects/ContentNote/123/Content", + new SalesforceConstants().salesforceNotesContentUrl("https://test.salesforce.com", "123")); + } + + @Test + void testSalesforceCreateTaskUrl() { + assertEquals("/services/data/v58.0/sobjects/Task", new SalesforceConstants().salesforceCreateTaskUrl()); + } + } diff --git a/src/test/java/com/salessparrow/api/unit/globalConstants/UserConstantsTest.java b/src/test/java/com/salessparrow/api/unit/globalConstants/UserConstantsTest.java index 9e82eb4e..0b3a70ef 100644 --- a/src/test/java/com/salessparrow/api/unit/globalConstants/UserConstantsTest.java +++ b/src/test/java/com/salessparrow/api/unit/globalConstants/UserConstantsTest.java @@ -11,16 +11,17 @@ @SpringBootTest public class UserConstantsTest { - @Test - void testGetName() { - assertEquals("SALESFORCE", UserConstants.SALESFORCE_USER_KIND); - } - - @Test - void testPrivateConstructor() throws NoSuchMethodException, IllegalAccessException, InstantiationException { - Constructor constructor = UserConstants.class.getDeclaredConstructor(); - constructor.setAccessible(true); - assertThrows(InvocationTargetException.class, constructor::newInstance); - } + + @Test + void testGetName() { + assertEquals("SALESFORCE", UserConstants.SALESFORCE_USER_KIND); + } + + @Test + void testPrivateConstructor() throws NoSuchMethodException, IllegalAccessException, InstantiationException { + Constructor constructor = UserConstants.class.getDeclaredConstructor(); + constructor.setAccessible(true); + assertThrows(InvocationTargetException.class, constructor::newInstance); + } } diff --git a/src/test/java/com/salessparrow/api/unit/lib/UtilTest.java b/src/test/java/com/salessparrow/api/unit/lib/UtilTest.java index 4af3f629..8d589b93 100644 --- a/src/test/java/com/salessparrow/api/unit/lib/UtilTest.java +++ b/src/test/java/com/salessparrow/api/unit/lib/UtilTest.java @@ -7,26 +7,27 @@ import com.salessparrow.api.lib.Util; public class UtilTest { - - @Test - public void testEscapeSpecialChars() { - String[] inputStrings = {"\\a","%a","_a","'a","\"a"}; - String[] expectedOutputs = {"\\\\a","\\%a","\\_a","\\'a","\\\"a"}; - - for(int i = 0; i < inputStrings.length; i++) { - String result = Util.escapeSpecialChars(inputStrings[i]); - assertEquals(expectedOutputs[i], result); - } - } - - @Test - public void testUrlEncoder() { - String[] inputStrings = {"\\\\a","\\%a","\\_a","\\'a","\\\"a","a+b","a b"}; - String[] expectedOutputs = {"%5C%5Ca","%5C%25a","%5C_a","%5C%27a","%5C%22a","a%2Bb","a+b"}; - - for(int i = 0; i < inputStrings.length; i++) { - String result = Util.urlEncoder(inputStrings[i]); - assertEquals(expectedOutputs[i], result); - } - } + + @Test + public void testEscapeSpecialChars() { + String[] inputStrings = { "\\a", "%a", "_a", "'a", "\"a" }; + String[] expectedOutputs = { "\\\\a", "\\%a", "\\_a", "\\'a", "\\\"a" }; + + for (int i = 0; i < inputStrings.length; i++) { + String result = Util.escapeSpecialChars(inputStrings[i]); + assertEquals(expectedOutputs[i], result); + } + } + + @Test + public void testUrlEncoder() { + String[] inputStrings = { "\\\\a", "\\%a", "\\_a", "\\'a", "\\\"a", "a+b", "a b" }; + String[] expectedOutputs = { "%5C%5Ca", "%5C%25a", "%5C_a", "%5C%27a", "%5C%22a", "a%2Bb", "a+b" }; + + for (int i = 0; i < inputStrings.length; i++) { + String result = Util.urlEncoder(inputStrings[i]); + assertEquals(expectedOutputs[i], result); + } + } + } diff --git a/src/test/java/com/salessparrow/api/unit/lib/openAi/OpenAiRequestTest.java b/src/test/java/com/salessparrow/api/unit/lib/openAi/OpenAiRequestTest.java index a598d998..37b6ec60 100644 --- a/src/test/java/com/salessparrow/api/unit/lib/openAi/OpenAiRequestTest.java +++ b/src/test/java/com/salessparrow/api/unit/lib/openAi/OpenAiRequestTest.java @@ -26,55 +26,61 @@ import com.salessparrow.api.lib.openAi.OpenAiRequest; @SpringBootTest -@Import({Common.class, OpenAiRequest.class}) +@Import({ Common.class, OpenAiRequest.class }) public class OpenAiRequestTest { - @Autowired - private OpenAiRequest openAiRequest; - - @Autowired - private Common common; - - @MockBean - private HttpClient httpClientMock; - - @Test - void testOpenAiRequest() throws IOException { - List testDataItems = common.loadScenariosData("classpath:data/unit/lib/openAi/openAiRequest.scenarios.json"); - MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); - - for (Scenario testDataItem : testDataItems) { - ObjectMapper objectMapper = new ObjectMapper(); - - HttpResponse openAiMocksResponse = new HttpResponse(); - openAiMocksResponse.setResponseBody(objectMapper.writeValueAsString(testDataItem.getMocks().get("makeRequest"))); - httpClientMockedStatic.when(() -> HttpClient.makePostRequest(anyString(), anyMap(), any(), anyInt())) - .thenReturn(openAiMocksResponse); - - HttpResponse actualResponse = openAiRequest.makeRequest(testDataItem.getInput().get("payload")); - String expectedOutput = objectMapper.writeValueAsString(testDataItem.getOutput()); - - assertEquals(actualResponse.getResponseBody(), expectedOutput); - } - httpClientMockedStatic.close(); - } - - @Test - void testOpenAiRequestError() throws IOException { - List testDataItems = common.loadScenariosData("classpath:data/unit/lib/openAi/openAiRequestError.scenarios.json"); - MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); - - for (Scenario testDataItem : testDataItems) { - int statusCode = (int) testDataItem.getInput().get("statusCode"); - httpClientMockedStatic.when(() -> HttpClient.makePostRequest(anyString(), anyMap(), any(), anyInt())) - .thenThrow( new WebClientResponseException("error", statusCode, "error", null, null, null)); - try { - openAiRequest.makeRequest(testDataItem.getInput().get("payload")); - } catch (CustomException e) { - String expectedApiErrorIdentifier = (String) testDataItem.getOutput().get("apiErrorIdentifier"); - - assertEquals(e.getErrorObject().getApiErrorIdentifier(), expectedApiErrorIdentifier); - } - } - httpClientMockedStatic.close(); - } + + @Autowired + private OpenAiRequest openAiRequest; + + @Autowired + private Common common; + + @MockBean + private HttpClient httpClientMock; + + @Test + void testOpenAiRequest() throws IOException { + List testDataItems = common + .loadScenariosData("classpath:data/unit/lib/openAi/openAiRequest.scenarios.json"); + MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); + + for (Scenario testDataItem : testDataItems) { + ObjectMapper objectMapper = new ObjectMapper(); + + HttpResponse openAiMocksResponse = new HttpResponse(); + openAiMocksResponse + .setResponseBody(objectMapper.writeValueAsString(testDataItem.getMocks().get("makeRequest"))); + httpClientMockedStatic.when(() -> HttpClient.makePostRequest(anyString(), anyMap(), any(), anyInt())) + .thenReturn(openAiMocksResponse); + + HttpResponse actualResponse = openAiRequest.makeRequest(testDataItem.getInput().get("payload")); + String expectedOutput = objectMapper.writeValueAsString(testDataItem.getOutput()); + + assertEquals(actualResponse.getResponseBody(), expectedOutput); + } + httpClientMockedStatic.close(); + } + + @Test + void testOpenAiRequestError() throws IOException { + List testDataItems = common + .loadScenariosData("classpath:data/unit/lib/openAi/openAiRequestError.scenarios.json"); + MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); + + for (Scenario testDataItem : testDataItems) { + int statusCode = (int) testDataItem.getInput().get("statusCode"); + httpClientMockedStatic.when(() -> HttpClient.makePostRequest(anyString(), anyMap(), any(), anyInt())) + .thenThrow(new WebClientResponseException("error", statusCode, "error", null, null, null)); + try { + openAiRequest.makeRequest(testDataItem.getInput().get("payload")); + } + catch (CustomException e) { + String expectedApiErrorIdentifier = (String) testDataItem.getOutput().get("apiErrorIdentifier"); + + assertEquals(e.getErrorObject().getApiErrorIdentifier(), expectedApiErrorIdentifier); + } + } + httpClientMockedStatic.close(); + } + } diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java index 58d18c00..d63e4198 100644 --- a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java @@ -24,114 +24,115 @@ import com.salessparrow.api.helper.LoadFixture; import com.salessparrow.api.helper.Setup; import com.salessparrow.api.repositories.SalesforceOauthTokenRepository; + @SpringBootTest @Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) public class SalesforceOauthTokenRepositoryTest { - @Autowired - private Setup setup; - - @Autowired - private Cleanup cleanup; - - @Autowired - private Common common; - - @Autowired - private LoadFixture loadFixture; - - private DynamoDBMapper mockDynamoDBMapper; - - private SalesforceOauthTokenRepository realSalesforceOauthTokenRepository; - - private SalesforceOauthTokenRepository mockSalesforceOauthTokenRepository; - - @BeforeEach - public void setUp() throws DynamobeeException, IOException { - setup.perform(); - // Use your Spring bean here - DynamoDBMapper dynamoDBMapper = new DynamoDBConfiguration().dynamoDBMapper(); - this.realSalesforceOauthTokenRepository = new SalesforceOauthTokenRepository(dynamoDBMapper); - - this.mockDynamoDBMapper = mock(DynamoDBMapper.class); // Mocked instance - this.mockSalesforceOauthTokenRepository = new SalesforceOauthTokenRepository(mockDynamoDBMapper); - } - - @AfterEach - public void tearDown() { - cleanup.perform(); - } - - /** - * Test valid case for saveSalesforceOauthToken method - */ - @Test - public void testValidSaveSalesforceOauthToken() { - //Valid Save Db Query - SalesforceOauthToken salesforceOauthTokenValid = new SalesforceOauthToken(); - salesforceOauthTokenValid.setExternalUserId("externalUserId-1"); - - SalesforceOauthToken salesforceOauthTokenResp = this.realSalesforceOauthTokenRepository.saveSalesforceOauthToken(salesforceOauthTokenValid); - assertEquals(salesforceOauthTokenValid.getExternalUserId(), salesforceOauthTokenResp.getExternalUserId()); - } - - /** - * Test invlaid case for saveSalesforceOauthToken method - */ - @Test - public void testInvalidSaveSalesforceOauthToken() { - // Invalid Save Db Query without partition key - SalesforceOauthToken salesforceOauthTokenInvalid = new SalesforceOauthToken(); - salesforceOauthTokenInvalid.setExternalUserId("externalUserId-2"); - - // Mock the behavior to throw an exception when save is called - doThrow(new AmazonDynamoDBException("mock db save error")) - .when(mockDynamoDBMapper) - .save(salesforceOauthTokenInvalid); - - // Test if CustomException is thrown with the expected error code - CustomException thrownException = assertThrows( - CustomException.class, - () -> mockSalesforceOauthTokenRepository.saveSalesforceOauthToken(salesforceOauthTokenInvalid) - ); - // Validate the error identifier to be a 500 error - assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); - } - - /** - * Test valid case for getSalesforceOauthTokenByExternalUserId method - */ - @Test - public void testValidGetSalesforceOauthTokenByExternalUserId() throws Exception{ - - String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/unit/repositories/salesforceOauthTokenRepository.json", currentFunctionName); - loadFixture.perform(fixtureData); - - //Valid Get Db Query - SalesforceOauthToken salesforceOauthTokenResp = this.realSalesforceOauthTokenRepository.getSalesforceOauthTokenByExternalUserId("0055i00000AUxQHAA1"); - assertEquals("0055i00000AUxQHAA1", salesforceOauthTokenResp.getExternalUserId()); - } - - /** - * Test invalid case for getSalesforceOauthTokenByExternalUserId method - */ - @Test - public void testInvalidGetSalesforceOauthTokenByExternalUserId() throws Exception{ - - String testExternalUserId = "externalUserId-3"; - - // Mock the behavior to throw an exception when load is called - when(mockDynamoDBMapper.load(SalesforceOauthToken.class, testExternalUserId)).thenThrow( - new AmazonDynamoDBException("mock db get error")); - - // Mock Invalid Get Db Query - // Test if CustomException is thrown with the expected error code - CustomException thrownException = assertThrows( - CustomException.class, - () -> mockSalesforceOauthTokenRepository.getSalesforceOauthTokenByExternalUserId(testExternalUserId) - ); - // Validate the error identifier to be a 500 error - assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); - } + @Autowired + private Setup setup; + + @Autowired + private Cleanup cleanup; + + @Autowired + private Common common; + + @Autowired + private LoadFixture loadFixture; + + private DynamoDBMapper mockDynamoDBMapper; + + private SalesforceOauthTokenRepository realSalesforceOauthTokenRepository; + + private SalesforceOauthTokenRepository mockSalesforceOauthTokenRepository; + + @BeforeEach + public void setUp() throws DynamobeeException, IOException { + setup.perform(); + // Use your Spring bean here + DynamoDBMapper dynamoDBMapper = new DynamoDBConfiguration().dynamoDBMapper(); + this.realSalesforceOauthTokenRepository = new SalesforceOauthTokenRepository(dynamoDBMapper); + + this.mockDynamoDBMapper = mock(DynamoDBMapper.class); // Mocked instance + this.mockSalesforceOauthTokenRepository = new SalesforceOauthTokenRepository(mockDynamoDBMapper); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + /** + * Test valid case for saveSalesforceOauthToken method + */ + @Test + public void testValidSaveSalesforceOauthToken() { + // Valid Save Db Query + SalesforceOauthToken salesforceOauthTokenValid = new SalesforceOauthToken(); + salesforceOauthTokenValid.setExternalUserId("externalUserId-1"); + + SalesforceOauthToken salesforceOauthTokenResp = this.realSalesforceOauthTokenRepository + .saveSalesforceOauthToken(salesforceOauthTokenValid); + assertEquals(salesforceOauthTokenValid.getExternalUserId(), salesforceOauthTokenResp.getExternalUserId()); + } + + /** + * Test invlaid case for saveSalesforceOauthToken method + */ + @Test + public void testInvalidSaveSalesforceOauthToken() { + // Invalid Save Db Query without partition key + SalesforceOauthToken salesforceOauthTokenInvalid = new SalesforceOauthToken(); + salesforceOauthTokenInvalid.setExternalUserId("externalUserId-2"); + + // Mock the behavior to throw an exception when save is called + doThrow(new AmazonDynamoDBException("mock db save error")).when(mockDynamoDBMapper) + .save(salesforceOauthTokenInvalid); + + // Test if CustomException is thrown with the expected error code + CustomException thrownException = assertThrows(CustomException.class, + () -> mockSalesforceOauthTokenRepository.saveSalesforceOauthToken(salesforceOauthTokenInvalid)); + // Validate the error identifier to be a 500 error + assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); + } + + /** + * Test valid case for getSalesforceOauthTokenByExternalUserId method + */ + @Test + public void testValidGetSalesforceOauthTokenByExternalUserId() throws Exception { + + String currentFunctionName = new Object() { + }.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture( + "classpath:fixtures/unit/repositories/salesforceOauthTokenRepository.json", currentFunctionName); + loadFixture.perform(fixtureData); + + // Valid Get Db Query + SalesforceOauthToken salesforceOauthTokenResp = this.realSalesforceOauthTokenRepository + .getSalesforceOauthTokenByExternalUserId("0055i00000AUxQHAA1"); + assertEquals("0055i00000AUxQHAA1", salesforceOauthTokenResp.getExternalUserId()); + } + + /** + * Test invalid case for getSalesforceOauthTokenByExternalUserId method + */ + @Test + public void testInvalidGetSalesforceOauthTokenByExternalUserId() throws Exception { + + String testExternalUserId = "externalUserId-3"; + + // Mock the behavior to throw an exception when load is called + when(mockDynamoDBMapper.load(SalesforceOauthToken.class, testExternalUserId)) + .thenThrow(new AmazonDynamoDBException("mock db get error")); + + // Mock Invalid Get Db Query + // Test if CustomException is thrown with the expected error code + CustomException thrownException = assertThrows(CustomException.class, + () -> mockSalesforceOauthTokenRepository.getSalesforceOauthTokenByExternalUserId(testExternalUserId)); + // Validate the error identifier to be a 500 error + assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); + } + } diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java index 0767323b..28d9f78b 100644 --- a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOrganizationRepositoryTest.java @@ -29,107 +29,108 @@ @Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) public class SalesforceOrganizationRepositoryTest { - @Autowired - private Setup setup; - - @Autowired - private Cleanup cleanup; - - @Autowired - private Common common; - - @Autowired - private LoadFixture loadFixture; - - private DynamoDBMapper mockDynamoDBMapper; - - private SalesforceOrganizationRepository realSalesforceOrganizationRepository; - - private SalesforceOrganizationRepository mockSalesforceOrganizationRepository; - - @BeforeEach - public void setUp() throws DynamobeeException, IOException { - setup.perform(); - // Use your Spring bean here - DynamoDBMapper dynamoDBMapper = new DynamoDBConfiguration().dynamoDBMapper(); - this.realSalesforceOrganizationRepository = new SalesforceOrganizationRepository(dynamoDBMapper); - - this.mockDynamoDBMapper = mock(DynamoDBMapper.class); // Mocked instance - this.mockSalesforceOrganizationRepository = new SalesforceOrganizationRepository(mockDynamoDBMapper); - } - - @AfterEach - public void tearDown() { - cleanup.perform(); - } - - /** - * Test Valid Save Db Query - */ - @Test - public void testValidSaveSalesforceOrganization() { - //Valid Save Db Query - SalesforceOrganization salesforceOrganizationValid = new SalesforceOrganization(); - salesforceOrganizationValid.setExternalOrganizationId("externalUserId-1"); - SalesforceOrganization salesforceOrganizationResp = this.realSalesforceOrganizationRepository.saveSalesforceOrganization(salesforceOrganizationValid); - assertEquals(salesforceOrganizationValid.getExternalOrganizationId(), salesforceOrganizationResp.getExternalOrganizationId()); - } - - /** - * Test Invalid Save Db Query - */ - @Test - public void testInvalidSaveSalesforceOrganization() { - // Invalid Save Db Query without partition key - SalesforceOrganization salesforceOrganizationInvalid = new SalesforceOrganization(); - salesforceOrganizationInvalid.setExternalOrganizationId("externalUserId-2"); - - // Mock the behavior to throw an exception when save is called - doThrow(new AmazonDynamoDBException("mock db save error")) - .when(mockDynamoDBMapper) - .save(salesforceOrganizationInvalid); - - // Test if CustomException is thrown with the expected error code - CustomException thrownException = assertThrows( - CustomException.class, - () -> mockSalesforceOrganizationRepository.saveSalesforceOrganization(salesforceOrganizationInvalid) - ); - // Validate the error identifier to be a 500 error - assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); - } - - /** - * Test Valid Get Db Query - */ - @Test - public void testValidGetSalesforceOrganizationByExternalOrganizationId() throws Exception{ - String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/unit/repositories/salesforceOrganizationRepository.json", currentFunctionName); - loadFixture.perform(fixtureData); - - //Valid Get Db Query - SalesforceOrganization salesforceOrganizationResp = this.realSalesforceOrganizationRepository.getSalesforceOrganizationByExternalOrganizationId("000Org-id"); - assertEquals("000Org-id", salesforceOrganizationResp.getExternalOrganizationId()); - } - - /** - * Test Invalid Get Db Query - */ - @Test - public void testInvalidGetSalesforceOrganizationByExternalOrganizationId() throws Exception{ - String testExternalOrganizationId = "externalUserId-2"; - - // Mock the behavior to throw an exception when load is called - when(mockDynamoDBMapper.load(SalesforceOrganization.class, testExternalOrganizationId)).thenThrow( - new AmazonDynamoDBException("mock db get error")); - - // Mock Invalid Get Db Query - // Test if CustomException is thrown with the expected error code - CustomException thrownException = assertThrows( - CustomException.class, - () -> mockSalesforceOrganizationRepository.getSalesforceOrganizationByExternalOrganizationId(testExternalOrganizationId) - ); - // Validate the error identifier to be a 500 error - assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); - } + @Autowired + private Setup setup; + + @Autowired + private Cleanup cleanup; + + @Autowired + private Common common; + + @Autowired + private LoadFixture loadFixture; + + private DynamoDBMapper mockDynamoDBMapper; + + private SalesforceOrganizationRepository realSalesforceOrganizationRepository; + + private SalesforceOrganizationRepository mockSalesforceOrganizationRepository; + + @BeforeEach + public void setUp() throws DynamobeeException, IOException { + setup.perform(); + // Use your Spring bean here + DynamoDBMapper dynamoDBMapper = new DynamoDBConfiguration().dynamoDBMapper(); + this.realSalesforceOrganizationRepository = new SalesforceOrganizationRepository(dynamoDBMapper); + + this.mockDynamoDBMapper = mock(DynamoDBMapper.class); // Mocked instance + this.mockSalesforceOrganizationRepository = new SalesforceOrganizationRepository(mockDynamoDBMapper); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + /** + * Test Valid Save Db Query + */ + @Test + public void testValidSaveSalesforceOrganization() { + // Valid Save Db Query + SalesforceOrganization salesforceOrganizationValid = new SalesforceOrganization(); + salesforceOrganizationValid.setExternalOrganizationId("externalUserId-1"); + SalesforceOrganization salesforceOrganizationResp = this.realSalesforceOrganizationRepository + .saveSalesforceOrganization(salesforceOrganizationValid); + assertEquals(salesforceOrganizationValid.getExternalOrganizationId(), + salesforceOrganizationResp.getExternalOrganizationId()); + } + + /** + * Test Invalid Save Db Query + */ + @Test + public void testInvalidSaveSalesforceOrganization() { + // Invalid Save Db Query without partition key + SalesforceOrganization salesforceOrganizationInvalid = new SalesforceOrganization(); + salesforceOrganizationInvalid.setExternalOrganizationId("externalUserId-2"); + + // Mock the behavior to throw an exception when save is called + doThrow(new AmazonDynamoDBException("mock db save error")).when(mockDynamoDBMapper) + .save(salesforceOrganizationInvalid); + + // Test if CustomException is thrown with the expected error code + CustomException thrownException = assertThrows(CustomException.class, + () -> mockSalesforceOrganizationRepository.saveSalesforceOrganization(salesforceOrganizationInvalid)); + // Validate the error identifier to be a 500 error + assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); + } + + /** + * Test Valid Get Db Query + */ + @Test + public void testValidGetSalesforceOrganizationByExternalOrganizationId() throws Exception { + String currentFunctionName = new Object() { + }.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common.loadFixture( + "classpath:fixtures/unit/repositories/salesforceOrganizationRepository.json", currentFunctionName); + loadFixture.perform(fixtureData); + + // Valid Get Db Query + SalesforceOrganization salesforceOrganizationResp = this.realSalesforceOrganizationRepository + .getSalesforceOrganizationByExternalOrganizationId("000Org-id"); + assertEquals("000Org-id", salesforceOrganizationResp.getExternalOrganizationId()); + } + + /** + * Test Invalid Get Db Query + */ + @Test + public void testInvalidGetSalesforceOrganizationByExternalOrganizationId() throws Exception { + String testExternalOrganizationId = "externalUserId-2"; + + // Mock the behavior to throw an exception when load is called + when(mockDynamoDBMapper.load(SalesforceOrganization.class, testExternalOrganizationId)) + .thenThrow(new AmazonDynamoDBException("mock db get error")); + + // Mock Invalid Get Db Query + // Test if CustomException is thrown with the expected error code + CustomException thrownException = assertThrows(CustomException.class, () -> mockSalesforceOrganizationRepository + .getSalesforceOrganizationByExternalOrganizationId(testExternalOrganizationId)); + // Validate the error identifier to be a 500 error + assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); + } + } diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java index cb0cad51..bd9f9a7e 100644 --- a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceUserRepositoryTest.java @@ -33,113 +33,109 @@ @Import({ Setup.class, Cleanup.class, Common.class, LoadFixture.class }) public class SalesforceUserRepositoryTest { - @Autowired - private Setup setup; - - @Autowired - private Cleanup cleanup; - - @Autowired - private Common common; - - @Autowired - private LoadFixture loadFixture; - - private DynamoDBMapper mockDynamoDBMapper; - - private SalesforceUserRepository realSalesforceUserRepository; - - private SalesforceUserRepository mockSalesforceUserRepository; - - @BeforeEach - public void setUp() throws DynamobeeException, IOException { - setup.perform(); - // Use your Spring bean here - DynamoDBMapper dynamoDBMapper = new DynamoDBConfiguration().dynamoDBMapper(); - this.realSalesforceUserRepository = new SalesforceUserRepository(dynamoDBMapper); - - this.mockDynamoDBMapper = mock(DynamoDBMapper.class); // Mocked instance - this.mockSalesforceUserRepository = new SalesforceUserRepository(mockDynamoDBMapper); - } - - @AfterEach - public void tearDown() { - cleanup.perform(); - } - - /** - * Test Valid Save Db Query - * - */ - @Test - public void testValidSaveSalesforceUser() { - //Valid Save Db Query - SalesforceUser salesforceUserValid = new SalesforceUser(); - salesforceUserValid.setExternalUserId("externalUserId-test1"); - SalesforceUser salesforceUserResp = this.realSalesforceUserRepository.saveSalesforceUser(salesforceUserValid); - assertEquals(salesforceUserValid.getExternalUserId(), salesforceUserResp.getExternalUserId()); - } - - /** - * Test Invalid Save Db Query - * - */ - @Test - public void testInvalidSaveSalesforceUser() { - // Invalid Save Db Query without partition key - SalesforceUser salesforceUserInvalid = new SalesforceUser(); - salesforceUserInvalid.setExternalUserId("externalUserId-test2"); - - // Mock the behavior to throw an exception when save is called - doThrow(new AmazonDynamoDBException("mock db save error")) - .when(mockDynamoDBMapper) - .save(salesforceUserInvalid); - - // Test if CustomException is thrown with the expected error code - CustomException thrownException = assertThrows( - CustomException.class, - () -> mockSalesforceUserRepository.saveSalesforceUser(salesforceUserInvalid) - ); - // Validate the error identifier to be a 500 error - assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); - } - - /** - * Test Valid Get Db Query - * - * @throws Exception - */ - @Test - public void testValidGetSalesforceUserByExternalUserId() throws Exception{ - String currentFunctionName = new Object(){}.getClass().getEnclosingMethod().getName(); - FixtureData fixtureData = common.loadFixture("classpath:fixtures/unit/repositories/salesforceUserRepository.json", currentFunctionName); - loadFixture.perform(fixtureData); - - //Valid Get Db Query - SalesforceUser salesforceUserResp = this.realSalesforceUserRepository.getSalesforceUserByExternalUserId("0055i00000AUxQHAA1"); - assertEquals("0055i00000AUxQHAA1", salesforceUserResp.getExternalUserId()); - } - - /** - * Test Invalid Get Db Query - * - * @throws Exception - */ - @Test - public void testInvalidGetSalesforceUserByExternalUserId() throws Exception{ - String testExternalUserId = "externalUserId-test3"; - - // Mock the behavior to throw an exception when load is called - when(mockDynamoDBMapper.load(SalesforceUser.class, testExternalUserId)).thenThrow( - new AmazonDynamoDBException("mock db get error")); - - // Mock Invalid Get Db Query - // Test if CustomException is thrown with the expected error code - CustomException thrownException = assertThrows( - CustomException.class, - () -> mockSalesforceUserRepository.getSalesforceUserByExternalUserId(testExternalUserId) - ); - // Validate the error identifier to be a 500 error - assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); - } -} + @Autowired + private Setup setup; + + @Autowired + private Cleanup cleanup; + + @Autowired + private Common common; + + @Autowired + private LoadFixture loadFixture; + + private DynamoDBMapper mockDynamoDBMapper; + + private SalesforceUserRepository realSalesforceUserRepository; + + private SalesforceUserRepository mockSalesforceUserRepository; + + @BeforeEach + public void setUp() throws DynamobeeException, IOException { + setup.perform(); + // Use your Spring bean here + DynamoDBMapper dynamoDBMapper = new DynamoDBConfiguration().dynamoDBMapper(); + this.realSalesforceUserRepository = new SalesforceUserRepository(dynamoDBMapper); + + this.mockDynamoDBMapper = mock(DynamoDBMapper.class); // Mocked instance + this.mockSalesforceUserRepository = new SalesforceUserRepository(mockDynamoDBMapper); + } + + @AfterEach + public void tearDown() { + cleanup.perform(); + } + + /** + * Test Valid Save Db Query + * + */ + @Test + public void testValidSaveSalesforceUser() { + // Valid Save Db Query + SalesforceUser salesforceUserValid = new SalesforceUser(); + salesforceUserValid.setExternalUserId("externalUserId-test1"); + SalesforceUser salesforceUserResp = this.realSalesforceUserRepository.saveSalesforceUser(salesforceUserValid); + assertEquals(salesforceUserValid.getExternalUserId(), salesforceUserResp.getExternalUserId()); + } + + /** + * Test Invalid Save Db Query + * + */ + @Test + public void testInvalidSaveSalesforceUser() { + // Invalid Save Db Query without partition key + SalesforceUser salesforceUserInvalid = new SalesforceUser(); + salesforceUserInvalid.setExternalUserId("externalUserId-test2"); + + // Mock the behavior to throw an exception when save is called + doThrow(new AmazonDynamoDBException("mock db save error")).when(mockDynamoDBMapper).save(salesforceUserInvalid); + + // Test if CustomException is thrown with the expected error code + CustomException thrownException = assertThrows(CustomException.class, + () -> mockSalesforceUserRepository.saveSalesforceUser(salesforceUserInvalid)); + // Validate the error identifier to be a 500 error + assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); + } + + /** + * Test Valid Get Db Query + * @throws Exception + */ + @Test + public void testValidGetSalesforceUserByExternalUserId() throws Exception { + String currentFunctionName = new Object() { + }.getClass().getEnclosingMethod().getName(); + FixtureData fixtureData = common + .loadFixture("classpath:fixtures/unit/repositories/salesforceUserRepository.json", currentFunctionName); + loadFixture.perform(fixtureData); + + // Valid Get Db Query + SalesforceUser salesforceUserResp = this.realSalesforceUserRepository + .getSalesforceUserByExternalUserId("0055i00000AUxQHAA1"); + assertEquals("0055i00000AUxQHAA1", salesforceUserResp.getExternalUserId()); + } + + /** + * Test Invalid Get Db Query + * @throws Exception + */ + @Test + public void testInvalidGetSalesforceUserByExternalUserId() throws Exception { + String testExternalUserId = "externalUserId-test3"; + + // Mock the behavior to throw an exception when load is called + when(mockDynamoDBMapper.load(SalesforceUser.class, testExternalUserId)) + .thenThrow(new AmazonDynamoDBException("mock db get error")); + + // Mock Invalid Get Db Query + // Test if CustomException is thrown with the expected error code + CustomException thrownException = assertThrows(CustomException.class, + () -> mockSalesforceUserRepository.getSalesforceUserByExternalUserId(testExternalUserId)); + // Validate the error identifier to be a 500 error + assertEquals("something_went_wrong", thrownException.getErrorObject().getApiErrorIdentifier()); + } + +} diff --git a/src/test/java/com/salessparrow/api/unit/utility/MemcachedTest.java b/src/test/java/com/salessparrow/api/unit/utility/MemcachedTest.java index a3941aee..78c7618e 100644 --- a/src/test/java/com/salessparrow/api/unit/utility/MemcachedTest.java +++ b/src/test/java/com/salessparrow/api/unit/utility/MemcachedTest.java @@ -14,75 +14,75 @@ class MemcachedTest { - @Mock - private MemcachedClient memcachedClient; + @Mock + private MemcachedClient memcachedClient; - private Cache memcachedCache; + private Cache memcachedCache; - @BeforeEach - void setUp() { - MockitoAnnotations.openMocks(this); - memcachedCache = new Memcached("testCache", 3600, memcachedClient); - } + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + memcachedCache = new Memcached("testCache", 3600, memcachedClient); + } - @Test - void testGetName() { - assertEquals("testCache", memcachedCache.getName()); - } + @Test + void testGetName() { + assertEquals("testCache", memcachedCache.getName()); + } - @Test - void testGetNativeCache() { - assertEquals(memcachedClient, memcachedCache.getNativeCache()); - } + @Test + void testGetNativeCache() { + assertEquals(memcachedClient, memcachedCache.getNativeCache()); + } - @Test - void testGetCacheHit() { - String key = "testKey"; - String value = "testValue"; - when(memcachedClient.get("testCache_" + key)).thenReturn(value); + @Test + void testGetCacheHit() { + String key = "testKey"; + String value = "testValue"; + when(memcachedClient.get("testCache_" + key)).thenReturn(value); - Cache.ValueWrapper result = memcachedCache.get(key); + Cache.ValueWrapper result = memcachedCache.get(key); - assertNotNull(result); - assertEquals(value, result.get()); - verify(memcachedClient, times(1)).get("testCache_" + key); - } + assertNotNull(result); + assertEquals(value, result.get()); + verify(memcachedClient, times(1)).get("testCache_" + key); + } - @Test - void testGetCacheMiss() { - String key = "nonExistentKey"; - when(memcachedClient.get("testCache_" + key)).thenReturn(null); + @Test + void testGetCacheMiss() { + String key = "nonExistentKey"; + when(memcachedClient.get("testCache_" + key)).thenReturn(null); - Cache.ValueWrapper result = memcachedCache.get(key); + Cache.ValueWrapper result = memcachedCache.get(key); - assertNull(result); - verify(memcachedClient, times(1)).get("testCache_" + key); - } + assertNull(result); + verify(memcachedClient, times(1)).get("testCache_" + key); + } - @Test - void testPut() { - String key = "testKey"; - String value = "testValue"; + @Test + void testPut() { + String key = "testKey"; + String value = "testValue"; - memcachedCache.put(key, value); + memcachedCache.put(key, value); - verify(memcachedClient, times(1)).set("testCache_" + key, 3600, value); - } + verify(memcachedClient, times(1)).set("testCache_" + key, 3600, value); + } - @Test - void testEvict() { - String key = "testKey"; + @Test + void testEvict() { + String key = "testKey"; - memcachedCache.evict(key); + memcachedCache.evict(key); - verify(memcachedClient, times(1)).delete("testCache_" + key); - } + verify(memcachedClient, times(1)).delete("testCache_" + key); + } - @Test - void testClear() { - memcachedCache.clear(); + @Test + void testClear() { + memcachedCache.clear(); - verify(memcachedClient, times(1)).flush(); - } -} + verify(memcachedClient, times(1)).flush(); + } +} From d83a4cb938da65a2f1b2d937be81d4e75a506844 Mon Sep 17 00:00:00 2001 From: VRDighe Date: Wed, 30 Aug 2023 12:45:45 +0530 Subject: [PATCH 155/195] Added code review changes --- .../salesforce/dto/SalesforceContactDto.java | 38 +++++++++++++++++++ .../dto/SalesforceContactWrapperDto.java | 11 ++++++ .../accounts/GetAccountsFeedService.java | 33 ++++++++-------- .../GetAccountsFeedTest.java | 31 ++++++++++++--- .../getAccountsFeed.fixtures.json | 4 +- 5 files changed, 92 insertions(+), 25 deletions(-) create mode 100644 src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceContactDto.java create mode 100644 src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceContactWrapperDto.java diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceContactDto.java b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceContactDto.java new file mode 100644 index 00000000..210d02de --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceContactDto.java @@ -0,0 +1,38 @@ +package com.salessparrow.api.lib.salesforce.dto; + +import java.util.HashMap; +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; +import com.google.common.base.CaseFormat; +import com.salessparrow.api.dto.entities.ContactEntity; + +import lombok.Data; + +@Data +@JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) +public class SalesforceContactDto { + private String id; + private String name; + private Map additionalFields = new HashMap<>(); + + public ContactEntity getContactEntity() { + ContactEntity contactEntity = new ContactEntity(); + contactEntity.setId(this.id); + contactEntity.setName(this.name); + contactEntity.setAdditionalFields(this.additionalFields); + return contactEntity; + } + + @JsonAnySetter + public void setAdditionalField(String fieldName, Object value) { + fieldName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, + fieldName); + if (!fieldName.equals("attributes")) { + additionalFields.put(fieldName, value); + } + } + +} \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceContactWrapperDto.java b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceContactWrapperDto.java new file mode 100644 index 00000000..6b1a486e --- /dev/null +++ b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceContactWrapperDto.java @@ -0,0 +1,11 @@ +package com.salessparrow.api.lib.salesforce.dto; + +import java.util.ArrayList; +import java.util.List; + +import lombok.Data; + +@Data +public class SalesforceContactWrapperDto { + private List records = new ArrayList<>(); +} \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/services/accounts/GetAccountsFeedService.java b/src/main/java/com/salessparrow/api/services/accounts/GetAccountsFeedService.java index 84f44a1c..0d230542 100644 --- a/src/main/java/com/salessparrow/api/services/accounts/GetAccountsFeedService.java +++ b/src/main/java/com/salessparrow/api/services/accounts/GetAccountsFeedService.java @@ -13,7 +13,6 @@ import com.salessparrow.api.dto.requestMapper.GetAccountsFeedDto; import com.salessparrow.api.dto.responseMapper.GetAccountsFeedResponseDto; import com.salessparrow.api.exception.CustomException; -import com.salessparrow.api.lib.UserLoginCookieAuth; import com.salessparrow.api.lib.Util; import com.salessparrow.api.lib.crmActions.getAccounts.GetAccountsFactory; import com.salessparrow.api.lib.errorLib.ErrorObject; @@ -33,7 +32,7 @@ public class GetAccountsFeedService { @Autowired private Util util; - Logger logger = LoggerFactory.getLogger(UserLoginCookieAuth.class); + Logger logger = LoggerFactory.getLogger(GetAccountsFeedService.class); int offset; int pageNumber = 1; @@ -75,42 +74,40 @@ public GetAccountsFeedResponseDto getAccountsFeed(HttpServletRequest request, AccountConstants.FEED_VIEW_KIND, offset)); } - /** - * Preparing response - * - * @param accountsFactoryRes GetAccountsFormatterDto - * @return GetAccountsFeedResponseDto - */ private GetAccountsFeedResponseDto prepareResponse(GetAccountsFormatterDto accountsFactoryRes) { logger.info("Preparing response"); GetAccountsFeedResponseDto accountsFeedResponse = new GetAccountsFeedResponseDto(); - accountsFeedResponse.setAccountIds(accountsFactoryRes.getAccountIds()); - accountsFeedResponse.setAccountMapById(accountsFactoryRes.getAccountMapById()); - accountsFeedResponse.setContactMapById(accountsFactoryRes.getContactMapById()); - accountsFeedResponse.setAccountContactAssociationsMapById( - accountsFactoryRes.getAccountContactAssociationsMapById()); + setResponseFields(accountsFeedResponse, accountsFactoryRes); + setNextPagePayload(accountsFeedResponse); - NextPagePayloadEntity nextPagePayload = new NextPagePayloadEntity(); + return accountsFeedResponse; + } + private void setResponseFields(GetAccountsFeedResponseDto response, GetAccountsFormatterDto factoryRes) { + response.setAccountIds(factoryRes.getAccountIds()); + response.setAccountMapById(factoryRes.getAccountMapById()); + response.setContactMapById(factoryRes.getContactMapById()); + response.setAccountContactAssociationsMapById(factoryRes.getAccountContactAssociationsMapById()); + } + + private void setNextPagePayload(GetAccountsFeedResponseDto response) { logger.info("Preparing pagination identifier"); PaginationIdentifierFormatterDto paginationIdentifier = new PaginationIdentifierFormatterDto(); paginationIdentifier.setPageNumber(pageNumber + 1); try { String paginationJson = mapper.writeValueAsString(paginationIdentifier); + NextPagePayloadEntity nextPagePayload = new NextPagePayloadEntity(); nextPagePayload.setPaginationIdentifier(util.base64Encode(paginationJson)); + response.setNextPagePayload(nextPagePayload); } catch (Exception e) { throw new CustomException( new ErrorObject( "s_a_gafs_gaf_pr_1", "something_went_wrong", e.getMessage())); - } - - accountsFeedResponse.setNextPagePayload(nextPagePayload); - return accountsFeedResponse; } } diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountsFeedTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountsFeedTest.java index a14a83bc..353a86bb 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountsFeedTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountsFeedTest.java @@ -84,16 +84,27 @@ public void tearDown() { @MethodSource("testScenariosProvider") public void getAccountsFeed(Scenario testScenario) throws Exception { System.out.println("Description: " + testScenario.getDescription()); - // Load fixture data + String currentFunctionName = new Object() { }.getClass().getEnclosingMethod().getName(); + // Load fixture data and set up mocks + loadFixtureDataAndSetUpMocks(testScenario, currentFunctionName); + + // Perform the request + ResultActions resultActions = performRequest(testScenario); + + // Check the response + checkResponse(testScenario, resultActions); + } + + private void loadFixtureDataAndSetUpMocks(Scenario testScenario, String currentFunctionName) throws Exception { + FixtureData fixtureData = common.loadFixture( "classpath:fixtures/controllers/accountController/getAccountsFeed.fixtures.json", currentFunctionName); loadFixture.perform(fixtureData); // Read data from the scenario ObjectMapper objectMapper = new ObjectMapper(); - String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; // Prepare makeCompositeRequestMock responses if (testScenario.getMocks() != null && testScenario.getMocks().containsKey("makeCompositeRequest")) { @@ -102,6 +113,7 @@ public void getAccountsFeed(Scenario testScenario) throws Exception { .setResponseBody(objectMapper.writeValueAsString(testScenario.getMocks().get("makeCompositeRequest"))); when(makeCompositeRequestMock.makePostRequest(any(), any())).thenReturn(getAccountMockResponse); } + if (testScenario.getMocks() != null && testScenario.getMocks().containsKey("writeValueAsString")) { ObjectMapper mapper = mock(ObjectMapper.class); @@ -126,9 +138,13 @@ public void getAccountsFeed(Scenario testScenario) throws Exception { when(salesforceRequestInterfaceMock.execute(any(), any())) .thenThrow(new RuntimeException(errorMessage)); } + } + + private ResultActions performRequest(Scenario testScenario) throws Exception { + // existing code for performing the request - // Perform the request String url = "/api/v1/accounts/feed"; + String cookieValue = Constants.SALESFORCE_ACTIVE_USER_COOKIE_VALUE; String paginationIdentifier = testScenario.getInput().get("pagination_identifier").toString(); ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get(url) @@ -136,7 +152,12 @@ public void getAccountsFeed(Scenario testScenario) throws Exception { .param("pagination_identifier", paginationIdentifier) .contentType(MediaType.APPLICATION_JSON)); - // Check the response + return resultActions; + } + + private void checkResponse(Scenario testScenario, ResultActions resultActions) throws Exception { + // existing code for checking the response + ObjectMapper objectMapper = new ObjectMapper(); String expectedOutput = objectMapper.writeValueAsString(testScenario.getOutput()); String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); @@ -156,7 +177,7 @@ static Stream testScenariosProvider() throws IOException { } private static List loadScenarios() throws IOException { - String scenariosPath = "classpath:data/controllers/accountController/getAccountsFeed.scenarios.json"; + String scenariosPath = "classpath:data/functional/controllers/accountController/getAccountsFeed.scenarios.json"; Resource resource = new DefaultResourceLoader().getResource(scenariosPath); ObjectMapper objectMapper = new ObjectMapper(); return objectMapper.readValue(resource.getInputStream(), new TypeReference>() { diff --git a/src/test/resources/fixtures/controllers/accountController/getAccountsFeed.fixtures.json b/src/test/resources/fixtures/controllers/accountController/getAccountsFeed.fixtures.json index 783268cc..a2959bbe 100644 --- a/src/test/resources/fixtures/controllers/accountController/getAccountsFeed.fixtures.json +++ b/src/test/resources/fixtures/controllers/accountController/getAccountsFeed.fixtures.json @@ -2,12 +2,12 @@ "getAccountsFeed": { "salesforce_users": [ { - "filepath": "classpath:fixtures/repositories/salesforceUser/ActiveSalesforceUser.json" + "filepath": "classpath:fixtures/common/repositories/salesforceUser/ActiveSalesforceUser.json" } ], "salesforce_oauth_tokens": [ { - "filepath": "classpath:fixtures/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" + "filepath": "classpath:fixtures/common/repositories/salesforceOauthToken/ActiveSalesforceOauthToken.json" } ] } From 66e69d31bc22b3e81bdcfceba36835506e284b74 Mon Sep 17 00:00:00 2001 From: ajinkyac03 Date: Wed, 30 Aug 2023 13:04:24 +0530 Subject: [PATCH 156/195] 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 701bda2128853317eed64c9574d48bf2959122af Mon Sep 17 00:00:00 2001 From: VRDighe Date: Wed, 30 Aug 2023 13:06:12 +0530 Subject: [PATCH 157/195] Added code review changes --- .../getAccounts/GetSalesforceAccounts.java | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java index 3de4d695..2b3fb2a9 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java @@ -105,10 +105,10 @@ public GetAccountsFormatterDto parseResponse(String responseBody) { if (httpStatusCodeNode.asInt() != 200 && httpStatusCodeNode.asInt() != 201) { throw new CustomException( - new ErrorObject( - "l_ca_ga_gsa_pr_1", - "something_went_wrong", - "Error in fetching accounts from salesforce")); + new ErrorObject( + "l_ca_ga_gsa_pr_1", + "something_went_wrong", + "Error in fetching accounts from salesforce")); } JsonNode recordsNode = rootNode.get("compositeResponse").get(0).get("body").get("records"); @@ -122,19 +122,7 @@ public GetAccountsFormatterDto parseResponse(String responseBody) { accountIds.add(accountEntity.getId()); accountIdToEntityMap.put(accountEntity.getId(), accountEntity); - if (salesforceAccount.getContacts() != null) { - List contactIds = new ArrayList(); - - for (SalesforceAccountDto.Contact contact : salesforceAccount.getContacts().getRecords()) { - ContactEntity contactEntity = contact.getContactEntity(); - contactMapById.put(contactEntity.getId(), contactEntity); - contactIds.add(contactEntity.getId()); - } - - AccountContactAssociationsEntity accountContactAssociationsEntity = new AccountContactAssociationsEntity(); - accountContactAssociationsEntity.setContactIds(contactIds); - accountContactAssociationsMapById.put(accountEntity.getId(), accountContactAssociationsEntity); - } + handleContacts(salesforceAccount, contactMapById, accountContactAssociationsMapById); } GetAccountsFormatterDto getAccountsResponse = new GetAccountsFormatterDto(); @@ -145,4 +133,20 @@ public GetAccountsFormatterDto parseResponse(String responseBody) { return getAccountsResponse; } + + private void handleContacts(SalesforceAccountDto salesforceAccount, Map contactMapById, + Map accountContactAssociationsMapById) { + List contactIds = new ArrayList(); + + for (SalesforceAccountDto.Contact contact : salesforceAccount.getContacts().getRecords()) { + ContactEntity contactEntity = contact.getContactEntity(); + contactMapById.put(contactEntity.getId(), contactEntity); + contactIds.add(contactEntity.getId()); + } + + AccountContactAssociationsEntity accountContactAssociationsEntity = new AccountContactAssociationsEntity(); + accountContactAssociationsEntity.setContactIds(contactIds); + accountContactAssociationsMapById.put(salesforceAccount.getAccountEntity().getId(), + accountContactAssociationsEntity); + } } From baac0b4d81bd1427c5036c3b0d94d7b8768fcfb0 Mon Sep 17 00:00:00 2001 From: VRDighe Date: Wed, 30 Aug 2023 13:27:18 +0530 Subject: [PATCH 158/195] Added code review changes --- .../java/com/salessparrow/api/lib/Util.java | 37 ++++++------- .../getAccounts/GetSalesforceAccounts.java | 9 +++- .../salesforce/dto/SalesforceAccountDto.java | 37 +------------ .../salesforce/helper/SalesforceRequest.java | 18 +++---- .../accounts/GetAccountListService.java | 10 ++-- .../accounts/GetAccountsFeedService.java | 53 ++++++++++++------- src/main/resources/config/ApiErrorConfig.json | 15 ++++-- .../salessparrow/api/unit/lib/UtilTest.java | 51 ++++++++---------- 8 files changed, 110 insertions(+), 120 deletions(-) diff --git a/src/main/java/com/salessparrow/api/lib/Util.java b/src/main/java/com/salessparrow/api/lib/Util.java index 72035fdf..c8f85aef 100644 --- a/src/main/java/com/salessparrow/api/lib/Util.java +++ b/src/main/java/com/salessparrow/api/lib/Util.java @@ -74,7 +74,7 @@ public static String generateHeaderLogString(HttpServletRequest request) { * @param plainText - String to be encoded * @return String - Encoded string */ - public String base64Encode(String plainText) { + public static String base64Encode(String plainText) { String encodedText = null; try { @@ -96,7 +96,7 @@ public String base64Encode(String plainText) { * @param encodedText - String to be decoded * @return String - Decoded string */ - public String base64Decode(String encodedText) { + public static String base64Decode(String encodedText) { String decodedText = null; try { @@ -116,20 +116,22 @@ public String base64Decode(String encodedText) { /** * Escape special characters in a string for use in a regular expression. * SOQL is important from security point of view. - * Refer https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql_select_quotedstringescapes.htm for more details. + * Refer + * https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql_select_quotedstringescapes.htm + * for more details. * * @param input * * @return String */ public static String escapeSpecialChars(String input) { - if(input == null || input == "") + if (input == null || input == "") return input; - String[] specialChars = {"\\", "%", "'", "\"", "_"}; - + String[] specialChars = { "\\", "%", "'", "\"", "_" }; + for (String specialChar : specialChars) { - input = input.replace(specialChar, "\\" + specialChar); + input = input.replace(specialChar, "\\" + specialChar); } return input; @@ -142,24 +144,23 @@ public static String escapeSpecialChars(String input) { * * @return String */ - public static String urlEncoder(String input){ - if(input == null || input == "") + public static String urlEncoder(String input) { + if (input == null || input == "") return input; - + try { return URLEncoder.encode(input, "UTF-8"); } catch (UnsupportedEncodingException e) { throw new CustomException( - new ErrorObject( - "u_u_ue_1", - "something_went_wrong", - e.getMessage() - ) - ); + new ErrorObject( + "u_u_ue_1", + "something_went_wrong", + e.getMessage())); } } - - /** Get date format from datetime + + /** + * Get date format from datetime * * @param date * diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java index 2b3fb2a9..d7f1e802 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java @@ -27,6 +27,7 @@ import com.salessparrow.api.lib.httpLib.HttpClient; import com.salessparrow.api.lib.salesforce.dto.CompositeRequestDto; import com.salessparrow.api.lib.salesforce.dto.SalesforceAccountDto; +import com.salessparrow.api.lib.salesforce.dto.SalesforceContactDto; import com.salessparrow.api.lib.salesforce.helper.MakeCompositeRequest; import com.salessparrow.api.lib.salesforce.helper.SalesforceQueryBuilder; @@ -42,6 +43,9 @@ public class GetSalesforceAccounts implements GetAccounts { @Autowired private MakeCompositeRequest makeCompositeRequest; + @Autowired + private Util util; + Logger logger = LoggerFactory.getLogger(UserLoginCookieAuth.class); /** @@ -98,9 +102,10 @@ public GetAccountsFormatterDto parseResponse(String responseBody) { Map contactMapById = new HashMap<>(); Map accountContactAssociationsMapById = new HashMap<>(); - Util util = new Util(); JsonNode rootNode = util.getJsonNode(responseBody); + System.out.println("rootNode--->>>" + rootNode); + JsonNode httpStatusCodeNode = rootNode.get("compositeResponse").get(0).get("httpStatusCode"); if (httpStatusCodeNode.asInt() != 200 && httpStatusCodeNode.asInt() != 201) { @@ -138,7 +143,7 @@ private void handleContacts(SalesforceAccountDto salesforceAccount, Map accountContactAssociationsMapById) { List contactIds = new ArrayList(); - for (SalesforceAccountDto.Contact contact : salesforceAccount.getContacts().getRecords()) { + for (SalesforceContactDto contact : salesforceAccount.getContacts().getRecords()) { ContactEntity contactEntity = contact.getContactEntity(); contactMapById.put(contactEntity.getId(), contactEntity); contactIds.add(contactEntity.getId()); diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceAccountDto.java b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceAccountDto.java index e2eea17c..703427d5 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceAccountDto.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/dto/SalesforceAccountDto.java @@ -1,8 +1,6 @@ package com.salessparrow.api.lib.salesforce.dto; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; import com.fasterxml.jackson.annotation.JsonAnySetter; @@ -10,7 +8,6 @@ import com.fasterxml.jackson.databind.annotation.JsonNaming; import com.google.common.base.CaseFormat; import com.salessparrow.api.dto.entities.AccountEntity; -import com.salessparrow.api.dto.entities.ContactEntity; import lombok.Data; @@ -20,7 +17,7 @@ public class SalesforceAccountDto { private String id; private String name; private Map additionalFields = new HashMap<>(); - private ContactsWrapper Contacts; + private SalesforceContactWrapperDto Contacts; public AccountEntity getAccountEntity() { AccountEntity accountEntity = new AccountEntity(); @@ -39,36 +36,4 @@ public void setAdditionalField(String fieldName, Object value) { additionalFields.put(fieldName, value); } } - - @Data - public static class ContactsWrapper { - private List records = new ArrayList<>(); - } - - @Data - @JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) - public static class Contact { - private String id; - private String name; - private Map additionalFields = new HashMap<>(); - - public ContactEntity getContactEntity() { - ContactEntity contactEntity = new ContactEntity(); - contactEntity.setId(this.id); - contactEntity.setName(this.name); - contactEntity.setAdditionalFields(this.additionalFields); - return contactEntity; - } - - @JsonAnySetter - public void setAdditionalField(String fieldName, Object value) { - fieldName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, - fieldName); - if (!fieldName.equals("attributes")) { - additionalFields.put(fieldName, value); - } - } - - } - } \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceRequest.java b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceRequest.java index 9f999e5d..e3b93d8f 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceRequest.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceRequest.java @@ -38,23 +38,23 @@ public T makeRequest(String salesforceUserId, SalesforceRequestInterface try { return request.execute(decryptedAccessToken, sfOAuthToken.getInstanceUrl()); } catch (WebClientResponseException e) { - if(e.getStatusCode().value() == 401) { + if (e.getStatusCode().value() == 401) { try { decryptedAccessToken = getAccessTokenService.updateAndGetRefreshedAccessToken(sfOAuthToken); return request.execute(decryptedAccessToken, sfOAuthToken.getInstanceUrl()); } catch (Exception e1) { throw new CustomException( - new ErrorObject( - "l_s_h_sr_mr_1", - "something_went_wrong", - e.getMessage())); + new ErrorObject( + "l_s_h_sr_mr_1", + "something_went_wrong", + e.getMessage())); } } throw new CustomException( - new ErrorObject( - "l_s_h_sr_mr_2", - "something_went_wrong", - e.getMessage())); + new ErrorObject( + "l_s_h_sr_mr_2", + "something_went_wrong", + e.getMessage())); } } } diff --git a/src/main/java/com/salessparrow/api/services/accounts/GetAccountListService.java b/src/main/java/com/salessparrow/api/services/accounts/GetAccountListService.java index 7afaf9e3..84554457 100644 --- a/src/main/java/com/salessparrow/api/services/accounts/GetAccountListService.java +++ b/src/main/java/com/salessparrow/api/services/accounts/GetAccountListService.java @@ -33,15 +33,19 @@ public GetAccountListResponseDto getAccounts(HttpServletRequest request, GetAcco User currentUser = (User) request.getAttribute("current_user"); String formattedSearchString = ""; - if(getAccountsDto.getQ() != null){ + if (getAccountsDto.getQ() != null) { formattedSearchString = formatSearchString(getAccountsDto.getQ()); } GetAccountsFormatterDto getAccountsFormatterDto = getAccountsFactory.getAccounts(currentUser, formattedSearchString, AccountConstants.BASIC_VIEW_KIND, 0); GetAccountListResponseDto getAccountListResponseDto = new GetAccountListResponseDto(); - getAccountListResponseDto.setAccountIds(getAccountsFormatterDto.getAccountIds()); - getAccountListResponseDto.setAccountMapById(getAccountsFormatterDto.getAccountMapById()); + if (getAccountsFormatterDto.getAccountIds() != null) { + getAccountListResponseDto.setAccountIds(getAccountsFormatterDto.getAccountIds()); + } + if (getAccountsFormatterDto.getAccountMapById() != null) { + getAccountListResponseDto.setAccountMapById(getAccountsFormatterDto.getAccountMapById()); + } return getAccountListResponseDto; } diff --git a/src/main/java/com/salessparrow/api/services/accounts/GetAccountsFeedService.java b/src/main/java/com/salessparrow/api/services/accounts/GetAccountsFeedService.java index 0d230542..d909a267 100644 --- a/src/main/java/com/salessparrow/api/services/accounts/GetAccountsFeedService.java +++ b/src/main/java/com/salessparrow/api/services/accounts/GetAccountsFeedService.java @@ -29,16 +29,8 @@ public class GetAccountsFeedService { @Autowired private GetAccountsFactory getAccountsFactory; - @Autowired - private Util util; - Logger logger = LoggerFactory.getLogger(GetAccountsFeedService.class); - int offset; - int pageNumber = 1; - String searchTerm = null; - ObjectMapper mapper = new ObjectMapper(); - /** * Get accounts feed method * @@ -51,35 +43,57 @@ public GetAccountsFeedResponseDto getAccountsFeed(HttpServletRequest request, logger.info("Getting accounts feed"); User currentUser = (User) request.getAttribute("current_user"); - offset = 0; + int pageNumber = 1; + String searchTerm = null; + + int offset = calculateOffset(getAccountsFeedDto.getPagination_identifier()); + + return prepareResponse(getAccountsFactory.getAccounts(currentUser, searchTerm, + AccountConstants.FEED_VIEW_KIND, offset), pageNumber); + } + + /** + * Calculate offset for pagination using pagination identifier + * + * @param paginationIdentifier String + * @return int + */ + private int calculateOffset(String paginationIdentifier) { + int offset = 0; - if (getAccountsFeedDto.getPagination_identifier() != null) { + if (paginationIdentifier != null) { logger.info("Pagination identifier found"); - String decodedPaginationIdentifier = util.base64Decode(getAccountsFeedDto.getPagination_identifier()); + String decodedPaginationIdentifier = Util.base64Decode(paginationIdentifier); PaginationIdentifierFormatterDto paginationIdentifierObj = null; try { + ObjectMapper mapper = new ObjectMapper(); paginationIdentifierObj = mapper.readValue(decodedPaginationIdentifier, PaginationIdentifierFormatterDto.class); } catch (Exception e) { throw new CustomException( new ErrorObject( "s_a_gafs_gaf_1", - "something_went_wrong", + "pagination_identifier_parsing_error", e.getMessage())); } - pageNumber = paginationIdentifierObj.getPageNumber(); + int pageNumber = paginationIdentifierObj.getPageNumber(); offset = (pageNumber - 1) * AccountConstants.PAGINATION_LIMIT; } - return prepareResponse(getAccountsFactory.getAccounts(currentUser, searchTerm, - AccountConstants.FEED_VIEW_KIND, offset)); + return offset; } - private GetAccountsFeedResponseDto prepareResponse(GetAccountsFormatterDto accountsFactoryRes) { + /** + * Preparing response + * + * @param accountsFactoryRes GetAccountsFormatterDto + * @return GetAccountsFeedResponseDto + */ + private GetAccountsFeedResponseDto prepareResponse(GetAccountsFormatterDto accountsFactoryRes, int pageNumber) { logger.info("Preparing response"); GetAccountsFeedResponseDto accountsFeedResponse = new GetAccountsFeedResponseDto(); setResponseFields(accountsFeedResponse, accountsFactoryRes); - setNextPagePayload(accountsFeedResponse); + setNextPagePayload(accountsFeedResponse, pageNumber); return accountsFeedResponse; } @@ -91,15 +105,16 @@ private void setResponseFields(GetAccountsFeedResponseDto response, GetAccountsF response.setAccountContactAssociationsMapById(factoryRes.getAccountContactAssociationsMapById()); } - private void setNextPagePayload(GetAccountsFeedResponseDto response) { + private void setNextPagePayload(GetAccountsFeedResponseDto response, int pageNumber) { logger.info("Preparing pagination identifier"); PaginationIdentifierFormatterDto paginationIdentifier = new PaginationIdentifierFormatterDto(); paginationIdentifier.setPageNumber(pageNumber + 1); try { + ObjectMapper mapper = new ObjectMapper(); String paginationJson = mapper.writeValueAsString(paginationIdentifier); NextPagePayloadEntity nextPagePayload = new NextPagePayloadEntity(); - nextPagePayload.setPaginationIdentifier(util.base64Encode(paginationJson)); + nextPagePayload.setPaginationIdentifier(Util.base64Encode(paginationJson)); response.setNextPagePayload(nextPagePayload); } catch (Exception e) { throw new CustomException( diff --git a/src/main/resources/config/ApiErrorConfig.json b/src/main/resources/config/ApiErrorConfig.json index e4b86a59..34901185 100644 --- a/src/main/resources/config/ApiErrorConfig.json +++ b/src/main/resources/config/ApiErrorConfig.json @@ -44,9 +44,14 @@ "code": "INVALID_PARAMS", "message": "At least one parameter is invalid or missing." }, - "forbidden_api_request": { - "httpCode": "403", - "code": "FORBIDDEN", - "message": "Forbidden API request. You do not have the necessary permissions." - } + "forbidden_api_request": { + "httpCode": "403", + "code": "FORBIDDEN", + "message": "Forbidden API request. You do not have the necessary permissions." + }, + "pagination_identifier_parsing_error": { + "httpCode": "400", + "code": "PAGINATION_IDENTIFIER_PARSING_ERROR", + "message": "Error parsing pagination identifier." + } } \ No newline at end of file diff --git a/src/test/java/com/salessparrow/api/unit/lib/UtilTest.java b/src/test/java/com/salessparrow/api/unit/lib/UtilTest.java index 6b3c53df..a88ce9cb 100644 --- a/src/test/java/com/salessparrow/api/unit/lib/UtilTest.java +++ b/src/test/java/com/salessparrow/api/unit/lib/UtilTest.java @@ -6,19 +6,14 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; -import org.mockito.Mock; import org.mockito.MockitoAnnotations; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import com.salessparrow.api.exception.CustomException; import com.salessparrow.api.lib.Util; public class UtilTest { - @Mock - private ObjectMapper objectMapper; - @InjectMocks private Util util; @@ -30,47 +25,47 @@ public void setup() { @Test public void testEncode() { String plainText = "Hello, World!"; - String encodedText = util.base64Encode(plainText); + String encodedText = Util.base64Encode(plainText); assertEquals("SGVsbG8sIFdvcmxkIQ==", encodedText); } @Test public void testEncodeEmptyString() { String plainText = ""; - String encodedText = util.base64Encode(plainText); + String encodedText = Util.base64Encode(plainText); assertEquals("", encodedText); } @Test public void testEncodeNullString() { String plainText = null; - assertThrows(CustomException.class, () -> util.base64Encode(plainText)); + assertThrows(CustomException.class, () -> Util.base64Encode(plainText)); } @Test public void testDecode() { String encodedText = "SGVsbG8sIFdvcmxkIQ=="; - String decodedText = util.base64Decode(encodedText); + String decodedText = Util.base64Decode(encodedText); assertEquals("Hello, World!", decodedText); } @Test public void testDecodeEmptyString() { String encodedText = ""; - String decodedText = util.base64Decode(encodedText); + String decodedText = Util.base64Decode(encodedText); assertEquals("", decodedText); } @Test public void testDecodeNullString() { String encodedText = null; - assertThrows(CustomException.class, () -> util.base64Decode(encodedText)); + assertThrows(CustomException.class, () -> Util.base64Decode(encodedText)); } @Test public void testDecodeInvalidString() { String encodedText = "SGVsbG8sIFdvcmxkIQ="; - assertThrows(CustomException.class, () -> util.base64Decode(encodedText)); + assertThrows(CustomException.class, () -> Util.base64Decode(encodedText)); } @Test @@ -90,24 +85,24 @@ public void testGetJsonNode_InvalidJson() throws Exception { } @Test - public void testEscapeSpecialChars() { - String[] inputStrings = {"\\a","%a","_a","'a","\"a"}; - String[] expectedOutputs = {"\\\\a","\\%a","\\_a","\\'a","\\\"a"}; - - for(int i = 0; i < inputStrings.length; i++) { - String result = Util.escapeSpecialChars(inputStrings[i]); - assertEquals(expectedOutputs[i], result); - } + public void testEscapeSpecialChars() { + String[] inputStrings = { "\\a", "%a", "_a", "'a", "\"a" }; + String[] expectedOutputs = { "\\\\a", "\\%a", "\\_a", "\\'a", "\\\"a" }; + + for (int i = 0; i < inputStrings.length; i++) { + String result = Util.escapeSpecialChars(inputStrings[i]); + assertEquals(expectedOutputs[i], result); } + } - @Test - public void testUrlEncoder() { - String[] inputStrings = {"\\\\a","\\%a","\\_a","\\'a","\\\"a","a+b","a b"}; - String[] expectedOutputs = {"%5C%5Ca","%5C%25a","%5C_a","%5C%27a","%5C%22a","a%2Bb","a+b"}; + @Test + public void testUrlEncoder() { + String[] inputStrings = { "\\\\a", "\\%a", "\\_a", "\\'a", "\\\"a", "a+b", "a b" }; + String[] expectedOutputs = { "%5C%5Ca", "%5C%25a", "%5C_a", "%5C%27a", "%5C%22a", "a%2Bb", "a+b" }; - for(int i = 0; i < inputStrings.length; i++) { - String result = Util.urlEncoder(inputStrings[i]); - assertEquals(expectedOutputs[i], result); - } + for (int i = 0; i < inputStrings.length; i++) { + String result = Util.urlEncoder(inputStrings[i]); + assertEquals(expectedOutputs[i], result); } + } } From fc937875a6c8ce0c868d0656cc9a5ffcb75a4e79 Mon Sep 17 00:00:00 2001 From: VRDighe Date: Wed, 30 Aug 2023 13:30:07 +0530 Subject: [PATCH 159/195] Added code review changes --- .../lib/crmActions/getAccounts/GetSalesforceAccounts.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java index d7f1e802..09ce401b 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java @@ -127,7 +127,10 @@ public GetAccountsFormatterDto parseResponse(String responseBody) { accountIds.add(accountEntity.getId()); accountIdToEntityMap.put(accountEntity.getId(), accountEntity); - handleContacts(salesforceAccount, contactMapById, accountContactAssociationsMapById); + if (salesforceAccount.getContacts() != null && salesforceAccount.getContacts().getRecords() != null + && salesforceAccount.getContacts().getRecords().size() > 0) { + handleContacts(salesforceAccount, contactMapById, accountContactAssociationsMapById); + } } GetAccountsFormatterDto getAccountsResponse = new GetAccountsFormatterDto(); From 086f08ff513a0ff9486e440942eb29f0f7ec378f Mon Sep 17 00:00:00 2001 From: VRDighe Date: Wed, 30 Aug 2023 13:37:13 +0530 Subject: [PATCH 160/195] Added code review changes --- .../controllers/accountController/GetAccountsFeedTest.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountsFeedTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountsFeedTest.java index 353a86bb..2bf6f07c 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountsFeedTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountsFeedTest.java @@ -14,6 +14,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; @@ -64,6 +66,8 @@ public class GetAccountsFeedTest { @Autowired private Cleanup cleanup; + Logger logger = LoggerFactory.getLogger(GetAccountsFeedTest.class); + @MockBean private MakeCompositeRequest makeCompositeRequestMock; @@ -83,8 +87,8 @@ public void tearDown() { @ParameterizedTest @MethodSource("testScenariosProvider") public void getAccountsFeed(Scenario testScenario) throws Exception { - System.out.println("Description: " + testScenario.getDescription()); + logger.info("Running test scenario: " + testScenario.getDescription()); String currentFunctionName = new Object() { }.getClass().getEnclosingMethod().getName(); // Load fixture data and set up mocks @@ -125,7 +129,6 @@ private void loadFixtureDataAndSetUpMocks(Scenario testScenario, String currentF if (testScenario.getMocks() != null && testScenario.getMocks().containsKey("readValue")) { ObjectMapper mapper = mock(ObjectMapper.class); - System.out.println("in base64Encode"); String errorMessage = testScenario.getMocks().get("readValue").toString(); when(mapper.readValue(any(JsonParser.class), eq(PaginationIdentifierFormatterDto.class))) .thenThrow(new RuntimeException(errorMessage)); From 58544e295be45612911f9b929d67629edb023a18 Mon Sep 17 00:00:00 2001 From: VRDighe Date: Wed, 30 Aug 2023 13:47:13 +0530 Subject: [PATCH 161/195] Added code review changes --- src/main/java/com/salessparrow/api/lib/Util.java | 4 ++-- .../crmActions/getAccounts/GetSalesforceAccounts.java | 2 -- .../accountController/GetAccountsFeedTest.java | 8 ++++++-- .../controllers/authController/PostLogoutTest.java | 11 +++++++---- .../authController/PostSalesforceConnectTest.java | 10 +++++++--- 5 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/salessparrow/api/lib/Util.java b/src/main/java/com/salessparrow/api/lib/Util.java index c8f85aef..9ebe0c3d 100644 --- a/src/main/java/com/salessparrow/api/lib/Util.java +++ b/src/main/java/com/salessparrow/api/lib/Util.java @@ -58,9 +58,9 @@ public static String generateHeaderLogString(HttpServletRequest request) { if (headerName.equals("authorization") || headerName.equals("cookie") || headerName.equals("password")) { - headerBuilder.append(headerName).append(":**********, "); + headerBuilder.append(headerName).append(":**********"); } else { - headerBuilder.append(headerName).append(":").append(request.getHeader(headerName)).append(", "); + headerBuilder.append(headerName).append(":").append(request.getHeader(headerName)); } }); headerBuilder.append("}"); diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java b/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java index 09ce401b..3d99e54f 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/getAccounts/GetSalesforceAccounts.java @@ -104,8 +104,6 @@ public GetAccountsFormatterDto parseResponse(String responseBody) { JsonNode rootNode = util.getJsonNode(responseBody); - System.out.println("rootNode--->>>" + rootNode); - JsonNode httpStatusCodeNode = rootNode.get("compositeResponse").get(0).get("httpStatusCode"); if (httpStatusCodeNode.asInt() != 200 && httpStatusCodeNode.asInt() != 201) { diff --git a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountsFeedTest.java b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountsFeedTest.java index 2bf6f07c..f227222e 100644 --- a/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountsFeedTest.java +++ b/src/test/java/com/salessparrow/api/functional/controllers/accountController/GetAccountsFeedTest.java @@ -175,8 +175,12 @@ private void checkResponse(Scenario testScenario, ResultActions resultActions) t } static Stream testScenariosProvider() throws IOException { - List testScenarios = loadScenarios(); - return testScenarios.stream(); + try { + List testScenarios = loadScenarios(); + return testScenarios.stream(); + } catch (IOException e) { + throw new RuntimeException("Failed to load test scenarios", e); + } } private static List loadScenarios() throws IOException { 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..b2df6a01 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 @@ -8,6 +8,8 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; @@ -23,6 +25,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.dynamobee.exception.DynamobeeException; +import com.salessparrow.api.changelogs.DatabaseChangelog; import com.salessparrow.api.helper.Cleanup; import com.salessparrow.api.helper.Common; import com.salessparrow.api.helper.FixtureData; @@ -57,6 +60,8 @@ public class PostLogoutTest { @Autowired private LoadFixture loadFixture; + Logger logger = LoggerFactory.getLogger(DatabaseChangelog.class); + @BeforeEach public void setUp() throws DynamobeeException, IOException { setup.perform(); @@ -80,9 +85,10 @@ public void testPostLogout() throws Exception { List testDataItems = loadTestData(currentFunctionName); for (Scenario testDataItem : testDataItems) { - System.out.println("Test description: " + testDataItem.getDescription()); + logger.info("Running test scenario: " + testDataItem.getDescription()); ObjectMapper objectMapper = new ObjectMapper(); String expectedOutput = objectMapper.writeValueAsString(testDataItem.getOutput()); + logger.info("Expected output: " + expectedOutput); String cookieValue = (String) testDataItem.getInput().get("cookie"); ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.post("/api/v1/auth/logout") @@ -92,9 +98,6 @@ public void testPostLogout() throws Exception { 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/java/com/salessparrow/api/functional/controllers/authController/PostSalesforceConnectTest.java b/src/test/java/com/salessparrow/api/functional/controllers/authController/PostSalesforceConnectTest.java index dafdf4c0..4f328116 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 @@ -4,6 +4,8 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.anyString; @@ -34,6 +36,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.dynamobee.exception.DynamobeeException; +import com.salessparrow.api.changelogs.DatabaseChangelog; import com.salessparrow.api.helper.Cleanup; import com.salessparrow.api.helper.Common; import com.salessparrow.api.helper.FixtureData; @@ -80,6 +83,8 @@ public class PostSalesforceConnectTest { @InjectMocks private AuthService authService; + Logger logger = LoggerFactory.getLogger(DatabaseChangelog.class); + @BeforeEach public void setUp() throws DynamobeeException, IOException { MockitoAnnotations.openMocks(this); @@ -99,7 +104,7 @@ public void testPostSalesforceConnectSignup() throws Exception { List testDataItems = loadTestData(currentFunctionName); for (Scenario testDataItem : testDataItems) { - System.out.println("Test description: " + testDataItem.getDescription()); + logger.info("Running test scenario: " + testDataItem.getDescription()); ObjectMapper objectMapper = new ObjectMapper(); HttpResponse getTokensMockRes = new HttpResponse(); @@ -117,7 +122,6 @@ public void testPostSalesforceConnectSignup() throws Exception { .contentType(MediaType.APPLICATION_JSON)); String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); - System.out.println("actualOutput: " + actualOutput); if (resultActions.andReturn().getResponse().getStatus() == 200) { assertEquals(objectMapper.writeValueAsString(testDataItem.getOutput()), actualOutput); @@ -142,7 +146,7 @@ public void testPostSalesforceConnectLogin() throws Exception { List testDataItems = loadTestData(currentFunctionName); for (Scenario testDataItem : testDataItems) { - System.out.println("Test description: " + testDataItem.getDescription()); + logger.info("Running test scenario: " + testDataItem.getDescription()); ObjectMapper objectMapper = new ObjectMapper(); HttpResponse getTokensMockRes = new HttpResponse(); From 4d7215c15deb02971dc83161516fb8f6cf3eadf4 Mon Sep 17 00:00:00 2001 From: VRDighe Date: Wed, 30 Aug 2023 14:05:39 +0530 Subject: [PATCH 162/195] Added code review changes --- .../functional/controllers/authController/PostLogoutTest.java | 3 +-- .../controllers/authController/PostSalesforceConnectTest.java | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) 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 b2df6a01..c7a86c34 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 @@ -25,7 +25,6 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.dynamobee.exception.DynamobeeException; -import com.salessparrow.api.changelogs.DatabaseChangelog; import com.salessparrow.api.helper.Cleanup; import com.salessparrow.api.helper.Common; import com.salessparrow.api.helper.FixtureData; @@ -60,7 +59,7 @@ public class PostLogoutTest { @Autowired private LoadFixture loadFixture; - Logger logger = LoggerFactory.getLogger(DatabaseChangelog.class); + Logger logger = LoggerFactory.getLogger(PostLogoutTest.class); @BeforeEach public void setUp() throws DynamobeeException, IOException { 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 4f328116..fff524c2 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 @@ -36,7 +36,6 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.dynamobee.exception.DynamobeeException; -import com.salessparrow.api.changelogs.DatabaseChangelog; import com.salessparrow.api.helper.Cleanup; import com.salessparrow.api.helper.Common; import com.salessparrow.api.helper.FixtureData; @@ -83,7 +82,7 @@ public class PostSalesforceConnectTest { @InjectMocks private AuthService authService; - Logger logger = LoggerFactory.getLogger(DatabaseChangelog.class); + Logger logger = LoggerFactory.getLogger(PostSalesforceConnectTest.class); @BeforeEach public void setUp() throws DynamobeeException, IOException { From 0b109ae63736aafdba5b98cfb63778151a6a4bb0 Mon Sep 17 00:00:00 2001 From: ajinkyac03 Date: Wed, 30 Aug 2023 14:15:41 +0530 Subject: [PATCH 163/195] 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 2592fc3781edb092d5aaf0bbdbc4ffada2f7ca56 Mon Sep 17 00:00:00 2001 From: VRDighe Date: Wed, 30 Aug 2023 14:28:34 +0530 Subject: [PATCH 164/195] Added fix --- .../api/services/accounts/GetAccountsFeedService.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/salessparrow/api/services/accounts/GetAccountsFeedService.java b/src/main/java/com/salessparrow/api/services/accounts/GetAccountsFeedService.java index d909a267..1dd71db7 100644 --- a/src/main/java/com/salessparrow/api/services/accounts/GetAccountsFeedService.java +++ b/src/main/java/com/salessparrow/api/services/accounts/GetAccountsFeedService.java @@ -30,6 +30,7 @@ public class GetAccountsFeedService { private GetAccountsFactory getAccountsFactory; Logger logger = LoggerFactory.getLogger(GetAccountsFeedService.class); + int pageNumber; /** * Get accounts feed method @@ -43,13 +44,13 @@ public GetAccountsFeedResponseDto getAccountsFeed(HttpServletRequest request, logger.info("Getting accounts feed"); User currentUser = (User) request.getAttribute("current_user"); - int pageNumber = 1; + pageNumber = 1; String searchTerm = null; int offset = calculateOffset(getAccountsFeedDto.getPagination_identifier()); return prepareResponse(getAccountsFactory.getAccounts(currentUser, searchTerm, - AccountConstants.FEED_VIEW_KIND, offset), pageNumber); + AccountConstants.FEED_VIEW_KIND, offset)); } /** @@ -75,7 +76,7 @@ private int calculateOffset(String paginationIdentifier) { "pagination_identifier_parsing_error", e.getMessage())); } - int pageNumber = paginationIdentifierObj.getPageNumber(); + pageNumber = paginationIdentifierObj.getPageNumber(); offset = (pageNumber - 1) * AccountConstants.PAGINATION_LIMIT; } @@ -88,7 +89,7 @@ private int calculateOffset(String paginationIdentifier) { * @param accountsFactoryRes GetAccountsFormatterDto * @return GetAccountsFeedResponseDto */ - private GetAccountsFeedResponseDto prepareResponse(GetAccountsFormatterDto accountsFactoryRes, int pageNumber) { + private GetAccountsFeedResponseDto prepareResponse(GetAccountsFormatterDto accountsFactoryRes) { logger.info("Preparing response"); GetAccountsFeedResponseDto accountsFeedResponse = new GetAccountsFeedResponseDto(); From 336619b2cb0cc3c70abb4230113537059f735782 Mon Sep 17 00:00:00 2001 From: ajinkyac03 Date: Wed, 30 Aug 2023 14:39:29 +0530 Subject: [PATCH 165/195] 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 36b5fdbc1dc38e08d0ab3d4fda789c12f3b6c580 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Wed, 30 Aug 2023 15:13:58 +0530 Subject: [PATCH 166/195] refactored sanitization filter and test cases --- docker-compose.yml | 30 +-- .../salessparrow/api/config/FilterConfig.java | 6 +- .../api/filter/SanitizationFilter.java | 238 ++++++++---------- .../lib/wrappers/SanitizedRequestWrapper.java | 134 ++++++++-- .../unit/filters/SanitizationFilterTest.java | 143 ++++++----- 5 files changed, 319 insertions(+), 232 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index ef4a3d10..4b410fe6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,16 +1,16 @@ -version: '3' +version: "3" services: api: build: context: . dockerfile: Dockerfile.local ports: - - '8080:8080' + - "8080:8080" networks: - localdev volumes: - - './:/app' - - '~/.m2:/root/.m2' + - "./:/app" + - "~/.m2:/root/.m2" environment: - ENVIRONMENT=development - AWS_ACCESS_KEY_ID=local @@ -27,12 +27,12 @@ services: context: . dockerfile: Dockerfile.local ports: - - '8080:8080' + - "8080:8080" networks: - localdev volumes: - - './:/app' - - '~/.m2:/root/.m2' + - "./:/app" + - "~/.m2:/root/.m2" environment: - ENVIRONMENT=local-test - AWS_ACCESS_KEY_ID=local @@ -47,14 +47,14 @@ services: memcached: image: memcached ports: - - '11211:11211' + - "11211:11211" networks: - localdev - + localkms: image: nsmithuk/local-kms ports: - - '4599:8080' + - "4599:8080" volumes: - ./init:/init networks: @@ -66,18 +66,18 @@ services: - KMS_ACCOUNT_ID='111122223333' - KMS_REGION='us-east-1' - KMS_SEED_PATH=init/seed.yaml - + dynamodb: image: amazon/dynamodb-local:latest ports: - - '8000:8000' + - "8000:8000" networks: - localdev volumes: - - "./docker/dynamodb:/home/dynamodblocal/data" + - "./docker/dynamodb:/home/dynamodblocal/data" working_dir: /home/dynamodblocal - command: '-jar DynamoDBLocal.jar -sharedDb -dbPath ./data' + command: "-jar DynamoDBLocal.jar -sharedDb -dbPath ./data" networks: localdev: - driver: bridge \ No newline at end of file + driver: bridge diff --git a/src/main/java/com/salessparrow/api/config/FilterConfig.java b/src/main/java/com/salessparrow/api/config/FilterConfig.java index 5fed9df3..3d4b8414 100644 --- a/src/main/java/com/salessparrow/api/config/FilterConfig.java +++ b/src/main/java/com/salessparrow/api/config/FilterConfig.java @@ -16,7 +16,8 @@ public class FilterConfig { */ @Bean public FilterRegistrationBean sameSiteCookieFilter() { - FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); + FilterRegistrationBean registrationBean = + new FilterRegistrationBean<>(); registrationBean.setFilter(new SameSiteCookieFilter()); registrationBean.addUrlPatterns("/*"); // or specific URL patterns registrationBean.setOrder(1); @@ -30,7 +31,8 @@ public FilterRegistrationBean sameSiteCookieFilter() { */ @Bean public FilterRegistrationBean sanitizationFilter() { - FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); + FilterRegistrationBean registrationBean = + new FilterRegistrationBean<>(); registrationBean.setFilter(new SanitizationFilter()); registrationBean.addUrlPatterns("/*"); registrationBean.setOrder(0); diff --git a/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java b/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java index aa899959..34c8ecb3 100644 --- a/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java +++ b/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java @@ -7,7 +7,6 @@ import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; import jakarta.servlet.http.HttpServletRequest; - import org.owasp.html.HtmlPolicyBuilder; import org.owasp.html.PolicyFactory; @@ -15,11 +14,7 @@ import java.io.BufferedReader; import java.io.IOException; -import java.util.Collections; import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; -import java.util.Map; /** * Class to sanitize the request @@ -27,133 +22,118 @@ public class SanitizationFilter implements Filter { private SanitizedRequestWrapper sanitizedRequest; - private final PolicyFactory policy = new HtmlPolicyBuilder() - .allowElements( - "a", "label", "h1", "h2", "h3", "h4", "h5", "h6", - "p", "i", "b", "u", "strong", "em", "strike", "code", "hr", "br", "div", - "table", "thead", "caption", "tbody", "tr", "th", "td", "pre") - .allowUrlProtocols("https") - .allowAttributes("href").onElements("a") - .allowAttributes("target").onElements("a") - .allowAttributes("class").globally() - .allowAttributes("id").globally() - .disallowElements( - "script", "iframe", "object", "embed", "form", "input", "button", "select", - "textarea", "style", "link", "meta", "base" - ) - .toFactory(); - - @Override - public void init(FilterConfig filterConfig) { - } - - /** - * Method to sanitize the request - * - * @param servletRequest - Servlet request object - * @param servletResponse - Servlet response object - * @param chain - Filter chain - Filter chain - * - * @throws IOException - IOException - * @throws ServletException - ServletException - * - * @return void - */ - @Override - public void doFilter( - ServletRequest servletRequest, - ServletResponse servletResponse, - FilterChain chain - ) throws IOException, ServletException { - if (!(servletRequest instanceof HttpServletRequest)) { - throw new ServletException("Can only process HttpServletRequest"); - } - HttpServletRequest request = (HttpServletRequest) servletRequest; - sanitizeRequestBody(request); - sanitizeRequestParams(); - sanitizeRequestHeaders(); - - chain.doFilter(sanitizedRequest, servletResponse); - } - - /** - * Method to sanitize the request body - * - * @param request - Servlet request object - * - * @return void - */ - private void sanitizeRequestBody(HttpServletRequest request) { - String originalBody = getRequestBody(request); - String sanitizedBody = sanitizeHtml(originalBody); - this.sanitizedRequest = new SanitizedRequestWrapper(request, sanitizedBody); + private final PolicyFactory policy = new HtmlPolicyBuilder().toFactory(); + + @Override + public void init(FilterConfig filterConfig) {} + + /** + * Method to sanitize the request + * + * @param servletRequest - Servlet request object + * @param servletResponse - Servlet response object + * @param chain - Filter chain - Filter chain + * + * @throws IOException - IOException + * @throws ServletException - ServletException + * + * @return void + */ + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, + FilterChain chain) throws IOException, ServletException { + if (!(servletRequest instanceof HttpServletRequest)) { + throw new ServletException("Can only process HttpServletRequest"); } - - /** - * Method to sanitize the request params - * - * @return void - */ - private void sanitizeRequestParams() { - Map parameterMapCopy = new HashMap<>(this.sanitizedRequest.getParameterMap()); - parameterMapCopy.forEach((key, value) -> { - String sanitizedValue = sanitizeHtml(value[0]); + HttpServletRequest request = (HttpServletRequest) servletRequest; + sanitizeRequestBody(request); + sanitizeRequestParams(request); + sanitizeRequestHeaders(request); + + chain.doFilter(sanitizedRequest, servletResponse); + } + + /** + * Method to sanitize the request body + * + * @param request - Servlet request object + * + * @return void + */ + private void sanitizeRequestBody(HttpServletRequest request) { + String originalBody = getRequestBody(request); + String sanitizedBody = sanitizeHtml(originalBody); + this.sanitizedRequest = new SanitizedRequestWrapper(request, sanitizedBody); + } + + /** + * Method to sanitize the request params + * + * @return void + */ + private void sanitizeRequestParams(HttpServletRequest request) { + request.getParameterMap().forEach((key, values) -> { + for (int index = 0; index < values.length; index++) { + String sanitizedValue = sanitizeHtml(values[index]); this.sanitizedRequest.setParameter(key, sanitizedValue); - }); - } - - /** - * Method to sanitize the request headers - * - * @return void - */ - private void sanitizeRequestHeaders() { - Enumeration headerNames = this.sanitizedRequest.getHeaderNames(); - - if (headerNames != null && headerNames.hasMoreElements()) { - List headerNamesCopy = Collections.list(this.sanitizedRequest.getHeaderNames()); - headerNamesCopy.forEach(headerName -> { - String sanitizedValue = sanitizeHtml(this.sanitizedRequest.getHeader(headerName)); - this.sanitizedRequest.setHeader(headerName, sanitizedValue); - }); + } + }); + } + + /** + * Method to sanitize the request headers + * + * @return void + */ + private void sanitizeRequestHeaders(HttpServletRequest request) { + Enumeration headerNames = request.getHeaderNames(); + + while (headerNames != null && headerNames.hasMoreElements()) { + String headerName = headerNames.nextElement(); + Enumeration headerValues = request.getHeaders(headerName); + + while (headerValues != null && headerValues.hasMoreElements()) { + String headerValue = headerValues.nextElement(); + String sanitizedValue = sanitizeHtml(headerValue); + this.sanitizedRequest.setHeader(headerName, sanitizedValue); } } - - /** - * Method to get the request body - * - * @param request - Servlet request object - * @return String - Request body - */ - private String getRequestBody(HttpServletRequest request) { - try { - BufferedReader reader = request.getReader(); - String line; - StringBuilder requestBody = new StringBuilder(); - while ((line = reader.readLine()) != null) { - requestBody.append(line); - } - return requestBody.toString(); - } catch (IOException e) { - throw new RuntimeException("Error reading request body", e); + } + + /** + * Method to get the request body + * + * @param request - Servlet request object + * @return String - Request body + */ + private String getRequestBody(HttpServletRequest request) { + try { + BufferedReader reader = request.getReader(); + String line; + StringBuilder requestBody = new StringBuilder(); + while ((line = reader.readLine()) != null) { + requestBody.append(line); } - } - - /** - * Method to sanitize the html - * - * @param input - Input string - * @return String - Sanitized string - */ - public String sanitizeHtml(String input) { - String sanitizedInput = policy.sanitize(input); - return sanitizedInput; - } - - /** - * Method to destroy the filter - */ - @Override - public void destroy() { - } + return requestBody.toString(); + } catch (IOException e) { + throw new RuntimeException("Error reading request body", e); + } + } + + /** + * Method to sanitize the html + * + * @param input - Input string + * @return String - Sanitized string + */ + public String sanitizeHtml(String input) { + String sanitizedInput = policy.sanitize(input); + return sanitizedInput; + } + + /** + * Method to destroy the filter + */ + @Override + public void destroy() {} } diff --git a/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java b/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java index 34f6f7bf..40496c69 100644 --- a/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java +++ b/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java @@ -9,24 +9,26 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; import java.util.HashMap; +import java.util.List; import java.util.Map; -import org.apache.commons.text.StringEscapeUtils; - /** * Custom request wrapper to sanitize the request body */ public class SanitizedRequestWrapper extends HttpServletRequestWrapper { private final String sanitizedBody; - private Map sanitizedParams; + private Map> sanitizedParams; - private Map sanitizedHeaders; + private Map> sanitizedHeaders; public SanitizedRequestWrapper(HttpServletRequest request, String sanitizedBody) { super(request); - this.sanitizedBody = StringEscapeUtils.unescapeHtml4(sanitizedBody); + this.sanitizedBody = escapeQuotes(sanitizedBody); this.sanitizedParams = new HashMap<>(); this.sanitizedHeaders = new HashMap<>(); } @@ -37,8 +39,7 @@ public SanitizedRequestWrapper(HttpServletRequest request, String sanitizedBody) @Override public BufferedReader getReader() throws IOException { return new BufferedReader( - new InputStreamReader( - new ByteArrayInputStream(sanitizedBody.getBytes()))); + new InputStreamReader(new ByteArrayInputStream(sanitizedBody.getBytes()))); } /** @@ -46,7 +47,8 @@ public BufferedReader getReader() throws IOException { */ @Override public ServletInputStream getInputStream() throws IOException { - final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(sanitizedBody.getBytes()); + final ByteArrayInputStream byteArrayInputStream = + new ByteArrayInputStream(sanitizedBody.getBytes()); return new ServletInputStream() { @Override @@ -80,21 +82,68 @@ public void setReadListener(ReadListener readListener) { * @return void */ public void setParameter(String key, String value) { - this.sanitizedParams.put(key, value); + List values = this.sanitizedParams.getOrDefault(key, new ArrayList()); + values.add(value); + this.sanitizedParams.put(key, values); } /** - * Method to get the request parameter value by - * key from the sanitized params map if present - * else from the super class + * Method to get the request parameter value by key from the sanitized params map. * - * @param key - Request parameter key + * @param key - parameter key * - * @return String - Request parameter value + * @return String - parameter value */ @Override public String getParameter(String key) { - return this.sanitizedParams.getOrDefault(key, super.getParameter(key)); + List values = this.sanitizedParams.get(key); + if (values != null && !values.isEmpty()) { + return values.get(0); + } + + return null; + } + + /** + * Method to get the request parameter map from the sanitized params map. + * + * @return Map - parameter map + */ + @Override + public Map getParameterMap() { + Map sanitizedParamsMap = new HashMap<>(); + this.sanitizedParams.forEach((key, values) -> { + String[] stringValues = values.toArray(new String[0]); + sanitizedParamsMap.put(key, stringValues); + }); + + return sanitizedParamsMap; + } + + /** + * Method to get the request parameter names from the sanitized params map. + * + * @return Enumeration - parameter names + */ + @Override + public Enumeration getParameterNames() { + return Collections.enumeration(this.sanitizedParams.keySet()); + } + + /** + * Method to get the request parameter values by key from the sanitized params map. + * + * @param key - parameter key + * + * @return String[] - parameter values + */ + @Override + public String[] getParameterValues(String key) { + List values = this.sanitizedParams.get(key); + if (values != null && !values.isEmpty()) { + return values.toArray(new String[0]); + } + return null; } /** @@ -106,12 +155,63 @@ public String getParameter(String key) { * @return void */ public void setHeader(String key, String value) { - this.sanitizedHeaders.put(key, value); + List headerValues = this.sanitizedHeaders.getOrDefault(key, new ArrayList()); + headerValues.add(value); + this.sanitizedHeaders.put(key, headerValues); } + /** + * Method to get the request header value by key from the sanitized headers map. + * + * @param key - header key + * + * @return String - header value + */ @Override public String getHeader(String key) { - return this.sanitizedHeaders.getOrDefault(key, super.getHeader(key)); + List values = this.sanitizedHeaders.get(key); + if (values != null && !values.isEmpty()) { + return values.get(0); + } + return null; + } + + /** + * Method to get the request header names from the sanitized headers map. + * + * @return Enumeration - header names + * + * @return void + */ + @Override + public Enumeration getHeaderNames() { + return Collections.enumeration(this.sanitizedHeaders.keySet()); + } + + /** + * Method to get the request header values by key from the sanitized headers map. + * + * @param key - header key + * + * @return Enumeration - header values + */ + @Override + public Enumeration getHeaders(String key) { + List values = this.sanitizedHeaders.get(key); + if (values != null && !values.isEmpty()) { + return Collections.enumeration(values); + } + return Collections.enumeration(Collections.emptyList()); + } + + /** + * Method to escape single quotes and double quotes. + * + * @param input + * @return + */ + private String escapeQuotes(String input) { + return input.replace(""", "\"").replace("'", "'"); } } diff --git a/src/test/java/com/salessparrow/api/unit/filters/SanitizationFilterTest.java b/src/test/java/com/salessparrow/api/unit/filters/SanitizationFilterTest.java index 9b141fe3..7cd7c7ca 100644 --- a/src/test/java/com/salessparrow/api/unit/filters/SanitizationFilterTest.java +++ b/src/test/java/com/salessparrow/api/unit/filters/SanitizationFilterTest.java @@ -1,28 +1,31 @@ package com.salessparrow.api.unit.filters; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; import jakarta.servlet.ServletRequest; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; - import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; - import com.salessparrow.api.filter.SanitizationFilter; - import java.io.BufferedReader; -import java.io.InputStream; -import java.io.InputStreamReader; +import java.io.IOException; import java.io.StringReader; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.Vector; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.*; - -public class SanitizationFilterTest { +class SanitizationFilterTest { @Mock private HttpServletRequest request; @@ -31,82 +34,84 @@ public class SanitizationFilterTest { private HttpServletResponse response; @Mock - private FilterChain chain; + private FilterChain filterChain; + + @Mock + private ServletRequest nonHttpRequest; - private SanitizationFilter filter; + @InjectMocks + private SanitizationFilter sanitizationFilter; @BeforeEach - public void setUp() { - MockitoAnnotations.initMocks(this); - filter = new SanitizationFilter(); - filter.init(null); + void setUp() { + MockitoAnnotations.openMocks(this); } @Test - public void testSanitizeHtmlRemovesScriptTags() { - String input = ""; - String expected = ""; // Expecting empty string after removing script tags + void testDoFilter() throws Exception { + mockCommonRequestBehaviors(); + sanitizationFilter.doFilter(request, response, filterChain); + verify(filterChain).doFilter(any(), eq(response)); + assertTrue(true, "doFilter should complete without exceptions."); + } - String sanitized = filter.sanitizeHtml(input); - assertEquals(expected, sanitized); + @Test + void testRequestBodySanitization() throws Exception { + mockCommonRequestBehaviors(); + sanitizationFilter.doFilter(request, response, filterChain); + verify(request).getReader(); + assertTrue(true, "Request body should be read without exceptions."); } @Test - public void testSanitizeHtmlAllowsSafeTags() { - String input = "

Paragraph

"; - String expected = "

Paragraph

"; // The string should remain unchanged + void testRequestParamsSanitization() throws Exception { + mockCommonRequestBehaviors(); + sanitizationFilter.doFilter(request, response, filterChain); + verify(request).getParameterMap(); + assertTrue(true, "Request parameters should be read without exceptions."); + } - String sanitized = filter.sanitizeHtml(input); - assertEquals(expected, sanitized); + @Test + void testRequestHeadersSanitization() throws Exception { + mockCommonRequestBehaviors(); + sanitizationFilter.doFilter(request, response, filterChain); + verify(request).getHeaderNames(); + assertTrue(true, "Request headers should be read without exceptions."); } @Test - public void testDoFilterSanitizesScriptTags() throws Exception { - ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(ServletRequest.class); - - String input = ""; - StringReader stringReader = new StringReader(input); - BufferedReader reader = new BufferedReader(stringReader); - - when(request.getReader()).thenReturn(reader); - filter.doFilter(request, response, chain); - - verify(chain).doFilter(argumentCaptor.capture(), eq(response)); - - ServletRequest capturedRequest = argumentCaptor.getValue(); - String sanitizedBody = convertInputStreamToString(capturedRequest.getInputStream()); - - assertEquals("", sanitizedBody); + void testIOException() throws Exception { + assertThrows(RuntimeException.class, () -> { + when(request.getReader()).thenThrow(new IOException("Test IOException")); + sanitizationFilter.doFilter(request, response, filterChain); + }, "Expected doFilter to throw RuntimeException"); } @Test - public void testDoFilterAllowsSafeTags() throws Exception { - ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(ServletRequest.class); - - String input = "

Paragraph

"; - StringReader stringReader = new StringReader(input); - BufferedReader reader = new BufferedReader(stringReader); - - when(request.getReader()).thenReturn(reader); - filter.doFilter(request, response, chain); - - verify(chain).doFilter(argumentCaptor.capture(), eq(response)); - - ServletRequest capturedRequest = argumentCaptor.getValue(); - String sanitizedBody = convertInputStreamToString(capturedRequest.getInputStream()); - - assertEquals("

Paragraph

", sanitizedBody); + void testNonHttpRequest() { + assertThrows(ServletException.class, () -> { + sanitizationFilter.doFilter(nonHttpRequest, response, filterChain); + }, "Expected doFilter to throw ServletException"); } - private String convertInputStreamToString(InputStream inputStream) throws Exception { - try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream))) { - StringBuilder sb = new StringBuilder(); - String line; - while ((line = br.readLine()) != null) { - sb.append(line); - } - return sb.toString(); - } + // Helper methods + private void mockCommonRequestBehaviors() throws IOException { + when(request.getReader()).thenReturn(new BufferedReader(new StringReader("some request body"))); + when(request.getParameterMap()).thenReturn(mockedParamMap()); + when(request.getHeaderNames()).thenReturn(mockedHeaderNames()); + } + + private static Enumeration mockedHeaderNames() { + Vector headerNames = new Vector<>(); + headerNames.add("Header1"); + headerNames.add("Header2"); + return headerNames.elements(); } -} + private static Map mockedParamMap() { + Map paramMap = new HashMap<>(); + paramMap.put("param1", new String[] {"value1"}); + paramMap.put("param2", new String[] {"value2"}); + return paramMap; + } +} From b4f183373d3d05166bd5ea2c615eba06102f7967 Mon Sep 17 00:00:00 2001 From: VRDighe Date: Wed, 30 Aug 2023 15:25:11 +0530 Subject: [PATCH 167/195] 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", From d4cf0032cc10891db715c3cb457f73d16d4b7ce3 Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Wed, 30 Aug 2023 15:35:03 +0530 Subject: [PATCH 168/195] Added verification for unit tests --- .../lib/salesforce/helper/SalesforceRequestTest.java | 2 ++ .../wrappers/SalesforceGetIdentityTest.java | 10 +++++++++- .../wrappers/SalesforceGetNoteContentTest.java | 12 +++++------- .../SalesforceGetRefreshedAccessTokenTest.java | 2 ++ .../salesforce/wrappers/SalesforceGetTokensTest.java | 1 - 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceRequestTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceRequestTest.java index 9faa9917..bd78ed3d 100644 --- a/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceRequestTest.java +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceRequestTest.java @@ -89,6 +89,8 @@ public void testMakeRequest_WebClientResponseException() { // Verify that the methods were called with the expected parameters verify(sfOauthTokenRepository).getSalesforceOauthTokenByExternalUserId("user123"); verify(salesforceOAuthToken).fetchAccessToken(sfOAuthToken); + + // Verify that the updateAndGetRefreshedAccessToken method was called once verify(salesforceOAuthToken, times(1)).updateAndGetRefreshedAccessToken(sfOAuthToken); } diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetIdentityTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetIdentityTest.java index e934b22f..cb28e87e 100644 --- a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetIdentityTest.java +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetIdentityTest.java @@ -18,17 +18,21 @@ import org.springframework.beans.factory.annotation.Autowired; import com.salessparrow.api.exception.CustomException; import com.salessparrow.api.lib.errorLib.ErrorObject; +import com.salessparrow.api.lib.globalConstants.SalesforceConstants; import com.salessparrow.api.lib.httpLib.HttpClient; import com.salessparrow.api.lib.httpLib.HttpClient.HttpResponse; import com.salessparrow.api.lib.salesforce.wrappers.SalesforceGetIdentity; @SpringBootTest -@Import({SalesforceGetIdentity.class}) +@Import({SalesforceGetIdentity.class, SalesforceConstants.class}) public class SalesforceGetIdentityTest { @Autowired private SalesforceGetIdentity salesforceGetIdentity; + @Autowired + private SalesforceConstants salesforceConstants; + @Test public void testGetUserIdentity_Success() throws Exception { MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); @@ -51,6 +55,8 @@ public void testGetUserIdentity_Success() throws Exception { // Assertions assertEquals(mockResponse.getResponseBody(), actualResponse.getResponseBody()); + httpClientMockedStatic.verify(() -> HttpClient.makeGetRequest(instanceUrl + salesforceConstants.identityUrl(), headers, 10000), Mockito.times(1)); + httpClientMockedStatic.close(); } @@ -82,6 +88,8 @@ public void testGetUserIdentity_Exception() throws Exception { assertEquals("l_s_w_sgi_gui_1", errorObject.getInternalErrorIdentifier()); assertEquals("bad_request", errorObject.getApiErrorIdentifier()); + httpClientMockedStatic.verify(() -> HttpClient.makeGetRequest(instanceUrl + salesforceConstants.identityUrl(), headers, 10000), Mockito.times(1)); + httpClientMockedStatic.close(); } } diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetNoteContentTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetNoteContentTest.java index a4aa52f4..9385587c 100644 --- a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetNoteContentTest.java +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetNoteContentTest.java @@ -8,33 +8,31 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.util.ReflectionTestUtils; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; @SpringBootTest public class SalesforceGetNoteContentTest { - @Autowired - private SalesforceGetNoteContent salesforceGetNoteContent; - @Mock private SalesforceConstants salesforceConstants; @Mock private SalesforceRequest salesforceRequest; + @InjectMocks + private SalesforceGetNoteContent salesforceGetNoteContent; + @BeforeEach public void setUp() { MockitoAnnotations.openMocks(this); - ReflectionTestUtils.setField(salesforceGetNoteContent, "salesforceConstants", salesforceConstants); - ReflectionTestUtils.setField(salesforceGetNoteContent, "salesforceOauthRequest", salesforceRequest); } @Test diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetRefreshedAccessTokenTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetRefreshedAccessTokenTest.java index 4752f5cb..416dddac 100644 --- a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetRefreshedAccessTokenTest.java +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetRefreshedAccessTokenTest.java @@ -4,6 +4,7 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyMap; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.times; import java.util.HashMap; import java.util.Map; @@ -46,6 +47,7 @@ public void testSalesforceGetRefreshedAccessToken() throws Exception { // Assertions assertEquals(mockResponse.getResponseBody(), actualResponse.getResponseBody()); + httpClientMockedStatic.verify(() -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt()), times(1)); httpClientMockedStatic.close(); } diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetTokensTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetTokensTest.java index f162565a..580e681e 100644 --- a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetTokensTest.java +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetTokensTest.java @@ -17,7 +17,6 @@ import org.springframework.context.annotation.Import; import org.springframework.beans.factory.annotation.Autowired; 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.httpLib.HttpClient; import com.salessparrow.api.lib.httpLib.HttpClient.HttpResponse; From 862debce382db9440028bac77b519bcecbef0e8f Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Wed, 30 Aug 2023 15:43:50 +0530 Subject: [PATCH 169/195] added formatter command in local setup doc --- repo-docs/LOCAL_SETUP.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/repo-docs/LOCAL_SETUP.md b/repo-docs/LOCAL_SETUP.md index 3a68f435..c7759aa5 100644 --- a/repo-docs/LOCAL_SETUP.md +++ b/repo-docs/LOCAL_SETUP.md @@ -30,8 +30,8 @@ $ git submodule update --init 1. Copy the contents of `sample.secrets.json` to `secrets.json`. 2. Update the values of the environment variables in secrets.json: - - Copy Salesforce credentials from the Salesforce connected app and update `SALESFORCE_CLIENT_ID`, `SALESFORCE_CLIENT_SECRET`, `SALESFORCE_AUTH_URL`. - - Update `KMS_KEY_ID` with value `arn:aws:kms:'us-east-1':'111122223333':key/bc436485-5092-42b8-92a3-0aa8b93536dc`. This local Docker setup uses the [local-kms](https://hub.docker.com/r/nsmithuk/local-kms) Docker image, and the key is already configured using [seed](init/seed.yaml). + - Copy Salesforce credentials from the Salesforce connected app and update `SALESFORCE_CLIENT_ID`, `SALESFORCE_CLIENT_SECRET`, `SALESFORCE_AUTH_URL`. + - Update `KMS_KEY_ID` with value `arn:aws:kms:'us-east-1':'111122223333':key/bc436485-5092-42b8-92a3-0aa8b93536dc`. This local Docker setup uses the [local-kms](https://hub.docker.com/r/nsmithuk/local-kms) Docker image, and the key is already configured using [seed](init/seed.yaml). ### Start the API Server with Docker @@ -44,11 +44,13 @@ $ docker-compose up api #### Set Test-Related Environment Variables 1. Create a `test.secrets.json` file: + ```sh $ touch test.secrets.json ``` 2. Add the following environment variables to `test.secrets.json`: + ```json { "ENCRYPTION_KEY": "1234567890", @@ -71,9 +73,18 @@ $ touch test.secrets.json } ``` +#### Apply Spring Java Format + +Before committing the changes, it's good practice to apply the Spring Java format to your code to ensure it adheres to a consistent style. + +```sh +$ ./mvnw spring-javaformat:apply +``` + #### Run Test Cases ```sh $ docker-compose up test ``` -To view the test coverage, simply open the target/site/index.html file in a web browser. \ No newline at end of file + +To view the test coverage, simply open the target/site/index.html file in a web browser. From 791a060a735da06d89ce1cc2f220ff20957b7a3e Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Wed, 30 Aug 2023 15:46:28 +0530 Subject: [PATCH 170/195] Updated method name in test case --- .../unit/lib/salesforce/helper/SalesforceOAuthTokenTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceOAuthTokenTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceOAuthTokenTest.java index 49430fff..8f3b1c0b 100644 --- a/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceOAuthTokenTest.java +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceOAuthTokenTest.java @@ -73,7 +73,7 @@ public void testUpdateAndGetRefreshedAccessToken() throws Exception { when(awsKms.encryptToken("new_access_token")).thenReturn("encrypted_access_token"); - when(salesforceOauthTokenRepository.saveSalesforceOauthToken(any(SalesforceOauthToken.class))) + when(salesforceOauthTokenRepository.updateSalesforceOauthToken(any(SalesforceOauthToken.class))) .thenAnswer(invocation -> invocation.getArgument(0)); // Return the argument back String decryptedAccessToken = salesforceOauthToken.updateAndGetRefreshedAccessToken(sfOAuthToken); From 848c57469b71fa6bed59d651dc3f23023fb6a81c Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Wed, 30 Aug 2023 15:55:37 +0530 Subject: [PATCH 171/195] Added error case for SalesforceGetNoteContentTest --- .../wrappers/SalesforceGetNoteContentTest.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetNoteContentTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetNoteContentTest.java index 9385587c..6f96f8ac 100644 --- a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetNoteContentTest.java +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetNoteContentTest.java @@ -14,6 +14,7 @@ import org.springframework.boot.test.context.SpringBootTest; 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.eq; import static org.mockito.Mockito.*; @@ -59,4 +60,20 @@ public void testGetNoteContent() { assertEquals("Note Content", response.getResponseBody()); assertEquals("text/plain", response.getContentType()); } + + @Test + public void testGetNoteContent_ErrorScenario() { + String noteId = "note123"; + String salesforceUserId = "user123"; + + // Mock SalesforceConstants + when(salesforceConstants.timeoutMillis()).thenReturn(5000); + + // Mock SalesforceRequest to simulate an error + when(salesforceRequest.makeRequest(eq(salesforceUserId), any(SalesforceRequestInterface.class))) + .thenThrow(new RuntimeException("Simulated error")); + + // Test the method and verify that it handles the error correctly + assertThrows(RuntimeException.class, () -> salesforceGetNoteContent.getNoteContent(noteId, salesforceUserId)); + } } From 7ff2e5db0a1b820b5b85f0b63af60dbac961716c Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Wed, 30 Aug 2023 16:26:59 +0530 Subject: [PATCH 172/195] added review changes --- .../api/filter/SanitizationFilter.java | 5 +++-- .../api/lib/wrappers/SanitizedRequestWrapper.java | 15 +++++++++++---- .../api/unit/filters/SanitizationFilterTest.java | 1 - 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java b/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java index 34c8ecb3..4146131f 100644 --- a/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java +++ b/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java @@ -110,13 +110,14 @@ private String getRequestBody(HttpServletRequest request) { try { BufferedReader reader = request.getReader(); String line; + // TODO: Consider using a more efficient way to read the request body, such as streaming StringBuilder requestBody = new StringBuilder(); while ((line = reader.readLine()) != null) { requestBody.append(line); } return requestBody.toString(); } catch (IOException e) { - throw new RuntimeException("Error reading request body", e); + throw new RuntimeException("Error reading request body: ", e.getCause()); } } @@ -126,7 +127,7 @@ private String getRequestBody(HttpServletRequest request) { * @param input - Input string * @return String - Sanitized string */ - public String sanitizeHtml(String input) { + private String sanitizeHtml(String input) { String sanitizedInput = policy.sanitize(input); return sanitizedInput; } diff --git a/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java b/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java index 40496c69..267c0e27 100644 --- a/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java +++ b/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java @@ -205,10 +205,17 @@ public Enumeration getHeaders(String key) { } /** - * Method to escape single quotes and double quotes. - * - * @param input - * @return + * Escapes HTML-encoded quotes in a given sanitized JSON string. + * + * This method is specifically designed to work on JSON strings that have been + * HTML-sanitized. In the sanitization process, quotes could be converted to their + * HTML-encoded form (""" for double quotes and "'" for single quotes). + * + * This method replaces these HTML-encoded quotes back to their plain text versions + * (" and ' respectively) so that the JSON can be parsed correctly. + * + * @param input The sanitized JSON string that may contain HTML-encoded quotes. + * @return A JSON string with HTML-encoded quotes replaced by their plain text equivalents. */ private String escapeQuotes(String input) { return input.replace(""", "\"").replace("'", "'"); diff --git a/src/test/java/com/salessparrow/api/unit/filters/SanitizationFilterTest.java b/src/test/java/com/salessparrow/api/unit/filters/SanitizationFilterTest.java index 7cd7c7ca..ade2a2c0 100644 --- a/src/test/java/com/salessparrow/api/unit/filters/SanitizationFilterTest.java +++ b/src/test/java/com/salessparrow/api/unit/filters/SanitizationFilterTest.java @@ -52,7 +52,6 @@ void testDoFilter() throws Exception { mockCommonRequestBehaviors(); sanitizationFilter.doFilter(request, response, filterChain); verify(filterChain).doFilter(any(), eq(response)); - assertTrue(true, "doFilter should complete without exceptions."); } @Test From 3eb44eabc506686f1a72ef4df13266140b22139b Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Wed, 30 Aug 2023 16:30:12 +0530 Subject: [PATCH 173/195] Formatted test files --- .../helper/MakeCompositeRequestTest.java | 48 +++--- .../helper/SalesforceOAuthTokenTest.java | 83 +++++----- .../helper/SalesforceRequestTest.java | 145 +++++++++--------- .../wrappers/SalesforceGetIdentityTest.java | 101 ++++++------ .../SalesforceGetNoteContentTest.java | 83 +++++----- ...SalesforceGetRefreshedAccessTokenTest.java | 44 +++--- .../wrappers/SalesforceGetTokensTest.java | 87 +++++------ 7 files changed, 298 insertions(+), 293 deletions(-) diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/MakeCompositeRequestTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/MakeCompositeRequestTest.java index 03ba8114..25eb6487 100644 --- a/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/MakeCompositeRequestTest.java +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/MakeCompositeRequestTest.java @@ -23,38 +23,38 @@ @SpringBootTest public class MakeCompositeRequestTest { - @Mock - private SalesforceRequest salesforceRequest; + @Mock + private SalesforceRequest salesforceRequest; - @Mock - private SalesforceConstants salesforceConstants; + @Mock + private SalesforceConstants salesforceConstants; - @InjectMocks - private MakeCompositeRequest makeCompositeRequest; + @InjectMocks + private MakeCompositeRequest makeCompositeRequest; - @BeforeEach - public void setUp() { - MockitoAnnotations.openMocks(this); - } + @BeforeEach + public void setUp() { + MockitoAnnotations.openMocks(this); + } - @Test - public void testMakePostRequest() { + @Test + public void testMakePostRequest() { - List compositeRequests = new ArrayList<>(); - CompositeRequestDto requestDto = new CompositeRequestDto("endpoint", "method", null); - compositeRequests.add(requestDto); + List compositeRequests = new ArrayList<>(); + CompositeRequestDto requestDto = new CompositeRequestDto("endpoint", "method", null); + compositeRequests.add(requestDto); - when(salesforceConstants.timeoutMillis()).thenReturn(5000); + when(salesforceConstants.timeoutMillis()).thenReturn(5000); - when(salesforceConstants.salesforceCompositeUrl(anyString())).thenReturn("composite_url"); + when(salesforceConstants.salesforceCompositeUrl(anyString())).thenReturn("composite_url"); - when(salesforceRequest.makeRequest(anyString(), any(SalesforceRequestInterface.class))) - .thenReturn(new HttpClient.HttpResponse(200, "response", null, "application/json")); + when(salesforceRequest.makeRequest(anyString(), any(SalesforceRequestInterface.class))) + .thenReturn(new HttpClient.HttpResponse(200, "response", null, "application/json")); - HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, "user_id"); + HttpClient.HttpResponse response = makeCompositeRequest.makePostRequest(compositeRequests, "user_id"); - assertEquals(200, response.getStatusCode()); - assertEquals("response", response.getResponseBody()); - } -} + assertEquals(200, response.getStatusCode()); + assertEquals("response", response.getResponseBody()); + } +} diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceOAuthTokenTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceOAuthTokenTest.java index 8f3b1c0b..0677c074 100644 --- a/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceOAuthTokenTest.java +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceOAuthTokenTest.java @@ -17,68 +17,69 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.*; public class SalesforceOAuthTokenTest { - @Mock - private AwsKms awsKms; + @Mock + private AwsKms awsKms; - @Mock - private SalesforceOauthTokenRepository salesforceOauthTokenRepository; + @Mock + private SalesforceOauthTokenRepository salesforceOauthTokenRepository; - @Mock - private SalesforceGetRefreshedAccessToken salesforceGetRefreshedAccessToken; + @Mock + private SalesforceGetRefreshedAccessToken salesforceGetRefreshedAccessToken; - @Mock - private Util util; + @Mock + private Util util; - @InjectMocks - private SalesforceOAuthToken salesforceOauthToken; + @InjectMocks + private SalesforceOAuthToken salesforceOauthToken; - @BeforeEach - public void setUp() { - MockitoAnnotations.openMocks(this); - } + @BeforeEach + public void setUp() { + MockitoAnnotations.openMocks(this); + } - @Test - public void testFetchAccessToken() { + @Test + public void testFetchAccessToken() { - SalesforceOauthToken sfOAuthToken = new SalesforceOauthToken(); - sfOAuthToken.setAccessToken("encrypted_access_token"); + SalesforceOauthToken sfOAuthToken = new SalesforceOauthToken(); + sfOAuthToken.setAccessToken("encrypted_access_token"); - when(awsKms.decryptToken("encrypted_access_token")).thenReturn("decrypted_access_token"); + when(awsKms.decryptToken("encrypted_access_token")).thenReturn("decrypted_access_token"); - String decryptedAccessToken = salesforceOauthToken.fetchAccessToken(sfOAuthToken); + String decryptedAccessToken = salesforceOauthToken.fetchAccessToken(sfOAuthToken); - assertEquals("decrypted_access_token", decryptedAccessToken); - } + assertEquals("decrypted_access_token", decryptedAccessToken); + } - @Test - public void testUpdateAndGetRefreshedAccessToken() throws Exception { + @Test + public void testUpdateAndGetRefreshedAccessToken() throws Exception { - SalesforceOauthToken sfOAuthToken = new SalesforceOauthToken(); - sfOAuthToken.setRefreshToken("encrypted_refresh_token"); + SalesforceOauthToken sfOAuthToken = new SalesforceOauthToken(); + sfOAuthToken.setRefreshToken("encrypted_refresh_token"); - String responseBody = "{\"access_token\":\"new_access_token\"}"; - ObjectMapper map = new ObjectMapper(); - JsonNode responseBodyNode = map.readTree(responseBody); + String responseBody = "{\"access_token\":\"new_access_token\"}"; + ObjectMapper map = new ObjectMapper(); + JsonNode responseBodyNode = map.readTree(responseBody); - when(awsKms.decryptToken("encrypted_refresh_token")).thenReturn("decrypted_refresh_token"); + when(awsKms.decryptToken("encrypted_refresh_token")).thenReturn("decrypted_refresh_token"); - HttpClient.HttpResponse response = new HttpClient.HttpResponse(200, responseBody, null, "application/json"); - when(salesforceGetRefreshedAccessToken.getRefreshedAccessToken("decrypted_refresh_token")).thenReturn(response); + HttpClient.HttpResponse response = new HttpClient.HttpResponse(200, responseBody, null, "application/json"); + when(salesforceGetRefreshedAccessToken.getRefreshedAccessToken("decrypted_refresh_token")).thenReturn(response); - when(util.getJsonNode(responseBody)).thenReturn(responseBodyNode); + when(util.getJsonNode(responseBody)).thenReturn(responseBodyNode); - when(awsKms.encryptToken("new_access_token")).thenReturn("encrypted_access_token"); + when(awsKms.encryptToken("new_access_token")).thenReturn("encrypted_access_token"); - when(salesforceOauthTokenRepository.updateSalesforceOauthToken(any(SalesforceOauthToken.class))) - .thenAnswer(invocation -> invocation.getArgument(0)); // Return the argument back + when(salesforceOauthTokenRepository.updateSalesforceOauthToken(any(SalesforceOauthToken.class))) + .thenAnswer(invocation -> invocation.getArgument(0)); // Return the argument + // back - String decryptedAccessToken = salesforceOauthToken.updateAndGetRefreshedAccessToken(sfOAuthToken); + String decryptedAccessToken = salesforceOauthToken.updateAndGetRefreshedAccessToken(sfOAuthToken); - assertEquals("new_access_token", decryptedAccessToken); - } -} + assertEquals("new_access_token", decryptedAccessToken); + } +} diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceRequestTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceRequestTest.java index bd78ed3d..e9161c7f 100644 --- a/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceRequestTest.java +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceRequestTest.java @@ -22,105 +22,100 @@ @SpringBootTest public class SalesforceRequestTest { - @Mock - private SalesforceOAuthToken salesforceOAuthToken; + @Mock + private SalesforceOAuthToken salesforceOAuthToken; - @Mock - private SalesforceOauthTokenRepository sfOauthTokenRepository; + @Mock + private SalesforceOauthTokenRepository sfOauthTokenRepository; - @InjectMocks - private SalesforceRequest salesforceRequest; + @InjectMocks + private SalesforceRequest salesforceRequest; - @BeforeEach - public void setUp() { - MockitoAnnotations.openMocks(this); - } + @BeforeEach + public void setUp() { + MockitoAnnotations.openMocks(this); + } - @Test - public void testMakeRequest_Success() { + @Test + public void testMakeRequest_Success() { - SalesforceOauthToken sfOAuthToken = new SalesforceOauthToken(); - sfOAuthToken.setAccessToken("access_token"); - sfOAuthToken.setInstanceUrl("https://instance.url"); + SalesforceOauthToken sfOAuthToken = new SalesforceOauthToken(); + sfOAuthToken.setAccessToken("access_token"); + sfOAuthToken.setInstanceUrl("https://instance.url"); - when(sfOauthTokenRepository.getSalesforceOauthTokenByExternalUserId("user123")) - .thenReturn(sfOAuthToken); + when(sfOauthTokenRepository.getSalesforceOauthTokenByExternalUserId("user123")).thenReturn(sfOAuthToken); - // Mock SalesforceOAuthToken - when(salesforceOAuthToken.fetchAccessToken(any(SalesforceOauthToken.class))) - .thenReturn("access_token"); + // Mock SalesforceOAuthToken + when(salesforceOAuthToken.fetchAccessToken(any(SalesforceOauthToken.class))).thenReturn("access_token"); - // Mock SalesforceRequestInterface - SalesforceRequestInterface requestInterface = (token, instanceUrl) -> "Response"; - - // Test the method - String response = salesforceRequest.makeRequest("user123", requestInterface); + // Mock SalesforceRequestInterface + SalesforceRequestInterface requestInterface = (token, instanceUrl) -> "Response"; - // Verify that the methods were called with the expected parameters - verify(sfOauthTokenRepository).getSalesforceOauthTokenByExternalUserId("user123"); - verify(salesforceOAuthToken).fetchAccessToken(sfOAuthToken); + // Test the method + String response = salesforceRequest.makeRequest("user123", requestInterface); - // Verify the response - assertEquals("Response", response); - } + // Verify that the methods were called with the expected parameters + verify(sfOauthTokenRepository).getSalesforceOauthTokenByExternalUserId("user123"); + verify(salesforceOAuthToken).fetchAccessToken(sfOAuthToken); - @Test - public void testMakeRequest_WebClientResponseException() { + // Verify the response + assertEquals("Response", response); + } - SalesforceOauthToken sfOAuthToken = new SalesforceOauthToken(); - sfOAuthToken.setAccessToken("access_token"); - sfOAuthToken.setInstanceUrl("https://instance.url"); + @Test + public void testMakeRequest_WebClientResponseException() { - when(sfOauthTokenRepository.getSalesforceOauthTokenByExternalUserId("user123")) - .thenReturn(sfOAuthToken); + SalesforceOauthToken sfOAuthToken = new SalesforceOauthToken(); + sfOAuthToken.setAccessToken("access_token"); + sfOAuthToken.setInstanceUrl("https://instance.url"); - // Mock SalesforceOAuthToken - when(salesforceOAuthToken.fetchAccessToken(any(SalesforceOauthToken.class))) - .thenReturn("access_token"); + when(sfOauthTokenRepository.getSalesforceOauthTokenByExternalUserId("user123")).thenReturn(sfOAuthToken); - // Mock SalesforceRequestInterface - SalesforceRequestInterface requestInterface = (token, instanceUrl) -> { - throw new WebClientResponseException(401, "Unauthorized", null, null, null); - }; + // Mock SalesforceOAuthToken + when(salesforceOAuthToken.fetchAccessToken(any(SalesforceOauthToken.class))).thenReturn("access_token"); - // Test the method and expect a CustomException - assertThrows(CustomException.class, () -> salesforceRequest.makeRequest("user123", requestInterface)); + // Mock SalesforceRequestInterface + SalesforceRequestInterface requestInterface = (token, instanceUrl) -> { + throw new WebClientResponseException(401, "Unauthorized", null, null, null); + }; - // Verify that the methods were called with the expected parameters - verify(sfOauthTokenRepository).getSalesforceOauthTokenByExternalUserId("user123"); - verify(salesforceOAuthToken).fetchAccessToken(sfOAuthToken); + // Test the method and expect a CustomException + assertThrows(CustomException.class, () -> salesforceRequest.makeRequest("user123", requestInterface)); - // Verify that the updateAndGetRefreshedAccessToken method was called once - verify(salesforceOAuthToken, times(1)).updateAndGetRefreshedAccessToken(sfOAuthToken); - } + // Verify that the methods were called with the expected parameters + verify(sfOauthTokenRepository).getSalesforceOauthTokenByExternalUserId("user123"); + verify(salesforceOAuthToken).fetchAccessToken(sfOAuthToken); - @Test - public void testMakeRequest_InternalServerErrorException() { + // Verify that the updateAndGetRefreshedAccessToken method was called once + verify(salesforceOAuthToken, times(1)).updateAndGetRefreshedAccessToken(sfOAuthToken); + } - SalesforceOauthToken sfOAuthToken = new SalesforceOauthToken(); - sfOAuthToken.setAccessToken("access_token"); - sfOAuthToken.setInstanceUrl("https://instance.url"); + @Test + public void testMakeRequest_InternalServerErrorException() { - when(sfOauthTokenRepository.getSalesforceOauthTokenByExternalUserId("user123")) - .thenReturn(sfOAuthToken); + SalesforceOauthToken sfOAuthToken = new SalesforceOauthToken(); + sfOAuthToken.setAccessToken("access_token"); + sfOAuthToken.setInstanceUrl("https://instance.url"); - // Mock SalesforceOAuthToken - when(salesforceOAuthToken.fetchAccessToken(any(SalesforceOauthToken.class))) - .thenReturn("access_token"); + when(sfOauthTokenRepository.getSalesforceOauthTokenByExternalUserId("user123")).thenReturn(sfOAuthToken); - // Mock SalesforceRequestInterface - SalesforceRequestInterface requestInterface = (token, instanceUrl) -> { - throw new WebClientResponseException(500, "Internal Server Error", null, null, null); - }; + // Mock SalesforceOAuthToken + when(salesforceOAuthToken.fetchAccessToken(any(SalesforceOauthToken.class))).thenReturn("access_token"); - // Test the method and expect a CustomException - assertThrows(CustomException.class, () -> salesforceRequest.makeRequest("user123", requestInterface)); + // Mock SalesforceRequestInterface + SalesforceRequestInterface requestInterface = (token, instanceUrl) -> { + throw new WebClientResponseException(500, "Internal Server Error", null, null, null); + }; - // Verify that the methods were called with the expected parameters - verify(sfOauthTokenRepository).getSalesforceOauthTokenByExternalUserId("user123"); - verify(salesforceOAuthToken).fetchAccessToken(sfOAuthToken); + // Test the method and expect a CustomException + assertThrows(CustomException.class, () -> salesforceRequest.makeRequest("user123", requestInterface)); + + // Verify that the methods were called with the expected parameters + verify(sfOauthTokenRepository).getSalesforceOauthTokenByExternalUserId("user123"); + verify(salesforceOAuthToken).fetchAccessToken(sfOAuthToken); + + // Verify that the updateAndGetRefreshedAccessToken method was not called + verify(salesforceOAuthToken, never()).updateAndGetRefreshedAccessToken(sfOAuthToken); + } - // Verify that the updateAndGetRefreshedAccessToken method was not called - verify(salesforceOAuthToken, never()).updateAndGetRefreshedAccessToken(sfOAuthToken); - } } diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetIdentityTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetIdentityTest.java index cb28e87e..faae90b1 100644 --- a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetIdentityTest.java +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetIdentityTest.java @@ -24,72 +24,77 @@ import com.salessparrow.api.lib.salesforce.wrappers.SalesforceGetIdentity; @SpringBootTest -@Import({SalesforceGetIdentity.class, SalesforceConstants.class}) +@Import({ SalesforceGetIdentity.class, SalesforceConstants.class }) public class SalesforceGetIdentityTest { - @Autowired - private SalesforceGetIdentity salesforceGetIdentity; + @Autowired + private SalesforceGetIdentity salesforceGetIdentity; - @Autowired - private SalesforceConstants salesforceConstants; + @Autowired + private SalesforceConstants salesforceConstants; - @Test - public void testGetUserIdentity_Success() throws Exception { - MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); + @Test + public void testGetUserIdentity_Success() throws Exception { + MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); - String instanceUrl = "https://example.com"; - String accessToken = "dummyAccessToken"; + String instanceUrl = "https://example.com"; + String accessToken = "dummyAccessToken"; - Map headers = new HashMap<>(); - headers.put("Authorization", "Bearer " + accessToken); + Map headers = new HashMap<>(); + headers.put("Authorization", "Bearer " + accessToken); - String responseBody = "Mock Response Body"; - HttpResponse mockResponse = new HttpResponse(); - mockResponse.setResponseBody(responseBody); + String responseBody = "Mock Response Body"; + HttpResponse mockResponse = new HttpResponse(); + mockResponse.setResponseBody(responseBody); - httpClientMockedStatic.when(() -> HttpClient.makeGetRequest(anyString(), anyMap(), anyInt())) - .thenReturn(mockResponse); - - HttpResponse actualResponse = salesforceGetIdentity.getUserIdentity(instanceUrl, accessToken); + httpClientMockedStatic.when(() -> HttpClient.makeGetRequest(anyString(), anyMap(), anyInt())) + .thenReturn(mockResponse); - // Assertions - assertEquals(mockResponse.getResponseBody(), actualResponse.getResponseBody()); + HttpResponse actualResponse = salesforceGetIdentity.getUserIdentity(instanceUrl, accessToken); - httpClientMockedStatic.verify(() -> HttpClient.makeGetRequest(instanceUrl + salesforceConstants.identityUrl(), headers, 10000), Mockito.times(1)); + // Assertions + assertEquals(mockResponse.getResponseBody(), actualResponse.getResponseBody()); - httpClientMockedStatic.close(); - } + httpClientMockedStatic.verify( + () -> HttpClient.makeGetRequest(instanceUrl + salesforceConstants.identityUrl(), headers, 10000), + Mockito.times(1)); - @Test - public void testGetUserIdentity_Exception() throws Exception { - MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); + httpClientMockedStatic.close(); + } - String instanceUrl = "https://example.com"; - String accessToken = "dummyAccessToken"; + @Test + public void testGetUserIdentity_Exception() throws Exception { + MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); - Map headers = new HashMap<>(); - headers.put("Authorization", "Bearer " + accessToken); + String instanceUrl = "https://example.com"; + String accessToken = "dummyAccessToken"; - String responseBody = "Mock Response Body"; - HttpResponse mockResponse = new HttpResponse(); - mockResponse.setResponseBody(responseBody); + Map headers = new HashMap<>(); + headers.put("Authorization", "Bearer " + accessToken); - httpClientMockedStatic.when(() -> HttpClient.makeGetRequest(anyString(), anyMap(), anyInt())) - .thenThrow(new RuntimeException("Some error occurred")); + String responseBody = "Mock Response Body"; + HttpResponse mockResponse = new HttpResponse(); + mockResponse.setResponseBody(responseBody); - CustomException exception = assertThrows(CustomException.class, () -> { - salesforceGetIdentity.getUserIdentity(instanceUrl, accessToken); - }); + httpClientMockedStatic.when(() -> HttpClient.makeGetRequest(anyString(), anyMap(), anyInt())) + .thenThrow(new RuntimeException("Some error occurred")); - // Assertions - assertNotNull(exception); - ErrorObject errorObject = exception.getErrorObject(); - assertNotNull(errorObject); - assertEquals("l_s_w_sgi_gui_1", errorObject.getInternalErrorIdentifier()); - assertEquals("bad_request", errorObject.getApiErrorIdentifier()); + CustomException exception = assertThrows(CustomException.class, () -> { + salesforceGetIdentity.getUserIdentity(instanceUrl, accessToken); + }); - httpClientMockedStatic.verify(() -> HttpClient.makeGetRequest(instanceUrl + salesforceConstants.identityUrl(), headers, 10000), Mockito.times(1)); + // Assertions + assertNotNull(exception); + ErrorObject errorObject = exception.getErrorObject(); + assertNotNull(errorObject); + assertEquals("l_s_w_sgi_gui_1", errorObject.getInternalErrorIdentifier()); + assertEquals("bad_request", errorObject.getApiErrorIdentifier()); + + httpClientMockedStatic.verify( + () -> HttpClient.makeGetRequest(instanceUrl + salesforceConstants.identityUrl(), headers, 10000), + Mockito.times(1)); + + httpClientMockedStatic.close(); + } - httpClientMockedStatic.close(); - } } diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetNoteContentTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetNoteContentTest.java index 6f96f8ac..82b16eec 100644 --- a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetNoteContentTest.java +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetNoteContentTest.java @@ -22,58 +22,59 @@ @SpringBootTest public class SalesforceGetNoteContentTest { - @Mock - private SalesforceConstants salesforceConstants; + @Mock + private SalesforceConstants salesforceConstants; - @Mock - private SalesforceRequest salesforceRequest; + @Mock + private SalesforceRequest salesforceRequest; - @InjectMocks - private SalesforceGetNoteContent salesforceGetNoteContent; + @InjectMocks + private SalesforceGetNoteContent salesforceGetNoteContent; - @BeforeEach - public void setUp() { - MockitoAnnotations.openMocks(this); - } + @BeforeEach + public void setUp() { + MockitoAnnotations.openMocks(this); + } - @Test - public void testGetNoteContent() { - String noteId = "note123"; - String salesforceUserId = "user123"; + @Test + public void testGetNoteContent() { + String noteId = "note123"; + String salesforceUserId = "user123"; - // Mock SalesforceConstants - when(salesforceConstants.timeoutMillis()).thenReturn(5000); + // Mock SalesforceConstants + when(salesforceConstants.timeoutMillis()).thenReturn(5000); - // Mock SalesforceRequest - when(salesforceRequest.makeRequest(eq(salesforceUserId), any(SalesforceRequestInterface.class))) - .thenReturn(new HttpClient.HttpResponse(200, "Note Content", null, "text/plain")); + // Mock SalesforceRequest + when(salesforceRequest.makeRequest(eq(salesforceUserId), any(SalesforceRequestInterface.class))) + .thenReturn(new HttpClient.HttpResponse(200, "Note Content", null, "text/plain")); - // Test the method - HttpClient.HttpResponse response = salesforceGetNoteContent.getNoteContent(noteId, salesforceUserId); + // Test the method + HttpClient.HttpResponse response = salesforceGetNoteContent.getNoteContent(noteId, salesforceUserId); - // Verify that the methods were called with the expected parameters - verify(salesforceConstants).timeoutMillis(); - verify(salesforceRequest).makeRequest(eq(salesforceUserId), any(SalesforceRequestInterface.class)); + // Verify that the methods were called with the expected parameters + verify(salesforceConstants).timeoutMillis(); + verify(salesforceRequest).makeRequest(eq(salesforceUserId), any(SalesforceRequestInterface.class)); - // Verify the response - assertEquals(200, response.getStatusCode()); - assertEquals("Note Content", response.getResponseBody()); - assertEquals("text/plain", response.getContentType()); - } + // Verify the response + assertEquals(200, response.getStatusCode()); + assertEquals("Note Content", response.getResponseBody()); + assertEquals("text/plain", response.getContentType()); + } - @Test - public void testGetNoteContent_ErrorScenario() { - String noteId = "note123"; - String salesforceUserId = "user123"; + @Test + public void testGetNoteContent_ErrorScenario() { + String noteId = "note123"; + String salesforceUserId = "user123"; - // Mock SalesforceConstants - when(salesforceConstants.timeoutMillis()).thenReturn(5000); + // Mock SalesforceConstants + when(salesforceConstants.timeoutMillis()).thenReturn(5000); - // Mock SalesforceRequest to simulate an error - when(salesforceRequest.makeRequest(eq(salesforceUserId), any(SalesforceRequestInterface.class))) - .thenThrow(new RuntimeException("Simulated error")); + // Mock SalesforceRequest to simulate an error + when(salesforceRequest.makeRequest(eq(salesforceUserId), any(SalesforceRequestInterface.class))) + .thenThrow(new RuntimeException("Simulated error")); + + // Test the method and verify that it handles the error correctly + assertThrows(RuntimeException.class, () -> salesforceGetNoteContent.getNoteContent(noteId, salesforceUserId)); + } - // Test the method and verify that it handles the error correctly - assertThrows(RuntimeException.class, () -> salesforceGetNoteContent.getNoteContent(noteId, salesforceUserId)); - } } diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetRefreshedAccessTokenTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetRefreshedAccessTokenTest.java index 416dddac..c4f1b7f6 100644 --- a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetRefreshedAccessTokenTest.java +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetRefreshedAccessTokenTest.java @@ -21,34 +21,36 @@ import com.salessparrow.api.lib.salesforce.wrappers.SalesforceGetRefreshedAccessToken; @SpringBootTest -@Import({SalesforceGetRefreshedAccessToken.class}) +@Import({ SalesforceGetRefreshedAccessToken.class }) public class SalesforceGetRefreshedAccessTokenTest { - @Autowired - private SalesforceGetRefreshedAccessToken salesforceGetRefreshedAccessToken; + @Autowired + private SalesforceGetRefreshedAccessToken salesforceGetRefreshedAccessToken; - @Test - public void testSalesforceGetRefreshedAccessToken() throws Exception { - MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); + @Test + public void testSalesforceGetRefreshedAccessToken() throws Exception { + MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); - String refreshToken = "dummyRefreshToken"; + String refreshToken = "dummyRefreshToken"; - Map headers = new HashMap<>(); - headers.put("Authorization", "Bearer " + refreshToken); + Map headers = new HashMap<>(); + headers.put("Authorization", "Bearer " + refreshToken); - String responseBody = "Mock Response Body"; - HttpResponse mockResponse = new HttpResponse(); - mockResponse.setResponseBody(responseBody); + String responseBody = "Mock Response Body"; + HttpResponse mockResponse = new HttpResponse(); + mockResponse.setResponseBody(responseBody); - httpClientMockedStatic.when(() -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt())) - .thenReturn(mockResponse); - - HttpResponse actualResponse = salesforceGetRefreshedAccessToken.getRefreshedAccessToken(refreshToken); + httpClientMockedStatic.when(() -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt())) + .thenReturn(mockResponse); - // Assertions - assertEquals(mockResponse.getResponseBody(), actualResponse.getResponseBody()); - httpClientMockedStatic.verify(() -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt()), times(1)); + HttpResponse actualResponse = salesforceGetRefreshedAccessToken.getRefreshedAccessToken(refreshToken); + + // Assertions + assertEquals(mockResponse.getResponseBody(), actualResponse.getResponseBody()); + httpClientMockedStatic.verify(() -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt()), + times(1)); + + httpClientMockedStatic.close(); + } - httpClientMockedStatic.close(); - } } diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetTokensTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetTokensTest.java index 580e681e..ac6365bf 100644 --- a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetTokensTest.java +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetTokensTest.java @@ -23,64 +23,65 @@ import com.salessparrow.api.lib.salesforce.wrappers.SalesforceGetTokens; @SpringBootTest -@Import({SalesforceGetTokens.class}) +@Import({ SalesforceGetTokens.class }) public class SalesforceGetTokensTest { - @Autowired - private SalesforceGetTokens salesforceGetTokens; + @Autowired + private SalesforceGetTokens salesforceGetTokens; - @Test - public void testSalesforceGetTokens_Success() throws Exception { - MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); + @Test + public void testSalesforceGetTokens_Success() throws Exception { + MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); - String code = "dummyCode"; - String redirectUri = "dummyRedirectUri"; + String code = "dummyCode"; + String redirectUri = "dummyRedirectUri"; - Map headers = new HashMap<>(); - headers.put("Authorization", "Dummy Bearer Header"); + Map headers = new HashMap<>(); + headers.put("Authorization", "Dummy Bearer Header"); - String responseBody = "Mock Response Body"; - HttpResponse mockResponse = new HttpResponse(); - mockResponse.setResponseBody(responseBody); + String responseBody = "Mock Response Body"; + HttpResponse mockResponse = new HttpResponse(); + mockResponse.setResponseBody(responseBody); - httpClientMockedStatic.when(() -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt())) - .thenReturn(mockResponse); - - HttpResponse actualResponse = salesforceGetTokens.getTokens(code, redirectUri); + httpClientMockedStatic.when(() -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt())) + .thenReturn(mockResponse); - // Assertions - assertEquals(mockResponse.getResponseBody(), actualResponse.getResponseBody()); + HttpResponse actualResponse = salesforceGetTokens.getTokens(code, redirectUri); - httpClientMockedStatic.close(); - } + // Assertions + assertEquals(mockResponse.getResponseBody(), actualResponse.getResponseBody()); - @Test - public void testSalesforceGetTokens_Exception() throws Exception { - MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); + httpClientMockedStatic.close(); + } - String code = "dummyCode"; - String redirectUri = "dummyRedirectUri"; + @Test + public void testSalesforceGetTokens_Exception() throws Exception { + MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); - Map headers = new HashMap<>(); - headers.put("Authorization", "Dummy Bearer Header"); + String code = "dummyCode"; + String redirectUri = "dummyRedirectUri"; - String responseBody = "Mock Response Body"; - HttpResponse mockResponse = new HttpResponse(); - mockResponse.setResponseBody(responseBody); + Map headers = new HashMap<>(); + headers.put("Authorization", "Dummy Bearer Header"); - httpClientMockedStatic.when(() -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt())) - .thenThrow(new RuntimeException("Some error occurred")); + String responseBody = "Mock Response Body"; + HttpResponse mockResponse = new HttpResponse(); + mockResponse.setResponseBody(responseBody); - CustomException exception = assertThrows(CustomException.class, () -> { - salesforceGetTokens.getTokens(code, redirectUri); - }); + httpClientMockedStatic.when(() -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt())) + .thenThrow(new RuntimeException("Some error occurred")); - // Assertions - assertNotNull(exception); - ParamErrorObject paramErrorObject = exception.getParamErrorObject(); - assertNotNull(paramErrorObject); - assertEquals("l_s_w_sgt_gt_1", paramErrorObject.getInternalErrorIdentifier()); + CustomException exception = assertThrows(CustomException.class, () -> { + salesforceGetTokens.getTokens(code, redirectUri); + }); + + // Assertions + assertNotNull(exception); + ParamErrorObject paramErrorObject = exception.getParamErrorObject(); + assertNotNull(paramErrorObject); + assertEquals("l_s_w_sgt_gt_1", paramErrorObject.getInternalErrorIdentifier()); + + httpClientMockedStatic.close(); + } - httpClientMockedStatic.close(); - } } From 5b9eb5cfca7d24261a90dbfde3b9f22276ff0f1b Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Wed, 30 Aug 2023 16:54:20 +0530 Subject: [PATCH 174/195] Moved httpClientMockedStatic to try block --- .../wrappers/SalesforceGetIdentityTest.java | 81 +++++++++---------- ...SalesforceGetRefreshedAccessTokenTest.java | 30 +++---- .../wrappers/SalesforceGetTokensTest.java | 66 +++++++-------- 3 files changed, 88 insertions(+), 89 deletions(-) diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetIdentityTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetIdentityTest.java index faae90b1..0381fbd7 100644 --- a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetIdentityTest.java +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetIdentityTest.java @@ -35,66 +35,65 @@ public class SalesforceGetIdentityTest { @Test public void testGetUserIdentity_Success() throws Exception { - MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); + try (MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class)) { - String instanceUrl = "https://example.com"; - String accessToken = "dummyAccessToken"; + String instanceUrl = "https://example.com"; + String accessToken = "dummyAccessToken"; - Map headers = new HashMap<>(); - headers.put("Authorization", "Bearer " + accessToken); + Map headers = new HashMap<>(); + headers.put("Authorization", "Bearer " + accessToken); - String responseBody = "Mock Response Body"; - HttpResponse mockResponse = new HttpResponse(); - mockResponse.setResponseBody(responseBody); + String responseBody = "Mock Response Body"; + HttpResponse mockResponse = new HttpResponse(); + mockResponse.setResponseBody(responseBody); - httpClientMockedStatic.when(() -> HttpClient.makeGetRequest(anyString(), anyMap(), anyInt())) - .thenReturn(mockResponse); + httpClientMockedStatic.when(() -> HttpClient.makeGetRequest(anyString(), anyMap(), anyInt())) + .thenReturn(mockResponse); - HttpResponse actualResponse = salesforceGetIdentity.getUserIdentity(instanceUrl, accessToken); + HttpResponse actualResponse = salesforceGetIdentity.getUserIdentity(instanceUrl, accessToken); - // Assertions - assertEquals(mockResponse.getResponseBody(), actualResponse.getResponseBody()); + // Assertions + assertEquals(mockResponse.getResponseBody(), actualResponse.getResponseBody()); - httpClientMockedStatic.verify( - () -> HttpClient.makeGetRequest(instanceUrl + salesforceConstants.identityUrl(), headers, 10000), - Mockito.times(1)); - - httpClientMockedStatic.close(); + httpClientMockedStatic.verify( + () -> HttpClient.makeGetRequest(instanceUrl + salesforceConstants.identityUrl(), headers, 10000), + Mockito.times(1)); + } } @Test public void testGetUserIdentity_Exception() throws Exception { - MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); + try (MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class)) { - String instanceUrl = "https://example.com"; - String accessToken = "dummyAccessToken"; + String instanceUrl = "https://example.com"; + String accessToken = "dummyAccessToken"; - Map headers = new HashMap<>(); - headers.put("Authorization", "Bearer " + accessToken); + Map headers = new HashMap<>(); + headers.put("Authorization", "Bearer " + accessToken); - String responseBody = "Mock Response Body"; - HttpResponse mockResponse = new HttpResponse(); - mockResponse.setResponseBody(responseBody); + String responseBody = "Mock Response Body"; + HttpResponse mockResponse = new HttpResponse(); + mockResponse.setResponseBody(responseBody); - httpClientMockedStatic.when(() -> HttpClient.makeGetRequest(anyString(), anyMap(), anyInt())) - .thenThrow(new RuntimeException("Some error occurred")); + httpClientMockedStatic.when(() -> HttpClient.makeGetRequest(anyString(), anyMap(), anyInt())) + .thenThrow(new RuntimeException("Some error occurred")); - CustomException exception = assertThrows(CustomException.class, () -> { - salesforceGetIdentity.getUserIdentity(instanceUrl, accessToken); - }); + CustomException exception = assertThrows(CustomException.class, () -> { + salesforceGetIdentity.getUserIdentity(instanceUrl, accessToken); + }); - // Assertions - assertNotNull(exception); - ErrorObject errorObject = exception.getErrorObject(); - assertNotNull(errorObject); - assertEquals("l_s_w_sgi_gui_1", errorObject.getInternalErrorIdentifier()); - assertEquals("bad_request", errorObject.getApiErrorIdentifier()); + // Assertions + assertNotNull(exception); + ErrorObject errorObject = exception.getErrorObject(); + assertNotNull(errorObject); + assertEquals("l_s_w_sgi_gui_1", errorObject.getInternalErrorIdentifier()); + assertEquals("bad_request", errorObject.getApiErrorIdentifier()); - httpClientMockedStatic.verify( - () -> HttpClient.makeGetRequest(instanceUrl + salesforceConstants.identityUrl(), headers, 10000), - Mockito.times(1)); + httpClientMockedStatic.verify( + () -> HttpClient.makeGetRequest(instanceUrl + salesforceConstants.identityUrl(), headers, 10000), + Mockito.times(1)); - httpClientMockedStatic.close(); + } } } diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetRefreshedAccessTokenTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetRefreshedAccessTokenTest.java index c4f1b7f6..6269e024 100644 --- a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetRefreshedAccessTokenTest.java +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetRefreshedAccessTokenTest.java @@ -29,28 +29,28 @@ public class SalesforceGetRefreshedAccessTokenTest { @Test public void testSalesforceGetRefreshedAccessToken() throws Exception { - MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); + try (MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class)) { - String refreshToken = "dummyRefreshToken"; + String refreshToken = "dummyRefreshToken"; - Map headers = new HashMap<>(); - headers.put("Authorization", "Bearer " + refreshToken); + Map headers = new HashMap<>(); + headers.put("Authorization", "Bearer " + refreshToken); - String responseBody = "Mock Response Body"; - HttpResponse mockResponse = new HttpResponse(); - mockResponse.setResponseBody(responseBody); + String responseBody = "Mock Response Body"; + HttpResponse mockResponse = new HttpResponse(); + mockResponse.setResponseBody(responseBody); - httpClientMockedStatic.when(() -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt())) - .thenReturn(mockResponse); + httpClientMockedStatic.when(() -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt())) + .thenReturn(mockResponse); - HttpResponse actualResponse = salesforceGetRefreshedAccessToken.getRefreshedAccessToken(refreshToken); + HttpResponse actualResponse = salesforceGetRefreshedAccessToken.getRefreshedAccessToken(refreshToken); - // Assertions - assertEquals(mockResponse.getResponseBody(), actualResponse.getResponseBody()); - httpClientMockedStatic.verify(() -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt()), - times(1)); + // Assertions + assertEquals(mockResponse.getResponseBody(), actualResponse.getResponseBody()); + httpClientMockedStatic + .verify(() -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt()), times(1)); - httpClientMockedStatic.close(); + } } } diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetTokensTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetTokensTest.java index ac6365bf..3599dcee 100644 --- a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetTokensTest.java +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetTokensTest.java @@ -31,57 +31,57 @@ public class SalesforceGetTokensTest { @Test public void testSalesforceGetTokens_Success() throws Exception { - MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); + try (MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class)) { - String code = "dummyCode"; - String redirectUri = "dummyRedirectUri"; + String code = "dummyCode"; + String redirectUri = "dummyRedirectUri"; - Map headers = new HashMap<>(); - headers.put("Authorization", "Dummy Bearer Header"); + Map headers = new HashMap<>(); + headers.put("Authorization", "Dummy Bearer Header"); - String responseBody = "Mock Response Body"; - HttpResponse mockResponse = new HttpResponse(); - mockResponse.setResponseBody(responseBody); + String responseBody = "Mock Response Body"; + HttpResponse mockResponse = new HttpResponse(); + mockResponse.setResponseBody(responseBody); - httpClientMockedStatic.when(() -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt())) - .thenReturn(mockResponse); + httpClientMockedStatic.when(() -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt())) + .thenReturn(mockResponse); - HttpResponse actualResponse = salesforceGetTokens.getTokens(code, redirectUri); + HttpResponse actualResponse = salesforceGetTokens.getTokens(code, redirectUri); - // Assertions - assertEquals(mockResponse.getResponseBody(), actualResponse.getResponseBody()); + // Assertions + assertEquals(mockResponse.getResponseBody(), actualResponse.getResponseBody()); + } - httpClientMockedStatic.close(); } @Test public void testSalesforceGetTokens_Exception() throws Exception { - MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class); + try (MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class)) { - String code = "dummyCode"; - String redirectUri = "dummyRedirectUri"; + String code = "dummyCode"; + String redirectUri = "dummyRedirectUri"; - Map headers = new HashMap<>(); - headers.put("Authorization", "Dummy Bearer Header"); + Map headers = new HashMap<>(); + headers.put("Authorization", "Dummy Bearer Header"); - String responseBody = "Mock Response Body"; - HttpResponse mockResponse = new HttpResponse(); - mockResponse.setResponseBody(responseBody); + String responseBody = "Mock Response Body"; + HttpResponse mockResponse = new HttpResponse(); + mockResponse.setResponseBody(responseBody); - httpClientMockedStatic.when(() -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt())) - .thenThrow(new RuntimeException("Some error occurred")); + httpClientMockedStatic.when(() -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt())) + .thenThrow(new RuntimeException("Some error occurred")); - CustomException exception = assertThrows(CustomException.class, () -> { - salesforceGetTokens.getTokens(code, redirectUri); - }); + CustomException exception = assertThrows(CustomException.class, () -> { + salesforceGetTokens.getTokens(code, redirectUri); + }); - // Assertions - assertNotNull(exception); - ParamErrorObject paramErrorObject = exception.getParamErrorObject(); - assertNotNull(paramErrorObject); - assertEquals("l_s_w_sgt_gt_1", paramErrorObject.getInternalErrorIdentifier()); + // Assertions + assertNotNull(exception); + ParamErrorObject paramErrorObject = exception.getParamErrorObject(); + assertNotNull(paramErrorObject); + assertEquals("l_s_w_sgt_gt_1", paramErrorObject.getInternalErrorIdentifier()); - httpClientMockedStatic.close(); + } } } From fc6a6f82ef4a37bd6682f03649b761d73404e028 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Wed, 30 Aug 2023 16:59:04 +0530 Subject: [PATCH 175/195] added review changes --- .../salessparrow/api/unit/filters/SanitizationFilterTest.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/test/java/com/salessparrow/api/unit/filters/SanitizationFilterTest.java b/src/test/java/com/salessparrow/api/unit/filters/SanitizationFilterTest.java index 4b53db83..9be83258 100644 --- a/src/test/java/com/salessparrow/api/unit/filters/SanitizationFilterTest.java +++ b/src/test/java/com/salessparrow/api/unit/filters/SanitizationFilterTest.java @@ -1,7 +1,6 @@ package com.salessparrow.api.unit.filters; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; @@ -59,7 +58,6 @@ void testRequestBodySanitization() throws Exception { mockCommonRequestBehaviors(); sanitizationFilter.doFilter(request, response, filterChain); verify(request).getReader(); - assertTrue(true, "Request body should be read without exceptions."); } @Test @@ -67,7 +65,6 @@ void testRequestParamsSanitization() throws Exception { mockCommonRequestBehaviors(); sanitizationFilter.doFilter(request, response, filterChain); verify(request).getParameterMap(); - assertTrue(true, "Request parameters should be read without exceptions."); } @Test @@ -75,7 +72,6 @@ void testRequestHeadersSanitization() throws Exception { mockCommonRequestBehaviors(); sanitizationFilter.doFilter(request, response, filterChain); verify(request).getHeaderNames(); - assertTrue(true, "Request headers should be read without exceptions."); } @Test From 472e8ddc8751ef0f8bd0ef49a874c7dea22a40e3 Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Wed, 30 Aug 2023 17:10:54 +0530 Subject: [PATCH 176/195] Added verification for test cases --- .../unit/lib/salesforce/helper/SalesforceOAuthTokenTest.java | 3 +++ .../lib/salesforce/wrappers/SalesforceGetTokensTest.java | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceOAuthTokenTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceOAuthTokenTest.java index 0677c074..3bfdfd65 100644 --- a/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceOAuthTokenTest.java +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceOAuthTokenTest.java @@ -16,6 +16,7 @@ import org.mockito.MockitoAnnotations; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; @@ -80,6 +81,8 @@ public void testUpdateAndGetRefreshedAccessToken() throws Exception { String decryptedAccessToken = salesforceOauthToken.updateAndGetRefreshedAccessToken(sfOAuthToken); assertEquals("new_access_token", decryptedAccessToken); + assertEquals(200, response.getStatusCode()); + assertTrue(responseBodyNode.has("access_token")); } } diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetTokensTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetTokensTest.java index 3599dcee..002b8844 100644 --- a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetTokensTest.java +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetTokensTest.java @@ -50,6 +50,8 @@ public void testSalesforceGetTokens_Success() throws Exception { // Assertions assertEquals(mockResponse.getResponseBody(), actualResponse.getResponseBody()); + httpClientMockedStatic.verify( + () -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt()), Mockito.times(1)); } } @@ -81,6 +83,9 @@ public void testSalesforceGetTokens_Exception() throws Exception { assertNotNull(paramErrorObject); assertEquals("l_s_w_sgt_gt_1", paramErrorObject.getInternalErrorIdentifier()); + httpClientMockedStatic.verify( + () -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt()), Mockito.times(1)); + } } From a168d399fb5379e088d5ad4fc2b6bbea32b48513 Mon Sep 17 00:00:00 2001 From: VRDighe Date: Wed, 30 Aug 2023 17:51:13 +0530 Subject: [PATCH 177/195] Updated post logout test --- .../functional/controllers/authController/PostLogoutTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 c7860f7f..e70a5f5d 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 @@ -84,8 +84,8 @@ public void testPostLogout() throws Exception { String cookieValue = (String) testDataItem.getInput().get("cookie"); ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.post("/api/v1/auth/logout") - .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) - .contentType(MediaType.APPLICATION_JSON)); + .cookie(new Cookie(CookieConstants.USER_LOGIN_COOKIE_NAME, cookieValue)) + .contentType(MediaType.APPLICATION_JSON)); String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); From 80c938c844af50291093c11044c4ef3f94d79ef8 Mon Sep 17 00:00:00 2001 From: Raj Shah Date: Wed, 30 Aug 2023 17:57:57 +0530 Subject: [PATCH 178/195] Moved SalesforceGetTokens test methods to SalesforceTokens --- .../helper/SalesforceRequestTest.java | 6 +- .../wrappers/SalesforceGetIdentityTest.java | 4 +- .../SalesforceGetNoteContentTest.java | 2 +- .../wrappers/SalesforceGetTokensTest.java | 92 ------------------- .../wrappers/SalesforceTokensTest.java | 65 +++++++++++++ 5 files changed, 71 insertions(+), 98 deletions(-) delete mode 100644 src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetTokensTest.java diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceRequestTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceRequestTest.java index e9161c7f..e6cf281c 100644 --- a/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceRequestTest.java +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/helper/SalesforceRequestTest.java @@ -37,7 +37,7 @@ public void setUp() { } @Test - public void testMakeRequest_Success() { + public void testMakeRequestSuccess() { SalesforceOauthToken sfOAuthToken = new SalesforceOauthToken(); sfOAuthToken.setAccessToken("access_token"); @@ -63,7 +63,7 @@ public void testMakeRequest_Success() { } @Test - public void testMakeRequest_WebClientResponseException() { + public void testMakeRequestWebClientResponseException() { SalesforceOauthToken sfOAuthToken = new SalesforceOauthToken(); sfOAuthToken.setAccessToken("access_token"); @@ -91,7 +91,7 @@ public void testMakeRequest_WebClientResponseException() { } @Test - public void testMakeRequest_InternalServerErrorException() { + public void testMakeRequestInternalServerErrorException() { SalesforceOauthToken sfOAuthToken = new SalesforceOauthToken(); sfOAuthToken.setAccessToken("access_token"); diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetIdentityTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetIdentityTest.java index 0381fbd7..28708919 100644 --- a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetIdentityTest.java +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetIdentityTest.java @@ -34,7 +34,7 @@ public class SalesforceGetIdentityTest { private SalesforceConstants salesforceConstants; @Test - public void testGetUserIdentity_Success() throws Exception { + public void testGetUserIdentitySuccess() throws Exception { try (MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class)) { String instanceUrl = "https://example.com"; @@ -62,7 +62,7 @@ public void testGetUserIdentity_Success() throws Exception { } @Test - public void testGetUserIdentity_Exception() throws Exception { + public void testGetUserIdentityException() throws Exception { try (MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class)) { String instanceUrl = "https://example.com"; diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetNoteContentTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetNoteContentTest.java index 82b16eec..dc667cc1 100644 --- a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetNoteContentTest.java +++ b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetNoteContentTest.java @@ -62,7 +62,7 @@ public void testGetNoteContent() { } @Test - public void testGetNoteContent_ErrorScenario() { + public void testGetNoteContentErrorScenario() { String noteId = "note123"; String salesforceUserId = "user123"; diff --git a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetTokensTest.java b/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetTokensTest.java deleted file mode 100644 index 002b8844..00000000 --- a/src/test/java/com/salessparrow/api/unit/lib/salesforce/wrappers/SalesforceGetTokensTest.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.salessparrow.api.unit.lib.salesforce.wrappers; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyMap; -import static org.mockito.ArgumentMatchers.anyString; - -import java.util.HashMap; -import java.util.Map; - -import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Import; -import org.springframework.beans.factory.annotation.Autowired; -import com.salessparrow.api.exception.CustomException; -import com.salessparrow.api.lib.errorLib.ParamErrorObject; -import com.salessparrow.api.lib.httpLib.HttpClient; -import com.salessparrow.api.lib.httpLib.HttpClient.HttpResponse; -import com.salessparrow.api.lib.salesforce.wrappers.SalesforceGetTokens; - -@SpringBootTest -@Import({ SalesforceGetTokens.class }) -public class SalesforceGetTokensTest { - - @Autowired - private SalesforceGetTokens salesforceGetTokens; - - @Test - public void testSalesforceGetTokens_Success() throws Exception { - try (MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class)) { - - String code = "dummyCode"; - String redirectUri = "dummyRedirectUri"; - - Map headers = new HashMap<>(); - headers.put("Authorization", "Dummy Bearer Header"); - - String responseBody = "Mock Response Body"; - HttpResponse mockResponse = new HttpResponse(); - mockResponse.setResponseBody(responseBody); - - httpClientMockedStatic.when(() -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt())) - .thenReturn(mockResponse); - - HttpResponse actualResponse = salesforceGetTokens.getTokens(code, redirectUri); - - // Assertions - assertEquals(mockResponse.getResponseBody(), actualResponse.getResponseBody()); - httpClientMockedStatic.verify( - () -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt()), Mockito.times(1)); - } - - } - - @Test - public void testSalesforceGetTokens_Exception() throws Exception { - try (MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class)) { - - String code = "dummyCode"; - String redirectUri = "dummyRedirectUri"; - - Map headers = new HashMap<>(); - headers.put("Authorization", "Dummy Bearer Header"); - - String responseBody = "Mock Response Body"; - HttpResponse mockResponse = new HttpResponse(); - mockResponse.setResponseBody(responseBody); - - httpClientMockedStatic.when(() -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt())) - .thenThrow(new RuntimeException("Some error occurred")); - - CustomException exception = assertThrows(CustomException.class, () -> { - salesforceGetTokens.getTokens(code, redirectUri); - }); - - // Assertions - assertNotNull(exception); - ParamErrorObject paramErrorObject = exception.getParamErrorObject(); - assertNotNull(paramErrorObject); - assertEquals("l_s_w_sgt_gt_1", paramErrorObject.getInternalErrorIdentifier()); - - httpClientMockedStatic.verify( - () -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt()), Mockito.times(1)); - - } - } - -} 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 index 974dc40e..f845ec17 100644 --- 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 @@ -1,12 +1,16 @@ package com.salessparrow.api.unit.lib.salesforce.wrappers; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; 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 java.util.HashMap; +import java.util.Map; + import org.junit.jupiter.api.Test; import org.mockito.MockedStatic; import org.mockito.Mockito; @@ -16,6 +20,7 @@ import org.springframework.context.annotation.Import; import com.salessparrow.api.exception.CustomException; +import com.salessparrow.api.lib.errorLib.ParamErrorObject; import com.salessparrow.api.lib.httpLib.HttpClient; import com.salessparrow.api.lib.httpLib.HttpClient.HttpResponse; import com.salessparrow.api.lib.salesforce.wrappers.SalesforceTokens; @@ -66,4 +71,64 @@ public void testRevokeTokensFailure() throws Exception { httpClientMockedStatic.close(); } + @Test + public void testGetTokensSuccess() throws Exception { + try (MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class)) { + + String code = "dummyCode"; + String redirectUri = "dummyRedirectUri"; + + Map headers = new HashMap<>(); + headers.put("Authorization", "Dummy Bearer Header"); + + String responseBody = "Mock Response Body"; + HttpResponse mockResponse = new HttpResponse(); + mockResponse.setResponseBody(responseBody); + + httpClientMockedStatic.when(() -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt())) + .thenReturn(mockResponse); + + HttpResponse actualResponse = salesforceTokens.getTokens(code, redirectUri); + + // Assertions + assertEquals(mockResponse.getResponseBody(), actualResponse.getResponseBody()); + httpClientMockedStatic.verify( + () -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt()), Mockito.times(1)); + } + + } + + @Test + public void testGetTokensException() throws Exception { + try (MockedStatic httpClientMockedStatic = Mockito.mockStatic(HttpClient.class)) { + + String code = "dummyCode"; + String redirectUri = "dummyRedirectUri"; + + Map headers = new HashMap<>(); + headers.put("Authorization", "Dummy Bearer Header"); + + String responseBody = "Mock Response Body"; + HttpResponse mockResponse = new HttpResponse(); + mockResponse.setResponseBody(responseBody); + + httpClientMockedStatic.when(() -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt())) + .thenThrow(new RuntimeException("Some error occurred")); + + CustomException exception = assertThrows(CustomException.class, () -> { + salesforceTokens.getTokens(code, redirectUri); + }); + + // Assertions + assertNotNull(exception); + ParamErrorObject paramErrorObject = exception.getParamErrorObject(); + assertNotNull(paramErrorObject); + assertEquals("l_s_w_sgt_gt_1", paramErrorObject.getInternalErrorIdentifier()); + + httpClientMockedStatic.verify( + () -> HttpClient.makePostRequest(anyString(), anyMap(), anyString(), anyInt()), Mockito.times(1)); + + } + } + } From 0f05622db96070f5fd0802b885d74c0331b20d71 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Wed, 30 Aug 2023 18:30:08 +0530 Subject: [PATCH 179/195] updated test cases based on review --- .../unit/filters/SanitizationFilterTest.java | 112 ++++++++++++++---- 1 file changed, 88 insertions(+), 24 deletions(-) diff --git a/src/test/java/com/salessparrow/api/unit/filters/SanitizationFilterTest.java b/src/test/java/com/salessparrow/api/unit/filters/SanitizationFilterTest.java index 9be83258..8283d320 100644 --- a/src/test/java/com/salessparrow/api/unit/filters/SanitizationFilterTest.java +++ b/src/test/java/com/salessparrow/api/unit/filters/SanitizationFilterTest.java @@ -1,5 +1,7 @@ package com.salessparrow.api.unit.filters; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -12,6 +14,7 @@ import jakarta.servlet.http.HttpServletResponse; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -23,6 +26,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Vector; +import java.util.stream.Collectors; class SanitizationFilterTest { @@ -48,30 +52,77 @@ void setUp() { @Test void testDoFilter() throws Exception { - mockCommonRequestBehaviors(); - sanitizationFilter.doFilter(request, response, filterChain); - verify(filterChain).doFilter(any(), eq(response)); + // Arrange: Setup common request behaviors with unsafe body and params + when(request.getReader()).thenReturn( + new BufferedReader(new StringReader("")) + ); + when(request.getParameterMap()).thenReturn(mockedParamMap(true)); + + // Act: Pass through sanitization filter + sanitizationFilter.doFilter(request, response, filterChain); + + // Assert: Check that the filterChain's doFilter is called + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(HttpServletRequest.class); + verify(filterChain).doFilter(requestCaptor.capture(), eq(response)); + HttpServletRequest sanitizedRequest = requestCaptor.getValue(); + + // Assert: Check that request body is sanitized + String sanitizedBody = getRequestBody(sanitizedRequest); + assertFalse(sanitizedBody.contains(""))); sanitizationFilter.doFilter(request, response, filterChain); - verify(request).getReader(); + + ArgumentCaptor requestCaptor = + ArgumentCaptor.forClass(HttpServletRequest.class); + verify(filterChain).doFilter(requestCaptor.capture(), eq(response)); + HttpServletRequest sanitizedRequest = requestCaptor.getValue(); + + String sanitizedBody = getRequestBody(sanitizedRequest); + assertFalse(sanitizedBody.contains("" }); + paramMap.put("param2", new String[] { "" }); + } + else { + paramMap.put("param1", new String[] { "safe_value1" }); + paramMap.put("param2", new String[] { "safe_value2" }); + } return paramMap; } + public String getRequestBody(HttpServletRequest request) throws IOException { + BufferedReader reader = request.getReader(); + if (reader == null) { + return ""; + } + + return reader.lines().collect(Collectors.joining(System.lineSeparator())); + } + } From f9b5c06a78337aa8d47df6575cf235e81417d07a Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Wed, 30 Aug 2023 19:23:01 +0530 Subject: [PATCH 180/195] unescaped & from note tile and task subject --- src/main/java/com/salessparrow/api/lib/Util.java | 9 +++++++++ .../createAccountNote/CreateSalesforceNote.java | 11 ++++++++--- .../CreateSalesforceAccountTask.java | 12 +++++++++--- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/salessparrow/api/lib/Util.java b/src/main/java/com/salessparrow/api/lib/Util.java index ce855ffc..2d08ae58 100644 --- a/src/main/java/com/salessparrow/api/lib/Util.java +++ b/src/main/java/com/salessparrow/api/lib/Util.java @@ -123,4 +123,13 @@ public String getDateFormatFromDatetime(Date date) { return null; } + /** + * Unescape special characters in a string. Currently, only "&" is unescaped. + * @param input + * @return Unescaped string + */ + public String unEscapeSpecialCharacters(String input) { + return input.replace("&", "&"); + } + } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java index 8249b7cf..7cd0aca2 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java @@ -122,11 +122,16 @@ private CreateNoteFormatterDto parseResponse(String createNoteResponse) { * @return String */ private String getNoteTitleFromContent(NoteDto note) { - if (note.getText().length() < 50) { - return note.getText(); + String noteText = note.getText(); + + Util util = new Util(); + noteText = util.unEscapeSpecialCharacters(noteText); + + if (noteText.length() < 50) { + return noteText; } - return note.getText().substring(0, 50); + return noteText.substring(0, 50); } } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateSalesforceAccountTask.java b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateSalesforceAccountTask.java index d26afde7..8345ec5b 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateSalesforceAccountTask.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateSalesforceAccountTask.java @@ -111,11 +111,17 @@ private CreateTaskFormatterDto parseResponse(String createTaskResponse) { */ private String getTaskSubjectFromDescription(CreateAccountTaskDto task) { logger.info("getting task subject from description"); - if (task.getDescription().length() < 60) { - return task.getDescription(); + + String taskDescription = task.getDescription(); + + Util util = new Util(); + taskDescription = util.unEscapeSpecialCharacters(taskDescription); + + if (taskDescription.length() < 60) { + return taskDescription; } - return task.getDescription().substring(0, 60); + return taskDescription.substring(0, 60); } } From d22f05737764f9e91e972923b77ca56c887577f5 Mon Sep 17 00:00:00 2001 From: Ajinkya Chikhale <86607732+ajinkyac03@users.noreply.github.com> Date: Wed, 30 Aug 2023 20:38:18 +0530 Subject: [PATCH 181/195] Fix: Send error mail fix and added debugging logs. (#85) --- .../api/exception/GlobalExceptionHandler.java | 2 ++ .../com/salessparrow/api/lib/GetCrmActionSuggestions.java | 2 +- .../createAccountNote/CreateSalesforceNote.java | 5 +++++ .../deleteAccountNote/DeleteSalesforceAccountNote.java | 1 + .../deleteAccountTask/DeleteSalesforceAccountTask.java | 1 + .../api/lib/globalConstants/SecretConstants.java | 4 ++-- .../api/lib/salesforce/helper/SalesforceQueryBuilder.java | 4 ++-- .../api/lib/salesforce/helper/SalesforceRequest.java | 8 ++++++++ .../authController/PostSalesforceConnectTest.java | 3 --- .../repositories/SalesforceOauthTokenRepositoryTest.java | 1 - 10 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/salessparrow/api/exception/GlobalExceptionHandler.java b/src/main/java/com/salessparrow/api/exception/GlobalExceptionHandler.java index 44382d01..fe628eee 100644 --- a/src/main/java/com/salessparrow/api/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/salessparrow/api/exception/GlobalExceptionHandler.java @@ -67,6 +67,7 @@ public ResponseEntity handleCustomException(CustomException if (ex.getParamErrorObject() != null) { ParamErrorObject paramErrorObject = ex.getParamErrorObject(); + logger.error("Message from custom exception: {}", paramErrorObject.getMessage()); errorResponse = er.getParamErrorResponse(paramErrorObject.getInternalErrorIdentifier(), paramErrorObject.getMessage(), paramErrorObject.getParamErrorIdentifiers()); } @@ -75,6 +76,7 @@ else if (ex.getErrorObject() == null || ex.getErrorObject().getApiErrorIdentifie } else { ErrorObject errorObject = ex.getErrorObject(); + logger.error("Message from custom exception: {}", errorObject.getMessage()); errorResponse = er.getErrorResponse(errorObject.getApiErrorIdentifier(), errorObject.getInternalErrorIdentifier(), errorObject.getMessage()); } diff --git a/src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java b/src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java index 85e46bc8..daefd4e2 100644 --- a/src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java +++ b/src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java @@ -42,7 +42,7 @@ public class GetCrmActionSuggestions { * @return */ public CrmActionSuggestionsFormatterDto getTaskSuggestions(String text) { - logger.info("Crm actions suggestions lib called"); + logger.info("Crm actions suggestions lib called for text: " + text); String escapedText = escapeForJson(text); String payload = openAiPayloadBuilder.payloadForCrmActionsSuggestions(escapedText); diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java index 8249b7cf..1b1ab6e1 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java @@ -5,6 +5,8 @@ import java.util.List; import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -40,6 +42,8 @@ public class CreateSalesforceNote implements CreateNoteInterface { @Autowired private Base64Helper base64Helper; + Logger logger = LoggerFactory.getLogger(CreateSalesforceNote.class); + /** * Create a note for a given account. * @param user @@ -91,6 +95,7 @@ private CreateNoteFormatterDto parseResponse(String createNoteResponse) { if (!createNoteStatusCode.equals("200") && !createNoteStatusCode.equals("201")) { String errorBody = createNoteCompositeResponse.get("body").asText(); + logger.error("createNoteCompositeResponse: " + createNoteCompositeResponse); throw new CustomException(new ErrorObject("l_s_fse_fscn_fcn_1", "internal_server_error", errorBody)); } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteSalesforceAccountNote.java b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteSalesforceAccountNote.java index 9ca8ca7f..07bd0299 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteSalesforceAccountNote.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountNote/DeleteSalesforceAccountNote.java @@ -71,6 +71,7 @@ public void parseResponse(String responseBody) { Integer deleteNoteStatusCode = deleteNoteCompositeResponse.get("httpStatusCode").asInt(); if (deleteNoteStatusCode != 200 && deleteNoteStatusCode != 201 && deleteNoteStatusCode != 204) { + logger.error("Error in deleting note in salesforce:{}", deleteNoteCompositeResponse); String errorBody = deleteNoteCompositeResponse.get("body").asText(); // MALFORMED_ID or NOT_FOUND diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteSalesforceAccountTask.java b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteSalesforceAccountTask.java index cb9f866a..ea237034 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteSalesforceAccountTask.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/deleteAccountTask/DeleteSalesforceAccountTask.java @@ -74,6 +74,7 @@ private void parseResponse(String responseBody) { Integer deleteNoteStatusCode = deleteNoteCompositeResponse.get("httpStatusCode").asInt(); if (deleteNoteStatusCode != 200 && deleteNoteStatusCode != 201 && deleteNoteStatusCode != 204) { + logger.error("Error in deleting task in salesforce:{}", deleteNoteCompositeResponse); String errorBody = deleteNoteCompositeResponse.get("body").asText(); // MALFORMED_ID or NOT_FOUND diff --git a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java index 63d50a78..89d646b0 100644 --- a/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java +++ b/src/main/java/com/salessparrow/api/lib/globalConstants/SecretConstants.java @@ -125,11 +125,11 @@ public static String openAiApiKey() { } public static String errorEmailFrom() { - return getSecret("ERROR_EMAIL_FROM"); + return getSecret("ERROR_MAIL_FROM"); } public static String errorEmailTo() { - return getSecret("ERROR_EMAIL_TO"); + return getSecret("ERROR_MAIL_TO"); } public static String dynamoDbUrl() { diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java index af5cacd7..eeacbeda 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceQueryBuilder.java @@ -105,11 +105,11 @@ public String getCrmOrganizationUsersQuery(String searchTerm) { String query = ""; if (searchTerm == "") { - query = "SELECT Id, Name FROM User ORDER BY LastModifiedDate DESC LIMIT 20"; + query = "SELECT Id, Name FROM User WHERE IsActive = true ORDER BY LastModifiedDate DESC LIMIT 20"; } else { query = "SELECT Id, Name FROM User WHERE Name LIKE '%" + searchTerm - + "%' ORDER BY LastModifiedDate DESC LIMIT 20"; + + "%' AND IsActive = true ORDER BY LastModifiedDate DESC LIMIT 20"; } return Util.urlEncoder(query); diff --git a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceRequest.java b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceRequest.java index 837f606c..3f892dbb 100644 --- a/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceRequest.java +++ b/src/main/java/com/salessparrow/api/lib/salesforce/helper/SalesforceRequest.java @@ -7,8 +7,12 @@ import com.salessparrow.api.domain.SalesforceOauthToken; import com.salessparrow.api.exception.CustomException; import com.salessparrow.api.lib.errorLib.ErrorObject; +import com.salessparrow.api.lib.httpLib.HttpClient; import com.salessparrow.api.repositories.SalesforceOauthTokenRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * SalesforceRequest is a class for making a request to the Salesforce API. */ @@ -21,6 +25,8 @@ public class SalesforceRequest { @Autowired private SalesforceOauthTokenRepository salesforceOauthTokenRepository; + Logger logger = LoggerFactory.getLogger(SalesforceRequest.class); + /** * Make a request to the Salesforce API. * @param salesforceUserId @@ -43,9 +49,11 @@ public T makeRequest(String salesforceUserId, SalesforceRequestInterface return request.execute(decryptedAccessToken, sfOAuthToken.getInstanceUrl()); } catch (Exception e1) { + logger.error("Error while refreshing access token {}", e1); throw new CustomException(new ErrorObject("l_s_h_sr_mr_1", "something_went_wrong", e.getMessage())); } } + logger.error("Error while making request to salesforce {}", e); throw new CustomException(new ErrorObject("l_s_h_sr_mr_2", "something_went_wrong", e.getMessage())); } } 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 1e315a7f..df83fe06 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 @@ -193,8 +193,6 @@ public void testPostSalesforceConnectDisconnectedUserSignup() throws Exception { "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(); @@ -214,7 +212,6 @@ public void testPostSalesforceConnectDisconnectedUserSignup() throws Exception { .contentType(MediaType.APPLICATION_JSON)); String actualOutput = resultActions.andReturn().getResponse().getContentAsString(); - System.out.println("actualOutput: " + actualOutput); if (resultActions.andReturn().getResponse().getStatus() == 200) { assertEquals(objectMapper.writeValueAsString(testDataItem.getOutput()), actualOutput); diff --git a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java index 920e4713..ee5c7fa7 100644 --- a/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java +++ b/src/test/java/com/salessparrow/api/unit/repositories/SalesforceOauthTokenRepositoryTest.java @@ -202,7 +202,6 @@ public void testInsert() throws Exception { List testDataItems = loadTestData(currentFunctionName); for (Scenario testDataItem : testDataItems) { - System.out.println("Test description: " + testDataItem.getDescription()); ObjectMapper objectMapper = new ObjectMapper(); SalesforceOauthToken salesforceOauthToken = objectMapper.readValue( From fdcf51afca7f974f4d8dfaf0e64c266bd360996a Mon Sep 17 00:00:00 2001 From: ajinkyac03 Date: Thu, 31 Aug 2023 11:37:50 +0530 Subject: [PATCH 182/195] Updated escapeForJson for openai payload. --- .../api/lib/GetCrmActionSuggestions.java | 13 +++++++++++-- .../salessparrow/api/lib/openAi/OpenAiRequest.java | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java b/src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java index daefd4e2..d28da757 100644 --- a/src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java +++ b/src/main/java/com/salessparrow/api/lib/GetCrmActionSuggestions.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; + import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -109,7 +110,15 @@ private CrmActionSuggestionsFormatterDto parseResponse(String responseBody) { * @return */ private String escapeForJson(String input) { - return input.replace("\"", "\\\"").replace("\n", "\\n"); + return input.replace("\\", "\\\\") // Escape backslashes + .replace("\"", "\\\"") // Escape double quotes + .replace("\n", "\\n") // Escape newlines + .replace("\r", "\\r") // Escape carriage returns + .replace("\t", "\\t") // Escape tabs + .replace("\b", "\\b") // Escape backspace + .replace("\f", "\\f") // Escape form feeds + .replaceAll("[\u0000-\u001F]", ""); // Replace control characters with empty + // string } -} +} \ No newline at end of file diff --git a/src/main/java/com/salessparrow/api/lib/openAi/OpenAiRequest.java b/src/main/java/com/salessparrow/api/lib/openAi/OpenAiRequest.java index 08bfd163..c9389108 100644 --- a/src/main/java/com/salessparrow/api/lib/openAi/OpenAiRequest.java +++ b/src/main/java/com/salessparrow/api/lib/openAi/OpenAiRequest.java @@ -45,6 +45,7 @@ public HttpClient.HttpResponse makeRequest(Object payload) { return response; } catch (WebClientResponseException e) { + logger.error("Error while making request to OpenAI API: " + e.getResponseBodyAsString()); if (e.getStatusCode().value() == 401) { throw new CustomException( new ErrorObject("l_o_a_oar_mr_1", "something_went_wrong", "Invalid OpenAI API key")); From 30128bb891831028434de3de0a23e0fa7ce25020 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 31 Aug 2023 12:21:38 +0530 Subject: [PATCH 183/195] sanitization review changes --- pom.xml | 12 ++---- .../api/filter/SanitizationFilter.java | 38 +++++++++++++++---- .../java/com/salessparrow/api/lib/Util.java | 18 ++++++--- .../CreateSalesforceNote.java | 2 +- .../CreateSalesforceAccountTask.java | 2 +- .../lib/wrappers/SanitizedRequestWrapper.java | 19 +--------- 6 files changed, 49 insertions(+), 42 deletions(-) diff --git a/pom.xml b/pom.xml index e81e9d30..c9e70ecb 100644 --- a/pom.xml +++ b/pom.xml @@ -164,15 +164,9 @@ - com.googlecode.owasp-java-html-sanitizer - owasp-java-html-sanitizer - 20220608.1 - - - - org.apache.commons - commons-text - 1.10.0 + org.jsoup + jsoup + 1.16.1 diff --git a/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java b/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java index 477c2abe..78d6a679 100644 --- a/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java +++ b/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java @@ -7,8 +7,10 @@ import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; import jakarta.servlet.http.HttpServletRequest; -import org.owasp.html.HtmlPolicyBuilder; -import org.owasp.html.PolicyFactory; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.safety.Safelist; +import org.jsoup.nodes.Entities.EscapeMode; import com.salessparrow.api.lib.wrappers.SanitizedRequestWrapper; @@ -23,8 +25,6 @@ public class SanitizationFilter implements Filter { private SanitizedRequestWrapper sanitizedRequest; - private final PolicyFactory policy = new HtmlPolicyBuilder().toFactory(); - @Override public void init(FilterConfig filterConfig) { } @@ -118,12 +118,34 @@ private String getRequestBody(HttpServletRequest request) { } /** - * Method to sanitize the html - * @param input - Input string - * @return String - Sanitized string + * Sanitizes a given HTML string by removing all HTML tags and attributes, leaving + * only the text content. Also handles basic HTML entity escaping using the 'base' + * escape mode. + * + * This function uses the Jsoup library's 'clean' method with a 'none' safelist, which + * means no HTML tags are allowed and will be removed. + * + * The function also disables pretty-printing to ensure the resulting HTML is not + * reformatted, and sets the escape mode to 'base' to handle basic HTML entities like + * & and <. + * + * If the input is null or empty, the function returns an empty string. + * @param input The original HTML string that needs to be sanitized. + * @return A sanitized version of the input string, safe for display as text. */ private String sanitizeHtml(String input) { - String sanitizedInput = policy.sanitize(input); + if (input == null || input.isEmpty()) { + return ""; + } + + Safelist safelist = Safelist.none(); + + Document.OutputSettings outputSettings = new Document.OutputSettings(); + outputSettings.prettyPrint(false); + outputSettings.escapeMode(EscapeMode.base); + + String sanitizedInput = Jsoup.clean(input, "", safelist, outputSettings); + return sanitizedInput; } diff --git a/src/main/java/com/salessparrow/api/lib/Util.java b/src/main/java/com/salessparrow/api/lib/Util.java index 114280d2..1f5e29d2 100644 --- a/src/main/java/com/salessparrow/api/lib/Util.java +++ b/src/main/java/com/salessparrow/api/lib/Util.java @@ -64,7 +64,7 @@ public static String generateHeaderLogString(HttpServletRequest request) { } /** - * <<<<<<< HEAD Encode plain text to base64 + * Encode plain text to base64 * @param plainText - String to be encoded * @return String - Encoded string */ @@ -161,11 +161,19 @@ public String getDateFormatFromDatetime(Date date) { } /** - * Unescape special characters in a string. Currently, only "&" is unescaped. - * @param input - * @return Unescaped string + * Unescape special characters in a string intended for plaintext contexts only. + * + * This function is intended for use only with strings that will be rendered as + * plaintext. It is NOT suitable for HTML strings, XML strings, or any other context + * where special characters may have syntactic meaning. + * + * Current Implementation: - The ampersand ("&") is unescaped to "&" + * + * Future versions may include additional un-escaping rules as needed. + * @param input The original string containing escaped special characters. + * @return A new string where certain special characters have been unescaped. */ - public String unEscapeSpecialCharacters(String input) { + public String unEscapeSpecialCharactersForPlainText(String input) { return input.replace("&", "&"); } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java index 7cd0aca2..d2f0b543 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java @@ -125,7 +125,7 @@ private String getNoteTitleFromContent(NoteDto note) { String noteText = note.getText(); Util util = new Util(); - noteText = util.unEscapeSpecialCharacters(noteText); + noteText = util.unEscapeSpecialCharactersForPlainText(noteText); if (noteText.length() < 50) { return noteText; diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateSalesforceAccountTask.java b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateSalesforceAccountTask.java index 8345ec5b..dbece281 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateSalesforceAccountTask.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateSalesforceAccountTask.java @@ -115,7 +115,7 @@ private String getTaskSubjectFromDescription(CreateAccountTaskDto task) { String taskDescription = task.getDescription(); Util util = new Util(); - taskDescription = util.unEscapeSpecialCharacters(taskDescription); + taskDescription = util.unEscapeSpecialCharactersForPlainText(taskDescription); if (taskDescription.length() < 60) { return taskDescription; diff --git a/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java b/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java index 1ee1939e..1383ca60 100644 --- a/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java +++ b/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java @@ -29,7 +29,7 @@ public class SanitizedRequestWrapper extends HttpServletRequestWrapper { public SanitizedRequestWrapper(HttpServletRequest request, String sanitizedBody) { super(request); - this.sanitizedBody = escapeQuotes(sanitizedBody); + this.sanitizedBody = sanitizedBody; this.sanitizedParams = new HashMap<>(); this.sanitizedHeaders = new HashMap<>(); } @@ -187,21 +187,4 @@ public Enumeration getHeaders(String key) { return Collections.enumeration(Collections.emptyList()); } - /** - * Escapes HTML-encoded quotes in a given sanitized JSON string. - * - * This method is specifically designed to work on JSON strings that have been - * HTML-sanitized. In the sanitization process, quotes could be converted to their - * HTML-encoded form (""" for double quotes and "'" for single quotes). - * - * This method replaces these HTML-encoded quotes back to their plain text versions (" - * and ' respectively) so that the JSON can be parsed correctly. - * @param input The sanitized JSON string that may contain HTML-encoded quotes. - * @return A JSON string with HTML-encoded quotes replaced by their plain text - * equivalents. - */ - private String escapeQuotes(String input) { - return input.replace(""", "\"").replace("'", "'"); - } - } From 6fe53b74247bf0f1d28d68d127633a2aae3b495a Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 31 Aug 2023 13:12:36 +0530 Subject: [PATCH 184/195] added logs for debugging sanitization changes --- .../crmActions/createAccountNote/CreateSalesforceNote.java | 1 + .../api/lib/wrappers/SanitizedRequestWrapper.java | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java index 4eca0cba..2f16914f 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java @@ -54,6 +54,7 @@ public class CreateSalesforceNote implements CreateNoteInterface { public CreateNoteFormatterDto createNote(SalesforceUser user, String accountId, NoteDto note) { String salesforceUserId = user.getExternalUserId(); + logger.info("createNote note text: ", note.getText()); String noteTitle = getNoteTitleFromContent(note); String encodedNoteContent = base64Helper.base64Encode(note.getText()); diff --git a/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java b/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java index 1383ca60..6fe5cc31 100644 --- a/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java +++ b/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java @@ -15,12 +15,16 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Custom request wrapper to sanitize the request body */ public class SanitizedRequestWrapper extends HttpServletRequestWrapper { + Logger logger = LoggerFactory.getLogger(SanitizedRequestWrapper.class); + private final String sanitizedBody; private Map> sanitizedParams; @@ -29,6 +33,7 @@ public class SanitizedRequestWrapper extends HttpServletRequestWrapper { public SanitizedRequestWrapper(HttpServletRequest request, String sanitizedBody) { super(request); + logger.info("SanitizedRequestWrapper sanitizedBody: ", sanitizedBody); this.sanitizedBody = sanitizedBody; this.sanitizedParams = new HashMap<>(); this.sanitizedHeaders = new HashMap<>(); From 458e989f1863ff335b88edee835ee285c3257dc7 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 31 Aug 2023 13:18:45 +0530 Subject: [PATCH 185/195] unescaped task description and subject --- .../CreateSalesforceAccountTask.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateSalesforceAccountTask.java b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateSalesforceAccountTask.java index dbece281..2af0c2a9 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateSalesforceAccountTask.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateSalesforceAccountTask.java @@ -49,13 +49,16 @@ public class CreateSalesforceAccountTask implements CreateAccountTask { public CreateTaskFormatterDto createAccountTask(User User, String accountId, CreateAccountTaskDto task) { String salesforceUserId = User.getExternalUserId(); - String taskSubject = getTaskSubjectFromDescription(task); + logger.info("createAccountTask task description: ", task.getDescription()); + Util util = new Util(); + String unEscapedTaskDescription = util.unEscapeSpecialCharactersForPlainText(task.getDescription()); + String taskSubject = getTaskSubjectFromDescription(unEscapedTaskDescription); logger.info("performing create task in salesforce"); Map taskBody = new HashMap(); taskBody.put("Subject", taskSubject); - taskBody.put("Description", task.getDescription()); + taskBody.put("Description", unEscapedTaskDescription); taskBody.put("OwnerId", task.getCrmOrganizationUserId()); taskBody.put("ActivityDate", task.getDueDate()); taskBody.put("WhatId", accountId); @@ -109,14 +112,9 @@ private CreateTaskFormatterDto parseResponse(String createTaskResponse) { * @param task CreateTaskDto object * @return String task subject */ - private String getTaskSubjectFromDescription(CreateAccountTaskDto task) { + private String getTaskSubjectFromDescription(String taskDescription) { logger.info("getting task subject from description"); - String taskDescription = task.getDescription(); - - Util util = new Util(); - taskDescription = util.unEscapeSpecialCharactersForPlainText(taskDescription); - if (taskDescription.length() < 60) { return taskDescription; } From 179ec79105d036062e933ec2786fe8bf95d8ed6b Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 31 Aug 2023 13:22:13 +0530 Subject: [PATCH 186/195] formatted changes --- .../salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java b/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java index 6fe5cc31..bb847b2a 100644 --- a/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java +++ b/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java @@ -24,7 +24,7 @@ public class SanitizedRequestWrapper extends HttpServletRequestWrapper { Logger logger = LoggerFactory.getLogger(SanitizedRequestWrapper.class); - + private final String sanitizedBody; private Map> sanitizedParams; From 2d2dec86116341ab3bcbb8f4f36a9b23e567439d Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 31 Aug 2023 13:37:54 +0530 Subject: [PATCH 187/195] added logs for debugging --- .../lib/crmActions/createAccountNote/CreateSalesforceNote.java | 2 +- .../createAccountTask/CreateSalesforceAccountTask.java | 2 +- .../salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java index 2f16914f..55354492 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java @@ -54,7 +54,7 @@ public class CreateSalesforceNote implements CreateNoteInterface { public CreateNoteFormatterDto createNote(SalesforceUser user, String accountId, NoteDto note) { String salesforceUserId = user.getExternalUserId(); - logger.info("createNote note text: ", note.getText()); + logger.info("createNote note text: {}", note.getText()); String noteTitle = getNoteTitleFromContent(note); String encodedNoteContent = base64Helper.base64Encode(note.getText()); diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateSalesforceAccountTask.java b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateSalesforceAccountTask.java index 2af0c2a9..be02ebb9 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateSalesforceAccountTask.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountTask/CreateSalesforceAccountTask.java @@ -49,7 +49,7 @@ public class CreateSalesforceAccountTask implements CreateAccountTask { public CreateTaskFormatterDto createAccountTask(User User, String accountId, CreateAccountTaskDto task) { String salesforceUserId = User.getExternalUserId(); - logger.info("createAccountTask task description: ", task.getDescription()); + logger.info("createAccountTask task description: {}", task.getDescription()); Util util = new Util(); String unEscapedTaskDescription = util.unEscapeSpecialCharactersForPlainText(task.getDescription()); String taskSubject = getTaskSubjectFromDescription(unEscapedTaskDescription); diff --git a/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java b/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java index bb847b2a..e5998477 100644 --- a/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java +++ b/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java @@ -33,7 +33,7 @@ public class SanitizedRequestWrapper extends HttpServletRequestWrapper { public SanitizedRequestWrapper(HttpServletRequest request, String sanitizedBody) { super(request); - logger.info("SanitizedRequestWrapper sanitizedBody: ", sanitizedBody); + logger.info("SanitizedRequestWrapper sanitizedBody: {}", sanitizedBody); this.sanitizedBody = sanitizedBody; this.sanitizedParams = new HashMap<>(); this.sanitizedHeaders = new HashMap<>(); From e6541a208b0e520997b3eaf7ea86671d1fca1862 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 31 Aug 2023 13:44:24 +0530 Subject: [PATCH 188/195] added logs for debugging --- repo-docs/CHANGELOG.md | 2 +- src/main/java/com/salessparrow/api/lib/ErrorEmailService.java | 2 +- .../lib/crmActions/createAccountNote/CreateSalesforceNote.java | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/repo-docs/CHANGELOG.md b/repo-docs/CHANGELOG.md index 65969f66..c6c64c62 100644 --- a/repo-docs/CHANGELOG.md +++ b/repo-docs/CHANGELOG.md @@ -20,7 +20,6 @@ ### Bug Fixes: - Bug: DynamoDB Upsert Behavior Updates All Fields Instead of Specific Ones [#41](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/41) -- Fix: Updated status enum values [#27](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/pull/27) ### Miscellaneous: @@ -46,6 +45,7 @@ - API - Search Accounts Endpoint [#15](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/15) - API - Create Note Endpoint [#16](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/16) - API - Get Note By Id Endpoint [#17](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/17) +- Updated status enum values [#27](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/pull/27) --- diff --git a/src/main/java/com/salessparrow/api/lib/ErrorEmailService.java b/src/main/java/com/salessparrow/api/lib/ErrorEmailService.java index 29236e02..cde6743c 100644 --- a/src/main/java/com/salessparrow/api/lib/ErrorEmailService.java +++ b/src/main/java/com/salessparrow/api/lib/ErrorEmailService.java @@ -68,7 +68,7 @@ public void sendErrorMail(String contextString, ErrorResponseObject errorObj, * @param body - body of email * @return void */ - @Async + // @Async public void sendEmail(String from, String to, String subject, String body) { logger.info("send SES Email"); try { diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java index 55354492..11922f6c 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java @@ -57,6 +57,7 @@ public CreateNoteFormatterDto createNote(SalesforceUser user, String accountId, logger.info("createNote note text: {}", note.getText()); String noteTitle = getNoteTitleFromContent(note); String encodedNoteContent = base64Helper.base64Encode(note.getText()); + logger.info("---- encodedNoteContent: {}", encodedNoteContent); Map createNoteBody = new HashMap(); createNoteBody.put("Title", noteTitle); From 280631457763dfb78a0c3268cf7c6e284eb0eb2e Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 31 Aug 2023 14:10:59 +0530 Subject: [PATCH 189/195] replace new line with br --- .../com/salessparrow/api/SalesSparrowApi.java | 2 +- .../java/com/salessparrow/api/lib/Util.java | 4 +++ .../CreateSalesforceNote.java | 26 ++++++++++++------- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/salessparrow/api/SalesSparrowApi.java b/src/main/java/com/salessparrow/api/SalesSparrowApi.java index 1fe1c6e5..3b046ba8 100644 --- a/src/main/java/com/salessparrow/api/SalesSparrowApi.java +++ b/src/main/java/com/salessparrow/api/SalesSparrowApi.java @@ -8,7 +8,7 @@ @SpringBootApplication(exclude = { UserDetailsServiceAutoConfiguration.class }) @EnableCaching // This enables caching -@EnableAsync // This enables asynchronous processing in Spring +// @EnableAsync // This enables asynchronous processing in Spring public class SalesSparrowApi { public static void main(String[] args) { diff --git a/src/main/java/com/salessparrow/api/lib/Util.java b/src/main/java/com/salessparrow/api/lib/Util.java index 1f5e29d2..2ca7e414 100644 --- a/src/main/java/com/salessparrow/api/lib/Util.java +++ b/src/main/java/com/salessparrow/api/lib/Util.java @@ -177,4 +177,8 @@ public String unEscapeSpecialCharactersForPlainText(String input) { return input.replace("&", "&"); } + public String replaceNewLineWithBreak(String input) { + return input.replace("\n", "
"); + } + } diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java index 11922f6c..9572cfe9 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java @@ -54,9 +54,17 @@ public class CreateSalesforceNote implements CreateNoteInterface { public CreateNoteFormatterDto createNote(SalesforceUser user, String accountId, NoteDto note) { String salesforceUserId = user.getExternalUserId(); - logger.info("createNote note text: {}", note.getText()); - String noteTitle = getNoteTitleFromContent(note); - String encodedNoteContent = base64Helper.base64Encode(note.getText()); + Util util = new Util(); + String noteContent = note.getText(); + logger.info("createNote noteContent: {}", noteContent); + + String noteTitle = getNoteTitleFromContent(noteContent); + logger.info("createNote noteTitle: {}", noteTitle); + + noteContent = util.replaceNewLineWithBreak(noteContent); + logger.info("---- noteContent after replacing \\n: {}", noteContent); + + String encodedNoteContent = base64Helper.base64Encode(noteContent); logger.info("---- encodedNoteContent: {}", encodedNoteContent); Map createNoteBody = new HashMap(); @@ -128,17 +136,15 @@ private CreateNoteFormatterDto parseResponse(String createNoteResponse) { * @param note - note dto * @return String */ - private String getNoteTitleFromContent(NoteDto note) { - String noteText = note.getText(); - + private String getNoteTitleFromContent(String noteContent) { Util util = new Util(); - noteText = util.unEscapeSpecialCharactersForPlainText(noteText); + noteContent = util.unEscapeSpecialCharactersForPlainText(noteContent); - if (noteText.length() < 50) { - return noteText; + if (noteContent.length() < 50) { + return noteContent; } - return noteText.substring(0, 50); + return noteContent.substring(0, 50); } } From 0f1a202991fe422f1868ae9841ecee71a362694a Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 31 Aug 2023 15:37:31 +0530 Subject: [PATCH 190/195] used local sanitization http request --- .../salessparrow/api/config/FilterConfig.java | 26 +++++++++---------- .../api/filter/SanitizationFilter.java | 22 +++++++++------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/salessparrow/api/config/FilterConfig.java b/src/main/java/com/salessparrow/api/config/FilterConfig.java index f3a04b14..8ba64fc8 100644 --- a/src/main/java/com/salessparrow/api/config/FilterConfig.java +++ b/src/main/java/com/salessparrow/api/config/FilterConfig.java @@ -11,28 +11,28 @@ public class FilterConfig { /** - * Register SameSiteCookieFilter - * @return FilterRegistrationBean + * Register SanitizationFilter + * @return FilterRegistrationBean */ @Bean - public FilterRegistrationBean sameSiteCookieFilter() { - FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); - registrationBean.setFilter(new SameSiteCookieFilter()); - registrationBean.addUrlPatterns("/*"); // or specific URL patterns + public FilterRegistrationBean sanitizationFilter() { + FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); + registrationBean.setFilter(new SanitizationFilter()); + registrationBean.addUrlPatterns("/*"); registrationBean.setOrder(1); return registrationBean; } /** - * Register SanitizationFilter - * @return FilterRegistrationBean + * Register SameSiteCookieFilter + * @return FilterRegistrationBean */ @Bean - public FilterRegistrationBean sanitizationFilter() { - FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); - registrationBean.setFilter(new SanitizationFilter()); - registrationBean.addUrlPatterns("/*"); - registrationBean.setOrder(0); + public FilterRegistrationBean sameSiteCookieFilter() { + FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); + registrationBean.setFilter(new SameSiteCookieFilter()); + registrationBean.addUrlPatterns("/*"); // or specific URL patterns + registrationBean.setOrder(2); return registrationBean; } diff --git a/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java b/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java index 78d6a679..f3ca7650 100644 --- a/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java +++ b/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java @@ -23,7 +23,7 @@ */ public class SanitizationFilter implements Filter { - private SanitizedRequestWrapper sanitizedRequest; + // private SanitizedRequestWrapper sanitizedRequest; @Override public void init(FilterConfig filterConfig) { @@ -44,10 +44,11 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo if (!(servletRequest instanceof HttpServletRequest)) { throw new ServletException("Can only process HttpServletRequest"); } + HttpServletRequest request = (HttpServletRequest) servletRequest; - sanitizeRequestBody(request); - sanitizeRequestParams(request); - sanitizeRequestHeaders(request); + SanitizedRequestWrapper sanitizedRequest = sanitizeRequestBody(request); + sanitizeRequestParams(request, sanitizedRequest); + sanitizeRequestHeaders(request, sanitizedRequest); chain.doFilter(sanitizedRequest, servletResponse); } @@ -57,21 +58,22 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo * @param request - Servlet request object * @return void */ - private void sanitizeRequestBody(HttpServletRequest request) { + private SanitizedRequestWrapper sanitizeRequestBody(HttpServletRequest request) { String originalBody = getRequestBody(request); String sanitizedBody = sanitizeHtml(originalBody); - this.sanitizedRequest = new SanitizedRequestWrapper(request, sanitizedBody); + + return new SanitizedRequestWrapper(request, sanitizedBody); } /** * Method to sanitize the request params * @return void */ - private void sanitizeRequestParams(HttpServletRequest request) { + private void sanitizeRequestParams(HttpServletRequest request, SanitizedRequestWrapper sanitizedRequest) { request.getParameterMap().forEach((key, values) -> { for (int index = 0; index < values.length; index++) { String sanitizedValue = sanitizeHtml(values[index]); - this.sanitizedRequest.setParameter(key, sanitizedValue); + sanitizedRequest.setParameter(key, sanitizedValue); } }); } @@ -80,7 +82,7 @@ private void sanitizeRequestParams(HttpServletRequest request) { * Method to sanitize the request headers * @return void */ - private void sanitizeRequestHeaders(HttpServletRequest request) { + private void sanitizeRequestHeaders(HttpServletRequest request, SanitizedRequestWrapper sanitizedRequest) { Enumeration headerNames = request.getHeaderNames(); while (headerNames != null && headerNames.hasMoreElements()) { @@ -90,7 +92,7 @@ private void sanitizeRequestHeaders(HttpServletRequest request) { while (headerValues != null && headerValues.hasMoreElements()) { String headerValue = headerValues.nextElement(); String sanitizedValue = sanitizeHtml(headerValue); - this.sanitizedRequest.setHeader(headerName, sanitizedValue); + sanitizedRequest.setHeader(headerName, sanitizedValue); } } } From 573ace14f8e624c14ed638bc68d8611e8454ac00 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 31 Aug 2023 15:39:17 +0530 Subject: [PATCH 191/195] formatted code --- .../java/com/salessparrow/api/filter/SanitizationFilter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java b/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java index f3ca7650..75a73649 100644 --- a/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java +++ b/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java @@ -61,7 +61,7 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo private SanitizedRequestWrapper sanitizeRequestBody(HttpServletRequest request) { String originalBody = getRequestBody(request); String sanitizedBody = sanitizeHtml(originalBody); - + return new SanitizedRequestWrapper(request, sanitizedBody); } From bfe04e838c4c0e772684634cabb77d86aa12da11 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 31 Aug 2023 15:46:58 +0530 Subject: [PATCH 192/195] removed logs added for debugging --- src/main/java/com/salessparrow/api/SalesSparrowApi.java | 2 +- .../com/salessparrow/api/filter/SanitizationFilter.java | 2 -- .../java/com/salessparrow/api/lib/ErrorEmailService.java | 2 +- .../crmActions/createAccountNote/CreateSalesforceNote.java | 7 ------- .../api/lib/wrappers/SanitizedRequestWrapper.java | 1 - 5 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/salessparrow/api/SalesSparrowApi.java b/src/main/java/com/salessparrow/api/SalesSparrowApi.java index 3b046ba8..1fe1c6e5 100644 --- a/src/main/java/com/salessparrow/api/SalesSparrowApi.java +++ b/src/main/java/com/salessparrow/api/SalesSparrowApi.java @@ -8,7 +8,7 @@ @SpringBootApplication(exclude = { UserDetailsServiceAutoConfiguration.class }) @EnableCaching // This enables caching -// @EnableAsync // This enables asynchronous processing in Spring +@EnableAsync // This enables asynchronous processing in Spring public class SalesSparrowApi { public static void main(String[] args) { diff --git a/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java b/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java index 75a73649..69276f88 100644 --- a/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java +++ b/src/main/java/com/salessparrow/api/filter/SanitizationFilter.java @@ -23,8 +23,6 @@ */ public class SanitizationFilter implements Filter { - // private SanitizedRequestWrapper sanitizedRequest; - @Override public void init(FilterConfig filterConfig) { } diff --git a/src/main/java/com/salessparrow/api/lib/ErrorEmailService.java b/src/main/java/com/salessparrow/api/lib/ErrorEmailService.java index cde6743c..29236e02 100644 --- a/src/main/java/com/salessparrow/api/lib/ErrorEmailService.java +++ b/src/main/java/com/salessparrow/api/lib/ErrorEmailService.java @@ -68,7 +68,7 @@ public void sendErrorMail(String contextString, ErrorResponseObject errorObj, * @param body - body of email * @return void */ - // @Async + @Async public void sendEmail(String from, String to, String subject, String body) { logger.info("send SES Email"); try { diff --git a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java index 9572cfe9..5e06f69e 100644 --- a/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java +++ b/src/main/java/com/salessparrow/api/lib/crmActions/createAccountNote/CreateSalesforceNote.java @@ -56,16 +56,9 @@ public CreateNoteFormatterDto createNote(SalesforceUser user, String accountId, Util util = new Util(); String noteContent = note.getText(); - logger.info("createNote noteContent: {}", noteContent); - String noteTitle = getNoteTitleFromContent(noteContent); - logger.info("createNote noteTitle: {}", noteTitle); - noteContent = util.replaceNewLineWithBreak(noteContent); - logger.info("---- noteContent after replacing \\n: {}", noteContent); - String encodedNoteContent = base64Helper.base64Encode(noteContent); - logger.info("---- encodedNoteContent: {}", encodedNoteContent); Map createNoteBody = new HashMap(); createNoteBody.put("Title", noteTitle); diff --git a/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java b/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java index e5998477..e7f2a1c1 100644 --- a/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java +++ b/src/main/java/com/salessparrow/api/lib/wrappers/SanitizedRequestWrapper.java @@ -33,7 +33,6 @@ public class SanitizedRequestWrapper extends HttpServletRequestWrapper { public SanitizedRequestWrapper(HttpServletRequest request, String sanitizedBody) { super(request); - logger.info("SanitizedRequestWrapper sanitizedBody: {}", sanitizedBody); this.sanitizedBody = sanitizedBody; this.sanitizedParams = new HashMap<>(); this.sanitizedHeaders = new HashMap<>(); From 9c9d44011f9f07b63272d7f3d7ae1b71c0fea8bb Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 31 Aug 2023 16:37:16 +0530 Subject: [PATCH 193/195] updated Merging section in Release Process Docs --- repo-docs/RELEASE_PROCESS.md | 1 - 1 file changed, 1 deletion(-) diff --git a/repo-docs/RELEASE_PROCESS.md b/repo-docs/RELEASE_PROCESS.md index b7cc7189..f2c6e780 100644 --- a/repo-docs/RELEASE_PROCESS.md +++ b/repo-docs/RELEASE_PROCESS.md @@ -53,7 +53,6 @@ ### **3.1 Merging** - Once the release candidate is deemed stable, merge the `release/vX.Y.Z` branch (or the `milestone` branch) into the `main` branch. -- Create a tagged commit on the main branch with the version number. ### **3.2 GitHub Release** From 4af29a4b061a194bab8573c4b3f4378219cd2f4a Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 31 Aug 2023 16:49:39 +0530 Subject: [PATCH 194/195] updated changelog with sanitization issue --- repo-docs/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/repo-docs/CHANGELOG.md b/repo-docs/CHANGELOG.md index c6c64c62..50bd86b5 100644 --- a/repo-docs/CHANGELOG.md +++ b/repo-docs/CHANGELOG.md @@ -16,6 +16,7 @@ - API - Delete Task in an Account Endpoint [#59](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/59) - Add CHANGELOG.md [#62](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/62) - Add RELEASE_PROCESS.md [#63](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/63) +- Add Sanitization Filter for Request Params, Request Body, and Headers [#87](https://github.com/TrueSparrowSystems/AI-SalesSparrow-API/issues/87) ### Bug Fixes: From e37954b110e2d4343317b54b4eb1afc4fb64f8a5 Mon Sep 17 00:00:00 2001 From: Kiran Kamalakar Date: Thu, 31 Aug 2023 17:04:09 +0530 Subject: [PATCH 195/195] Updated docs submodule --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index 17628f44..8e2977e2 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 17628f44f8389830e4f4290064ba539c1863d385 +Subproject commit 8e2977e29d59a9858d78369ea267bd86259bc839