/// <summary>
        /// The non-boilerplated test code of the APIs for managing the lifecycle of a given database's data masking policy. It is meant to be called with a name of an already exisiting database (and therefore already existing 
        /// server and resource group). This test does not create these resources and does not remove them.
        /// </summary>
        private void TestDataMaskingPolicyAPIs(SqlManagementClient sqlClient, string resourceGroupName, Server server, Database database)
        {
            DataMaskingPolicyGetResponse getDefaultPolicyResponse = sqlClient.DataMasking.GetPolicy(resourceGroupName, server.Name, database.Name);
            DataMaskingPolicyProperties properties = getDefaultPolicyResponse.DataMaskingPolicy.Properties;
            
            // Verify that the initial Get request contains the default policy.
            TestUtilities.ValidateOperationResponse(getDefaultPolicyResponse, HttpStatusCode.OK);
            VerifyDataMaskingPolicyInformation(MakeDefaultDataMaskingPolicyProperties(), properties);

            // Modify the policy properties, send and receive, see it its still ok
            properties.DataMaskingState = "Enabled";
            properties.ExemptPrincipals = "principal1;principal2";
            DataMaskingPolicyCreateOrUpdateParameters updateParams = new DataMaskingPolicyCreateOrUpdateParameters(); 
            updateParams.Properties = properties;

            var updateResponse = sqlClient.DataMasking.CreateOrUpdatePolicy(resourceGroupName, server.Name, database.Name, updateParams);

            // Verify that the initial Get request of contains the default policy.
            TestUtilities.ValidateOperationResponse(updateResponse, HttpStatusCode.OK);

            DataMaskingPolicyGetResponse getUpdatedPolicyResponse = sqlClient.DataMasking.GetPolicy(resourceGroupName, server.Name, database.Name);
            DataMaskingPolicyProperties updatedProperties = getUpdatedPolicyResponse.DataMaskingPolicy.Properties;

            // Verify that the Get request contains the updated policy.
            TestUtilities.ValidateOperationResponse(getUpdatedPolicyResponse, HttpStatusCode.OK);
            VerifyDataMaskingPolicyInformation(properties, updatedProperties);
        }
 /// <summary>
 /// Creates or updates an Azure SQL Database data masking policy
 /// </summary>
 /// <param name='operations'>
 /// Reference to the
 /// Microsoft.Azure.Management.Sql.IDataMaskingOperations.
 /// </param>
 /// <param name='resourceGroupName'>
 /// Required. The name of the Resource Group to which the server
 /// belongs.
 /// </param>
 /// <param name='serverName'>
 /// Required. The name of the Azure SQL Database Server on which the
 /// database is hosted.
 /// </param>
 /// <param name='databaseName'>
 /// Required. The name of the Azure SQL Database for which the data
 /// masking rule applies.
 /// </param>
 /// <param name='parameters'>
 /// Required. The required parameters for createing or updating a
 /// firewall rule.
 /// </param>
 /// <returns>
 /// A standard service response including an HTTP status code and
 /// request ID.
 /// </returns>
 public static AzureOperationResponse CreateOrUpdatePolicy(this IDataMaskingOperations operations, string resourceGroupName, string serverName, string databaseName, DataMaskingPolicyCreateOrUpdateParameters parameters)
 {
     return Task.Factory.StartNew((object s) => 
     {
         return ((IDataMaskingOperations)s).CreateOrUpdatePolicyAsync(resourceGroupName, serverName, databaseName, parameters);
     }
     , operations, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap().GetAwaiter().GetResult();
 }
 /// <summary>
 /// Set (or create) the data masking policy for a specific database
 /// </summary>
 public void SetDatabaseDataMaskingPolicy(string resourceGroupName, string serverName, string databaseName, string clientRequestId, DataMaskingPolicyCreateOrUpdateParameters parameters)
 {
     IDataMaskingOperations operations = GetCurrentSqlClient(clientRequestId).DataMasking;
     operations.CreateOrUpdatePolicy(resourceGroupName, serverName, databaseName, parameters);
 }
 /// <summary>
 /// Takes the cmdlets model object and transform it to the policy as expected by the endpoint
 /// </summary>
 /// <param name="model">The data masking Policy model object</param>
 /// <returns>The communication model object</returns>
 private DataMaskingPolicyCreateOrUpdateParameters PolicizeDatabaseDataMaskingModel(DatabaseDataMaskingPolicyModel model)
 {
     DataMaskingPolicyCreateOrUpdateParameters updateParameters = new DataMaskingPolicyCreateOrUpdateParameters();
     DataMaskingPolicyProperties properties = new DataMaskingPolicyProperties();
     updateParameters.Properties = properties;
     properties.DataMaskingState = (model.DataMaskingState == DataMaskingStateType.Disabled) ? SecurityConstants.DataMaskingEndpoint.Disabled : SecurityConstants.DataMaskingEndpoint.Enabled;
     properties.ExemptPrincipals = model.PrivilegedUsers ?? "";
     return updateParameters;
 }
        /// <summary>
        /// The non-boilerplated test code of the APIs for managing the lifecycle data masking rules. 
        /// It is meant to be called with a name of an already exisiting database (and therefore already existing server and resource group). 
        /// This test does not create these resources and does not remove them.
        /// The flow is:
        /// 1) Create policy (it's a prereq)
        /// 2) Create rule1, validate its creation and its content by doing another GET call
        /// 3) Update rule1, validate the update by doing another GET call
        /// 4) Create rule2, validate its creation and its content
        /// 5) Get the list of rules, see that there are two and each one of them has the right content
        /// 6) Delete rule1, see that we get OK
        /// 8) List the rules, see that we now have one rule there and it is rule 2
        /// </summary>
        /// <param name="sqlClient">The sqlClient</param>
        /// <param name="resourceGroupName">The resource group name to use in this test</param>
        /// <param name="server">The server to use in this test</param>
        /// <param name="database">The database to use in this test</param>
        private void TestDataMaskingRuleAPIs(SqlManagementClient sqlClient, string resourceGroupName, Server server, Database database)
        {
            DataMaskingPolicyCreateOrUpdateParameters policyParams = new DataMaskingPolicyCreateOrUpdateParameters();
            policyParams.Properties = MakeDefaultDataMaskingPolicyProperties();
            policyParams.Properties.DataMaskingState = "Enabled";
            sqlClient.DataMasking.CreateOrUpdatePolicy(resourceGroupName, server.Name, database.Name, policyParams);
 
            int ruleCounter = 1;
            DataMaskingRuleCreateOrUpdateParameters ruleParams = new DataMaskingRuleCreateOrUpdateParameters();
            string serverName = server.Properties.FullyQualifiedDomainName;
            string uid = server.Properties.AdministratorLogin;
            string pwd = server.Properties.AdministratorLoginPassword;
            string dbName = database.Name;
            string connString = string.Format("Server={0};uid={1}; pwd={2};Database={3};Integrated Security=False;", serverName, uid, pwd, dbName);
            var conn = new SqlConnection();
            conn.ConnectionString = connString;
            string tableName = "table1", columnName = "column1";
            string firewallRuleName = TestUtilities.GenerateName("all");
            string startIp1 = "1.1.1.1";
            string endIp1 = "255.255.255.255";

            sqlClient.FirewallRules.CreateOrUpdate(resourceGroupName, serverName.Split('.').ElementAt(0), firewallRuleName, new FirewallRuleCreateOrUpdateParameters()
            {
                Properties = new FirewallRuleCreateOrUpdateProperties()
                {
                    StartIpAddress = startIp1,
                    EndIpAddress = endIp1,
                }
            });
            CreateDatabaseContents(conn, tableName, columnName);
            ruleParams.Properties = MakeRuleProperties(ruleCounter++ ,tableName, columnName);
            string rule1Name = ruleParams.Properties.Id;
            var createRuleResponse = sqlClient.DataMasking.CreateOrUpdateRule(resourceGroupName, server.Name, database.Name, rule1Name, ruleParams);

            // Verify that the initial create request went well.
            TestUtilities.ValidateOperationResponse(createRuleResponse, HttpStatusCode.OK);
            
            var getAfterCreateResponse = sqlClient.DataMasking.GetRule(resourceGroupName, server.Name, database.Name, rule1Name);

            TestUtilities.ValidateOperationResponse(getAfterCreateResponse, HttpStatusCode.OK);
            VerifyDataMaskingRuleInformation(getAfterCreateResponse.DataMaskingRule.Properties, ruleParams.Properties);

            // Modify the policy properties, send and receive, see it its still ok
            string updatedTableName = "tbl2";
            CreateDatabaseContents(conn, updatedTableName, columnName);
            ruleParams.Properties.TableName = updatedTableName;

            var updateResponse = sqlClient.DataMasking.CreateOrUpdateRule(resourceGroupName, server.Name, database.Name, rule1Name, ruleParams);

            TestUtilities.ValidateOperationResponse(updateResponse, HttpStatusCode.OK);

            var getAfterUpdateResponse = sqlClient.DataMasking.GetRule(resourceGroupName, server.Name, database.Name, rule1Name);

            TestUtilities.ValidateOperationResponse(getAfterUpdateResponse, HttpStatusCode.OK);
            VerifyDataMaskingRuleInformation(getAfterUpdateResponse.DataMaskingRule.Properties, ruleParams.Properties);

            DataMaskingRuleCreateOrUpdateParameters ruleParams2 = new DataMaskingRuleCreateOrUpdateParameters();
            tableName = "table2";
            columnName = "column2";
            CreateDatabaseContents(conn, tableName, columnName);
            ruleParams2.Properties = MakeRuleProperties(ruleCounter++, tableName, columnName);
            string rule2Name = ruleParams2.Properties.Id;

            createRuleResponse = sqlClient.DataMasking.CreateOrUpdateRule(resourceGroupName, server.Name, database.Name, rule2Name, ruleParams2);
            TestUtilities.ValidateOperationResponse(updateResponse, HttpStatusCode.OK);

            DataMaskingRuleListResponse listResponse = sqlClient.DataMasking.List(resourceGroupName, server.Name, database.Name);
            TestUtilities.ValidateOperationResponse(listResponse, HttpStatusCode.OK);

            Assert.Equal(2, listResponse.DataMaskingRules.Count);

            VerifyDataMaskingRuleInformation(listResponse.DataMaskingRules.FirstOrDefault(r => r.Properties.Id == rule1Name).Properties, ruleParams.Properties);
            VerifyDataMaskingRuleInformation(listResponse.DataMaskingRules.FirstOrDefault(r => r.Properties.Id == rule2Name).Properties, ruleParams2.Properties);

            AzureOperationResponse deleteResponse = sqlClient.DataMasking.Delete(resourceGroupName, server.Name, database.Name, rule1Name);
            TestUtilities.ValidateOperationResponse(deleteResponse, HttpStatusCode.OK);

            DataMaskingRuleListResponse listAfterDeleteResponse = sqlClient.DataMasking.List(resourceGroupName, server.Name, database.Name);
            TestUtilities.ValidateOperationResponse(listAfterDeleteResponse, HttpStatusCode.OK);

            Assert.Equal(listAfterDeleteResponse.DataMaskingRules.Count, 1);
            VerifyDataMaskingRuleInformation(listResponse.DataMaskingRules.FirstOrDefault(r => r.Properties.Id == rule2Name).Properties, ruleParams2.Properties);
        }
        /// <summary>
        /// The non-boilerplated test code of the APIs for managing the lifecycle data masking rules. 
        /// It is meant to be called with a name of an already exisiting database (and therefore already existing server and resource group). 
        /// This test does not create these resources and does not remove them.
        /// The flow is:
        /// 1) Create policy (it's a prereq)
        /// 2) Create rule1, validate its creation and its content by doing another GET call
        /// 3) Update rule1, validate the update by doing another GET call
        /// 4) Create rule2, validate its creation and its content
        /// 5) Get the list of rules, see that there are two and each one of them has the right content
        /// 6) Delete rule1, see that we get OK
        /// 8) List the rules, see that we now have one rule there and it is rule 2
        /// </summary>
        /// <param name="sqlClient">The sqlClient</param>
        /// <param name="resourceGroupName">The resource group name to use in this test</param>
        /// <param name="server">The server to use in this test</param>
        /// <param name="database">The database to use in this test</param>
        private void TestDataMaskingRuleAPIs(SqlManagementClient sqlClient, string resourceGroupName, Server server, Database database)
        {
            DataMaskingPolicyCreateOrUpdateParameters policyParams = new DataMaskingPolicyCreateOrUpdateParameters();
            policyParams.Properties = MakeDefaultDataMaskingPolicyProperties();
            policyParams.Properties.DataMaskingState = "Enabled";
            sqlClient.DataMasking.CreateOrUpdatePolicy(resourceGroupName, server.Name, database.Name, policyParams);
 
            int ruleCounter = 1;
            DataMaskingRuleCreateOrUpdateParameters ruleParams = new DataMaskingRuleCreateOrUpdateParameters();
            string serverName = server.Properties.FullyQualifiedDomainName;
            string uid = server.Properties.AdministratorLogin;
            string pwd = server.Properties.AdministratorLoginPassword;
            string dbName = database.Name;
            string connString = string.Format("Server={0};uid={1}; pwd={2};Database={3};Integrated Security=False;", serverName, uid, pwd, dbName);
            var conn = new SqlConnection();
            conn.ConnectionString = connString;
            string tableName = "table1", columnName = "column1";
            string firewallRuleName = TestUtilities.GenerateName("all");
            string startIp1 = "1.1.1.1";
            string endIp1 = "255.255.255.255";

            sqlClient.FirewallRules.CreateOrUpdate(resourceGroupName, serverName.Split('.').ElementAt(0), firewallRuleName, new FirewallRuleCreateOrUpdateParameters()
            {
                Properties = new FirewallRuleCreateOrUpdateProperties()
                {
                    StartIpAddress = startIp1,
                    EndIpAddress = endIp1,
                }
            });
            CreateDatabaseContents(conn, tableName, columnName);

            Func<DataMaskingRuleCreateOrUpdateParameters, Func<DataMaskingRule, bool>> isRuleOnColumn = (DataMaskingRuleCreateOrUpdateParameters parms) =>
            {
                return (DataMaskingRule r1) =>
                {
                    return parms.Properties.ColumnName == r1.Properties.ColumnName &&
                   parms.Properties.TableName == r1.Properties.TableName &&
                   parms.Properties.SchemaName == r1.Properties.SchemaName;
                };
            };

            ruleParams.Properties = MakeRuleProperties(ruleCounter++ ,tableName, columnName);
            string rule1Name = ruleParams.Properties.Id;
           
            var createRuleResponse = sqlClient.DataMasking.CreateOrUpdateRule(resourceGroupName, server.Name, database.Name, rule1Name, ruleParams);            
            TestUtilities.ValidateOperationResponse(createRuleResponse, HttpStatusCode.OK);

            var listAfterCreateResponse = sqlClient.DataMasking.List(resourceGroupName, server.Name, database.Name);
            TestUtilities.ValidateOperationResponse(listAfterCreateResponse, HttpStatusCode.OK);
            Assert.Equal(1, listAfterCreateResponse.DataMaskingRules.Count);

            DataMaskingRule receivedRule = listAfterCreateResponse.DataMaskingRules.FirstOrDefault(isRuleOnColumn(ruleParams));
            VerifyDataMaskingRuleInformation(receivedRule.Properties, ruleParams.Properties);


            // Modify the policy properties, send and receive, see it its still ok

            ruleParams.Properties.PrefixSize = "2";
            ruleParams.Properties.ReplacementString = "ABC";
            ruleParams.Properties.SuffixSize = "1";

            var updateRuleResponse = sqlClient.DataMasking.CreateOrUpdateRule(resourceGroupName, server.Name, database.Name, rule1Name, ruleParams);
            TestUtilities.ValidateOperationResponse(updateRuleResponse, HttpStatusCode.OK);

            var listUpdateResponse = sqlClient.DataMasking.List(resourceGroupName, server.Name, database.Name);
            TestUtilities.ValidateOperationResponse(listUpdateResponse, HttpStatusCode.OK);
            Assert.Equal(1, listUpdateResponse.DataMaskingRules.Count);

            var updatedRule = listUpdateResponse.DataMaskingRules.FirstOrDefault(isRuleOnColumn(ruleParams));
            VerifyDataMaskingRuleInformation(updatedRule.Properties, ruleParams.Properties);

            DataMaskingRuleCreateOrUpdateParameters ruleParams2 = new DataMaskingRuleCreateOrUpdateParameters();
            tableName = "table2";
            columnName = "column2";
            CreateDatabaseContents(conn, tableName, columnName);

            ruleParams2.Properties = MakeRuleProperties(ruleCounter++, tableName, columnName);
            string rule2Name = ruleParams2.Properties.Id;

            var createSecondRuleResponse = sqlClient.DataMasking.CreateOrUpdateRule(resourceGroupName, server.Name, database.Name, rule2Name, ruleParams2);
            TestUtilities.ValidateOperationResponse(createSecondRuleResponse, HttpStatusCode.OK);

            DataMaskingRuleListResponse listAfterSecondCreateResponse = sqlClient.DataMasking.List(resourceGroupName, server.Name, database.Name);
            TestUtilities.ValidateOperationResponse(listAfterSecondCreateResponse, HttpStatusCode.OK);

            Assert.Equal(2, listAfterSecondCreateResponse.DataMaskingRules.Count);


            updatedRule = listUpdateResponse.DataMaskingRules.FirstOrDefault(isRuleOnColumn(ruleParams));
            VerifyDataMaskingRuleInformation(updatedRule.Properties, ruleParams.Properties);

            var receivedSecondRule = listAfterSecondCreateResponse.DataMaskingRules.FirstOrDefault(isRuleOnColumn(ruleParams2));
            VerifyDataMaskingRuleInformation(receivedSecondRule.Properties, ruleParams2.Properties);

            AzureOperationResponse deleteResponse = sqlClient.DataMasking.Delete(resourceGroupName, server.Name, database.Name, rule1Name);
            TestUtilities.ValidateOperationResponse(deleteResponse, HttpStatusCode.OK);

            DataMaskingRuleListResponse listAfterDeleteResponse = sqlClient.DataMasking.List(resourceGroupName, server.Name, database.Name);
            TestUtilities.ValidateOperationResponse(listAfterDeleteResponse, HttpStatusCode.OK);

            Assert.Equal(listAfterDeleteResponse.DataMaskingRules.Count, 1);
            var receivedAfterDelete = listAfterSecondCreateResponse.DataMaskingRules.FirstOrDefault(isRuleOnColumn(ruleParams2));
            VerifyDataMaskingRuleInformation(receivedAfterDelete.Properties, ruleParams2.Properties);
        }
        /// <summary>
        /// The non-boilerplated test code of the APIs for managing the lifecycle data masking rules. 
        /// It is meant to be called with a name of an already exisiting database (and therefore already existing server and resource group). 
        /// This test does not create these resources and does not remove them.
        /// The flow is:
        /// 1) Create policy (it's a prereq)
        /// 2) Create rule1, validate its creation and its content by doing another GET call
        /// 3) Update rule1, validate the update by doing another GET call
        /// 4) Create rule2, validate its creation and its content
        /// 5) Get the list of rules, see that there are two and each one of them has the right content
        /// 6) Delete rule1, see that we get OK
        /// 8) List the rules, see that we now have one rule there and it is rule 2
        /// </summary>
        /// <param name="sqlClient">The sqlClient</param>
        /// <param name="resourceGroupName">The resource group name to use in this test</param>
        /// <param name="server">The server to use in this test</param>
        /// <param name="database">The database to use in this test</param>
        private void TestDataMaskingRuleAPIs(SqlManagementClient sqlClient, string resourceGroupName, Server server, Database database)
        {
            DataMaskingPolicyCreateOrUpdateParameters policyParams = new DataMaskingPolicyCreateOrUpdateParameters();
            policyParams.Properties = MakeDefaultDataMaskingPolicyProperties();
            policyParams.Properties.MaskingLevel = "Relaxed";
            sqlClient.DataMasking.CreateOrUpdatePolicy(resourceGroupName, server.Name, database.Name, policyParams);
 
            int ruleCounter = 1;
            DataMaskingRuleCreateOrUpdateParameters ruleParams = new DataMaskingRuleCreateOrUpdateParameters();
            ruleParams.Properties = MakeRuleProperties(ruleCounter++);
            string rule1Name = ruleParams.Properties.Id;
            var createRuleResponse = sqlClient.DataMasking.CreateOrUpdateRule(resourceGroupName, server.Name, database.Name, rule1Name, ruleParams);

            // Verify that the initial create request went well.
            TestUtilities.ValidateOperationResponse(createRuleResponse, HttpStatusCode.OK);
            
            var getAfterCreateResponse = sqlClient.DataMasking.GetRule(resourceGroupName, server.Name, database.Name, rule1Name);

            TestUtilities.ValidateOperationResponse(getAfterCreateResponse, HttpStatusCode.OK);
            VerifyDataMaskingRuleInformation(getAfterCreateResponse.DataMaskingRule.Properties, ruleParams.Properties);

            // Modify the policy properties, send and receive, see it its still ok
            ruleParams.Properties.TableName = "tbl2";

            var updateResponse = sqlClient.DataMasking.CreateOrUpdateRule(resourceGroupName, server.Name, database.Name, rule1Name, ruleParams);

            TestUtilities.ValidateOperationResponse(updateResponse, HttpStatusCode.OK);

            var getAfterUpdateResponse = sqlClient.DataMasking.GetRule(resourceGroupName, server.Name, database.Name, rule1Name);

            TestUtilities.ValidateOperationResponse(getAfterUpdateResponse, HttpStatusCode.OK);
            VerifyDataMaskingRuleInformation(getAfterUpdateResponse.DataMaskingRule.Properties, ruleParams.Properties);

            DataMaskingRuleCreateOrUpdateParameters ruleParams2 = new DataMaskingRuleCreateOrUpdateParameters();
            ruleParams2.Properties = MakeRuleProperties(ruleCounter++);
            string rule2Name = ruleParams2.Properties.Id;

            createRuleResponse = sqlClient.DataMasking.CreateOrUpdateRule(resourceGroupName, server.Name, database.Name, rule2Name, ruleParams2);
            TestUtilities.ValidateOperationResponse(updateResponse, HttpStatusCode.OK);

            DataMaskingRuleListResponse listResponse = sqlClient.DataMasking.List(resourceGroupName, server.Name, database.Name);
            TestUtilities.ValidateOperationResponse(listResponse, HttpStatusCode.OK);

            Assert.Equal(2, listResponse.DataMaskingRules.Count);

            VerifyDataMaskingRuleInformation(listResponse.DataMaskingRules.FirstOrDefault(r => r.Name == rule1Name).Properties, ruleParams.Properties);
            VerifyDataMaskingRuleInformation(listResponse.DataMaskingRules.FirstOrDefault(r => r.Name == rule2Name).Properties, ruleParams2.Properties);

            AzureOperationResponse deleteResponse = sqlClient.DataMasking.Delete(resourceGroupName, server.Name, database.Name, rule1Name);
            TestUtilities.ValidateOperationResponse(deleteResponse, HttpStatusCode.OK);

            DataMaskingRuleListResponse listAfterDeleteResponse = sqlClient.DataMasking.List(resourceGroupName, server.Name, database.Name);
            TestUtilities.ValidateOperationResponse(listAfterDeleteResponse, HttpStatusCode.OK);

            Assert.Equal(listAfterDeleteResponse.DataMaskingRules.Count, 1);
            VerifyDataMaskingRuleInformation(listResponse.DataMaskingRules.FirstOrDefault(r => r.Name == rule2Name).Properties, ruleParams2.Properties);
        }
 /// <summary>
 /// Creates or updates an Azure SQL Database data masking policy
 /// </summary>
 /// <param name='operations'>
 /// Reference to the
 /// Microsoft.Azure.Management.Sql.IDataMaskingOperations.
 /// </param>
 /// <param name='resourceGroupName'>
 /// Required. The name of the Resource Group to which the server
 /// belongs.
 /// </param>
 /// <param name='serverName'>
 /// Required. The name of the Azure SQL Database Server on which the
 /// database is hosted.
 /// </param>
 /// <param name='databaseName'>
 /// Required. The name of the Azure SQL Database for which the data
 /// masking rule applies.
 /// </param>
 /// <param name='parameters'>
 /// Required. The required parameters for createing or updating a
 /// firewall rule.
 /// </param>
 /// <returns>
 /// A standard service response including an HTTP status code and
 /// request ID.
 /// </returns>
 public static Task<AzureOperationResponse> CreateOrUpdatePolicyAsync(this IDataMaskingOperations operations, string resourceGroupName, string serverName, string databaseName, DataMaskingPolicyCreateOrUpdateParameters parameters)
 {
     return operations.CreateOrUpdatePolicyAsync(resourceGroupName, serverName, databaseName, parameters, CancellationToken.None);
 }