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);
}