Skip to content

Conversation

@wadahiro
Copy link
Contributor

@wadahiro wadahiro commented Aug 7, 2025

Summary

This PR delivers comprehensive enhancements to the Google Apps connector including new features (UpdateDelta operations, enhanced search capabilities, group membership management), architectural improvements through handler separation and API executor introduction, bug fixes for attribute handling, and robust test coverage with automated tests.

New Feature

1. UpdateDelta Operation Implementation

  • Implements ConnID's UpdateDelta interface for partial updates
  • Handles special attributes (aliases, photos, isAdmin) correctly
  • Enables efficient incremental updates

2. Enhanced Search Capabilities

  • Name-based lookups for users and groups
  • Improved filter translation with GoogleFilterTranslator
  • OrderBy support for search results (email, givenName, familyName)
  • Proper pagination handling
  • Offset-based pagination support (OP_PAGED_RESULTS_OFFSET) for MidPoint

3. Group Membership Operations

  • Support for group memberships during user creation
  • Add/remove/replace group memberships via UpdateDelta
  • Fixed member ID usage for proper group operations

Configuration Enhancements

Service Account Configuration

  • serviceAccountScopes - Custom OAuth2 scopes for service account authentication

Proxy Configuration

  • httpProxyHost - HTTP proxy server hostname
  • httpProxyPort - HTTP proxy server port
  • httpProxyUser - HTTP proxy authentication username
  • httpProxyPassword - HTTP proxy authentication password

HTTP Timeout Configuration

  • httpConnectTimeout - Connection establishment timeout in milliseconds (default: 10000)
  • httpSocketTimeout - Socket read timeout in milliseconds (default: 10000)
  • httpConnectionRequestTimeout - Connection manager request timeout in milliseconds (default: 10000)

Pagination Configuration

  • userPagingMaxResults - Maximum results per page for User searches (1-500, default: 500)
  • groupPagingMaxResults - Maximum results per page for Group searches (1-200, default: 200)

Advanced API Configuration

  • directoryBaseUrl - Custom Google Directory API base URL (for testing/special deployments)
  • licensingBaseUrl - Custom Google Licensing API base URL (for testing/special deployments)
  • oauth2TokenServerUrl - Custom OAuth2 token server URL (for testing/special deployments)

Bug Fixes & Improvements

  • Fixed attribute clearing for single-valued attributes using Data.NULL_STRING
  • Corrected group member addition using member ID instead of email
  • Resolved query handling issues in search operations
  • Fixed structured attributes JSON formatting

Architecture Refactoring

  • Separated logic into specialized handlers (UserHandler, GroupHandler, etc.)
  • Introduced GoogleApiExecutor for centralized API call management
  • Reduced GoogleAppsConnector.java complexity significantly
  • Extracted common patterns for better code reuse

Test Infrastructure

  • Implemented using WireMock
  • Covering all major operations
  • Comprehensive coverage for:
    • CRUD operations for all object types
    • UpdateDelta operations with various scenarios
    • Search filters, pagination, and ordering
    • Special attributes and multi-value handling
    • Error cases and edge conditions

Testing

mvn test

midPoint Configuration Example

Group Membership Mapping Example

With the group membership management in midPoint can be configured more efficiently using associations. Here's a recommended configuration:

            <attribute>
                <c:ref>icfs:groups</c:ref>
                <fetchStrategy>explicit</fetchStrategy>
            </attribute>

            <association>
                <c:ref>ri:group</c:ref>
                <tolerant>false</tolerant>
                <displayName>Group Membership</displayName>
                <kind>entitlement</kind>
                <intent>group</intent>
                <direction>subjectToObject</direction>
                <associationAttribute>icfs:groups</associationAttribute>
                <valueAttribute>icfs:uid</valueAttribute>
            </association>

This configuration enables:

  • Automatic group membership synchronization
  • Efficient partial updates using UpdateDelta operations

The UpdateDelta implementation ensures that only changed memberships are processed, improving performance for users with many group memberships.

Structured Attributes Mapping Example

The connector now provides consistent JSON formatting for structured attributes like externalIds, emails, phones, and organizations. This ensures reliable midPoint integration and prevents unnecessary update operations due to format inconsistencies.

Important Note: When constructing JSON strings in midPoint expressions, ensure that keys are specified in alphabetical order to match the connector's consistent output format. In the following example, "type" comes before "value" alphabetically, which matches the connector's sorted JSON output.

            <attribute>
                <c:ref>ri:externalIds</c:ref>
                <outbound>
                    <strength>strong</strength>
                    <source>
                        <c:path>$focus/name</c:path>
                    </source>
                    <expression>
                        <script>
                            <code>
                                return """{"type":"account","value":"$name"}"""
                            </code>
                        </script>
                    </expression>
                    <target>
                        <set>
                            <predefined>all</predefined>
                        </set>
                    </target>
                </outbound>
            </attribute>

wadahiro added 7 commits July 31, 2025 13:58
  - Add createMemberById() to correctly handle member additions using member IDs
  - Rename createMember() to createMemberByEmail() for clarity
  - Fix bug where member IDs were incorrectly passed as emails when adding users to groups
- Use group IDs instead of emails for safer, immutable references
- Fix null handling bug that prevented "Remove all membership" from working
- Enable users to be assigned to groups during creation, not just updates
- Add support for Name-based query in addition to UID-based query
- Fix incorrect logger message in executeAccountReadQuery (was "Groups#Get")
- Add proper Name attribute definition with case-insensitive subtype for Group and User
- Add ENABLE operational attribute support for user activation/deactivation
…omprehensive testing

Major Features and Enhancements:
- Implement PoolableConnector for connection pool management and improved performance
- Migrate from UpdateOp to UpdateDeltaOp for more granular attribute updates
- Add support for ALLOW_PARTIAL_ATTRIBUTE_VALUES operation option for incomplete attributes
- Add support for RETURN_DEFAULT_ATTRIBUTES operation option for optimized data retrieval
- Implement activation support with __ENABLE__ attribute for user account suspended state
- Implement OP_PAGED_RESULTS_OFFSET support

Architecture Improvements:
- Split monolithic GoogleAppsConnector into specialized handlers
- Add GoogleApiExecutor for centralized API execution with retry logic
- Implement GoogleFilter and GoogleFilterTranslator for enhanced filtering capabilities
- Extract UserConverter, GroupConverter and SchemaDefinition classes for better separation of concerns
- Introduce specialized handlers: UserHandler, GroupHandler, MemberHandler, OrgunitsHandler, LicenseAssignmentsHandler

Configuration Enhancements:
- Add timeout configurations
- Add proxy configuration
- Add custom API base URL configuration for private/testing endpoints
- Add service account scopes configuration for fine-grained permissions control

Dependency Updates:
- Update Google APIs dependencies to latest versions
- Add google-http-client-apache-v2 for Apache HttpClient

Bug Fixes and Improvements:
- Fix attribute clearing using Data.NULL_STRING for proper null handling
- Fix group membership operations to use immutable IDs instead of emails
- Add Name-based lookups for users and groups via GoogleFilter

Testing Infrastructure:
- Add comprehensive test suite using WireMock
- Implement GoogleApiMockServer for HTTP-level API testing
- Add specialized test coverage for all operation types (Create, Update, Delete, Search)
- Include edge case testing for partial attributes, pagination, filtering, and ordering
- Replace key-value separator from '=' to ':' for proper JSON format
- Sort keys alphabetically using TreeMap to ensure consistent output
- Add comprehensive test coverage for structured attributes JSON output

This fixes issues where midPoint's string comparison would fail due to
inconsistent key ordering in JSON strings returned for structured attributes
(emails, phones, externalIds, organizations, etc).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant