public void Create(CreateOpContext context) { ExchangeConnector exconn = (ExchangeConnector)context.Connector; Command cmdNew = ExchangeUtility.GetCommand( new PSExchangeConnector.CommandInfo(GetNewCommandName()), context.Attributes, exconn.Configuration); try { context.Uid = _helper.InvokePipelineAndGetGuid(exconn, cmdNew); } catch (ProxyAddressExistsException e) { // This is a tricky exception. Sometimes when creating an object that is already there (e.g. DistributionGroup), // PowerShell reports "ProxyAddressExists" instead of something like "ObjectExists" :( // So we have to distinguish these situations somehow... Name nameAttribute = ConnectorAttributeUtil.GetNameFromAttributes(context.Attributes); if (nameAttribute == null || nameAttribute.Value == null || nameAttribute.Value.Count() != 1) { LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "ProxyAddressExistsException reported; but no single-valued NAME attribute present -- reporting as is"); throw new ConnectorException(e.Message, e); } String name = (String)nameAttribute.Value[0]; LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "ProxyAddressExistsException reported; trying to see if object named " + name + " exists"); Command cmdGet = ExchangeUtility.GetCommand( new PSExchangeConnector.CommandInfo(GetGetCommandName()), exconn.Configuration); cmdGet.Parameters.Add("Identity", name); ICollection <PSObject> objects; try { objects = _helper.InvokePipeline(exconn, cmdGet); } catch (ObjectNotFoundException e1) { objects = null; } if (objects == null || objects.Count == 0) { LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "...it does not -- reporting as is"); throw new ConnectorException(e.Message, e); } else { LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "...it exists -- reporting as AlreadyExistsException"); throw new AlreadyExistsException(e.Message, e); } } if (ExecuteSetAfterNew()) { Command cmdSet = ExchangeUtility.GetCommand( new PSExchangeConnector.CommandInfo(GetSetCommandName()), context.Attributes, context.Uid, exconn.Configuration); try { _helper.InvokePipeline(exconn, cmdSet); } catch { // TODO rollback // rethrow original exception throw; } } }
protected Uid ExecuteCreate(String scriptName, ObjectClass objectClass, ICollection <ConnectorAttribute> createAttributes, OperationOptions options) { var result = new MsPowerShellUidHandler(); var arguments = new Dictionary <String, Object> { { Result, result } }; if (ConnectorAttributeUtil.GetNameFromAttributes(createAttributes) != null) { arguments.Add(Id, ConnectorAttributeUtil.GetNameFromAttributes(createAttributes).GetNameValue()); } ExecuteScript(GetScript(scriptName), CreateBinding(arguments, OperationType.CREATE, objectClass, null, createAttributes, options)); return(result.Uid.GetUidValue() != null ? result.Uid : null); }
/// <summary> /// This does not work ... for now, don't handle container changes /// </summary> /// <param name="type"></param> /// <param name="directoryEntry"></param> /// <param name="attributes"></param> /// <param name="config"></param> private static void HandleContainerChange(UpdateType type, DirectoryEntry directoryEntry, ICollection <ConnectorAttribute> attributes, ActiveDirectoryConfiguration config) { Name nameAttribute = ConnectorAttributeUtil.GetNameFromAttributes(attributes); if (nameAttribute == null) { // no name, so must not be a container change return; } if (!type.Equals(UpdateType.REPLACE)) { // this only make sense for replace. you can't // add a name or delete a name return; } String oldContainer = GetParentDn(directoryEntry.Path); String newContainer = GetParentDn(nameAttribute.GetNameValue()); if (!NormalizeLdapString(oldContainer).Equals(NormalizeLdapString(newContainer))) { if (newContainer != null) { try { if (!NormalizeLdapString(oldContainer).Equals( NormalizeLdapString(newContainer))) { String newContainerLdapPath = ActiveDirectoryUtils.GetLDAPPath( config.LDAPHostName, newContainer); DirectoryEntry newContainerDe = new DirectoryEntry(newContainerLdapPath, config.DirectoryAdminName, config.DirectoryAdminPassword); directoryEntry.MoveTo(newContainerDe); } } catch (Exception e) { throw e; } } } }
public virtual Uid Create(ObjectClass objectClass, ICollection <ConnectorAttribute> createAttributes, OperationOptions options) { if (ObjectClass.ACCOUNT.Equals(objectClass) || ObjectClass.GROUP.Equals(objectClass)) { Name name = ConnectorAttributeUtil.GetNameFromAttributes(createAttributes); if (name != null) { // do real create here return(new Uid(ConnectorAttributeUtil.GetStringValue(name).ToLower())); } throw new InvalidAttributeValueException("Name attribute is required"); } Trace.TraceWarning("Delete of type {0} is not supported", _configuration.ConnectorMessages.Format(objectClass.GetDisplayNameKey(), objectClass.GetObjectClassValue())); throw new NotSupportedException("Delete of type" + objectClass.GetObjectClassValue() + " is not supported"); }
private static void HandleNameChange(UpdateType type, DirectoryEntry directoryEntry, ICollection <ConnectorAttribute> attributes) { Name nameAttribute = ConnectorAttributeUtil.GetNameFromAttributes(attributes); if (nameAttribute != null) { // this only make sense for replace. you can't // add a name or delete a name if (type.Equals(UpdateType.REPLACE)) { String oldName = directoryEntry.Name; String newName = GetRelativeName(nameAttribute); if (!NormalizeLdapString(oldName).Equals(NormalizeLdapString(newName))) { directoryEntry.Rename(newName); } } } }
/// <summary> /// </summary> /// <param name="type"></param> /// <param name="directoryEntry"></param> /// <param name="attributes"></param> /// <param name="config"></param> private static void HandleNameAndContainerChange(UpdateType type, DirectoryEntry directoryEntry, ICollection <ConnectorAttribute> attributes, ActiveDirectoryConfiguration config) { Name nameAttribute = ConnectorAttributeUtil.GetNameFromAttributes(attributes); if (nameAttribute == null) { // no name, so must not be a container change return; } if (!type.Equals(UpdateType.REPLACE)) { // this only make sense for replace. you can't // add a name or delete a name return; } String oldName = directoryEntry.Name; String newName = GetRelativeName(nameAttribute); bool nameChanged = !NormalizeLdapString(oldName).Equals(NormalizeLdapString(newName), StringComparison.OrdinalIgnoreCase); String oldContainer = GetParentDn(directoryEntry.Path); String newContainer = GetParentDn(nameAttribute.GetNameValue()); bool containerChanged = !NormalizeLdapString(oldContainer).Equals(NormalizeLdapString(newContainer), StringComparison.OrdinalIgnoreCase); if (!nameChanged && !containerChanged) { return; } if (nameChanged && !containerChanged) // rename without moving { LOGGER.TraceEvent(TraceEventType.Verbose, CAT_DEFAULT, "Renaming {0} to {1}", oldName, newName); directoryEntry.Rename(newName); LOGGER.TraceEvent(TraceEventType.Verbose, CAT_DEFAULT, "Rename OK"); return; } // so this is move with or without rename // step 1: if WITH rename, we have to rename the entry to a temporary name first String temporaryName = null; if (nameChanged) { temporaryName = oldName + "-" + RandomStr(); LOGGER.TraceEvent(TraceEventType.Verbose, CAT_DEFAULT, "Renaming {0} to a temporary name of {1}", oldName, temporaryName); directoryEntry.Rename(temporaryName); LOGGER.TraceEvent(TraceEventType.Verbose, CAT_DEFAULT, "Rename OK"); } // step 2: do the move try { String newContainerLdapPath = ActiveDirectoryUtils.GetLDAPPath(config.LDAPHostName, newContainer); DirectoryEntry newContainerDe = new DirectoryEntry(newContainerLdapPath, config.DirectoryAdminName, config.DirectoryAdminPassword); LOGGER.TraceEvent(TraceEventType.Verbose, CAT_DEFAULT, "Moving from {0} to {1} ({2})", oldContainer, newContainer, newContainerLdapPath); directoryEntry.MoveTo(newContainerDe); LOGGER.TraceEvent(TraceEventType.Verbose, CAT_DEFAULT, "Move OK"); newContainerDe.Dispose(); } catch (Exception e) { LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "Exception caught when moving: {0}", e); if (nameChanged) { LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "Renaming back from temporary name of {0} to {1}", temporaryName, oldName); directoryEntry.Rename(oldName); LOGGER.TraceEvent(TraceEventType.Verbose, CAT_DEFAULT, "Rename OK"); } throw e; } // step 3: if WITH rename, then rename from temporary name to the new name if (nameChanged) { LOGGER.TraceEvent(TraceEventType.Verbose, CAT_DEFAULT, "Renaming from temporary name of {0} to a new name of {1}", temporaryName, newName); directoryEntry.Rename(newName); LOGGER.TraceEvent(TraceEventType.Verbose, CAT_DEFAULT, "Rename OK"); } }
/// <summary> /// Creates command based on the commanf info, reading the calues from attributes /// </summary> /// <param name="cmdInfo">Command defition</param> /// <param name="attributes">Attribute values - UID in these is ignored! It should be passed as a separate parameter</param> /// <param name="config">Configuration object</param> /// <returns> /// Ready to execute Command /// </returns> /// <exception cref="ArgumentNullException">if some of the param is null</exception> internal static Command GetCommand(PSExchangeConnector.CommandInfo cmdInfo, ICollection <ConnectorAttribute> attributes, Uid uidAttribute, Name nameAttribute, ExchangeConfiguration config) { Assertions.NullCheck(cmdInfo, "cmdInfo"); LOG.Trace("GetCommand: cmdInfo name = {0}", cmdInfo.Name); ISet <string> parametersSet = new HashSet <string>(); // create command Command cmd = new Command(cmdInfo.Name); if (!string.IsNullOrEmpty(cmdInfo.UidParameter) && !parametersSet.Contains(cmdInfo.UidParameter)) { Uid uidAttr = uidAttribute != null ? uidAttribute : ConnectorAttributeUtil.GetUidAttribute(attributes); string uid = uidAttr != null?uidAttr.GetUidValue() : null; if (uid != null) { cmd.Parameters.Add(cmdInfo.UidParameter, ActiveDirectoryUtils.ConvertADGUIDtoObjectGUID(uid)); parametersSet.Add(cmdInfo.UidParameter); } } // map name attribute, if mapping specified if (!string.IsNullOrEmpty(cmdInfo.NameParameter) && !parametersSet.Contains(cmdInfo.NameParameter)) { Name nameAttr = nameAttribute != null ? nameAttribute : ConnectorAttributeUtil.GetNameFromAttributes(attributes); string name = nameAttr != null?nameAttr.GetNameValue() : null;; if (name != null) { cmd.Parameters.Add(cmdInfo.NameParameter, name); parametersSet.Add(cmdInfo.NameParameter); } } if (cmdInfo.UsesConfirm) { cmd.Parameters.Add("confirm", false); parametersSet.Add("confirm"); } if (cmdInfo.UsesDomainController) { cmd.Parameters.Add("DomainController", ActiveDirectoryUtils.GetDomainControllerName(config)); parametersSet.Add("DomainController"); } // TODO check this only for user-related operations bool emailAddressesPresent = GetAttValues(ExchangeConnectorAttributes.AttEmailAddresses, attributes) != null; bool primarySmtpAddressPresent = GetAttValues(ExchangeConnectorAttributes.AttPrimarySmtpAddress, attributes) != null; if (emailAddressesPresent && primarySmtpAddressPresent) { throw new ArgumentException(ExchangeConnectorAttributes.AttEmailAddresses + " and " + ExchangeConnectorAttributes.AttPrimarySmtpAddress + " cannot be both set."); } if (attributes != null) { foreach (string attName in cmdInfo.Parameters) { object valueToSet = null; ConnectorAttribute attribute = ConnectorAttributeUtil.Find(attName, attributes); if (attribute != null) { if (attribute.Value != null && attribute.Value.Count > 1) { List <string> stringValues = new List <string>(); foreach (object val in attribute.Value) { stringValues.Add(val.ToString()); } valueToSet = stringValues.ToArray(); } else { valueToSet = ConnectorAttributeUtil.GetSingleValue(attribute); } if (parametersSet.Contains(attName)) { throw new InvalidOperationException("Parameter " + attName + " is already defined for command " + cmdInfo.Name); } cmd.Parameters.Add(attName, valueToSet); parametersSet.Add(attName); } } } LOG.Trace("GetCommand exit: cmdInfo name = {0}", cmdInfo.Name); return(cmd); }