class LDAPService implements Flushable (View source)

Class LDAPService

Provides LDAP operations expressed in terms of the SilverStripe domain. All other modules should access LDAP through this class.

This class builds on top of LDAPGateway's detailed code by adding:

  • caching
  • data aggregation and restructuring from multiple lower-level calls
  • error handling

LDAPService relies on Laminas LDAP module's data structures for some parameters and some return values.

Traits

A class that can be instantiated or replaced via DI

Allows an object to have extensions applied to it.

Provides extensions to this object to integrate it with standard config API methods.

Allows an object to declare a set of custom methods

Config options

extensions array

An array of extension names and parameters to be applied to this object upon construction.

from  Extensible
unextendable_classes array

Classes that cannot be extended

from  Extensible
dependencies array
users_search_locations array

If configured, only user objects within these locations will be exposed to this service.

groups_search_locations array

If configured, only group objects within these locations will be exposed to this service.

new_users_dn string

Location to create new users in (distinguished name).

new_groups_dn string

Location to create new groups in (distinguished name).

_cache_nested_groups array
default_group string

If this is configured to a "Code" value of a Group in SilverStripe, the user will always be added to this group's membership when imported, regardless of any sort of group mappings.

password_history_workaround bool

For samba4 directory, there is no way to enforce password history on password resets.

Properties

protected static array $extra_methods

Custom method sources

from  CustomMethods
protected array $extra_method_registers

Name of methods to invoke by defineMethods for this instance

from  CustomMethods
protected static array $built_in_methods

Non-custom public methods.

from  CustomMethods
protected Extension[] $extension_instances from  Extensible
protected callable[][] $beforeExtendCallbacks

List of callbacks to call prior to extensions having extend called on them, each grouped by methodName.

from  Extensible
protected callable[][] $afterExtendCallbacks

List of callbacks to call after extensions having extend called on them, each grouped by methodName.

from  Extensible
public LDAPGateway $gateway

Methods

public static 
create(mixed ...$args)

An implementation of the factory method, allows you to create an instance of a class

public static 
singleton(string $class = null)

Creates a class instance by the "singleton" design pattern.

public
mixed
__call(string $method, array $arguments)

Attempts to locate and call a method dynamically added to a class at runtime if a default cannot be located

protected
defineMethods()

Adds any methods from Extension instances attached to this object.

protected
registerExtraMethodCallback(string $name, callable $callback)

Register an callback to invoke that defines extra methods

public
bool
hasMethod(string $method)

Return TRUE if a method exists on this object

protected
bool
hasCustomMethod($method)

Determines if a custom method with this name is defined.

protected
array
getExtraMethodConfig(string $method)

Get meta-data details on a named method

public
array
allMethodNames(bool $custom = false)

Return the names of all the methods available on this object

protected static 
array
findBuiltInMethods(string|object $class = null)

Get all public built in methods for this class

protected
array
findMethodsFrom(object $object)

Find all methods on the given object.

protected
addMethodsFrom(string $property, string|int $index = null)

Add all the methods from an object property.

protected
removeMethodsFrom(string $property, string|int $index = null)

Add all the methods from an object property (which is an Extension) to this object.

protected
addWrapperMethod(string $method, string $wrap)

Add a wrapper method - a method which points to another method with a different name. For example, Thumbnail(x) can be wrapped to generateThumbnail(x)

protected
addCallbackMethod(string $method, callable $callback)

Add callback as a method.

protected
beforeExtending(string $method, callable $callback)

Allows user code to hook into Object::extend prior to control being delegated to extensions. Each callback will be reset once called.

protected
afterExtending(string $method, callable $callback)

Allows user code to hook into Object::extend after control being delegated to extensions. Each callback will be reset once called.

protected
defineExtensionMethods()

Adds any methods from Extension instances attached to this object.

public static 
bool
add_extension(string $classOrExtension, string $extension = null)

Add an extension to a specific class.

public static 
remove_extension(string $extension)

Remove an extension from a class.

public static 
array
get_extensions(string $class = null, bool $includeArgumentString = false)

No description

public static 
array|null
get_extra_config_sources(string $class = null)

Get extra config sources for this class

public static 
bool
has_extension(string $classOrExtension, string $requiredExtension = null, bool $strict = false)

Return TRUE if a class has a specified extension.

public
array
invokeWithExtensions(string $method, mixed ...$arguments)

Calls a method if available on both this object and all applied Extensions, and then attempts to merge all results into an array

public
array
extend(string $method, mixed ...$arguments)

Run the given function on all of this object's extensions. Note that this method originally returned void, so if you wanted to return results, you're hosed

public
Extension|null
getExtensionInstance(string $extension)

Get an extension instance attached to this object by name.

public
bool
hasExtension(string $extension)

Returns TRUE if this object instance has a specific extension applied in $extension_instances. Extension instances are initialized at constructor time, meaning if you use add_extension() afterwards, the added extension will just be added to new instances of the extended class. Use the static method has_extension() to check if a class (not an instance) has a specific extension.

public
getExtensionInstances()

Get all extension instances for this specific object instance.

public static 
config()

Get a configuration accessor for this class. Short hand for Config::inst()->get($this->class, .....).

public
mixed
uninherited(string $name)

Gets the uninherited value for the given config option

public static 
CacheInterface
get_cache()

Get the cache object used for LDAP results. Note that the default lifetime set here is 8 hours, but you can change that by adding configuration:

public static 
flush()

Flushes out the LDAP results cache when flush=1 is called.

public
setGateway($gateway)

Setter for gateway. Useful for overriding the gateway with a fake for testing.

public
getGateway()

Return the LDAP gateway currently in use. Can be strung together to access the underlying Laminas\Ldap instance, or the PHP ldap resource itself. For example:

  • Get the Laminas\Ldap object: $service->getGateway()->getLdap() // Laminas\Ldap\Ldap object
  • Get the underlying PHP ldap resource: $service->getGateway()->getLdap()->getResource() // php resource

public
bool
enabled()

Checkes whether or not the service is enabled.

public
array
authenticate(string $username, string $password)

Authenticate the given username and password with LDAP.

public
array
getNodes(bool $cached = true, array $attributes = [])

Return all nodes (organizational units, containers, and domains) within the current base DN.

public
array
getGroups(bool $cached = true, array $attributes = [], string $indexBy = 'dn')

Return all AD groups in configured search locations, including all nested groups.

public
array
getNestedGroups(string $dn, array $attributes = [])

Return all member groups (and members of those, recursively) underneath a specific group DN.

public
array
getGroupByGUID(string $guid, array $attributes = [])

Get a particular AD group's data given a GUID.

public
array
getGroupByDN(string $dn, array $attributes = [])

Get a particular AD group's data given a DN.

public
array
getUsers(array $attributes = [])

Return all AD users in configured search locations, including all users in nested groups.

public
array
getUserByGUID(string $guid, array $attributes = [])

Get a specific AD user's data given a GUID.

public
array
getUserByDN(string $dn, array $attributes = [])

Get a specific AD user's data given a DN.

public
array
getUserByEmail(string $email, array $attributes = [])

Get a specific user's data given an email.

public
array
getUserByUsername(string $username, array $attributes = [])

Get a specific user's data given a username.

public
string|null
getUsernameByEmail(string $email)

Get a username for an email.

public
array
getLDAPGroupMembers(string $dn)

Given a group DN, get the group membership data in LDAP.

protected
bool
processThumbnailPhoto(Member $member, string $fieldName, array $data, string $attributeName)

Attempts to process the thumbnail photo for a given user and store it against a Member object. This will overwrite any old file with the same name. The filename of the photo will be set to 'thumbnailphoto-.jpg'.

public
updateMemberGroups(array $data, Member $member, array $mappedGroupsToKeep = [])

Ensure the user is mapped to any applicable groups.

public
bool
updateGroupFromLDAP(Group $group, array $data)

Sync a specific Group by updating it with LDAP data.

public
createLDAPUser(Member $member)

Creates a new LDAP user from the passed Member record.

public
createLDAPGroup(Group $group)

Creates a new LDAP group from the passed Group record.

public
updateLDAPFromMember(Member $member)

Update the Member data back to the corresponding LDAP user object.

public
updateLDAPGroupsForMember(Member $member)

Ensure the user belongs to the correct groups in LDAP from their membership to local LDAP mapped SilverStripe groups.

public
addLDAPUserToGroup(string $userDn, string $groupDn)

Add LDAP user by DN to LDAP group.

public
setPassword(Member $member, string $password, string|null $oldPassword = null)

Change a members password on the AD. Works with ActiveDirectory compatible services that saves the password in the unicodePwd attribute.

public
deleteLDAPMember(Member $member)

Delete an LDAP user mapped to the Member record

public
update(string $dn, array $attributes)

A simple proxy to LDAP update operation.

public
delete(string $dn, bool $recursively = false)

A simple proxy to LDAP delete operation.

public
move(string $fromDn, string $toDn, bool $recursively = false)

A simple proxy to LDAP copy/delete operation.

public
add(string $dn, array $attributes)

A simple proxy to LDAP add operation.

public
LoggerInterface
getLogger()

Get a logger

Details

static Injectable create(mixed ...$args)

An implementation of the factory method, allows you to create an instance of a class

This method will defer class substitution to the Injector API, which can be customised via the Config API to declare substitution classes.

This can be called in one of two ways - either calling via the class directly, or calling on Object and passing the class name as the first parameter. The following are equivalent: $list = DataList::create(SiteTree::class); $list = SiteTree::get();

Parameters

mixed ...$args

Return Value

Injectable

static Injectable singleton(string $class = null)

Creates a class instance by the "singleton" design pattern.

It will always return the same instance for this class, which can be used for performance reasons and as a simple way to access instance methods which don't rely on instance data (e.g. the custom SilverStripe static handling).

Parameters

string $class

Optional classname to create, if the called class should not be used

Return Value

Injectable

The singleton instance

mixed __call(string $method, array $arguments)

Attempts to locate and call a method dynamically added to a class at runtime if a default cannot be located

You can add extra methods to a class using Extensions}, {@link Object::createMethod() or Object::addWrapperMethod()

Parameters

string $method
array $arguments

Return Value

mixed

Exceptions

BadMethodCallException

protected defineMethods()

Adds any methods from Extension instances attached to this object.

All these methods can then be called directly on the instance (transparently mapped through __call()}), or called explicitly through {@link extend().

protected registerExtraMethodCallback(string $name, callable $callback)

Register an callback to invoke that defines extra methods

Parameters

string $name
callable $callback

bool hasMethod(string $method)

Return TRUE if a method exists on this object

This should be used rather than PHP's inbuild method_exists() as it takes into account methods added via extensions

Parameters

string $method

Return Value

bool

protected bool hasCustomMethod($method)

Determines if a custom method with this name is defined.

Parameters

$method

Return Value

bool

protected array getExtraMethodConfig(string $method)

Get meta-data details on a named method

Parameters

string $method

Return Value

array

List of custom method details, if defined for this method

array allMethodNames(bool $custom = false)

Return the names of all the methods available on this object

Parameters

bool $custom

include methods added dynamically at runtime

Return Value

array

Map of method names with lowercase keys

static protected array findBuiltInMethods(string|object $class = null)

Get all public built in methods for this class

Parameters

string|object $class

Class or instance to query methods from (defaults to static::class)

Return Value

array

Map of methods with lowercase key name

protected array findMethodsFrom(object $object)

Find all methods on the given object.

Parameters

object $object

Return Value

array

protected addMethodsFrom(string $property, string|int $index = null)

Add all the methods from an object property.

Parameters

string $property

the property name

string|int $index

an index to use if the property is an array

Exceptions

InvalidArgumentException

protected removeMethodsFrom(string $property, string|int $index = null)

Add all the methods from an object property (which is an Extension) to this object.

Parameters

string $property

the property name

string|int $index

an index to use if the property is an array

protected addWrapperMethod(string $method, string $wrap)

Add a wrapper method - a method which points to another method with a different name. For example, Thumbnail(x) can be wrapped to generateThumbnail(x)

Parameters

string $method

the method name to wrap

string $wrap

the method name to wrap to

protected addCallbackMethod(string $method, callable $callback)

Add callback as a method.

Parameters

string $method

Name of method

callable $callback

Callback to invoke. Note: $this is passed as first parameter to this callback and then $args as array

protected beforeExtending(string $method, callable $callback)

Allows user code to hook into Object::extend prior to control being delegated to extensions. Each callback will be reset once called.

Parameters

string $method

The name of the method to hook into

callable $callback

The callback to execute

protected afterExtending(string $method, callable $callback)

Allows user code to hook into Object::extend after control being delegated to extensions. Each callback will be reset once called.

Parameters

string $method

The name of the method to hook into

callable $callback

The callback to execute

protected defineExtensionMethods()

Adds any methods from Extension instances attached to this object.

All these methods can then be called directly on the instance (transparently mapped through __call()}), or called explicitly through {@link extend().

static bool add_extension(string $classOrExtension, string $extension = null)

Add an extension to a specific class.

The preferred method for adding extensions is through YAML config, since it avoids autoloading the class, and is easier to override in more specific configurations.

As an alternative, extensions can be added to a specific class directly in the Object::$extensions array. See SiteTree::$extensions for examples. Keep in mind that the extension will only be applied to new instances, not existing ones (including all instances created through singleton()).

Parameters

string $classOrExtension

Class that should be extended - has to be a subclass of Object

string $extension

Subclass of Extension with optional parameters as a string, e.g. "Versioned"

Return Value

bool

Flag if the extension was added

See also

http://doc.silverstripe.org/framework/en/trunk/reference/dataextension

static remove_extension(string $extension)

Remove an extension from a class.

Note: This will not remove extensions from parent classes, and must be called directly on the class assigned the extension.

Keep in mind that this won't revert any datamodel additions of the extension at runtime, unless its used before the schema building kicks in (in your _config.php). Doesn't remove the extension from any Object instances which are already created, but will have an effect on new extensions. Clears any previously created singletons through singleton() to avoid side-effects from stale extension information.

Parameters

string $extension

class name of an Extension subclass, without parameters

static array get_extensions(string $class = null, bool $includeArgumentString = false)

No description

Parameters

string $class

If omitted, will get extensions for the current class

bool $includeArgumentString

Include the argument string in the return array, FALSE would return array("Versioned"), TRUE returns array("Versioned('Stage','Live')").

Return Value

array

Numeric array of either DataExtension class names, or eval'ed class name strings with constructor arguments.

static array|null get_extra_config_sources(string $class = null)

Get extra config sources for this class

Parameters

string $class

Name of class. If left null will return for the current class

Return Value

array|null

static bool has_extension(string $classOrExtension, string $requiredExtension = null, bool $strict = false)

Return TRUE if a class has a specified extension.

This supports backwards-compatible format (static Object::has_extension($requiredExtension)) and new format ($object->has_extension($class, $requiredExtension))

Parameters

string $classOrExtension

Class to check extension for, or the extension name to check if the second argument is null.

string $requiredExtension

If the first argument is the parent class, this is the extension to check. If left null, the first parameter will be treated as the extension.

bool $strict

if the extension has to match the required extension and not be a subclass

Return Value

bool

Flag if the extension exists

array invokeWithExtensions(string $method, mixed ...$arguments)

Calls a method if available on both this object and all applied Extensions, and then attempts to merge all results into an array

Parameters

string $method

the method name to call

mixed ...$arguments

List of arguments

Return Value

array

List of results with nulls filtered out

array extend(string $method, mixed ...$arguments)

Run the given function on all of this object's extensions. Note that this method originally returned void, so if you wanted to return results, you're hosed

Currently returns an array, with an index resulting every time the function is called. Only adds returns if they're not NULL, to avoid bogus results from methods just defined on the parent extension. This is important for permission-checks through extend, as they use min() to determine if any of the returns is FALSE. As min() doesn't do type checking, an included NULL return would fail the permission checks.

The extension methods are defined during __construct()} in {@link defineMethods().

Parameters

string $method

the name of the method to call on each extension

mixed ...$arguments

Return Value

array

Extension|null getExtensionInstance(string $extension)

Get an extension instance attached to this object by name.

Parameters

string $extension

Return Value

Extension|null

bool hasExtension(string $extension)

Returns TRUE if this object instance has a specific extension applied in $extension_instances. Extension instances are initialized at constructor time, meaning if you use add_extension() afterwards, the added extension will just be added to new instances of the extended class. Use the static method has_extension() to check if a class (not an instance) has a specific extension.

Caution: Don't use singleton()->hasExtension() as it will give you inconsistent results based on when the singleton was first accessed.

Parameters

string $extension

Classname of an Extension subclass without parameters

Return Value

bool

Extension[] getExtensionInstances()

Get all extension instances for this specific object instance.

See get_extensions() to get all applied extension classes for this class (not the instance).

This method also provides lazy-population of the extension_instances property.

Return Value

Extension[]

Map of DataExtension instances, keyed by classname.

static Config_ForClass config()

Get a configuration accessor for this class. Short hand for Config::inst()->get($this->class, .....).

Return Value

Config_ForClass

mixed uninherited(string $name)

Gets the uninherited value for the given config option

Parameters

string $name

Return Value

mixed

static CacheInterface get_cache()

Get the cache object used for LDAP results. Note that the default lifetime set here is 8 hours, but you can change that by adding configuration:

SilverStripe\Core\Injector\Injector:
  Psr\SimpleCache\CacheInterface.ldap:
    constructor:
      defaultLifetime: 3600 # time in seconds

Return Value

CacheInterface

static flush()

Flushes out the LDAP results cache when flush=1 is called.

setGateway($gateway)

Setter for gateway. Useful for overriding the gateway with a fake for testing.

Parameters

$gateway

LDAPGateway getGateway()

Return the LDAP gateway currently in use. Can be strung together to access the underlying Laminas\Ldap instance, or the PHP ldap resource itself. For example:

  • Get the Laminas\Ldap object: $service->getGateway()->getLdap() // Laminas\Ldap\Ldap object
  • Get the underlying PHP ldap resource: $service->getGateway()->getLdap()->getResource() // php resource

Return Value

LDAPGateway

bool enabled()

Checkes whether or not the service is enabled.

Return Value

bool

array authenticate(string $username, string $password)

Authenticate the given username and password with LDAP.

Parameters

string $username
string $password

Return Value

array

array getNodes(bool $cached = true, array $attributes = [])

Return all nodes (organizational units, containers, and domains) within the current base DN.

Parameters

bool $cached

Cache the results from AD, so that subsequent calls are faster. Enabled by default.

array $attributes

List of specific AD attributes to return. Empty array means return everything.

Return Value

array

array getGroups(bool $cached = true, array $attributes = [], string $indexBy = 'dn')

Return all AD groups in configured search locations, including all nested groups.

Uses groups_search_locations if defined, otherwise falls back to NULL, which tells LDAPGateway to use the default baseDn defined in the connection.

Parameters

bool $cached

Cache the results from AD, so that subsequent calls are faster. Enabled by default.

array $attributes

List of specific AD attributes to return. Empty array means return everything.

string $indexBy

Attribute to use as an index.

Return Value

array

array getNestedGroups(string $dn, array $attributes = [])

Return all member groups (and members of those, recursively) underneath a specific group DN.

Note that these get cached in-memory per-request for performance to avoid re-querying for the same results.

Parameters

string $dn
array $attributes

List of specific AD attributes to return. Empty array means return everything.

Return Value

array

array getGroupByGUID(string $guid, array $attributes = [])

Get a particular AD group's data given a GUID.

Parameters

string $guid
array $attributes

List of specific AD attributes to return. Empty array means return everything.

Return Value

array

array getGroupByDN(string $dn, array $attributes = [])

Get a particular AD group's data given a DN.

Parameters

string $dn
array $attributes

List of specific AD attributes to return. Empty array means return everything.

Return Value

array

array getUsers(array $attributes = [])

Return all AD users in configured search locations, including all users in nested groups.

Uses users_search_locations if defined, otherwise falls back to NULL, which tells LDAPGateway to use the default baseDn defined in the connection.

Parameters

array $attributes

List of specific AD attributes to return. Empty array means return everything.

Return Value

array

array getUserByGUID(string $guid, array $attributes = [])

Get a specific AD user's data given a GUID.

Parameters

string $guid
array $attributes

List of specific AD attributes to return. Empty array means return everything.

Return Value

array

array getUserByDN(string $dn, array $attributes = [])

Get a specific AD user's data given a DN.

Parameters

string $dn
array $attributes

List of specific AD attributes to return. Empty array means return everything.

Return Value

array

array getUserByEmail(string $email, array $attributes = [])

Get a specific user's data given an email.

Parameters

string $email
array $attributes

List of specific AD attributes to return. Empty array means return everything.

Return Value

array

array getUserByUsername(string $username, array $attributes = [])

Get a specific user's data given a username.

Parameters

string $username
array $attributes

List of specific AD attributes to return. Empty array means return everything.

Return Value

array

string|null getUsernameByEmail(string $email)

Get a username for an email.

Parameters

string $email

Return Value

string|null

array getLDAPGroupMembers(string $dn)

Given a group DN, get the group membership data in LDAP.

Parameters

string $dn

Return Value

array

protected bool processThumbnailPhoto(Member $member, string $fieldName, array $data, string $attributeName)

Attempts to process the thumbnail photo for a given user and store it against a Member object. This will overwrite any old file with the same name. The filename of the photo will be set to 'thumbnailphoto-.jpg'.

At the moment only JPEG files are supported, as this is mainly to support Active Directory, which always provides the photo in a JPEG format, and always at a specific resolution.

Parameters

Member $member

The SilverStripe Member object we are storing this file on

string $fieldName

The SilverStripe field name we are storing this new file against

array $data

Array of all data returned about this user from LDAP

string $attributeName

Name of the attribute in the $data array to get the binary blog from

Return Value

bool

true on success, false on failure

Exceptions

ValidationException

updateMemberGroups(array $data, Member $member, array $mappedGroupsToKeep = [])

Ensure the user is mapped to any applicable groups.

Parameters

array $data
Member $member
array $mappedGroupsToKeep

bool updateGroupFromLDAP(Group $group, array $data)

Sync a specific Group by updating it with LDAP data.

Parameters

Group $group

An existing Group or a new Group object

array $data

LDAP group object data

Return Value

bool

createLDAPUser(Member $member)

Creates a new LDAP user from the passed Member record.

Note that the Member record must have a non-empty Username field for this to work.

Parameters

Member $member

Exceptions

ValidationException
Exception

createLDAPGroup(Group $group)

Creates a new LDAP group from the passed Group record.

Parameters

Group $group

Exceptions

ValidationException

updateLDAPFromMember(Member $member)

Update the Member data back to the corresponding LDAP user object.

Parameters

Member $member

Exceptions

ValidationException

updateLDAPGroupsForMember(Member $member)

Ensure the user belongs to the correct groups in LDAP from their membership to local LDAP mapped SilverStripe groups.

This also removes them from LDAP groups if they've been taken out of one. It will not affect group membership of non-mapped groups, so it will not touch such internal AD groups like "Domain Users".

Parameters

Member $member

Exceptions

ValidationException

addLDAPUserToGroup(string $userDn, string $groupDn)

Add LDAP user by DN to LDAP group.

Parameters

string $userDn
string $groupDn

Exceptions

Exception

ValidationResult setPassword(Member $member, string $password, string|null $oldPassword = null)

Change a members password on the AD. Works with ActiveDirectory compatible services that saves the password in the unicodePwd attribute.

Ensure that the LDAP bind:ed user can change passwords and that the connection is secure.

Parameters

Member $member
string $password
string|null $oldPassword

Supply old password to perform a password change (as opposed to password reset)

Return Value

ValidationResult

deleteLDAPMember(Member $member)

Delete an LDAP user mapped to the Member record

Parameters

Member $member

Exceptions

ValidationException

update(string $dn, array $attributes)

A simple proxy to LDAP update operation.

Parameters

string $dn

Location to add the entry at.

array $attributes

A simple associative array of attributes.

delete(string $dn, bool $recursively = false)

A simple proxy to LDAP delete operation.

Parameters

string $dn

Location of object to delete

bool $recursively

Recursively delete nested objects?

move(string $fromDn, string $toDn, bool $recursively = false)

A simple proxy to LDAP copy/delete operation.

Parameters

string $fromDn
string $toDn
bool $recursively

Recursively move nested objects?

add(string $dn, array $attributes)

A simple proxy to LDAP add operation.

Parameters

string $dn

Location to add the entry at.

array $attributes

A simple associative array of attributes.

LoggerInterface getLogger()

Get a logger

Return Value

LoggerInterface