Skip to content

Feature: add LDAP module#127

Open
Namoshek wants to merge 7 commits into
elsa-workflows:mainfrom
Namoshek:feature/ldap-module
Open

Feature: add LDAP module#127
Namoshek wants to merge 7 commits into
elsa-workflows:mainfrom
Namoshek:feature/ldap-module

Conversation

@Namoshek
Copy link
Copy Markdown

@Namoshek Namoshek commented Mar 1, 2026

This pull request introduces a new LDAP module to the solution, providing a suite of workflow activities for interacting with LDAP directories. It includes new activities for adding, modifying, deleting, moving, comparing, and searching LDAP entries, along with the necessary updates to the solution and package references.

LDAP Module Introduction:

  • Added a new module, Elsa.Ldap, including the main project and corresponding unit tests, and updated the solution file (Elsa.Extensions.sln) to include these projects and organize them under new solution folders. [1] [2] [3]
  • The new activities allow for automations around directory services like Microsoft Active Directory.

LDAP Workflow Activities:

  • Implemented AddLdapEntry, DeleteLdapEntry, ModifyLdapEntry, MoveLdapEntry, CompareLdapEntry, and SearchLdapEntries activities in the Elsa.Ldap module, enabling workflows to perform core LDAP operations such as adding, deleting, modifying, moving, comparing, and searching directory entries. [1] [2] [3] [4] [5] [6]

Package Reference Updates:

  • Added System.DirectoryServices.Protocols as a package dependency for both .NET 9.0 and .NET 10.0 target frameworks in Directory.Packages.props to support LDAP protocol operations. [1] [2]

Tests:

  • Added a comprehensive test suite in Elsa.Ldap.UnitTests. Some tests are a bit hacky because the System.DirectoryServices.Protocols classes are very well protected from outside usage (internal constructors, etc.).
  • The entire suite of activities has been tested against a local Active Directory:
    elsa_ldap_module_test

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Mar 1, 2026

Greptile Summary

This PR introduces a comprehensive LDAP module that enables workflow automation for directory services like Active Directory. The implementation includes six workflow activities (AddLdapEntry, DeleteLdapEntry, ModifyLdapEntry, MoveLdapEntry, CompareLdapEntry, and SearchLdapEntries) that cover the core LDAP operations.

Key Changes:

  • Added Elsa.Ldap module with activity implementations for all major LDAP operations
  • Implemented async LDAP operations with proper cancellation handling using APM-to-TAP conversion
  • Created LdapConnectionFactory with support for multiple named connections, SSL/TLS, and authentication
  • Added comprehensive unit tests using reflection-based workarounds for internal constructors
  • Integrated LDAP module into workbench projects with configuration support
  • Added System.DirectoryServices.Protocols package dependency for .NET 9.0 and 10.0

Implementation Quality:

  • Activities follow consistent patterns with Success/Failure or Found/NotFound outcomes
  • Proper error handling with logging at Error level while allowing workflows to handle failures gracefully
  • Clean separation of concerns with interfaces, extensions, and proxy patterns
  • Good dispose pattern implementation in LdapConnectionProxy

Minor Issue:

  • CompareLdapEntry inherits from Activity<bool> while all other activities use CodeActivity<bool> - this inconsistency doesn't affect functionality but could be aligned for consistency

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • Well-structured implementation with comprehensive test coverage, proper async patterns, and good error handling. The only issue is a minor base class inconsistency that doesn't affect functionality
  • No files require special attention - the minor inconsistency in CompareLdapEntry.cs is optional to address

Important Files Changed

Filename Overview
src/modules/ldap/Elsa.Ldap/Activities/CompareLdapEntry.cs Implements LDAP compare operation, but uses Activity<bool> instead of CodeActivity<bool> unlike other activities
src/modules/ldap/Elsa.Ldap/Services/LdapConnectionFactory.cs Creates LDAP connections with proper authentication and SSL support
src/modules/ldap/Elsa.Ldap/Extensions/LdapConnectionExtensions.cs Implements async LDAP operations with proper cancellation handling using APM pattern
src/modules/ldap/Elsa.Ldap/Activities/AddLdapEntry.cs Adds LDAP entries with Success/Failure outcomes and proper error logging
src/modules/ldap/Elsa.Ldap/Activities/SearchLdapEntry.cs Searches for single LDAP entry with Found/Not Found outcomes
src/workbench/Elsa.Server.Web/Program.cs Configures LDAP module for workbench, reads connection config from appsettings

Class Diagram

%%{init: {'theme': 'neutral'}}%%
classDiagram
    class ILdapConnectionFactory {
        <<interface>>
        +CreateConnection(connectionName) ILdapConnection
    }
    
    class LdapConnectionFactory {
        -LdapOptions _options
        +CreateConnection(connectionName) ILdapConnection
        -ResolveConnection(connectionName) LdapConnectionOptions
    }
    
    class ILdapConnection {
        <<interface>>
        +SendRequestAsync(AddRequest) Task~AddResponse~
        +SendRequestAsync(DeleteRequest) Task~DeleteResponse~
        +SendRequestAsync(ModifyRequest) Task~ModifyResponse~
        +SendRequestAsync(SearchRequest) Task~SearchResponse~
        +Dispose()
    }
    
    class LdapConnectionProxy {
        -LdapConnection _connection
        +SendRequestAsync(request) Task~Response~
        +Dispose()
    }
    
    class AddLdapEntry {
        +ConnectionName Input~string~
        +EntryDn Input~string~
        +Attributes Input~DirectoryAttribute~
        +ExecuteAsync() ValueTask
    }
    
    class DeleteLdapEntry {
        +ConnectionName Input~string~
        +EntryDn Input~string~
        +ExecuteAsync() ValueTask
    }
    
    class ModifyLdapEntry {
        +ConnectionName Input~string~
        +EntryDn Input~string~
        +Modifications Input~DirectoryAttributeModification~
        +ExecuteAsync() ValueTask
    }
    
    class SearchLdapEntries {
        +ConnectionName Input~string~
        +BaseDn Input~string~
        +Filter Input~string~
        +ExecuteAsync() ValueTask
    }
    
    class LdapFeature {
        +ConfigureOptions Action~LdapOptions~
        +Configure()
        +Apply()
    }
    
    ILdapConnectionFactory <|.. LdapConnectionFactory
    ILdapConnection <|.. LdapConnectionProxy
    LdapConnectionFactory --> ILdapConnection : creates
    LdapConnectionFactory --> LdapConnectionProxy : instantiates
    AddLdapEntry --> ILdapConnectionFactory : uses
    DeleteLdapEntry --> ILdapConnectionFactory : uses
    ModifyLdapEntry --> ILdapConnectionFactory : uses
    SearchLdapEntries --> ILdapConnectionFactory : uses
    LdapFeature --> ILdapConnectionFactory : registers
    LdapConnectionProxy --> LdapConnection : wraps
Loading

Last reviewed commit: dfb2641

Copy link
Copy Markdown

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

40 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment thread src/modules/ldap/Elsa.Ldap/Activities/CompareLdapEntry.cs
@Namoshek
Copy link
Copy Markdown
Author

Namoshek commented Mar 1, 2026

@dotnet-policy-service agree

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant