private void applyToolStripMenuItem_Click()

in src/IdFix/FormApp.cs [334:569]


        private void applyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DialogResult result = MessageBox.Show(StringLiterals.ApplyPendingBody,
                StringLiterals.ApplyPending,
                MessageBoxButtons.YesNo,
                MessageBoxIcon.Question,
                MessageBoxDefaultButton.Button2);

            if (result != DialogResult.Yes || grid.Rows.Count < 1)
            {
                return;
            }

            statusDisplay(StringLiterals.ApplyPending);

            grid.CurrentCell = grid.Rows[0].Cells[StringLiterals.DistinguishedName];

            files.DeleteByType(FileTypes.Apply);

            var connectionManager = new ConnectionManager();
            var connectionCache = new Dictionary<string, LdapConnection>();

            try
            {
                foreach (DataGridViewRow row in this.grid.Rows)
                {
                    if (row.Cells[StringLiterals.Action].Value == null)
                    {
                        continue;
                    }

                    // let's convert the action string into one of our known action types
                    if (!Enum.TryParse(row.GetCellString(StringLiterals.Action), true, out ActionType updateAction))
                    {
                        // fail to no action, safest choice
                        updateAction = ActionType.None;
                    }

                    if (updateAction == ActionType.Complete || updateAction == ActionType.None || updateAction == ActionType.Fail)
                    {
                        // there is nothing to do or we already failed on this row so don't try again
                        continue;
                    }

                    // this is the current value for this entity and attribute at the time the scan was done
                    var currentValue = row.GetCellString(StringLiterals.Value);

                    // this is the value, either proposed by us or edited by the user, that we will use to update the attribute for the given entity
                    var updateValue = row.GetCellString(StringLiterals.Update);

                    // this is the attribute name tied to this value
                    var updateAttribute = row.GetCellString(StringLiterals.Attribute);

                    // calculate the server & port combination we need to conduct the update
                    string distinguishedName = row.GetCellString(StringLiterals.DistinguishedName);
                    string domain = distinguishedName.Substring(distinguishedName.IndexOf("dc=", StringComparison.CurrentCultureIgnoreCase));
                    string modificationDomainName = domain.ToLowerInvariant().Replace(",dc=", ".").Replace("dc=", "");
                    string serverName = modificationDomainName;

                    if (SettingsManager.Instance.CurrentDirectoryType == DirectoryType.ActiveDirectory)
                    {
                        serverName = Domain.GetDomain(new DirectoryContext(DirectoryContextType.Domain, modificationDomainName)).FindDomainController().Name;
                        statusDisplay(String.Format("Using server {0} for updating", serverName));
                    }

                    // logic from original application
                    var updatePort = SettingsManager.Instance.Port == Constants.GlobalCatalogPort ? Constants.LdapPort : SettingsManager.Instance.Port;

                    // this is the full name used to create the connection
                    var fullServerName = string.Format("{0}:{1}", serverName, updatePort);

                    // let's see if we already have one of these connections available, or else we create one
                    LdapConnection connection;
                    if (connectionCache.ContainsKey(fullServerName))
                    {
                        connection = connectionCache[fullServerName];
                    }
                    else
                    {
                        connection = connectionManager.CreateConnection(fullServerName);
                        connectionCache.Add(fullServerName, connection);
                    }

                    var findObject = new SearchRequest();
                    findObject.DistinguishedName = distinguishedName;
                    findObject.Filter = SettingsManager.Instance.Filter;
                    findObject.Scope = System.DirectoryServices.Protocols.SearchScope.Base;
                    var entries = ((SearchResponse)connection.SendRequest(findObject))?.Entries;
                    if (entries == null || entries.Count != 1)
                    {
                        var count = entries != null ? entries.Count : 0;
                        statusDisplay(StringLiterals.Exception + "Found " + count + " entries when searching for " + distinguishedName + ", expected to find 1. Skipping update operation.");
                        continue;
                    }

                    // this are the requests sent to execute the modify operation
                    List<ModifyRequest> modifyRequest = new List<ModifyRequest>();

                    switch (updateAction)
                    {
                        case ActionType.Edit:
                            if (updateAttribute.Equals(StringLiterals.ProxyAddresses, StringComparison.CurrentCultureIgnoreCase))
                            {
                                if (String.IsNullOrEmpty(updateValue))
                                {
                                    updateValue = String.Empty;
                                    modifyRequest.Add(new ModifyRequest(distinguishedName, DirectoryAttributeOperation.Delete, updateAttribute, new string[] { currentValue }));
                                }
                                else
                                {
                                    modifyRequest.Add(new ModifyRequest(distinguishedName, DirectoryAttributeOperation.Delete, updateAttribute, new string[] { currentValue }));
                                    modifyRequest.Add(new ModifyRequest(distinguishedName, DirectoryAttributeOperation.Add, updateAttribute, new string[] { updateValue }));
                                }
                            }
                            else
                            {
                                if (String.IsNullOrEmpty(updateValue))
                                {
                                    modifyRequest.Add(new ModifyRequest(distinguishedName, DirectoryAttributeOperation.Delete, updateAttribute, null));
                                }
                                else
                                {
                                    modifyRequest.Add(new ModifyRequest(distinguishedName, DirectoryAttributeOperation.Replace, updateAttribute, updateValue));
                                }
                            }
                            break;
                        case ActionType.Remove:
                            row.Cells[StringLiterals.Update].Value = String.Empty;
                            if (updateAttribute.Equals(StringLiterals.ProxyAddresses, StringComparison.CurrentCultureIgnoreCase))
                            {
                                modifyRequest.Add(new ModifyRequest(distinguishedName, DirectoryAttributeOperation.Delete, updateAttribute, new string[] { currentValue }));
                            }
                            else
                            {
                                modifyRequest.Add(new ModifyRequest(distinguishedName, DirectoryAttributeOperation.Delete, updateAttribute, null));
                            }
                            break;
                        case ActionType.Undo:
                            if (updateAttribute.Equals(StringLiterals.ProxyAddresses, StringComparison.CurrentCultureIgnoreCase))
                            {
                                if (!String.IsNullOrEmpty(row.GetCellString(StringLiterals.Update)))
                                {
                                    modifyRequest.Add(new ModifyRequest(distinguishedName, DirectoryAttributeOperation.Delete, updateAttribute, new string[] { updateValue }));
                                }
                                modifyRequest.Add(new ModifyRequest(distinguishedName, DirectoryAttributeOperation.Add, updateAttribute, new string[] { currentValue }));
                            }
                            else
                            {
                                if (String.IsNullOrEmpty(currentValue))
                                {
                                    modifyRequest.Add(new ModifyRequest(distinguishedName, DirectoryAttributeOperation.Delete, updateAttribute, null));
                                }
                                else
                                {
                                    modifyRequest.Add(new ModifyRequest(distinguishedName, DirectoryAttributeOperation.Replace, updateAttribute, currentValue));
                                }
                            }
                            break;
                    }

                    try
                    {
                        // now we execute all of our collected modify requests (1 or 2) here so an error in one allows processing to continue
                        // previous versions would error out the entire update if one of the pre-requests failed
                        foreach (var request in modifyRequest)
                        {
                            connection.SendRequest(request);
                        }
                    }
                    catch (Exception ex)
                    {
                        if (!action.Items.Contains("FAIL"))
                        {
                            action.Items.Add("FAIL");
                        }
                        // mark this row as failed
                        row.Cells[StringLiterals.Action].Value = StringLiterals.Fail;

                        // show a status
                        statusDisplay(string.Format("{0}Update Failed: {1} with error: {2}.", StringLiterals.Exception, distinguishedName, ex.Message));
                    }

                    // we need to write to the apply file
                    if (!row.GetCellString(StringLiterals.Action).Equals(StringLiterals.Fail, StringComparison.CurrentCultureIgnoreCase))
                    {
                        // mark this row as now complete
                        row.Cells[StringLiterals.Action].Value = StringLiterals.Complete;

                        // show a status (which also logs this to the verbose file)
                        statusDisplay(string.Format("Update: [{0}] [{1}] [{2}] [{3}] [{4}] [{5}] [{6}]",
                            distinguishedName,
                            row.GetCellString(StringLiterals.ObjectClass),
                            updateAttribute,
                            row.GetCellString(StringLiterals.Error),
                            currentValue,
                            updateValue,
                            updateAction.ToString()));

                        try
                        {
                            files.AppendTo(FileTypes.Apply, (writer) =>
                            {
                                writer.WriteLine("distinguishedName: " + distinguishedName);
                                writer.WriteLine("objectClass: " + row.GetCellString(StringLiterals.ObjectClass));
                                writer.WriteLine("attribute: " + updateAttribute);
                                writer.WriteLine("error: " + row.GetCellString(StringLiterals.Error));
                                writer.WriteLine("value: " + currentValue);
                                writer.WriteLine("update: " + updateValue);
                                writer.WriteLine("action: " + updateAction.ToString());
                                writer.WriteLine("-");
                                writer.WriteLine();
                            });
                        }
                        catch (Exception err)
                        {
                            statusDisplay(StringLiterals.Exception + StringLiterals.WriteUpdate + "  " + err.Message);
                            throw;
                        }
                    }
                }
            }
            catch (Exception err)
            {
                statusDisplay(string.Format("{0}{1} {2}", StringLiterals.Exception, toolStripStatusLabel1.Text, err.Message));
                throw;
            }
            finally
            {
                foreach (var connPair in connectionCache)
                {
                    connPair.Value.Dispose();
                }
            }

            statusDisplay(StringLiterals.Complete);
        }