Ejemplo n.º 1
0
        public static DataAccessResponseType ProvisionAccount(Account account)
        {
            var response = new DataAccessResponseType();

            #region Pre Provisioning Verification

            bool _documentPartitioning = true;        //<-- If false will skip provisioning DocumentDB resources for accounts
            bool _searchPartitioning   = true;        //<-- If false will skip provisioning Search resources for accounts
            bool _storagePartitioning  = true;        //<-- If false will skip provisioning Search resources for accounts
            bool _sqlPartitioning      = true;        //<-- If false will skip provisioning a SQL Location and SchemeName for accounts

            StoragePartition storagePartition = null; //<-- Chosen partition for this account
            SearchPartition  searchPartition  = null; //<-- Chosen partition for this account

            //Make sure account isn't already provisioned
            if (account.Provisioned)
            {
                response.isSuccess    = false;
                response.ErrorMessage = "Account is already provisioned!";

                return(response);
            }
            if (account.StripeSubscriptionID == null || account.StripeCustomerID == null)
            {
                response.isSuccess    = false;
                response.ErrorMessage = "This account has not been assigned a payment plan or a Stripe CustomerID";

                return(response);
            }

            //If Account object is passed in without users get all/initial user(s):
            if (account.Users == null)
            {
                account.Users = AccountUserManager.GetUsers(account.AccountID.ToString());
            }

            #region Ensure that there is a storage partition available and select next available spot

            if (_storagePartitioning)
            {
                var storagePartitions = StoragePartitioningManager.GetStoragePartitions();


                //Sort with lowest tenant count at the top:
                storagePartitions = storagePartitions.OrderBy(o => o.TenantCount).ToList();

                if (storagePartitions.Count > 0)
                {
                    if (storagePartitions[0].TenantCount >= Settings.Platform.Partitioning.MaximumTenantsPerStorageAccount)
                    {
                        response.isSuccess    = false;
                        response.ErrorMessage = "There are no storage partitions available for this account! Please create one before attempting to provision.";

                        //Reset account to inactive so you can restart partitioning sequence after partition hopper has additional partitions added
                        AccountManager.UpdateAccountActiveState(account.AccountID.ToString(), false);

                        return(response);
                    }
                    else
                    {
                        //Assign storage partition:
                        storagePartition = storagePartitions[0];
                    }
                }
                else
                {
                    response.isSuccess    = false;
                    response.ErrorMessage = "There are no storage partitions available on this platform! Cannot provision any accounts!";

                    //Reset account to inactive so you can restart partitioning sequence after partition hopper has additional partitions added
                    AccountManager.UpdateAccountActiveState(account.AccountID.ToString(), false);

                    return(response);
                }
            }



            #endregion

            #region Ensure that there is a search partition available and select next available spot

            if (_searchPartitioning)
            {
                //Get search plan type for this plan tier
                string searchPlan = account.PaymentPlan.SearchPlan;

                //Get list of search partitions available with this plan type
                var searchPartitions = SearchPartitioningManager.GetSearchPartitions(searchPlan);

                int maxTenantsAllowed = Int32.Parse((searchPlan.Substring(searchPlan.LastIndexOf("-") + 1)));

                /* MAx Tenatnts are now pulled from the SarchPlan name
                 *
                 * int maxTenantsAllowed = 0;
                 *
                 * if(searchPlan == "Basic")
                 * {
                 *  maxTenantsAllowed = Settings.Platform.Partitioning.MaximumTenantsPerBasicSearchServiceShared;
                 * }
                 * else if (searchPlan == "Basic-Dedicated")
                 * {
                 *  maxTenantsAllowed = Settings.Platform.Partitioning.MaximumTenantsPerBasicSearchServiceDedicated;
                 * }
                 * else if(searchPlan == "S1")
                 * {
                 *  maxTenantsAllowed = Settings.Platform.Partitioning.MaximumTenantsPerS1SearchServiceShared;
                 * }
                 * else if (searchPlan == "S1-Dedicated")
                 * {
                 *  maxTenantsAllowed = Settings.Platform.Partitioning.MaximumTenantsPerS1SearchServiceDedicated;
                 * }
                 * else if (searchPlan == "S2")
                 * {
                 *  maxTenantsAllowed = Settings.Platform.Partitioning.MaximumTenantsPerS2SearchServiceShared;
                 * }
                 * else if (searchPlan == "S2-Dedicated")
                 * {
                 *  maxTenantsAllowed = Settings.Platform.Partitioning.MaximumTenantsPerS2SearchServiceDedicated;
                 * }
                 * else if(searchPlan == "Free")
                 * {
                 *  maxTenantsAllowed = Settings.Platform.Partitioning.MaximumTenantsPerFreeSearchService;
                 * }
                 */

                //Sort with lowest tenant count at the top:
                searchPartitions = searchPartitions.OrderBy(o => o.TenantCount).ToList();

                if (searchPartitions.Count > 0)
                {
                    if (searchPartitions[0].TenantCount >= maxTenantsAllowed)
                    {
                        response.isSuccess    = false;
                        response.ErrorMessage = "There are no '" + searchPlan + "' search partitions available for this account! Please create one before attempting to provision.";

                        //Reset account to inactive so you can restart partitioning sequence after partition hopper has additional partitions added
                        AccountManager.UpdateAccountActiveState(account.AccountID.ToString(), false);

                        return(response);
                    }
                    else
                    {
                        //Assign storage partition:
                        searchPartition = searchPartitions[0];
                    }
                }
                else
                {
                    response.isSuccess    = false;
                    response.ErrorMessage = "There are no '" + searchPlan + "' search partitions available on this platform! Cannot provision any accounts!";

                    //Reset account to inactive so you can restart partitioning sequence after partition hopper has additional partitions added
                    AccountManager.UpdateAccountActiveState(account.AccountID.ToString(), false);

                    return(response);
                }
            }



            #endregion

            #endregion

            #region Account Partitioning

            #region Document Database Partitioning (REMOVED)

            if (_documentPartitioning)
            {
                //Connect to the document client & get the database selfLink
                //var client = Sahara.Core.Settings.Azure.DocumentDbClients.AccountDocumentClient;

                //Sahara.Core.Settings.Azure.DocumentDbClients.AccountDocumentClient.OpenAsync().ConfigureAwait(false);
                //Sahara.Core.Settings.Azure.DocumentDbClients.AccountDocumentClient.OpenAsync();

                //var dataBaseSelfLink = Sahara.Core.Settings.Azure.DocumentDB.AccountPartitionDatabaseSelfLink;

                //STEP 1: Get or create the next available document partition for the 'Free' tier
                var partitioningResult = DocumentPartitioningManager.CreateDocumentCollectionAccountPartition(account.AccountNameKey, Sahara.Core.Settings.Azure.DocumentDbClients.AccountDocumentClient, Sahara.Core.Settings.Azure.DocumentDB.AccountPartitionDatabaseId);

                if (partitioningResult.isSuccess == true)
                {
                    DocumentCollection nextAvailablePartitionCollection = (DocumentCollection)partitioningResult.ResponseObject;

                    #region STEP 4: Add Account Settings Document for this account on the collection

                    var       accountSettingsDocumentCreated = false;
                    Exception accountSettingsException       = null;

                    try
                    {
                        var accountSettingsDocument = new AccountSettingsDocumentModel {
                            Id = "AccountSettings"
                        };

                        accountSettingsDocument.ContactSettings             = new ContactSettingsModel();
                        accountSettingsDocument.ContactSettings.ContactInfo = new ContactInfoModel();
                        accountSettingsDocument.SalesSettings = new SalesSettingsModel();

                        //Default LeadLabels
                        accountSettingsDocument.SalesSettings.LeadLabels = new List <string>();
                        accountSettingsDocument.SalesSettings.LeadLabels.Add("New");
                        accountSettingsDocument.SalesSettings.LeadLabels.Add("Archive");
                        accountSettingsDocument.SalesSettings.LeadLabels.Add("Deleted");

                        accountSettingsDocument.Theme = "Light";                                   //<-- Default Theme
                        accountSettingsDocument.SalesSettings.ButtonCopy      = "I'm interested!"; //<-- Default Theme
                        accountSettingsDocument.SalesSettings.DescriptionCopy = "Fill out our contact form and a member of our team will contact you directly.";



                        Sahara.Core.Settings.Azure.DocumentDbClients.AccountDocumentClient.CreateDocumentAsync(nextAvailablePartitionCollection.SelfLink, accountSettingsDocument).ConfigureAwait(false);

                        accountSettingsDocumentCreated = true;
                    }
                    #region Manage Exception & Create Manual Instructions

                    catch (DocumentClientException de)
                    {
                        accountSettingsException = de.GetBaseException();
                    }
                    catch (Exception e)
                    {
                        accountSettingsException = e;
                    }

                    if (!accountSettingsDocumentCreated)
                    {
                        #region Log Exception

                        if (accountSettingsException != null)
                        {
                            PlatformExceptionsHelper.LogExceptionAndAlertAdmins(
                                accountSettingsException,
                                "creating an account settings document into a partition during account provisioning",
                                System.Reflection.MethodBase.GetCurrentMethod(),
                                account.AccountID.ToString(),
                                account.AccountName
                                );
                        }


                        #endregion

                        #region Manual Instructions

                        //Not successfull, All tasks within 'GetNextAvailableDocumentPartition' must be run manually
                        PlatformLogManager.LogActivity(
                            CategoryType.ManualTask,
                            ActivityType.ManualTask_DocumentDB,
                            "AccountSettingsDocumentModel file creation failed during account provisioning",
                            "Please create the 'AccountSettingsDocumentModel' document for '" + account.AccountName + "' within the '" + nextAvailablePartitionCollection.Id + "' collection manually.",
                            account.AccountID.ToString(),
                            account.AccountName,
                            null,
                            null,
                            null,
                            null,
                            System.Reflection.MethodBase.GetCurrentMethod().ToString()
                            );

                        #endregion
                    }

                    #endregion

                    #endregion
                }
                else
                {
                    #region Manual Instructions

                    //Not successfull, All tasks within 'GetNextAvailableDocumentPartition' must be run manually
                    PlatformLogManager.LogActivity(
                        CategoryType.ManualTask,
                        ActivityType.ManualTask_Other,
                        "Document partitioning failed during account provisioning",
                        "Please run all tasks under 'DocumentPartitioningManager.GetNextAvailableDocumentPartition('Free', client, dataBaseSelfLink)' as Well as 'if (partitioningResult.isSuccess == true)' manually. This may include creating a new DocumentPartition, updating account DocumentPartitionId and creating an AccountPropertiesDocument for this account into the new partition.",
                        account.AccountID.ToString(),
                        account.AccountName,
                        null,
                        null,
                        null,
                        null,
                        System.Reflection.MethodBase.GetCurrentMethod().ToString()
                        );

                    #endregion
                }

                #region Depricated DocumentDB Code

                /*
                 * try
                 * {
                 *  DocumentClient client = Sahara.Core.Settings.Azure.DocumentDB.DocumentClients.AccountDocumentClient;
                 *  client.OpenAsync(); //<-- By default, the first request will have a higher latency because it has to fetch the address routing table. In order to avoid this startup latency on the first request, you should call OpenAsync() once during initialization as follows.
                 *
                 *
                 *  //Generate Account Database
                 *  Database accountDatabase = client.CreateDatabaseAsync(new Database { Id = account.AccountID.ToString() }).Result;
                 *
                 *
                 *  //Generate "AccountProperties" Collection on the database
                 *  DocumentCollection accountPropertiesCollection = client.CreateDocumentCollectionAsync(accountDatabase.SelfLink, new DocumentCollection { Id = "AccountProperties" }).Result;
                 *
                 *
                 *  //Generate "SelfLinkReferences" Document within AccountProperties" collection
                 *  Document selfLinkReferencesDocument = client.CreateDocumentAsync(accountPropertiesCollection.SelfLink, new SelfLinkReferencesDocumentModel { Id = "SelfLinkReferences" }).Result;
                 *
                 *
                 *  //Store all the SelfLinks
                 *  var documentUpdateResults = Sql.Statements.UpdateStatements.UpdateDocumentDatabaseLinks(account.AccountID.ToString(), accountDatabase.SelfLink, accountPropertiesCollection.SelfLink, selfLinkReferencesDocument.SelfLink);
                 *  if (documentUpdateResults)
                 *  {
                 *
                 *  }
                 *  else
                 *  {
                 *
                 *      var errorMessage = "DocumentDB Selflink insertion into the '" + account.AccountName + "' account has failed";
                 *      var errorDetails = "AccountID: '" + account.AccountID + "' Error: 'DocumentDB resources have been provisioned, but an error occured when updating database columns for the account'";
                 *
                 *      //Log Errors
                 *      PlatformLogManager.LogActivity(
                 *              CategoryType.Error,
                 *              ActivityType.Error_Other,
                 *              errorMessage,
                 *              errorDetails,
                 *              account.AccountID.ToString(),
                 *              account.AccountName
                 *          );
                 *
                 *      return new DataAccessResponseType { isSuccess = false, ErrorMessage = errorMessage };
                 *  }
                 * }
                 * catch (Exception e)
                 * {
                 #region Handle Exception
                 *
                 *  //Log exception and email platform admins
                 *  PlatformExceptionsHelper.LogExceptionAndAlertAdmins(
                 *      e,
                 *      "attempting to partition DocumentDB resources for the '" + account.AccountName + "' account during provisioning.",
                 *      System.Reflection.MethodBase.GetCurrentMethod(),
                 *      account.AccountID.ToString(),
                 *      account.AccountName
                 *  );
                 *
                 #endregion
                 * }
                 */

                #endregion
            }

            #endregion

            #region Storage Partitioning

            if (_storagePartitioning)
            {
                /* No longer need to set anything up (Back to document db)
                 *
                 * //Create setings JSON doc in storage (DocumentDB is now OFF)
                 * var accountSettingsDocument = new AccountSettingsDocumentModel { Id = "AccountSettings" };
                 *
                 * accountSettingsDocument.ContactSettings = new ContactSettingsModel();
                 * accountSettingsDocument.ContactSettings.ContactInfo = new ContactInfoModel();
                 * accountSettingsDocument.SalesSettings = new SalesSettingsModel();
                 *
                 * //Default LeadLabels
                 * accountSettingsDocument.SalesSettings.LeadLabels = new List<string>();
                 * accountSettingsDocument.SalesSettings.LeadLabels.Add("New");
                 * accountSettingsDocument.SalesSettings.LeadLabels.Add("Archive");
                 * accountSettingsDocument.SalesSettings.LeadLabels.Add("Deleted");
                 *
                 * accountSettingsDocument.Theme = "Light"; //<-- Default Theme
                 * accountSettingsDocument.SalesSettings.ButtonCopy = "I'm interested!"; //<-- Default Theme
                 * accountSettingsDocument.SalesSettings.DescriptionCopy = "Fill out our contact form and a member of our team will contact you directly.";
                 *
                 * //Save to designated storage account
                 * CloudStorageAccount storageAccount;
                 * StorageCredentials storageCredentials = new StorageCredentials(storagePartition.Name, storagePartition.Key);
                 * storageAccount = new CloudStorageAccount(storageCredentials, false);
                 * CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
                 *
                 * //Create and set retry policy
                 * IRetryPolicy exponentialRetryPolicy = new ExponentialRetry(TimeSpan.FromMilliseconds(400), 6);
                 * blobClient.DefaultRequestOptions.RetryPolicy = exponentialRetryPolicy;
                 *
                 * //Creat/Connect to the Blob Container for this account
                 * blobClient.GetContainerReference(account.AccountNameKey).CreateIfNotExists(BlobContainerPublicAccessType.Blob); //<-- Create and make public
                 *
                 *
                 * CloudBlobContainer blobContainer = blobClient.GetContainerReference(account.AccountNameKey);
                 *
                 * //Get reference to the text blob or create if not exists.
                 * CloudBlockBlob blockBlob = blobContainer.GetBlockBlobReference("settings/" + "accountSettings.json");
                 *
                 * blockBlob.UploadText(JsonConvert.SerializeObject(accountSettingsDocument));
                 *
                 * //Save to storage
                 * //Convert final BMP to byteArray
                 * //Byte[] finalByteArray;
                 *
                 * //finalByteArray = outStream.ToArray();
                 *
                 * //blockBlob.UploadFromByteArray(finalByteArray, 0, finalByteArray.Length);
                 *
                 */
            }

            #endregion

            #region SQL Partitioning

            if (_sqlPartitioning)
            {
                try
                {
                    // 1. Get and assign the next available database partition for this account to be provisioned into:
                    var getAndAssignPartitionResponse = SqlPartitioningManager.GetAndAssignNextAvailableAccountSqlPartition(account.AccountID.ToString());

                    if (getAndAssignPartitionResponse.isSuccess)
                    {
                        string DatabasePartitionName = getAndAssignPartitionResponse.SuccessMessage;

                        // 2. Run creation scripts to provision accounts schema to the selected partition:
                        var generateAccountSchemaResponse = AccountProvisioning.GenerateAccountSchema(account.AccountID.ToString(), DatabasePartitionName);

                        if (generateAccountSchemaResponse.isSuccess)
                        {
                            generateAccountSchemaResponse.SuccessMessage = DatabasePartitionName; //<-- Return the name of the database partition name
                        }
                        else
                        {
                            return(generateAccountSchemaResponse);
                        }
                    }
                    else
                    {
                        return(getAndAssignPartitionResponse);
                    }
                }
                catch (Exception e)
                {
                    #region Handle Exception

                    //Log exception and email platform admins
                    PlatformExceptionsHelper.LogExceptionAndAlertAdmins(
                        e,
                        "attempting to partition SQL for the '" + account.AccountName + "' account during provisioning.",
                        System.Reflection.MethodBase.GetCurrentMethod(),
                        account.AccountID.ToString(),
                        account.AccountName
                        );

                    #endregion
                }
            }



            #endregion

            #region Search Partitioning

            if (_searchPartitioning)
            {
                //Create an Product Search Index for this account on the selected search partition ---------------------
                var searchIndexCreated = ProductSearchManager.CreateProductSearchIndex(account.AccountNameKey, searchPartition.Name, searchPartition.Key);
            }

            #endregion

            #endregion

            #region Post Partitioning Tasks

            // 1. Mark the Account as Provisioned, Active and assign a ProvisioningDate:
            var result = Sql.Statements.UpdateStatements.UpdateProvisiongStatus(account.AccountID.ToString(), true, true, storagePartition.Name, searchPartition.Name);


            if (result)
            {
                // 1. Create a platform user account SO we can log into the account for management purposes:
                AccountUserManager.CreateAccountUser(account.AccountID.ToString(), "platformadmin@[Config_PlatformEmail]", "Platform", "Admin", "[Config_PlatformPassword_AzureKeyVault]", Settings.Accounts.Users.Authorization.Roles.PlatformAdmin, true, null, true);

                // 2. Invalidated/Update the cache for this account
                AccountManager.UpdateAccountDetailCache(account.AccountNameKey);

                // 3. Email the creator with sucessful provisioning message and login info:

                /*
                 * EmailManager.Send(
                 *      account.Users[0].Email, //<-- Will only have the initial user
                 *      Settings.Endpoints.Emails.FromProvisioning,
                 *      Settings.Copy.EmailMessages.ProvisioningComplete.FromName,
                 *      Settings.Copy.EmailMessages.ProvisioningComplete.Subject,
                 *      String.Format(Settings.Copy.EmailMessages.ProvisioningComplete.Body, account.AccountNameKey),
                 *      true
                 *  );*/

                // 4. Send an alert to the platform admin(s):
                EmailManager.Send(
                    Settings.Endpoints.Emails.PlatformEmailAddresses,
                    Settings.Endpoints.Emails.FromProvisioning,
                    "Provisioning " + Settings.Application.Name,
                    "Account Provisioned",
                    "<b>'" + account.AccountName + "'</b> has just been provisioned.",
                    true
                    );

                // 5. Log Successfull Provisioning Activity
                PlatformLogManager.LogActivity(CategoryType.Account,
                                               ActivityType.Account_Provisioned,
                                               "Provisioning of '" + account.AccountName + "' has completed",
                                               "AccountID: '" + account.AccountID + "'",
                                               account.AccountID.ToString(), account.AccountName);

                //Register subdomains
                try
                {
                    var cloudFlareResult = CloudFlareManager.RegisterSubdomains(account.AccountNameKey);

                    if (cloudFlareResult.isSuccess == false)
                    {
                        //Log exception and email platform admins
                        PlatformExceptionsHelper.LogErrorAndAlertAdmins(
                            cloudFlareResult.ErrorMessage,
                            "attempting to add cloudflare subdomains for the '" + account.AccountName + "' account during provisioning.",
                            System.Reflection.MethodBase.GetCurrentMethod(),
                            account.AccountID.ToString(),
                            account.AccountName
                            );
                    }
                }
                catch (Exception e)
                {
                    //Log exception and email platform admins
                    PlatformExceptionsHelper.LogExceptionAndAlertAdmins(
                        e,
                        "attempting to register cloudflare subdomains for the '" + account.AccountName + "' account during provisioning.",
                        System.Reflection.MethodBase.GetCurrentMethod(),
                        account.AccountID.ToString(),
                        account.AccountName
                        );
                }

                return(new DataAccessResponseType {
                    isSuccess = true
                });
            }
            else
            {
                var errorMessage = "Account has been fully provisioned, but an error occured when setting the Account table to Active and assigning a provisioning date";

                PlatformLogManager.LogActivity(CategoryType.Error,
                                               ActivityType.Error_Other,
                                               "Provisioning of '" + account.AccountName + "' has failed",
                                               errorMessage,
                                               account.AccountID.ToString(), account.AccountName);

                return(new DataAccessResponseType {
                    isSuccess = false, ErrorMessage = errorMessage
                });
            }



            #endregion
        }
        public static AccountSettingsDocumentModel GetAccountSettings(Account account, bool useCachedVersion = true)
        {
            AccountSettingsDocumentModel settingsDocument = null;

            #region Create Cache & HashField

            string redisHashField = string.Empty;

            //IDatabase cache = Sahara.Core.Settings.Azure.Redis.RedisMultiplexers.AccountManager_Multiplexer.GetDatabase();
            IDatabase cache = Sahara.Core.Settings.Azure.Redis.RedisMultiplexers.RedisMultiplexer.GetDatabase();

            redisHashField = AccountSettingsHash.Fields.Document(account.AccountNameKey);


            #endregion

            if (useCachedVersion)
            {
                #region Get settings from cache

                try
                {
                    var redisValue = cache.HashGet(AccountSettingsHash.Key(), redisHashField);
                    if (redisValue.HasValue)
                    {
                        settingsDocument = JsonConvert.DeserializeObject <AccountSettingsDocumentModel>(redisValue);
                    }
                }
                catch
                {
                }

                #endregion
            }

            if (settingsDocument == null)
            {
                #region Get settings from DocumentDB

                /**/
                //Get the DocumentDB Client
                //var client = Sahara.Core.Settings.Azure.DocumentDbClients.AccountDocumentClient;
                //var dbSelfLink = Sahara.Core.Settings.Azure.DocumentDB.AccountPartitionDatabaseSelfLink;
                //Sahara.Core.Settings.Azure.DocumentDbClients.AccountDocumentClient.OpenAsync();

                //Build a collection Uri out of the known IDs
                //(These helpers allow you to properly generate the following URI format for Document DB:
                //"dbs/{xxx}/colls/{xxx}/docs/{xxx}"
                Uri collectionUri = UriFactory.CreateDocumentCollectionUri(Sahara.Core.Settings.Azure.DocumentDB.AccountPartitionDatabaseId, account.DocumentPartition);

                string sqlQuery = "SELECT * FROM Settings s WHERE s.id ='AccountSettings'";

                var settingsResults = Sahara.Core.Settings.Azure.DocumentDbClients.AccountDocumentClient.CreateDocumentQuery <AccountSettingsDocumentModel>(collectionUri.ToString(), sqlQuery);

                //var accountCollection = client.Crea

                //applicationImages = result.ToList();
                settingsDocument = settingsResults.AsEnumerable().FirstOrDefault();


                #endregion

                #region Get settings from storage partition (Retired, now using DocumentDB)

                /*
                 *
                 * //Get storage partition for this account and create a BLOB client:
                 * CloudBlobClient blobClient = Sahara.Core.Settings.Azure.Storage.GetStoragePartitionAccount(account.StoragePartition).CreateCloudBlobClient();
                 *
                 * //Create and set retry policy
                 * IRetryPolicy exponentialRetryPolicy = new ExponentialRetry(TimeSpan.FromMilliseconds(500), 8);
                 * blobClient.DefaultRequestOptions.RetryPolicy = exponentialRetryPolicy;
                 *
                 * //CloudBlobContainer blobContainer = blobClient.GetContainerReference(account.AccountID.ToString());
                 * CloudBlobContainer blobContainer = blobClient.GetContainerReference(account.AccountNameKey);
                 *
                 *
                 * //Get reference to the text blob or create if not exists.
                 * CloudBlockBlob blockBlob = blobContainer.GetBlockBlobReference("settings/" + "accountSettings.json");
                 *
                 * //Deserialize new version of settings document
                 * settingsDocument = JsonConvert.DeserializeObject<AccountSettingsDocumentModel>(blockBlob.DownloadText());
                 */

                #endregion

                if (settingsDocument != null)
                {
                    #region Set into cache

                    try
                    {
                        cache.HashSet(AccountSettingsHash.Key(),
                                      AccountSettingsHash.Fields.Document(redisHashField),
                                      JsonConvert.SerializeObject(settingsDocument), When.Always, CommandFlags.FireAndForget);
                    }
                    catch
                    {
                    }

                    #endregion
                }
            }

            return(settingsDocument);
        }
        /// <summary>
        /// We update ALL settings as one huge document. Makign it easier to add properties as the application(s) evolve)
        /// </summary>
        /// <param name="account"></param>
        /// <param name="accountSettingsDocumentModel"></param>
        /// <returns></returns>
        public static DataAccessResponseType UpdateAccountSettings(Account account, AccountSettingsDocumentModel accountSettingsDocumentModel)
        {
            var response = new DataAccessResponseType();

            try
            {
                //Get the DocumentDB Client
                //var client = Sahara.Core.Settings.Azure.DocumentDbClients.AccountDocumentClient;
                //var dbSelfLink = Sahara.Core.Settings.Azure.DocumentDB.AccountPartitionDatabaseSelfLink;
                //Sahara.Core.Settings.Azure.DocumentDbClients.AccountDocumentClient.OpenAsync();

                //Build a collection Uri out of the known IDs
                //(These helpers allow you to properly generate the following URI format for Document DB:
                //"dbs/{xxx}/colls/{xxx}/docs/{xxx}"
                //Uri collectionUri = UriFactory.CreateDocumentCollectionUri(Sahara.Core.Settings.Azure.DocumentDB.AccountPartitionDatabaseId, account.DocumentPartition);
                Uri documentUri = UriFactory.CreateDocumentUri(Sahara.Core.Settings.Azure.DocumentDB.AccountPartitionDatabaseId, account.DocumentPartition, accountSettingsDocumentModel.Id);

                //Replace document:
                var updated = Sahara.Core.Settings.Azure.DocumentDbClients.AccountDocumentClient.ReplaceDocumentAsync(documentUri, accountSettingsDocumentModel).Result;

                response.isSuccess = true;

                #region Storage Version (Retired & Moved Back to DocumentDB)


                /*
                 *
                 *  //Get storage partition for this account and create a BLOB client:
                 *  CloudBlobClient blobClient = Sahara.Core.Settings.Azure.Storage.GetStoragePartitionAccount(account.StoragePartition).CreateCloudBlobClient();
                 *
                 *  //Create and set retry policy
                 *  IRetryPolicy exponentialRetryPolicy = new ExponentialRetry(TimeSpan.FromMilliseconds(500), 8);
                 *  blobClient.DefaultRequestOptions.RetryPolicy = exponentialRetryPolicy;
                 *
                 *  //CloudBlobContainer blobContainer = blobClient.GetContainerReference(account.AccountID.ToString());
                 *  CloudBlobContainer blobContainer = blobClient.GetContainerReference(account.AccountNameKey);
                 *
                 *
                 *  //Get reference to the text blob or create if not exists.
                 *  CloudBlockBlob blockBlob = blobContainer.GetBlockBlobReference("settings/" + "accountSettings.json");
                 *
                 *  //Serialize new version of settings document
                 *  blockBlob.UploadText(JsonConvert.SerializeObject(accountSettingsDocumentModel));
                 */

                #endregion
            }
            catch (Exception e)
            {
                response.isSuccess    = false;
                response.ErrorMessage = e.Message;
            }

            if (response.isSuccess)
            {
                if (response.isSuccess)
                {
                    //Clear Category Caches:
                    Caching.InvalidateSettingsCache(account.AccountNameKey);
                }
            }

            return(response);
        }
        public static DataAccessResponseType UpdateAccountSettings_Internal(string accountNameKey, AccountSettingsDocumentModel accountSettingsDocumentModel)
        {
            var response = new AccountManagementService.DataAccessResponseType();

            var accountManagementServiceClient = new AccountManagementService.AccountManagementServiceClient();

            try
            {
                accountManagementServiceClient.Open();
                response = accountManagementServiceClient.UpdateAccountSettings(accountNameKey, accountSettingsDocumentModel,
                                                                                AuthenticationCookieManager.GetAuthenticationCookie().Id,
                                                                                AccountAdminSite.AccountManagementService.RequesterType.AccountUser, Common.SharedClientKey);

                //Close the connection
                WCFManager.CloseConnection(accountManagementServiceClient);
            }
            catch (Exception e)
            {
                #region Manage Exception

                string exceptionMessage = e.Message.ToString();

                var    currentMethod       = System.Reflection.MethodBase.GetCurrentMethod();
                string currentMethodString = currentMethod.DeclaringType.FullName + "." + currentMethod.Name;

                // Abort the connection & manage the exception
                WCFManager.CloseConnection(accountManagementServiceClient, exceptionMessage, currentMethodString);

                // Upate the response object
                response.isSuccess    = false;
                response.ErrorMessage = WCFManager.UserFriendlyExceptionMessage;
                //response.ErrorMessages[0] = exceptionMessage;

                #endregion
            }

            return(response);
        }
        public static AccountSettingsDocumentModel GetAccountSettings_Internal(string accountNameKey)
        {
            AccountSettingsDocumentModel settingsDocument = null;

            #region From Redis

            try
            {
                IDatabase cache = CoreServices.RedisConnectionMultiplexers.RedisMultiplexer.GetDatabase();

                string hashMainKey   = "account:settings";
                string hashMainField = accountNameKey;

                var redisValue = cache.HashGet(hashMainKey, hashMainField);

                if (redisValue.HasValue)
                {
                    settingsDocument = JsonConvert.DeserializeObject <AccountSettingsDocumentModel>(redisValue);
                }
            }
            catch (Exception e)
            {
                var error = e.Message;
                //TODO: Log: error message for Redis call
            }

            #endregion

            if (settingsDocument == null)
            {
                #region From WCF

                var accountManagementServiceClient = new AccountManagementService.AccountManagementServiceClient();

                try
                {
                    accountManagementServiceClient.Open();

                    settingsDocument = accountManagementServiceClient.GetAccountSettings(accountNameKey, Common.SharedClientKey);
                    WCFManager.CloseConnection(accountManagementServiceClient);
                }
                catch (Exception e)
                {
                    #region Manage Exception

                    string exceptionMessage = e.Message.ToString();

                    var    currentMethod       = System.Reflection.MethodBase.GetCurrentMethod();
                    string currentMethodString = currentMethod.DeclaringType.FullName + "." + currentMethod.Name;

                    // Abort the connection & manage the exception
                    WCFManager.CloseConnection(accountManagementServiceClient, exceptionMessage, currentMethodString);

                    #endregion
                }

                #endregion
            }

            #region Instantiate instances of classes that are null

            if (settingsDocument.ContactSettings == null)
            {
                settingsDocument.ContactSettings = new ContactSettingsModel();
            }
            if (settingsDocument.ContactSettings.ContactInfo == null)
            {
                settingsDocument.ContactSettings.ContactInfo = new ContactInfoModel();
            }
            if (settingsDocument.SalesSettings == null)
            {
                settingsDocument.SalesSettings = new SalesSettingsModel();
            }

            #endregion

            return(settingsDocument);
        }
Ejemplo n.º 6
0
        public JsonNetResult GetAccount()
        {
            AccountDetailsJson accountDetailsJson = null;

            ExecutionType executionType = ExecutionType.local;
            Stopwatch     stopWatch     = new Stopwatch();

            stopWatch.Start();

            //Get the subdomain (if exists) for the api call
            string accountNameKey = Common.GetSubDomain(Request.Url);

            if (String.IsNullOrEmpty(accountNameKey))
            {
                return(new JsonNetResult {
                    Data = "Not found"
                });                                              //return Request.CreateResponse(HttpStatusCode.NotFound);
            }

            string localCacheKey = accountNameKey + ":accountDetails";

            #region (Plan A) Get json from local cache

            try
            {
                accountDetailsJson = (AccountDetailsJson)HttpRuntime.Cache[localCacheKey];
            }
            catch (Exception e)
            {
                var error = e.Message;
                //TODO: Log: error message for local cache call
            }

            #endregion

            if (accountDetailsJson == null)
            {
                #region (Plan B) Get Public json from second layer of Redis Cache

                IDatabase cache = CoreServices.RedisConnectionMultiplexers.RedisMultiplexer.GetDatabase();

                string pathAndQuery = Common.GetApiPathAndQuery(Request.Url);

                string hashApiKey   = accountNameKey + ":apicache";
                string hashApiField = pathAndQuery;

                try
                {
                    var redisApiValue = cache.HashGet(hashApiKey, hashApiField);

                    if (redisApiValue.HasValue)
                    {
                        accountDetailsJson = JsonConvert.DeserializeObject <AccountDetailsJson>(redisApiValue);
                        executionType      = ExecutionType.redis_secondary;
                    }
                }
                catch
                {
                }


                #endregion

                if (accountDetailsJson == null)
                {
                    #region (Plan C) Create Account Object, Get Settings & Images

                    var account = Common.GetAccountObject(accountNameKey);

                    accountDetailsJson         = new AccountDetailsJson();
                    accountDetailsJson.account = new AccountJson();
                    accountDetailsJson.account.contactSettings = new ContactSettingsJson();
                    accountDetailsJson.account.contactSettings.contactDetails = new ContactDetailsJson();
                    accountDetailsJson.account.salesSettings  = new SalesSettingsJson();
                    accountDetailsJson.account.accountName    = account.AccountName;
                    accountDetailsJson.account.accountNameKey = account.AccountNameKey;


                    //accountDetailsJson.account.paymentPlan = account.PaymentPlan;
                    accountDetailsJson.account.paymentPlan = account.PaymentPlan.PaymentPlanName;
                    //accountDetailsJson.account.paymentPlanFrequency = account.PaymentPlan.;


                    #region  Get Account Settings Document

                    AccountSettingsDocumentModel settingsDocument = DataAccess.AccountSettings.GetAccountSettings(accountNameKey);

                    #endregion

                    #region Build Sales Settings

                    if (settingsDocument.SalesSettings != null)
                    {
                        accountDetailsJson.account.salesSettings.useSalesLeads = settingsDocument.SalesSettings.UseSalesLeads;

                        if (accountDetailsJson.account.salesSettings.useSalesLeads == true)
                        {
                            accountDetailsJson.account.salesSettings.buttonCopy       = settingsDocument.SalesSettings.ButtonCopy;
                            accountDetailsJson.account.salesSettings.leadsDescription = settingsDocument.SalesSettings.DescriptionCopy;
                        }
                    }

                    #endregion

                    //Build Theme Object (removed)
                    //accountDetailsJson.account.themeSettings = new ThemeSettingsJson();
                    //accountDetailsJson.account.themeSettings.name = settingsDocument.Theme;

                    //ToDo: Pull theme info from Redis or WCF
                    #region Get Themes

                    //List<ThemeModel> themes = null;

                    #region From Redis

                    /*
                     * IDatabase platformCache = CoreServices.RedisConnectionMultiplexers.PlatformManager_Multiplexer.GetDatabase();
                     * string themesHashMainKey = "themes";
                     * string themesHashMainField = "list";
                     *
                     * try
                     * {
                     *  var themesRedis = platformCache.HashGet(themesHashMainKey, themesHashMainField);
                     *
                     *  if (themesRedis.HasValue)
                     *  {
                     *      themes = JsonConvert.DeserializeObject<List<ThemeModel>>(themesRedis);
                     *  }
                     * }
                     * catch
                     * {
                     *
                     * }
                     */
                    #endregion

                    #region From WCF

                    /*
                     * if(themes == null)
                     * {
                     *  var accountManagementServiceClient = new AccountManagementService.AccountManagementServiceClient();
                     *
                     *  try
                     *  {
                     *      accountManagementServiceClient.Open();
                     *
                     *      themes = accountManagementServiceClient.GetThemes().ToList();
                     *
                     *      WCFManager.CloseConnection(accountManagementServiceClient);
                     *
                     *  }
                     *  catch (Exception e)
                     *  {
                     #region Manage Exception
                     *
                     *      string exceptionMessage = e.Message.ToString();
                     *
                     *      var currentMethod = System.Reflection.MethodBase.GetCurrentMethod();
                     *      string currentMethodString = currentMethod.DeclaringType.FullName + "." + currentMethod.Name;
                     *
                     *      // Abort the connection & manage the exception
                     *      WCFManager.CloseConnection(accountManagementServiceClient, exceptionMessage, currentMethodString);
                     *
                     #endregion
                     *  }
                     * }
                     */
                    #endregion

                    #endregion

                    #region Build Theme

                    /*
                     * foreach(ThemeModel theme in themes)
                     * {
                     *  if(theme.Name == accountDetailsJson.account.themeSettings.name)
                     *  {
                     *      accountDetailsJson.account.themeSettings.font = theme.Font;
                     *
                     *      accountDetailsJson.account.themeSettings.colors.background = theme.Colors.Background;
                     *      accountDetailsJson.account.themeSettings.colors.backgroundGradientBottom = theme.Colors.BackgroundGradientBottom;
                     *      accountDetailsJson.account.themeSettings.colors.backgroundGradientTop = theme.Colors.BackgroundGradianetTop;
                     *      accountDetailsJson.account.themeSettings.colors.foreground = theme.Colors.Foreground;
                     *      accountDetailsJson.account.themeSettings.colors.highlight = theme.Colors.Highlight;
                     *      accountDetailsJson.account.themeSettings.colors.overlay = theme.Colors.Overlay;
                     *      accountDetailsJson.account.themeSettings.colors.shadow = theme.Colors.Shadow;
                     *      accountDetailsJson.account.themeSettings.colors.trim = theme.Colors.Trim;
                     *
                     *  }
                     * }
                     */
                    #endregion

                    accountDetailsJson.account.customDomain = settingsDocument.CustomDomain;


                    #region Build Sort Settings (removed)

                    /*
                     *
                     * if (settingsDocument.SortSettings != null)
                     * {
                     *  accountDetailsJson.account.sortSettings = new SortSettingsJson();
                     *
                     *  accountDetailsJson.account.sortSettings.truncatedList = new SortJson {
                     *      name = settingsDocument.SortSettings.TruncatedListing.Name,
                     *      value = settingsDocument.SortSettings.TruncatedListing.Value,
                     *  };
                     *
                     *  accountDetailsJson.account.sortSettings.mixedList = new SortJson
                     *  {
                     *      name = settingsDocument.SortSettings.MixedListing.Name,
                     *      value = settingsDocument.SortSettings.MixedListing.Value,
                     *  };
                     *
                     *  accountDetailsJson.account.sortSettings.fullList = new SortJson
                     *  {
                     *      name = settingsDocument.SortSettings.FullListing.Name,
                     *      value = settingsDocument.SortSettings.FullListing.Value,
                     *  };
                     * }*/

                    #endregion

                    #region Build Contact Settings & Info

                    if (settingsDocument.ContactSettings != null)
                    {
                        accountDetailsJson.account.contactSettings.showPhoneNumber = settingsDocument.ContactSettings.ShowPhoneNumber;
                        accountDetailsJson.account.contactSettings.showAddress     = settingsDocument.ContactSettings.ShowAddress;
                        accountDetailsJson.account.contactSettings.showEmail       = settingsDocument.ContactSettings.ShowEmail;

                        if (settingsDocument.ContactSettings.ContactInfo != null)
                        {
                            accountDetailsJson.account.contactSettings.contactDetails.phoneNumber = settingsDocument.ContactSettings.ContactInfo.PhoneNumber;
                            accountDetailsJson.account.contactSettings.contactDetails.email       = settingsDocument.ContactSettings.ContactInfo.Email;

                            accountDetailsJson.account.contactSettings.contactDetails.address1 = settingsDocument.ContactSettings.ContactInfo.Address1;
                            accountDetailsJson.account.contactSettings.contactDetails.address2 = settingsDocument.ContactSettings.ContactInfo.Address2;
                            accountDetailsJson.account.contactSettings.contactDetails.city     = settingsDocument.ContactSettings.ContactInfo.City;

                            accountDetailsJson.account.contactSettings.contactDetails.state      = settingsDocument.ContactSettings.ContactInfo.State;
                            accountDetailsJson.account.contactSettings.contactDetails.postalCode = settingsDocument.ContactSettings.ContactInfo.PostalCode;
                        }
                    }

                    #endregion

                    //Get Images:
                    accountDetailsJson.account.images = Dynamics.Images.BuildDynamicImagesListForJson(accountNameKey, "account", account.AccountID.ToString(), false);

                    #endregion

                    #region Cache into redisAPI layer

                    try
                    {
                        cache.HashSet(hashApiKey, hashApiField, JsonConvert.SerializeObject(accountDetailsJson), When.Always, CommandFlags.FireAndForget);
                    }
                    catch
                    {
                    }

                    #endregion
                }

                #region Cache locally

                HttpRuntime.Cache.Insert(localCacheKey, accountDetailsJson, null, DateTime.Now.AddMinutes(Common.AccountSettingsCacheTimeInMinutes), TimeSpan.Zero);

                #endregion
            }



            //Add execution data
            stopWatch.Stop();
            accountDetailsJson.executionType = executionType.ToString();
            accountDetailsJson.executionTime = stopWatch.Elapsed.TotalMilliseconds + "ms";

            JsonNetResult jsonNetResult = new JsonNetResult();
            jsonNetResult.Formatting = Newtonsoft.Json.Formatting.Indented;
            jsonNetResult.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local; //<-- Convert UTC times to LocalTime
            jsonNetResult.Data = accountDetailsJson;

            return(jsonNetResult);
        }