Esempio n. 1
0
        internal ConnectorObject GetCurrentObject(UpdateOpContext context, string query)
        {
            ConnectorObject currentObject = null;

            LOG.Trace("Fetching object using query {0}", query);

            ResultsHandler handler = new ResultsHandler()
            {
                Handle = cobject =>
                {
                    //LOGGER.TraceEvent(TraceEventType.Verbose, CAT_DEFAULT, "Object-to-be-modified: {0}", CommonUtils.DumpConnectorAttributes(cobject.GetAttributes()));
                    if (currentObject != null)
                    {
                        throw new InvalidOperationException("More than one object complying with " + query + " was found");
                    }
                    currentObject = cobject;
                    return(true);
                }
            };

            ((ExchangeConnector)context.Connector).ExecuteQuery(context.ObjectClass, query, handler, null);
            if (currentObject == null)
            {
                throw new ObjectNotFoundException("Object with UID " + context.Uid.GetUidValue() + " was not found");
            }

            return(currentObject);
        }
Esempio n. 2
0
        public void Update(UpdateOpContext context)
        {
            ExchangeConnector        exconn = (ExchangeConnector)context.Connector;
            ActiveDirectoryConnector adconn = exconn.ActiveDirectoryConnector;

            adconn.Update(context.UpdateType, context.ObjectClass, context.Uid, context.Attributes, context.Options);
        }
        public void UpdateMain(UpdateOpContext context)
        {
            Stopwatch stopWatch = new Stopwatch();

            stopWatch.Start();

            GetHandler(context).Update(context);

            LOG.Info("Exchange.Update method exiting, took {0} ms", stopWatch.ElapsedMilliseconds);
        }
Esempio n. 4
0
        public string DetermineOrigAndNewAttributeValue(UpdateOpContext context, ConnectorObject origObject, ICollection <ConnectorAttribute> attributesForReplace, string attributeName, out string origAttributeValue)
        {
            ConnectorAttribute originalAttribute = origObject.GetAttributeByName(attributeName);

            if (originalAttribute != null)
            {
                origAttributeValue = ConnectorAttributeUtil.GetAsStringValue(originalAttribute);
            }
            else
            {
                origAttributeValue = null;
            }

            ConnectorAttribute newAttribute = ConnectorAttributeUtil.Find(attributeName, attributesForReplace);

            if (newAttribute != null)
            {
                return(ConnectorAttributeUtil.GetAsStringValue(newAttribute));
            }
            else
            {
                return(origAttributeValue);
            }

            /*
             * string deltaValue = ConnectorAttributeUtil.GetAsStringValue(attribute);
             * if (attribute == null) {
             *  return origAttributeValue;
             * }
             * switch (context.UpdateType) {
             *  case UpdateType.ADD:
             *      if (deltaValue == null) {
             *          return origAttributeValue;
             *      }
             *      if (origAttributeValue != null && !origAttributeValue.Equals(deltaValue)) {
             *          throw new ArgumentException("Multiple values for " + attribute.Name + " are not allowed: existing = " + origAttributeValue + ", one being added = " + deltaValue);
             *      } else {
             *          return deltaValue;
             *      }
             *  case UpdateType.REPLACE:
             *      return deltaValue;
             *  case UpdateType.DELETE:
             *      if (deltaValue == null) {
             *          return origAttributeValue;
             *      }
             *      if (origAttributeValue == null || !origAttributeValue.Equals(deltaValue)) {
             *          LOGGER.TraceEvent(TraceEventType.Warning, CAT_DEFAULT, "Trying to remove value from " + attribute.Name + " that is not there: " + deltaValue);
             *          return origAttributeValue;
             *      } else {
             *          return null;
             *      }
             *  default:
             *      throw new ArgumentException("Invalid update type: " + context.UpdateType);
             * } */
        }
Esempio n. 5
0
        public void UpdateMain(UpdateOpContext context)
        {
            Stopwatch stopWatch = new Stopwatch();

            stopWatch.Start();

            GetHandler(context).Update(context);

            LOGGER_API.TraceEvent(TraceEventType.Information, CAT_DEFAULT,
                                  "Exchange.Update method exiting, took {0} ms", stopWatch.ElapsedMilliseconds);
        }
        public Uid Update(UpdateType updateType, ObjectClass oclass, Uid uid, ICollection <ConnectorAttribute> attributes, OperationOptions options)
        {
            const string operation = "Update";

            ExchangeUtility.NullCheck(updateType, "updateType", this._configuration);
            ExchangeUtility.NullCheck(oclass, "oclass", this._configuration);
            ExchangeUtility.NullCheck(uid, "uid", this._configuration);
            ExchangeUtility.NullCheck(attributes, "attributes", this._configuration);

            LOG.Info("Exchange.Update method; oclass = {0}, uid = {1}, type = {2}, attributes:\n{3}", oclass, uid, updateType, CommonUtils.DumpConnectorAttributes(attributes));

            if (attributes == null || attributes.Count == 0)
            {
                LOG.Info("Returning immediately, as there are no attributes to modify.");
                return(uid);
            }

            String database = (String)ExchangeUtility.GetAttValue("Database", attributes);

            LOG.Info("Database attribute before plugins call: " + database);
            plugins.OnBeforeUpdate(oclass, uid, attributes, options, _configuration);
            database = (String)ExchangeUtility.GetAttValue("Database", attributes);
            LOG.Info("Database attribute after plugins call: " + database);

            UpdateOpContext context = new UpdateOpContext()
            {
                UpdateType             = updateType,
                Attributes             = attributes,
                Connector              = this,
                ConnectorConfiguration = this._configuration,
                ObjectClass            = oclass,
                OperationName          = operation,
                Options = options,
                Uid     = uid
            };

            try {
                _scripting.ExecutePowerShell(context, Scripting.Position.BeforeMain);

                if (!_scripting.ExecutePowerShell(context, Scripting.Position.InsteadOfMain))
                {
                    UpdateMain(context);
                }

                _scripting.ExecutePowerShell(context, Scripting.Position.AfterMain);

                return(context.Uid);
            } catch (Exception e) {
                LOG.Error(e, "Exception while executing Update operation: {0}");
                throw;
            }
        }
Esempio n. 7
0
        public ICollection <ConnectorAttribute> DetermineNewAttributeValues(UpdateOpContext context, string query)
        {
            ConnectorObject originalObject;

            if (context.UpdateType != UpdateType.REPLACE)
            {
                originalObject = GetCurrentObject(context, query);
            }
            else
            {
                originalObject = null;          // not necessary here
            }
            return(DetermineNewAttributeValues(context, originalObject));
        }
        public void Update(UpdateOpContext context)
        {
            ExchangeConnector exconn = (ExchangeConnector)context.Connector;

            ICollection <ConnectorAttribute> attributesForReplace = _helper.DetermineNewAttributeValues(context, context.Uid.GetUidValue()); // query string is the UID value!

            Command cmdSet = ExchangeUtility.GetCommand(
                new PSExchangeConnector.CommandInfo(GetSetCommandName()),
                attributesForReplace, context.Uid, exconn.Configuration);

            try {
                _helper.InvokePipeline(exconn, cmdSet);
            } catch (ObjectNotFoundException e) {
                throw new UnknownUidException("Object with UID " + context.Uid.GetUidValue() + " couldn't be modified", e);
            }
        }
Esempio n. 9
0
        public Uid Update(UpdateType updateType, ObjectClass oclass, Uid uid, ICollection <ConnectorAttribute> attributes, OperationOptions options)
        {
            const string operation = "Update";

            ExchangeUtility.NullCheck(updateType, "updateType", this._configuration);
            ExchangeUtility.NullCheck(oclass, "oclass", this._configuration);
            ExchangeUtility.NullCheck(uid, "uid", this._configuration);
            ExchangeUtility.NullCheck(attributes, "attributes", this._configuration);

            LOGGER_API.TraceEvent(TraceEventType.Information, CAT_DEFAULT,
                                  "Exchange.Update method; oclass = {0}, uid = {1}, type = {2}, attributes:\n{3}", oclass, uid, updateType, CommonUtils.DumpConnectorAttributes(attributes));

            if (attributes == null || attributes.Count == 0)
            {
                LOGGER_API.TraceEvent(TraceEventType.Information, CAT_DEFAULT,
                                      "Returning immediately, as there are no attributes to modify.");
                return(uid);
            }

            UpdateOpContext context = new UpdateOpContext()
            {
                UpdateType             = updateType,
                Attributes             = attributes,
                Connector              = this,
                ConnectorConfiguration = this._configuration,
                ObjectClass            = oclass,
                OperationName          = operation,
                Options = options,
                Uid     = uid
            };

            try {
                _scripting.ExecutePowerShell(context, Scripting.Position.BeforeMain);

                if (!_scripting.ExecutePowerShell(context, Scripting.Position.InsteadOfMain))
                {
                    UpdateMain(context);
                }

                _scripting.ExecutePowerShell(context, Scripting.Position.AfterMain);

                return(context.Uid);
            } catch (Exception e) {
                LOGGER.TraceEvent(TraceEventType.Error, CAT_DEFAULT, "Exception while executing Update operation: {0}", e);
                throw;
            }
        }
Esempio n. 10
0
        // creates a collection of attributes that correspond to the original ones, but resolves ADD/DELETE using existing values of psuser
        public ICollection <ConnectorAttribute> DetermineNewAttributeValues(UpdateOpContext context, ConnectorObject originalObject)
        {
            if (context.UpdateType == UpdateType.REPLACE)
            {
                // TODO check multivaluedness and updateability (as below)
                return(new List <ConnectorAttribute>(context.Attributes));
            }
            else
            {
                Boolean add;
                if (context.UpdateType == UpdateType.ADD)
                {
                    add = true;
                }
                else if (context.UpdateType == UpdateType.DELETE)
                {
                    add = false;
                }
                else
                {
                    throw new ArgumentException("Unsupported update type: " + context.UpdateType);
                }

                Schema schema = null;
                ICollection <ConnectorAttribute> rv = new List <ConnectorAttribute>(context.Attributes.Count);
                foreach (ConnectorAttribute attribute in context.Attributes)
                {
                    ConnectorAttribute originalAttribute = originalObject.GetAttributeByName(attribute.Name);
                    IList <object>     newValues         = originalAttribute != null && originalAttribute.Value != null ? new List <object>(originalAttribute.Value) : new List <object>();
                    Boolean            changed           = false;
                    if (attribute.Value != null)
                    {
                        foreach (object item in attribute.Value)
                        {
                            if (add)
                            {
                                if (newValues.Contains(item))
                                {
                                    LOG.Warn("Trying to add value from " + attribute.Name + " that is already there: " + item);
                                }
                                else
                                {
                                    newValues.Add(item);
                                    changed = true;
                                }
                            }
                            else
                            {
                                if (!newValues.Contains(item))
                                {
                                    LOG.Warn("Trying to remove value from " + attribute.Name + " that is not there: " + item);
                                }
                                else
                                {
                                    newValues.Remove(item);
                                    changed = true;
                                }
                            }
                        }
                    }
                    if (changed)
                    {
                        ConnectorAttributeBuilder b = new ConnectorAttributeBuilder();
                        b.Name = attribute.Name;
                        b.AddValue(newValues);
                        ConnectorAttribute modified = b.Build();

                        if (schema == null)
                        {
                            ExchangeConnector connector = (ExchangeConnector)context.Connector;
                            schema = connector.Schema();
                        }
                        ObjectClassInfo oci = schema.FindObjectClassInfo(context.ObjectClass.Type);
                        if (oci == null)
                        {
                            throw new InvalidOperationException("No object class info for " + context.ObjectClass.Type + " in the schema");
                        }
                        var cai = ConnectorAttributeInfoUtil.Find(attribute.Name, oci.ConnectorAttributeInfos);
                        if (cai == null)
                        {
                            throw new InvalidOperationException("No connector attribute info for " + context.ObjectClass.Type + " in the schema");
                        }

                        if (!cai.IsUpdateable)
                        {
                            throw new ConnectorSecurityException("Attempt to update a non-updateable attribute (" + attribute.Name + "): " +
                                                                 CollectionUtil.Dump(newValues));
                        }

                        if (newValues.Count > 1 && !cai.IsMultiValued)
                        {
                            throw new InvalidAttributeValueException("More than one value in a single-valued attribute (" + attribute.Name + "): " +
                                                                     CollectionUtil.Dump(newValues));
                        }
                        rv.Add(modified);
                    }
                }
                return(rv);
            }
        }
Esempio n. 11
0
        public void Update(UpdateOpContext context)
        {
            ExchangeConnector        exconn = (ExchangeConnector)context.Connector;
            ActiveDirectoryConnector adconn = exconn.ActiveDirectoryConnector;

            // update in AD first
            var filtered = ExchangeUtility.FilterOut(
                context.Attributes,
                PSExchangeConnector.CommandInfo.EnableMailbox,
                PSExchangeConnector.CommandInfo.EnableMailUser,
                PSExchangeConnector.CommandInfo.SetMailbox,
                PSExchangeConnector.CommandInfo.SetMailUser);

            adconn.Update(context.UpdateType, context.ObjectClass, context.Uid, filtered, context.Options);

            // retrieve Exchange-related information about the user
            string          query         = "(objectGUID=" + ActiveDirectoryUtils.ConvertUIDToSearchString(context.Uid) + ")";
            ConnectorObject currentObject = _helper.GetCurrentObject(context, query);
            ICollection <ConnectorAttribute> attributesForReplace = _helper.DetermineNewAttributeValues(context, currentObject);

            attributesForReplace = DeduplicateEmailAddresses(context, attributesForReplace);

            string origRcptType;
            var    newRcptType = _helper.DetermineOrigAndNewAttributeValue(context, currentObject, attributesForReplace, ExchangeConnectorAttributes.AttRecipientType, out origRcptType);

            if (newRcptType == null)
            {
                newRcptType = ExchangeConnectorAttributes.RcptTypeUser;
            }

            string origDatabase;
            var    newDatabase = _helper.DetermineOrigAndNewAttributeValue(context, currentObject, attributesForReplace, ExchangeConnectorAttributes.AttDatabase, out origDatabase);

            // PART 1 - DEALING WITH MailUser CASE

            if (ExchangeConnectorAttributes.RcptTypeMailUser.Equals(newRcptType))
            {
                // disabling Mailbox if needed
                if (ExchangeConnectorAttributes.RcptTypeMailBox.Equals(origRcptType))
                {
                    Command cmdDisable = ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.DisableMailbox, attributesForReplace, context.Uid, exconn.Configuration);
                    cmdDisable.Parameters.Add("Confirm", false);
                    _helper.InvokePipeline(exconn, cmdDisable);
                }

                // enabling MailUser if needed
                if (!ExchangeConnectorAttributes.RcptTypeMailUser.Equals(origRcptType))
                {
                    // Enable-MailUser needs the value of ExternalEmailAddress, so we have to get it
                    string origExternalEmailAddress;
                    var    newExternalEmailAddress = _helper.DetermineOrigAndNewAttributeValue(context, currentObject, attributesForReplace, ExchangeConnectorAttributes.AttExternalEmailAddress, out origExternalEmailAddress);

                    if (String.IsNullOrEmpty(newExternalEmailAddress))
                    {
                        throw new InvalidOperationException("Missing ExternalEmailAddress value, which is required for a MailUser");
                    }
                    ExchangeUtility.SetAttValue(ExchangeConnectorAttributes.AttExternalEmailAddress, newExternalEmailAddress, attributesForReplace);

                    // now execute the Enable-MailUser command
                    Command cmdEnable = ExchangeUtility.GetCommand(
                        PSExchangeConnector.CommandInfo.EnableMailUser, attributesForReplace, context.Uid, exconn.Configuration);
                    _helper.InvokePipeline(exconn, cmdEnable);
                }

                // setting MailUser attributes
                Command cmdSet = ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.SetMailUser, attributesForReplace, context.Uid, exconn.Configuration);
                _helper.InvokePipeline(exconn, cmdSet);
            }

            // PART 2 - DEALING WITH UserMailbox CASE

            else if (ExchangeConnectorAttributes.RcptTypeMailBox.Equals(newRcptType))
            {
                // enable mailbox if necessary

                // we should execute something like this here:
                // get-user -identity id|?{$_.RecipientType -eq "User"}|enable-mailbox -database "db"
                // unfortunately I was not able to get it working with the pipeline... that's why there are two commands
                // executed :-(
                // alternatively there can be something like:
                // get-user -identity id -RecipientTypeDetails User|enable-mailbox -database "db", but we have then trouble
                // with detecting attempt to change the database attribute
                if (!ExchangeConnectorAttributes.RcptTypeMailBox.Equals(origRcptType))
                {
                    Command cmdEnable = ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.EnableMailbox, attributesForReplace, context.Uid, exconn.Configuration);
                    _helper.InvokePipeline(exconn, cmdEnable);
                }
                else
                {
                    // are we trying to update the database?
                    if (newDatabase != null && origDatabase != null && !newDatabase.Equals(origDatabase))
                    {
                        throw new ArgumentException(
                                  context.ConnectorConfiguration.ConnectorMessages.Format(
                                      "ex_not_updatable", "Update of [{0}] attribute is not supported", ExchangeConnectorAttributes.AttDatabase));
                    }
                }

                Command cmdSet = ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.SetMailbox, attributesForReplace, context.Uid, exconn.Configuration);
                _helper.InvokePipeline(exconn, cmdSet);
            }

            // PART 3 - DEALING WITH User CASE

            else if (ExchangeConnectorAttributes.RcptTypeUser.Equals(newRcptType))
            {
                if (ExchangeConnectorAttributes.RcptTypeMailBox.Equals(origRcptType))
                {
                    Command cmdDisable = ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.DisableMailbox, attributesForReplace, context.Uid, exconn.Configuration);
                    cmdDisable.Parameters.Add("Confirm", false);
                    _helper.InvokePipeline(exconn, cmdDisable);
                }
                else if (ExchangeConnectorAttributes.RcptTypeMailUser.Equals(origRcptType))
                {
                    Command cmdDisable = ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.DisableMailUser, attributesForReplace, context.Uid, exconn.Configuration);
                    cmdDisable.Parameters.Add("Confirm", false);
                    _helper.InvokePipeline(exconn, cmdDisable);
                }
                else if (ExchangeConnectorAttributes.RcptTypeUser.Equals(origRcptType))
                {
                    // if orig is User, there is no need to disable anything
                }
                else
                {
                    throw new InvalidOperationException("Invalid original recipient type: " + origRcptType);
                }

                Command cmdSet = ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.SetUser, attributesForReplace, context.Uid, exconn.Configuration);
                _helper.InvokePipeline(exconn, cmdSet);
            }
            else
            {
                // unsupported rcpt type
                throw new ArgumentException(
                          context.ConnectorConfiguration.ConnectorMessages.Format(
                              "ex_bad_rcpt", "Recipient type [{0}] is not supported", newRcptType));
            }
        }