예제 #1
0

        
예제 #2
0
        private Wireup(ConventionWireupParameters conventionWireup, IDictionary <string, Type> aliasTypes, IEnumerable <Type> transientTypes, IEnumerable <Assembly> assemblies)
        {
            Log.Info("Preparing to bootstrap the system.");
            var repository              = new DefaultRepository(new ConventionRoutingTable(assemblies));
            var persistenceFactory      = new PersistenceFactory(conventionWireup.JournalConnectionName, conventionWireup.DuplicateWindow, conventionWireup.JournalBatchSize);
            var snapshotFactory         = new SnapshotFactory(conventionWireup.SnapshotLocation, conventionWireup.PublicSnapshotConnectionName);
            var persistenceBootstrapper = new PersistenceBootstrapper(persistenceFactory);

            Log.Info("Connecting to message store.");
            this.info = persistenceBootstrapper.Restore();
            var duplicates       = new DuplicateStore(conventionWireup.DuplicateWindow, this.info.DuplicateIdentifiers);
            var timeoutFactory   = new TimeoutFactory();
            var messagingFactory = new MessagingFactory(conventionWireup.NodeId, conventionWireup.BrokerAddress, conventionWireup.SourceQueueName, duplicates);

            Log.Info("Loading bootstrap parameters.");
            var messageStore         = persistenceFactory.CreateMessageStore(this.info.SerializedTypes);
            var disruptorFactory     = new DisruptorFactory(messagingFactory, persistenceFactory, snapshotFactory, conventionWireup.SystemSnapshotFrequency, aliasTypes, transientTypes);
            var snapshotBootstrapper = new SnapshotBootstrapper(snapshotFactory, disruptorFactory, conventionWireup.SystemSnapshotFrequency);
            var messageBootstrapper  = new MessageBootstrapper(messageStore, disruptorFactory);

            this.bootstrapper = new Bootstrapper(repository, disruptorFactory, snapshotBootstrapper, messageBootstrapper, timeoutFactory, messagingFactory);
        }
예제 #3
0

        
예제 #4
0
        /// <summary>
        /// Runs the rules
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e">args</param>
        private void Run(object sender, DoWorkEventArgs e)
        {
            try
            {
                if (!(e.Argument is RulesRunnerDoWorkArgs args))
                {
                    e.Result = null;
                    throw new ArgumentException("RulesRunner expects arguments of type RulesRunnerDoWorkArgs.");
                }

                var stopwatch = DateTime.Now;

                // clear out our duplicate tracking each run
                DuplicateStore.Reset();

                // create the connection manager and bubble up any messages
                var connections = new ConnectionManager();
                connections.OnStatusUpdate += (string message) => { this.OnStatusUpdate?.Invoke(message); };

                // used to collect the results as we process rule collections
                var results = new RulesRunnerResult();

                connections.WithConnections((LdapConnection connection, string distinguishedName) =>
                {
                    if (this.CancellationPending)
                    {
                        e.Result = null;
                        return;
                    }

                    // we try and create a key from the queried directory and fail to random guid
                    var servers    = ((LdapDirectoryIdentifier)connection.Directory).Servers;
                    var identifier = servers.Length > 0 ? servers.First() : Guid.NewGuid().ToString("D");

                    // get the rule collection to run
                    var ruleCollection = this.GetRuleCollection(distinguishedName);

                    // runs the rule collection
                    var result = this.ExecuteRuleCollection(ruleCollection, connection);

                    // handle the cancel case
                    if (result == null && this.CancellationPending)
                    {
                        e.Result = null;
                        return;
                    }

                    // add our result to the list
                    results.Add(identifier, result);
                });

                // we pass back the collection of all results for processing into the UI grid
                e.Result = results;
            }
            catch (Exception err)
            {
                this.OnStatusUpdate?.Invoke("Error in RulesRunner: " + err.Message);
                e.Result = err;
            }
            finally
            {
                DuplicateStore.Reset();
            }
        }
예제 #5
0
        /// <summary>
        /// Executes implementation for this rule
        /// </summary>
        /// <param name="parent">The composed rule containing this rule</param>
        /// <param name="entry">The search result we are checking</param>
        /// <param name="attributeValue">The current attribute value as pass through the chain</param>
        /// <returns>Either a success or error result</returns>
        public override RuleResult Execute(ComposedRule parent, SearchResultEntry entry, string attributeValue)
        {
            // record in memory the entry details with a list of the attributes that end up needing to be checked
            if (DuplicateStore.IsDuplicate(parent.AttributeName, attributeValue, entry))
            {
                // we now need to execute some complicated logic from the original application depending
                // settings, etc. this isn't pretty but it follows the original for now

                var actionType    = ActionType.Edit;
                var originalValue = entry.Attributes[parent.AttributeName][0].ToString();

                // if nothing else has changed the value prior to this (which is why no duplicate rule needs to be run last)
                if (originalValue == attributeValue)
                {
                    switch (parent.AttributeName.ToLowerInvariant())
                    {
                    case "proxyaddresses":
                        if (Constants.SMTPRegex.IsMatch(attributeValue))
                        {
                            if (entry.Attributes.Contains(StringLiterals.MailNickName))
                            {
                                if (attributeValue.ToLowerInvariant().Substring(0, 5) == "smtp:")
                                {
                                    actionType = ActionType.Complete;
                                }
                            }
                            else
                            {
                                actionType = ActionType.Remove;
                            }
                        }
                        break;

                    case "userprincipalname":
                        if (entry.Attributes.Contains(StringLiterals.MailNickName))
                        {
                            actionType = ActionType.Complete;
                        }
                        break;

                    case "mail":
                        if (entry.Attributes.Contains(StringLiterals.MailNickName))
                        {
                            actionType = ActionType.Complete;
                        }
                        break;

                    case "mailnickname":
                        if (entry.Attributes.Contains(StringLiterals.HomeMdb))
                        {
                            actionType = ActionType.Complete;
                        }
                        break;

                    case "samaccountname":
                        if (entry.Attributes.Contains(StringLiterals.MailNickName))
                        {
                            actionType = ActionType.Complete;
                        }
                        break;
                    }
                }

                return(this.GetErrorResult(ErrorType.Duplicate, attributeValue, actionType));
            }

            return(this.GetSuccessResult());
        }
예제 #6
0
        /// <summary>
        /// Executes a rule collection against the supplied connection
        /// </summary>
        /// <param name="collection">The rule collection to execute</param>
        /// <param name="connection">The connection used to retrieve entries for processing</param>
        /// <returns><see cref="RuleCollectionResult"/> or null if canceled</returns>
        private RuleCollectionResult ExecuteRuleCollection(RuleCollection collection, LdapConnection connection)
        {
            // these count all the totals for the connection against which this RuleCollection is being run
            var  stopWatch      = new Stopwatch();
            long skipCount      = 0;
            long entryCount     = 0;
            long duplicateCount = 0;
            long errorCount     = 0;

            this.OnStatusUpdate?.Invoke(StringLiterals.LdapConnectionEstablishing);
            var searchRequest = collection.CreateSearchRequest();

            this.OnStatusUpdate?.Invoke(StringLiterals.LdapConnectionEstablished);

            var errors = new List <ComposedRuleResult>();

            this.OnStatusUpdate?.Invoke(StringLiterals.BeginningQuery);

            while (true)
            {
                var searchResponse = (SearchResponse)connection.SendRequest(searchRequest);

                // verify support for paged results
                if (searchResponse.Controls.Length != 1 || !(searchResponse.Controls[0] is PageResultResponseControl))
                {
                    this.OnStatusUpdate?.Invoke(StringLiterals.CannotPageResultSet);
                    throw new InvalidOperationException(StringLiterals.CannotPageResultSet);
                }

                foreach (SearchResultEntry entry in searchResponse.Entries)
                {
                    if (this.CancellationPending)
                    {
                        return(null);
                    }

                    if (collection.Skip(entry))
                    {
                        skipCount++;
                        continue;
                    }

                    // this tracks the number of entries we have processed and not skipped
                    entryCount++;

                    foreach (var composedRule in collection.Rules)
                    {
                        // run each composed rule which can produce multiple results
                        var results = composedRule.Execute(entry);

                        for (var i = 0; i < results.Length; i++)
                        {
                            var result = results[i];
                            if (!result.Success)
                            {
                                errorCount++;

                                if (result.Results.Any(r => (r.ErrorTypeFlags & ErrorType.Duplicate) != 0))
                                {
                                    duplicateCount++;

                                    if (result.ProposedAction == ActionType.Edit)
                                    {
                                        // Add original LDAP entry with the same value.
                                        var originalEntry    = DuplicateStore.GetOriginalSearchResultEntry(result.AttributeName, result.OriginalValue);
                                        var additionalResult = new ComposedRuleResult
                                        {
                                            AttributeName           = result.AttributeName,
                                            EntityDistinguishedName = originalEntry.DistinguishedName,
                                            EntityCommonName        = originalEntry.Attributes[StringLiterals.Cn][0].ToString(),
                                            ObjectType     = ComposedRule.GetObjectType(entry),
                                            OriginalValue  = result.OriginalValue,
                                            ProposedAction = result.ProposedAction,
                                            ProposedValue  = result.ProposedValue,
                                            Results        = new RuleResult[] {
                                                new RuleResult(false)
                                                {
                                                    ErrorTypeFlags = ErrorType.Duplicate,
                                                    ProposedAction = result.ProposedAction,
                                                    UpdatedValue   = result.OriginalValue
                                                }
                                            },
                                            Success = result.Success
                                        };
                                        errors.Add(additionalResult);
                                    }
                                }

                                errors.Add(result);
                            }
                        }
                    }
                }

                // handle paging
                var cookie = searchResponse.Controls.OfType <PageResultResponseControl>().First().Cookie;

                // if this is true, there are no more pages to request
                if (cookie.Length == 0)
                {
                    break;
                }

                searchRequest.Controls.OfType <PageResultRequestControl>().First().Cookie = cookie;
            }

            // we are all done, stop tracking time
            stopWatch.Stop();

            return(new RuleCollectionResult
            {
                TotalDuplicates = duplicateCount,
                TotalErrors = errorCount,
                TotalFound = skipCount + entryCount,
                TotalSkips = skipCount,
                TotalProcessed = entryCount,
                Elapsed = stopWatch.Elapsed,
                Errors = errors.ToArray()
            });
        }
예제 #7
0
        /// <summary>
        /// Runs the rules
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e">args</param>
        private void Run(object sender, DoWorkEventArgs e)
        {
            try
            {
                if (!(e.Argument is RulesRunnerDoWorkArgs args))
                {
                    e.Result = null;
                    throw new ArgumentException("RulesRunner expects arguments of type RulesRunnerDoWorkArgs.");
                }

                var stopwatch = DateTime.Now;

                // clear out our duplicate tracking each run
                DuplicateStore.Reset();

                // create the connection manager and bubble up any messages
                var connections = new ConnectionManager();
                connections.OnStatusUpdate += (string message) => { this.OnStatusUpdate?.Invoke(message); };

                // used to collect the results as we process rule collections
                var results = new RulesRunnerResult();

                connections.WithConnections((LdapConnection connection, string distinguishedName) =>
                {
                    if (this.CancellationPending)
                    {
                        e.Result = null;
                        return;
                    }

                    // we try and create a key from the queried directory and fail to random guid
                    var servers    = ((LdapDirectoryIdentifier)connection.Directory).Servers;
                    var identifier = servers.Length > 0 ? servers.First() : Guid.NewGuid().ToString("D");

                    // get the rule collection to run
                    var ruleCollection = this.GetRuleCollection(distinguishedName);

                    // if connecting to Global Catalog Server, make sure the collection's analyzed attributes are replicated.
                    if (SettingsManager.Instance.Port == Constants.GlobalCatalogPort)
                    {
                        var schemaResult = this.ExecuteRuleCollectionSchemaCheck(ruleCollection, connection);

                        // handle the cancel case
                        if (schemaResult == null && this.CancellationPending)
                        {
                            e.Result = null;
                            return;
                        }

                        // display errors
                        if (schemaResult.Count > 0)
                        {
                            DialogResult dialogResult = DialogResult.None;

                            // Show message box on main thread.
                            FormApp.Instance.Invoke(new Action(() =>
                            {
                                var message  = string.Format(StringLiterals.SchemaWarningMessage, Environment.NewLine + string.Join(Environment.NewLine, schemaResult.ToArray()));
                                dialogResult = MessageBox.Show(FormApp.Instance, message, StringLiterals.SchemaWarningTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                            }));

                            if (dialogResult == DialogResult.No)
                            {
                                return;
                            }
                        }
                    }

                    // runs the rule collection
                    var result = this.ExecuteRuleCollection(ruleCollection, connection);

                    // handle the cancel case
                    if (result == null && this.CancellationPending)
                    {
                        e.Result = null;
                        return;
                    }

                    // add our result to the list
                    results.Add(identifier, result);
                });

                // we pass back the collection of all results for processing into the UI grid
                e.Result = results;
            }
            catch (Exception err)
            {
                this.OnStatusUpdate?.Invoke("Error in RulesRunner: " + err.Message);
                e.Result = err;
            }
            finally
            {
                DuplicateStore.Reset();
            }
        }