Skip to content

[Bug]: New-entry plain-value inputs become disabled when objectClass is included as a template or MUST attribute #473

Description

@TomokiMuto

Is there an existing issue for this?

  • I have searched the existing issues

Environment

- Image: phpldapadmin/phpldapadmin:2.3.11
- VERSION file: 3c70bc73
- LDAP backend: Samba4 Active Directory

PLA Code

Docker hub

PLA Version

2.3.11 - 3c70bc7

Current Behavior

When creating a new LDAP entry from a custom template whose objectclasses explicitly includes top, all plain-value attribute inputs on the Step 2 creation form are rendered as disabled.

This affects fields such as:

  • mail
  • givenName
  • sn
  • displayName
  • sAMAccountName
  • homeDirectory
  • uidNumber
  • gidNumber

Fields configured with "type": "select" remain editable.

This occurs with Samba4 Active Directory because its schema defines top with objectClass as a MUST attribute:

top ABSTRACT MUST (
    objectClass $
    objectCategory $
    nTSecurityDescriptor $
    instanceType
)

The problem disappears when top is removed from the template's objectclasses array and inherited through the objectClass SUP chain instead.

Expected Behavior

Attributes explicitly declared by the template, as well as required attributes belonging to the template's objectClasses, should remain editable when creating an entry.

The objectClass attribute itself must not be reinitialized while the template attributes are being constructed.

Explicitly including top in a valid template should not cause unrelated attribute inputs to become dynamic or disabled.

Steps To Reproduce

  1. Use phpLDAPadmin with a Samba4 Active Directory LDAP backend.

  2. Create a custom template under templates/ containing an objectclasses array such as:

    "objectclasses": [
        "top",
        "person",
        "organizationalPerson",
        "user",
        "inetOrgPerson",
        "posixAccount"
    ]
  3. Include several normal attributes in the template, for example mail, givenName, sn, displayName, sAMAccountName, and homeDirectory.

  4. Include at least one attribute configured with "type": "select" for comparison.

  5. Start creating a new entry and select this template.

  6. Continue to the Step 2 creation form.

  7. Observe that all plain-value text and number inputs are disabled, while select fields remain editable.

  8. Remove top from the template's objectclasses array without making any other changes.

  9. Start entry creation again using the same template.

  10. Observe that the plain-value inputs are now editable.

Relevant log output

Anything else?

The issue appears to be caused by the template-selection branch in EntryController::add() initializing objectClass a second time.

The branch first correctly assigns the template's objectClasses:

$o->objectclass = [
    Entry::TAG_NOTAG => $template->objectclasses->toArray()
];

It then initializes every template or MUST attribute:

foreach ($o->getAvailableAttributes()
    ->filter(fn($item) =>
        $item->names_lc
            ->intersect($template->attributes->keys()->map('strtolower'))
            ->count()
        || $item->is_must
    )->sortBy(fn($item) => Arr::get($template->order, $item->name_lc)) as $ao)
{
    $o->{$ao->name} = [Entry::TAG_NOTAG => ['']];
}

This filter does not exclude the objectClass attribute itself.

When the LDAP schema reports objectClass as a MUST attribute, the loop executes the equivalent of:

$o->objectClass = [Entry::TAG_NOTAG => ['']];

This overwrites the previously initialized objectClass list with an empty value.

Attributes constructed after this point receive oc: ['']. Since this value cannot be resolved to an objectClass schema, their internal objectClass collection remains empty.

Consequently, Attribute::isDynamic() returns true:

public function isDynamic(): bool
{
    return $this->schema->used_in_object_classes
        ->keys()
        ->intersect($this->oc)
        ->count() === 0;
}

The normal value component then disables those fields:

@disabled($o->isDynamic())

Select fields use x-attribute.template.select, which does not check isDynamic(). This explains why select fields remain editable while plain-value fields are disabled.

The sibling non-template branch already excludes objectclass:

foreach ($o->getAvailableAttributes()
    ->filter(fn($item) =>
        $item->is_must
        && ($item->name_lc !== 'objectclass')
    ) as $ao)

Applying the same exclusion to the template branch fixes the issue:

foreach ($o->getAvailableAttributes()
    ->filter(fn($item) =>
        ($item->name_lc !== 'objectclass')
        && (
            $item->names_lc
                ->intersect(
                    $template->attributes->keys()->map('strtolower')
                )
                ->count()
            || $item->is_must
        )
    )->sortBy(
        fn($item) => Arr::get($template->order, $item->name_lc)
    ) as $ao)
{
    $o->{$ao->name} = [Entry::TAG_NOTAG => ['']];
}

I verified this change locally against a live Samba4 Active Directory backend. After adding the guard, the previously disabled plain-value fields became editable.

The bundled templates/user_account.json and templates/samba_sam_account.json avoid the issue because they do not explicitly include top.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions