Beispiel #1
0
        /// <summary>
        /// Finalizes the <paramref name="result"/> based on the individual <see cref="RuleResult"/> values contained in <paramref name="resultsCollector"/>
        /// </summary>
        /// <param name="result">The result to update</param>
        /// <param name="resultsCollector">The set of <see cref="RuleResult"/> values used to determine the compound outcome</param>
        /// <returns></returns>
        protected ComposedRuleResult FinalizeResult(ComposedRuleResult result, List <RuleResult> resultsCollector)
        {
            // set all the rule results on the compound result
            result.Results = resultsCollector.ToArray();

            // account for success if an entry doesn't have a given field
            result.Success = resultsCollector.Count < 1 || resultsCollector.All(r => r.Success);

            if (!result.Success)
            {
                // we propose the last proposed action, matching the original logic
                result.ProposedAction = result.Results.Where(r => !r.Success).Last().ProposedAction;

                // we propose the final result's updated value where success is false, matching the original logic
                result.ProposedValue = result.Results.Where(r => !r.Success).Last().UpdatedValue;
            }

            return(result);
        }
Beispiel #2
0
        /// <summary>
        /// Creates a consistent base <see cref="ComposedRuleResult"/> instance with default values
        /// </summary>
        /// <param name="entry">The entry for which we are creating a result</param>
        /// <param name="isValuePresent">Allows calling code to know if the <paramref name="entry"/> has a value for the given <see cref="AttributeName"/></param>
        /// <returns></returns>
        protected ComposedRuleResult InitResult(SearchResultEntry entry, out bool isValuePresent)
        {
            isValuePresent = false;

            var result = new ComposedRuleResult()
            {
                AttributeName           = this.AttributeName,
                EntityDistinguishedName = entry.Attributes[StringLiterals.DistinguishedName][0].ToString(),
                ObjectType     = ComposedRule.GetObjectType(entry),
                OriginalValue  = null,
                ProposedAction = ActionType.None
            };

            if (entry.Attributes.Contains(this.AttributeName))
            {
                isValuePresent       = true;
                result.OriginalValue = entry.Attributes[this.AttributeName][0].ToString();
            }

            return(result);
        }
Beispiel #3
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()
            });
        }