From 1b11917bf574ae06dbb3d392bc27569697e223f6 Mon Sep 17 00:00:00 2001 From: Dave Mc Nicoll Date: Wed, 24 Mar 2021 13:48:28 +0000 Subject: [PATCH] - Added the update keyword allowing modification for one field. --- src/Adapter/Ldap.php | 16 ++++++++---- src/Common/LdapObject.php | 47 +++++++++++++++++++++++++++-------- src/Common/PasswordHelper.php | 35 ++++++++++++++++++++++++++ src/Entity/User.php | 20 +++++++++++---- src/EntityTrait.php | 5 ++++ src/Query/Set.php | 21 ++++++++++++++++ src/Query/Update.php | 17 +++++++++++++ src/QueryBuilder.php | 21 +++++++++++++++- src/Repository.php | 25 +++++++++++++++++++ 9 files changed, 186 insertions(+), 21 deletions(-) create mode 100644 src/Common/PasswordHelper.php create mode 100644 src/Query/Set.php create mode 100644 src/Query/Update.php diff --git a/src/Adapter/Ldap.php b/src/Adapter/Ldap.php index f6bf3d2..e53e664 100644 --- a/src/Adapter/Ldap.php +++ b/src/Adapter/Ldap.php @@ -17,6 +17,8 @@ class Ldap implements \Ulmus\Adapter\AdapterInterface { public int $version = 3; public bool $encrypt; + + public bool $forceSSL = false; public array $hosts; @@ -106,7 +108,10 @@ class Ldap implements \Ulmus\Adapter\AdapterInterface { $ldapObject->startTLS(); } - + elseif ($this->forceSSL) { + $ldapObject->startTLS(); + } + return $ldapObject; } @@ -135,12 +140,13 @@ class Ldap implements \Ulmus\Adapter\AdapterInterface { throw new AdapterConfigurationException("Your `account_suffix` is missing from your configuration array"); } - /* - if ( false !== ( $configuration['app'] ?? false ) ) { - $this->app = $configuration['app']; + if ( false !== ( $configuration['force_ssl'] ?? false ) ) { + $this->forceSSL = true; } - */ + if ( getenv('DEBUG') ) { + ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, 7); + } } public function escapeIdentifier(string $segment, int $type, string $ignore = "") : string diff --git a/src/Common/LdapObject.php b/src/Common/LdapObject.php index 45c18bc..2e63b15 100644 --- a/src/Common/LdapObject.php +++ b/src/Common/LdapObject.php @@ -2,7 +2,7 @@ namespace Ulmus\Ldap\Common; -use function ldap_set_option, ldap_start_tls, ldap_bind, ldap_unbind, ldap_connect, ldap_close, ldap_get_entries, ldap_count_entries; +use function ldap_set_option, ldap_start_tls, ldap_bind, ldap_unbind, ldap_connect, ldap_close, ldap_get_entries, ldap_mod_replace, ldap_count_entries, ldap_errno, ldap_error; class LdapObject { @@ -27,7 +27,7 @@ class LdapObject { public function connect(string $host, string $baseDn) : bool { - $this->connection = ldap_connect($host); + $this->connection = ldap_connect("ldap://$host"); $this->dn = $baseDn; @@ -46,7 +46,7 @@ class LdapObject { ldap_start_tls($this->connection); } - public function bind(? string $dn, ? string $password) : bool + public function bind(? string $dn, ? string $password = null) : bool { if ($this->binded) { throw new \Exception("LdapObject is already binded with a user. Use the unbind() method to release it."); @@ -62,6 +62,13 @@ class LdapObject { } } + public function rebind(? string $dn, ? string $password = null) : bool + { + $this->unbind(); + + return $this->bind($dn, $password); + } + public function select(array $filter, array $fields = []) { static::$dump && call_user_func_array(static::$dump, [ $filter, $fields ]); @@ -94,13 +101,15 @@ class LdapObject { if ($result) { $this->bufferedRows--; - $dataset = []; + $dataset = [ + 'dn' => ldap_get_dn($this->connection, $result) + ]; if ( $attributes = ldap_get_attributes($this->connection, $result) ) { for ($i = 0; $i < $attributes['count']; $i++) { $key = $attributes[$i]; - $dataset[strtolower($key)] = $attributes[$key][0]; + $dataset[$key] = $attributes[$key][0]; } } @@ -110,15 +119,33 @@ class LdapObject { return false; } - public function rowCount() : int - { - return $this->rowCount; - } - public function fetchAll() { return ldap_get_entries($this->connection, $result); } + public function rowCount() : int + { + return $this->rowCount; + } + + public function runQuery(array $filter, array $dataset) + { + static::$dump && call_user_func_array(static::$dump, [ $filter, $dataset ]); + + if ( false === ( $queryResult = ldap_mod_replace($this->connection, $filter['dn'], $dataset) ) ) { + $this->throwLdapException(); + } + + $this->rowCount = 1; + + return $this; + } + + protected function throwLdapException() : void + { + throw new \Exception(sprintf('LDAP error #%s `%s`', ldap_errno($this->connection), ldap_error($this->connection))); + } + public function closeCursor() : void {} } diff --git a/src/Common/PasswordHelper.php b/src/Common/PasswordHelper.php new file mode 100644 index 0000000..7aed6e6 --- /dev/null +++ b/src/Common/PasswordHelper.php @@ -0,0 +1,35 @@ + 'unicodePwd') + */ + public string $unicodePassword; + + /** + * @Field + */ + public string $userPassword; + /** * @Field */ public Datetime $lastLogonDate; /** - * @Field('name' => 'createTimeStamp') + * #Field('name' => 'createTimeStamp') */ - public Datetime $createdAt; + # public Datetime $createdAt; /** - * @Field('name' => 'modifyTimeStamp') + * #Field('name' => 'modifyTimeStamp') */ - public Datetime $updatedAt; + # public Datetime $updatedAt; public function __toString() : string { diff --git a/src/EntityTrait.php b/src/EntityTrait.php index 88f50e5..5e339d8 100644 --- a/src/EntityTrait.php +++ b/src/EntityTrait.php @@ -9,6 +9,11 @@ use Ulmus\Ldap\Annotation\Classes\{ ObjectClass, }; trait EntityTrait { use \Ulmus\EntityTrait; + /** + * @Id + */ + public string $dn; + public static function resolveEntity() : EntityResolver { return Ulmus::resolveEntity(static::class); diff --git a/src/Query/Set.php b/src/Query/Set.php new file mode 100644 index 0000000..a6abebf --- /dev/null +++ b/src/Query/Set.php @@ -0,0 +1,21 @@ +dataset as $key => $value) { + $this->queryBuilder->addParameter($value, $key); + + $fields[] = $this->escapedFields[$key] ?? $key; + } + + return [ + 'fields' => $fields, + ]; + } +} \ No newline at end of file diff --git a/src/Query/Update.php b/src/Query/Update.php new file mode 100644 index 0000000..953e079 --- /dev/null +++ b/src/Query/Update.php @@ -0,0 +1,17 @@ + $this->dn, + ]; + } +} diff --git a/src/QueryBuilder.php b/src/QueryBuilder.php index e203585..44807ed 100644 --- a/src/QueryBuilder.php +++ b/src/QueryBuilder.php @@ -43,13 +43,32 @@ class QueryBuilder implements Ulmus\Query\QueryBuilderInterface return $this; } + public function set(array $dataset, ? array $escapedFields = null) : self + { + if ( null === ( $set = $this->getFragment(Query\Set::class) ) ) { + $set = new Query\Set($this); + $this->push($set); + } + + $set->set($dataset, $escapedFields); + + return $this; + } + public function from(string $table, ? string $alias, ? string $schema) : self { return $this; } - public function update(string $table, ? string $alias = null, ? string $database = null, ? string $schema = null) : self + public function update(string $dn) : self { + if ( null === ( $update = $this->getFragment(Query\Update::class) ) ) { + $update = new Query\Update($this); + $this->push($update); + } + + $update->dn = $dn; + return $this; } diff --git a/src/Repository.php b/src/Repository.php index 7089ba3..3738f20 100644 --- a/src/Repository.php +++ b/src/Repository.php @@ -34,6 +34,31 @@ class Repository extends \Ulmus\Repository return $this; } + protected function updateSqlQuery(array $dataset) : self + { + $condition = array_pop($this->queryBuilder->where->conditionList); + + if ($condition[0] === 'dn') { + if ( null === $this->queryBuilder->getFragment(Query\Update::class) ) { + $this->update($condition[1], "", ""); + } + } + else { + array_push($this->queryBuilder->where->conditionList, $condition); + } + + $this->set($dataset); + + return $this; + } + + public function update(string $dn, string $alias, ? string $schema) : self + { + $this->queryBuilder->update($dn, "", ""); + + return $this; + } + public function escapeValue(string $identifier) : string { return $this->adapter->adapter()->escapeIdentifier($identifier, Adapter\Ldap::IDENTIFIER_FILTER);