CauseFX 6 سال پیش
والد
کامیت
b23df64840
80فایلهای تغییر یافته به همراه1546 افزوده شده و 613 حذف شده
  1. 10 8
      api/composer.lock
  2. 2 0
      api/vendor/adldap2/adldap2/.gitignore
  3. 7 0
      api/vendor/adldap2/adldap2/.styleci.yml
  4. 1 0
      api/vendor/adldap2/adldap2/.travis.yml
  5. 5 3
      api/vendor/adldap2/adldap2/composer.json
  6. 16 0
      api/vendor/adldap2/adldap2/docs/_coverpage.md
  7. 3 2
      api/vendor/adldap2/adldap2/docs/_sidebar.md
  8. 18 16
      api/vendor/adldap2/adldap2/docs/index.html
  9. 1 0
      api/vendor/adldap2/adldap2/docs/media/bg.svg
  10. 0 6
      api/vendor/adldap2/adldap2/docs/models/entry.md
  11. 7 18
      api/vendor/adldap2/adldap2/docs/models/group.md
  12. 37 19
      api/vendor/adldap2/adldap2/docs/models/model.md
  13. 45 0
      api/vendor/adldap2/adldap2/docs/models/user.md
  14. 0 1
      api/vendor/adldap2/adldap2/docs/readme.md
  15. 1 1
      api/vendor/adldap2/adldap2/docs/troubleshooting.md
  16. 5 0
      api/vendor/adldap2/adldap2/phpunit.xml
  17. 2 0
      api/vendor/adldap2/adldap2/readme.md
  18. 23 15
      api/vendor/adldap2/adldap2/src/Adldap.php
  19. 2 2
      api/vendor/adldap2/adldap2/src/AdldapInterface.php
  20. 1 3
      api/vendor/adldap2/adldap2/src/Auth/BindException.php
  21. 4 6
      api/vendor/adldap2/adldap2/src/Auth/Guard.php
  22. 3 2
      api/vendor/adldap2/adldap2/src/Auth/GuardInterface.php
  23. 1 3
      api/vendor/adldap2/adldap2/src/Configuration/ConfigurationException.php
  24. 6 8
      api/vendor/adldap2/adldap2/src/Configuration/DomainConfiguration.php
  25. 1 3
      api/vendor/adldap2/adldap2/src/Configuration/Validators/ArrayValidator.php
  26. 1 3
      api/vendor/adldap2/adldap2/src/Configuration/Validators/BooleanValidator.php
  27. 2 2
      api/vendor/adldap2/adldap2/src/Configuration/Validators/ClassValidator.php
  28. 1 3
      api/vendor/adldap2/adldap2/src/Configuration/Validators/IntegerValidator.php
  29. 1 3
      api/vendor/adldap2/adldap2/src/Configuration/Validators/StringOrNullValidator.php
  30. 3 5
      api/vendor/adldap2/adldap2/src/Configuration/Validators/Validator.php
  31. 21 8
      api/vendor/adldap2/adldap2/src/Connections/ConnectionInterface.php
  32. 74 54
      api/vendor/adldap2/adldap2/src/Connections/Ldap.php
  33. 43 16
      api/vendor/adldap2/adldap2/src/Connections/Provider.php
  34. 7 6
      api/vendor/adldap2/adldap2/src/Connections/ProviderInterface.php
  35. 5 6
      api/vendor/adldap2/adldap2/src/Events/Dispatcher.php
  36. 1 1
      api/vendor/adldap2/adldap2/src/Events/DispatchesEvents.php
  37. 66 12
      api/vendor/adldap2/adldap2/src/Log/EventLogger.php
  38. 40 34
      api/vendor/adldap2/adldap2/src/Models/Attributes/AccountControl.php
  39. 4 4
      api/vendor/adldap2/adldap2/src/Models/Attributes/DistinguishedName.php
  40. 7 4
      api/vendor/adldap2/adldap2/src/Models/Attributes/Guid.php
  41. 2 2
      api/vendor/adldap2/adldap2/src/Models/Attributes/Sid.php
  42. 2 2
      api/vendor/adldap2/adldap2/src/Models/Attributes/TSProperty.php
  43. 17 16
      api/vendor/adldap2/adldap2/src/Models/Attributes/TSPropertyArray.php
  44. 11 13
      api/vendor/adldap2/adldap2/src/Models/BatchModification.php
  45. 8 14
      api/vendor/adldap2/adldap2/src/Models/Computer.php
  46. 5 5
      api/vendor/adldap2/adldap2/src/Models/Concerns/HasAttributes.php
  47. 3 3
      api/vendor/adldap2/adldap2/src/Models/Concerns/HasMemberOf.php
  48. 18 16
      api/vendor/adldap2/adldap2/src/Models/Concerns/HasUserProperties.php
  49. 1 3
      api/vendor/adldap2/adldap2/src/Models/Contact.php
  50. 3 7
      api/vendor/adldap2/adldap2/src/Models/Container.php
  51. 1 3
      api/vendor/adldap2/adldap2/src/Models/Entry.php
  52. 11 12
      api/vendor/adldap2/adldap2/src/Models/Factory.php
  53. 3 6
      api/vendor/adldap2/adldap2/src/Models/ForeignSecurityPrincipal.php
  54. 12 15
      api/vendor/adldap2/adldap2/src/Models/Group.php
  55. 121 42
      api/vendor/adldap2/adldap2/src/Models/Model.php
  56. 1 3
      api/vendor/adldap2/adldap2/src/Models/ModelDoesNotExistException.php
  57. 1 3
      api/vendor/adldap2/adldap2/src/Models/ModelNotFoundException.php
  58. 2 6
      api/vendor/adldap2/adldap2/src/Models/OrganizationalUnit.php
  59. 2 4
      api/vendor/adldap2/adldap2/src/Models/Printer.php
  60. 1 3
      api/vendor/adldap2/adldap2/src/Models/RootDse.php
  61. 111 28
      api/vendor/adldap2/adldap2/src/Models/User.php
  62. 1 3
      api/vendor/adldap2/adldap2/src/Models/UserPasswordIncorrectException.php
  63. 1 3
      api/vendor/adldap2/adldap2/src/Models/UserPasswordPolicyException.php
  64. 345 39
      api/vendor/adldap2/adldap2/src/Query/Builder.php
  65. 95 0
      api/vendor/adldap2/adldap2/src/Query/Cache.php
  66. 27 0
      api/vendor/adldap2/adldap2/src/Query/Collection.php
  67. 8 0
      api/vendor/adldap2/adldap2/src/Query/Events/Listing.php
  68. 8 0
      api/vendor/adldap2/adldap2/src/Query/Events/Paginate.php
  69. 54 0
      api/vendor/adldap2/adldap2/src/Query/Events/QueryExecuted.php
  70. 8 0
      api/vendor/adldap2/adldap2/src/Query/Events/Read.php
  71. 8 0
      api/vendor/adldap2/adldap2/src/Query/Events/Search.php
  72. 30 6
      api/vendor/adldap2/adldap2/src/Query/Factory.php
  73. 1 1
      api/vendor/adldap2/adldap2/src/Query/Operator.php
  74. 23 23
      api/vendor/adldap2/adldap2/src/Query/Processor.php
  75. 26 2
      api/vendor/adldap2/adldap2/src/Schemas/FreeIPA.php
  76. 8 0
      api/vendor/adldap2/adldap2/src/Schemas/OpenLDAP.php
  77. 32 30
      api/vendor/adldap2/adldap2/src/Schemas/Schema.php
  78. 27 9
      api/vendor/adldap2/adldap2/src/Schemas/SchemaInterface.php
  79. 20 5
      api/vendor/adldap2/adldap2/src/Utilities.php
  80. 11 9
      api/vendor/composer/installed.json

+ 10 - 8
api/composer.lock

@@ -8,24 +8,26 @@
     "packages": [
         {
             "name": "adldap2/adldap2",
-            "version": "v10.0.2",
+            "version": "v10.2.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/Adldap2/Adldap2.git",
-                "reference": "f38a58161c07a295f67d3e8877c4236cdd9170e6"
+                "reference": "f09ca4ae3a65dbf123b56dc7e4ace8682ea16cdb"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/Adldap2/Adldap2/zipball/f38a58161c07a295f67d3e8877c4236cdd9170e6",
-                "reference": "f38a58161c07a295f67d3e8877c4236cdd9170e6",
+                "url": "https://api.github.com/repos/Adldap2/Adldap2/zipball/f09ca4ae3a65dbf123b56dc7e4ace8682ea16cdb",
+                "reference": "f09ca4ae3a65dbf123b56dc7e4ace8682ea16cdb",
                 "shasum": ""
             },
             "require": {
+                "ext-json": "*",
                 "ext-ldap": "*",
-                "illuminate/contracts": "~5.0",
+                "illuminate/contracts": "~5.0|~6.0",
                 "php": ">=7.0",
-                "psr/log": "~1.1",
-                "tightenco/collect": "~5.0"
+                "psr/log": "~1.0",
+                "psr/simple-cache": "~1.0",
+                "tightenco/collect": "~5.0|~6.0"
             },
             "require-dev": {
                 "mockery/mockery": "~1.0",
@@ -61,7 +63,7 @@
                 "ldap",
                 "windows"
             ],
-            "time": "2019-02-16T04:26:37+00:00"
+            "time": "2019-12-18T15:07:31+00:00"
         },
         {
             "name": "composer/semver",

+ 2 - 0
api/vendor/adldap2/adldap2/.gitignore

@@ -1 +1,3 @@
+/.idea
 /vendor
+composer.lock

+ 7 - 0
api/vendor/adldap2/adldap2/.styleci.yml

@@ -0,0 +1,7 @@
+preset: recommended
+
+enabled:
+  - length_ordered_imports
+
+disabled:
+  - alpha_ordered_imports

+ 1 - 0
api/vendor/adldap2/adldap2/.travis.yml

@@ -5,6 +5,7 @@ php:
   - 7.1
   - 7.2
   - 7.3
+  - 7.4
 
 before_script:
   - travis_retry composer self-update

+ 5 - 3
api/vendor/adldap2/adldap2/composer.json

@@ -28,9 +28,11 @@
     "require": {
         "php": ">=7.0",
         "ext-ldap": "*",
-        "psr/log": "~1.1",
-        "tightenco/collect": "~5.0",
-        "illuminate/contracts": "~5.0"
+        "ext-json": "*",
+        "psr/log": "~1.0",
+        "psr/simple-cache": "~1.0",
+        "tightenco/collect": "~5.0|~6.0",
+        "illuminate/contracts": "~5.0|~6.0"
     },
     "require-dev": {
         "phpunit/phpunit": "~6.0",

+ 16 - 0
api/vendor/adldap2/adldap2/docs/_coverpage.md

@@ -0,0 +1,16 @@
+<!-- _coverpage.md -->
+
+# Adldap2
+
+<p align="center">
+    <a href="https://travis-ci.org/Adldap2/Adldap2"><img src="https://img.shields.io/travis/Adldap2/Adldap2.svg?style=flat-square"/></a>
+    <a href="https://scrutinizer-ci.com/g/Adldap2/Adldap2/?branch=master"><img src="https://img.shields.io/scrutinizer/g/adLDAP2/adLDAP2/master.svg?style=flat-square"/></a>
+    <a href="https://packagist.org/packages/adldap2/adldap2"><img src="https://img.shields.io/packagist/dt/adldap2/adldap2.svg?style=flat-square"/></a>
+    <a href="https://packagist.org/packages/adldap2/adldap2"><img src="https://img.shields.io/packagist/v/adldap2/adldap2.svg?style=flat-square"/></a>
+    <a href="https://packagist.org/packages/adldap2/adldap2"><img src="https://img.shields.io/packagist/l/adldap2/adldap2.svg?style=flat-square"/></a>
+</p>
+
+> Working with LDAP doesn't need to be hard.
+
+<!-- background image -->
+![](media/bg.svg)

+ 3 - 2
api/vendor/adldap2/adldap2/docs/_sidebar.md

@@ -1,3 +1,5 @@
+<!-- _sidebar.md -->
+
 * Getting Started
 
   * [Introduction](/)
@@ -14,11 +16,10 @@
   * [Troubleshooting](troubleshooting.md)
 
 * Models
-
+  * [Model (Base)](models/model.md)
   * [Computer](models/computer.md)
   * [Contact](models/contact.md)
   * [Container](models/container.md)
-  * [Entry (Base Model)](models/entry.md)
   * [Group](models/group.md)
   * [Organizational Unit](models/ou.md)
   * [Printer](models/printer.md)

+ 18 - 16
api/vendor/adldap2/adldap2/docs/index.html

@@ -1,6 +1,5 @@
 <!DOCTYPE html>
 <html lang="en">
-
     <head>
         <meta charset="UTF-8">
         <title>Adldap2 Documentation</title>
@@ -8,26 +7,29 @@
         <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
         <meta name="description" content="Adldap2 Documentation">
         <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
-        <link rel="stylesheet" href="//unpkg.com/docsify/lib/themes/vue.css">
+        <link rel="stylesheet" href="https://unpkg.com/docsify/lib/themes/vue.css">
     </head>
 
     <body>
         <div id="app"></div>
+
         <script>
-        window.$docsify = {
-            name: 'Adldap2',
-            repo: 'https://github.com/Adldap2/Adldap2',
-            autoHeader: true,
-            auto2top: true,
-            homepage: 'readme.md',
-            search: 'auto',
-            loadSidebar: true,
-            subMaxLevel: 3
-        }
+            window.$docsify = {
+                name: 'Adldap2',
+                repo: 'https://github.com/Adldap2/Adldap2',
+                autoHeader: true,
+                auto2top: true,
+                homepage: 'readme.md',
+                coverpage: true,
+                search: 'auto',
+                loadSidebar: true,
+                subMaxLevel: 3
+            }
         </script>
-        <script src="//unpkg.com/docsify/lib/docsify.min.js"></script>
-        <script src="//unpkg.com/prismjs/components/prism-php.min.js"></script>
-        <script src="//unpkg.com/docsify/lib/plugins/search.min.js"></script>
-    </body>
+        
 
+        <script src="https://unpkg.com/docsify/lib/docsify.min.js"></script>
+        <script src="https://unpkg.com/prismjs/components/prism-php.min.js"></script>
+        <script src="https://unpkg.com/docsify/lib/plugins/search.min.js"></script>
+    </body>
 </html>

+ 1 - 0
api/vendor/adldap2/adldap2/docs/media/bg.svg

@@ -0,0 +1 @@
+<svg xmlns='http://www.w3.org/2000/svg' width='100%' height='100%' viewBox='0 0 1600 800'><rect fill='#46ff55' width='1600' height='800'/><g ><path fill='#51ff76' d='M486 705.8c-109.3-21.8-223.4-32.2-335.3-19.4C99.5 692.1 49 703 0 719.8V800h843.8c-115.9-33.2-230.8-68.1-347.6-92.2C492.8 707.1 489.4 706.5 486 705.8z'/><path fill='#57ff94' d='M1600 0H0v719.8c49-16.8 99.5-27.8 150.7-33.5c111.9-12.7 226-2.4 335.3 19.4c3.4 0.7 6.8 1.4 10.2 2c116.8 24 231.7 59 347.6 92.2H1600V0z'/><path fill='#5affb1' d='M478.4 581c3.2 0.8 6.4 1.7 9.5 2.5c196.2 52.5 388.7 133.5 593.5 176.6c174.2 36.6 349.5 29.2 518.6-10.2V0H0v574.9c52.3-17.6 106.5-27.7 161.1-30.9C268.4 537.4 375.7 554.2 478.4 581z'/><path fill='#57ffcd' d='M0 0v429.4c55.6-18.4 113.5-27.3 171.4-27.7c102.8-0.8 203.2 22.7 299.3 54.5c3 1 5.9 2 8.9 3c183.6 62 365.7 146.1 562.4 192.1c186.7 43.7 376.3 34.4 557.9-12.6V0H0z'/><path fill='#50ffe8' d='M181.8 259.4c98.2 6 191.9 35.2 281.3 72.1c2.8 1.1 5.5 2.3 8.3 3.4c171 71.6 342.7 158.5 531.3 207.7c198.8 51.8 403.4 40.8 597.3-14.8V0H0v283.2C59 263.6 120.6 255.7 181.8 259.4z'/><path fill='#7dffe9' d='M1600 0H0v136.3c62.3-20.9 127.7-27.5 192.2-19.2c93.6 12.1 180.5 47.7 263.3 89.6c2.6 1.3 5.1 2.6 7.7 3.9c158.4 81.1 319.7 170.9 500.3 223.2c210.5 61 430.8 49 636.6-16.6V0z'/><path fill='#9effe9' d='M454.9 86.3C600.7 177 751.6 269.3 924.1 325c208.6 67.4 431.3 60.8 637.9-5.3c12.8-4.1 25.4-8.4 38.1-12.9V0H288.1c56 21.3 108.7 50.6 159.7 82C450.2 83.4 452.5 84.9 454.9 86.3z'/><path fill='#baffea' d='M1600 0H498c118.1 85.8 243.5 164.5 386.8 216.2c191.8 69.2 400 74.7 595 21.1c40.8-11.2 81.1-25.2 120.3-41.7V0z'/><path fill='#d2ffea' d='M1397.5 154.8c47.2-10.6 93.6-25.3 138.6-43.8c21.7-8.9 43-18.8 63.9-29.5V0H643.4c62.9 41.7 129.7 78.2 202.1 107.4C1020.4 178.1 1214.2 196.1 1397.5 154.8z'/><path fill='#e9ffeb' d='M1315.3 72.4c75.3-12.6 148.9-37.1 216.8-72.4h-723C966.8 71 1144.7 101 1315.3 72.4z'/></g></svg>

+ 0 - 6
api/vendor/adldap2/adldap2/docs/models/entry.md

@@ -1,6 +0,0 @@
-# The Entry Model
-
-The Entry model extends from the base `Adldap\Models\Model` class and contains
-no specific methods / attributes that are limited to it.
-
-This class exists for LDAP records that don't contain a valid / recognized `objectClass` to map to a specific model.

+ 7 - 18
api/vendor/adldap2/adldap2/docs/models/group.md

@@ -40,10 +40,7 @@ the members inside the group.
 $group = $provider->search()->groups()->first();
 
 foreach ($group->members as $member) {
-
-    // 'cn=John Doe,dc=corp,dc=acme,dc=org'
-    echo $member;
-
+    echo $member; // 'cn=John Doe,dc=corp,dc=acme,dc=org'
 }
 ```
 
@@ -55,24 +52,16 @@ This can be easily done with the `getMembers()` method on the group.
 $group = $provider->search()->groups()->first();
 
 foreach ($group->getMembers() as $member) {
-    // Will be an instance of a Adldap `Model`
-    $member->getCommonName();
+    echo get_class($member); // Instance of `Adldap\Models\Model`
+
+    echo $member->getCommonName();
 }
 ```
 
-You should be aware however, that calling the `getMembers()` method will
-query your `AD` server for **every** member contained in
-the group to retrieve its model.
-
-Think of this example below as what is being called behind the scenes:
+> **Note**: You should be aware however, that calling the `getMembers()` method will
+> query your `AD` server for **every** member contained in the group to retrieve
+> its model. For larger group sets it may be worth paginating them.
 
-```php
-$group = $provider->search()->groups()->first();
-
-foreach ($group->members as $member) {
-    $model = $provider->search()->findByDn($member);
-}
-```
 
 ### Paginating Group Members
 

+ 37 - 19
api/vendor/adldap2/adldap2/docs/models/model.md

@@ -2,8 +2,8 @@
 
 ## Introduction
 
-Adldap2 implements the ActiveRecord pattern. This means that each LDAP
-record in your directory is represented as it's own model instance.
+Adldap2 implements the [ActiveRecord](https://en.wikipedia.org/wiki/Active_record_pattern) pattern.
+This means that each LDAP record in your directory is represented as it's own model instance.
 
 ## Creating
 
@@ -21,7 +21,7 @@ Or you can chain all methods if you'd prefer:
 $user = $provider->make()->user();
 ```
 
-### Available Make Methods:
+### Available Make Methods
 
 When calling a make method, all of them accept an `$attributes` parameter
 to fill the model with your specified attributes.
@@ -130,9 +130,7 @@ $user = $provider->search()->find('jdoe');
 $user->exists; // Returns true.
 
 if ($user->delete()) {
-
     $user->exists; // Returns false.
-
 }
 ```
 
@@ -146,9 +144,7 @@ $user = $provider->make()->user([
 $user->exists; // Returns false.
 
 if ($user->save()) {
-    
     $user->exists; // Returns true.
-    
 }
 ```
 
@@ -375,6 +371,23 @@ $user->fill([
 ]);
 ```
 
+#### Setting Boolean Attributes
+
+When setting boolean attribute values, you cannot use `0` / `1` / `true` / `false` as these
+are simply converted to integer values when saving and your LDAP server will
+likely return an error for doing so on certain attributes.
+
+You will need to use the string versions of the boolean (`'TRUE'` / `'FALSE'`) for the
+boolean attribute to be set properly on your LDAP server.
+
+Here's an example:
+
+```php
+$user->setFirstAttribute('msExchHideFromAddressLists', 'TRUE');
+
+$user->save();
+```
+
 ### Creating Attributes
 
 To create an attribute that does not exist on the model, you can set it like a regular property:
@@ -514,36 +527,43 @@ $user->syncRaw();
 
 ## Moving / Renaming
 
-To move a user from one DN or OU to another, use the `move($newRdn, $newParentDn)` method:
+To move a user from one DN or OU to another, use the `move()` method:
 
-```php
-// New Relative distinguished name.
-$newRdn = 'cn=John Doe';
+> **Note**: The `move()` method is actually an alias for the `rename()` method.
 
+```php
 // New parent distiguished name.
 $newParentDn = 'OU=New Ou,DC=corp,DC=local';
 
-if ($user->move($newRdn, $newParentDn)) {
+if ($user->move($newParentDn)) {
     // User was successfully moved to the new OU.
 }
 ```
 
-If you would like to keep the models old RDN along side their new RDN, pass in false in the last parameter:
+You can also provide a model to move the child model into:
 
 ```php
-// New Relative distinguished name.
-$newRdn = 'cn=John Doe';
+// New parent OU.
+$newParentOu = $provider->search()->ous()->find('Accounting');
 
+if ($user->move($newParentOu)) {
+    // User was successfully moved to the new OU.
+}
+```
+
+If you would like to keep the models old RDN along side their new RDN, pass in false in the second parameter:
+
+```php
 // New parent distiguished name.
 $newParentDn = 'OU=New Ou,DC=corp,DC=local';
 
-if ($user->move($newRdn, $newParentDn, $deleteOldRdn = false)) {
+if ($user->move($newParentDn, $deleteOldRdn = false)) {
     // User was successfully moved to the new OU,
     // and their old RDN has been left in-tact.
 }
 ```
 
-To rename a users DN, just pass in their new relative distinguished name in the `rename($newRdn)` method:
+To rename a users DN, just pass in their new relative distinguished name in the `rename()` method:
 
 ```php
 $newRdn = 'cn=New Name';
@@ -553,8 +573,6 @@ if ($user->rename($newRdn)) {
 }
 ```
 
-> **Note**: The `rename()` method is actually an alias for the `move()` method.
-
 ## Deleting
 
 To delete a model, just call the `delete()` method:

+ 45 - 0
api/vendor/adldap2/adldap2/docs/models/user.md

@@ -3,6 +3,48 @@
 > **Note**: This model contains the trait `HasMemberOf`. For more information, visit the documentation:
 > [HasMemberOfTrait](/models/traits/has-member-of.md)
 
+## Creating
+
+> **Note**: If you need to create users with passwords, SSL or TLS **must** be enabled on your configured connection.
+> 
+> The password you enter for the user **must** also obey your LDAP servers password requirements,
+> otherwise you will receive a "Server is unwilling to perform" LDAP exception upon saving.
+
+```php
+// Construct a new User model instance.
+$user = $provider->make()->user();
+
+// Create the users distinguished name.
+// We're adding an OU onto the users base DN to have it be saved in the specified OU.
+$dn = $user->getDnBuilder()->addOu('Users'); // Built DN will be: "CN=John Doe,OU=Users,DC=acme,DC=org";
+
+// Set the users DN, account name.
+$user->setDn($dn);
+$user->setAccountName('jdoe');
+$user->setCommonName('John Doe');
+
+// Set the users password.
+// NOTE: This password must obey your AD servers password requirements
+// (including password history, length, special characters etc.)
+// otherwise saving will fail and you will receive an
+// "LDAP Server is unwilling to perform" message.
+$user->setPassword('correct-horse-battery-staple');
+
+// Get a new account control object for the user.
+$ac = $user->getUserAccountControlObject();
+
+// Mark the account as enabled (normal).
+$ac->accountIsNormal();
+
+// Set the account control on the user and save it.
+$user->setUserAccountControl($ac);
+
+// Save the user.
+$user->save();
+
+// All done! An enabled user will be created and is ready for use.
+```
+
 ## Methods
 
 There's a ton of available methods for the User model. Below is a list for a quick reference.
@@ -124,6 +166,9 @@ $user->getEmployeeId();
 // Get the users employee number.
 $user->getEmployeeNumber();
 
+// Get the users employee type
+$user->getEmployeeType();
+
 // Get the users room number.
 $user->getRoomNumber();
 

+ 0 - 1
api/vendor/adldap2/adldap2/docs/readme.md

@@ -31,7 +31,6 @@ Adldap2 allows you to easily manage the above problems without reinventing the w
 ## Implementations
 
 - [Laravel](https://github.com/Adldap2/Adldap2-Laravel)
-- [Kohana](https://github.com/Adldap2/Adldap2-Kohana)
 
 ## Quick Start
 

+ 1 - 1
api/vendor/adldap2/adldap2/docs/troubleshooting.md

@@ -48,7 +48,7 @@ $d = Adldap::getEventDispatcher();
 $d->listen(Failed::class, function (Failed $event) {
     $conn = $event->connection;
     
-    echo $conn->getLastError(); // 'Invalid credentails'
+    echo $conn->getLastError(); // 'Invalid credentials'
     echo $conn->getDiagnosticMessage(); // '80090308: LdapErr: DSID-0C09042A, comment: AcceptSecurityContext error, data 532, v3839'
     
     if ($error = $conn->getDetailedError()) {

+ 5 - 0
api/vendor/adldap2/adldap2/phpunit.xml

@@ -14,4 +14,9 @@
             <directory suffix="Test.php">./tests/</directory>
         </testsuite>
     </testsuites>
+    <filter>
+        <whitelist processUncoveredFilesFromWhitelist="true">
+            <directory suffix=".php">./src</directory>
+        </whitelist>
+    </filter>
 </phpunit>

+ 2 - 0
api/vendor/adldap2/adldap2/readme.md

@@ -1,3 +1,5 @@
+<!-- readme.md -->
+
 <h1 align="center">Adldap2</h1>
 
 <p align="center">

+ 23 - 15
api/vendor/adldap2/adldap2/src/Adldap.php

@@ -2,12 +2,12 @@
 
 namespace Adldap;
 
-use InvalidArgumentException;
 use Adldap\Log\EventLogger;
-use Adldap\Log\LogsInformation;
-use Adldap\Events\DispatchesEvents;
 use Adldap\Connections\Ldap;
+use InvalidArgumentException;
+use Adldap\Log\LogsInformation;
 use Adldap\Connections\Provider;
+use Adldap\Events\DispatchesEvents;
 use Adldap\Connections\ProviderInterface;
 use Adldap\Connections\ConnectionInterface;
 use Adldap\Configuration\DomainConfiguration;
@@ -30,6 +30,17 @@ class Adldap implements AdldapInterface
      */
     protected $providers = [];
 
+    /**
+     * The events to register listeners for during initialization.
+     *
+     * @var array
+     */
+    protected $listen = [
+        'Adldap\Auth\Events\*',
+        'Adldap\Query\Events\*',
+        'Adldap\Models\Events\*',
+    ];
+
     /**
      * {@inheritdoc}
      */
@@ -132,7 +143,7 @@ class Adldap implements AdldapInterface
     public function connect($name = null, $username = null, $password = null)
     {
         $provider = $name ? $this->getProvider($name) : $this->getDefaultProvider();
-        
+
         return $provider->connect($username, $password);
     }
 
@@ -163,17 +174,14 @@ class Adldap implements AdldapInterface
 
         $logger = $this->newEventLogger();
 
-        $dispatcher->listen('Adldap\Auth\Events\*', function ($eventName, $events) use ($logger) {
-            foreach ($events as $event) {
-                $logger->auth($event);
-            }
-        });
-
-        $dispatcher->listen('Adldap\Models\Events\*', function ($eventName, $events) use ($logger) {
-            foreach ($events as $event) {
-                $logger->model($event);
-            }
-        });
+        // We will go through each of our event wildcards and register their listener.
+        foreach ($this->listen as $event) {
+            $dispatcher->listen($event, function ($eventName, $events) use ($logger) {
+                foreach ($events as $event) {
+                    $logger->log($event);
+                }
+            });
+        }
     }
 
     /**

+ 2 - 2
api/vendor/adldap2/adldap2/src/AdldapInterface.php

@@ -14,9 +14,9 @@ interface AdldapInterface
      * @param string              $name
      * @param ConnectionInterface $connection
      *
-     * @return $this
-     *
      * @throws \InvalidArgumentException When an invalid type is given as the configuration argument.
+     *
+     * @return $this
      */
     public function addProvider($configuration, $name, ConnectionInterface $connection = null);
 

+ 1 - 3
api/vendor/adldap2/adldap2/src/Auth/BindException.php

@@ -6,11 +6,9 @@ use Adldap\AdldapException;
 use Adldap\Connections\DetailedError;
 
 /**
- * Class BindException
+ * Class BindException.
  *
  * Thrown when binding to an LDAP connection fails.
- *
- * @package Adldap\Auth
  */
 class BindException extends AdldapException
 {

+ 4 - 6
api/vendor/adldap2/adldap2/src/Auth/Guard.php

@@ -2,8 +2,8 @@
 
 namespace Adldap\Auth;
 
-use Throwable;
 use Exception;
+use Throwable;
 use Adldap\Auth\Events\Bound;
 use Adldap\Auth\Events\Failed;
 use Adldap\Auth\Events\Passed;
@@ -14,11 +14,9 @@ use Adldap\Connections\ConnectionInterface;
 use Adldap\Configuration\DomainConfiguration;
 
 /**
- * Class Guard
+ * Class Guard.
  *
  * Binds users to the current connection.
- *
- * @package Adldap\Auth
  */
 class Guard implements GuardInterface
 {
@@ -149,10 +147,10 @@ class Guard implements GuardInterface
      *
      * @param string $username
      *
-     * @return string
-     *
      * @throws \Adldap\Configuration\ConfigurationException If account_suffix or account_prefix do not
      *                                                      exist in the providers domain configuration
+     *
+     * @return string
      */
     protected function applyPrefixAndSuffix($username)
     {

+ 3 - 2
api/vendor/adldap2/adldap2/src/Auth/GuardInterface.php

@@ -22,7 +22,7 @@ interface GuardInterface
      * @param string $password   The users LDAP password.
      * @param bool   $bindAsUser Whether or not to bind as the user.
      *
-     * @throws \Adldap\Auth\BindException When re-binding to your LDAP server fails.
+     * @throws \Adldap\Auth\BindException             When re-binding to your LDAP server fails.
      * @throws \Adldap\Auth\UsernameRequiredException When username is empty.
      * @throws \Adldap\Auth\PasswordRequiredException When password is empty.
      *
@@ -36,7 +36,8 @@ interface GuardInterface
      * @param string|null $username
      * @param string|null $password
      *
-     * @throws \Adldap\Auth\BindException When binding to your LDAP server fails.
+     * @throws \Adldap\Auth\BindException              If binding to the LDAP server fails.
+     * @throws \Adldap\Connections\ConnectionException If upgrading the connection to TLS fails
      *
      * @return void
      */

+ 1 - 3
api/vendor/adldap2/adldap2/src/Configuration/ConfigurationException.php

@@ -5,12 +5,10 @@ namespace Adldap\Configuration;
 use Adldap\AdldapException;
 
 /**
- * Class ConfigurationException
+ * Class ConfigurationException.
  *
  * Thrown when a configuration value does not exist, or a
  * configuration value being set is not valid.
- *
- * @package Adldap\Configuration
  */
 class ConfigurationException extends AdldapException
 {

+ 6 - 8
api/vendor/adldap2/adldap2/src/Configuration/DomainConfiguration.php

@@ -6,11 +6,9 @@ use Adldap\Schemas\ActiveDirectory;
 use Adldap\Connections\ConnectionInterface;
 
 /**
- * Class DomainConfiguration
+ * Class DomainConfiguration.
  *
  * Contains an array of configuration options for a single LDAP connection.
- *
- * @package Adldap\Configuration
  */
 class DomainConfiguration
 {
@@ -92,7 +90,7 @@ class DomainConfiguration
      */
     public function set($key, $value)
     {
-        if($this->validate($key, $value)) {
+        if ($this->validate($key, $value)) {
             $this->options[$key] = $value;
         }
     }
@@ -104,9 +102,9 @@ class DomainConfiguration
      *
      * @param string $key
      *
-     * @return mixed
-     *
      * @throws ConfigurationException When the option specified does not exist.
+     *
+     * @return mixed
      */
     public function get($key)
     {
@@ -138,9 +136,9 @@ class DomainConfiguration
      * @param string $key
      * @param mixed  $value
      *
-     * @return bool
-     *
      * @throws ConfigurationException When an option value given is an invalid type.
+     *
+     * @return bool
      */
     protected function validate($key, $value)
     {

+ 1 - 3
api/vendor/adldap2/adldap2/src/Configuration/Validators/ArrayValidator.php

@@ -5,11 +5,9 @@ namespace Adldap\Configuration\Validators;
 use Adldap\Configuration\ConfigurationException;
 
 /**
- * Class ArrayValidator
+ * Class ArrayValidator.
  *
  * Validates that the configuration value is an array.
- *
- * @package Adldap\Configuration\Validators
  */
 class ArrayValidator extends Validator
 {

+ 1 - 3
api/vendor/adldap2/adldap2/src/Configuration/Validators/BooleanValidator.php

@@ -5,11 +5,9 @@ namespace Adldap\Configuration\Validators;
 use Adldap\Configuration\ConfigurationException;
 
 /**
- * Class BooleanValidator
+ * Class BooleanValidator.
  *
  * Validates that the configuration value is a boolean.
- *
- * @package Adldap\Configuration\Validators
  */
 class BooleanValidator extends Validator
 {

+ 2 - 2
api/vendor/adldap2/adldap2/src/Configuration/Validators/ClassValidator.php

@@ -9,9 +9,9 @@ class ClassValidator extends Validator
     /**
      * Validates the configuration value.
      *
-     * @return bool
-     *
      * @throws ConfigurationException When the value given fails validation.
+     *
+     * @return bool
      */
     public function validate()
     {

+ 1 - 3
api/vendor/adldap2/adldap2/src/Configuration/Validators/IntegerValidator.php

@@ -5,11 +5,9 @@ namespace Adldap\Configuration\Validators;
 use Adldap\Configuration\ConfigurationException;
 
 /**
- * Class IntegerValidator
+ * Class IntegerValidator.
  *
  * Validates that the configuration value is an integer / number.
- *
- * @package Adldap\Configuration\Validators
  */
 class IntegerValidator extends Validator
 {

+ 1 - 3
api/vendor/adldap2/adldap2/src/Configuration/Validators/StringOrNullValidator.php

@@ -5,11 +5,9 @@ namespace Adldap\Configuration\Validators;
 use Adldap\Configuration\ConfigurationException;
 
 /**
- * Class StringOrNullValidator
+ * Class StringOrNullValidator.
  *
  * Validates that the configuration value is a string or null.
- *
- * @package Adldap\Configuration\Validators
  */
 class StringOrNullValidator extends Validator
 {

+ 3 - 5
api/vendor/adldap2/adldap2/src/Configuration/Validators/Validator.php

@@ -3,11 +3,9 @@
 namespace Adldap\Configuration\Validators;
 
 /**
- * Class Validator
+ * Class Validator.
  *
  * Validates configuration values.
- *
- * @package Adldap\Configuration\Validators
  */
 abstract class Validator
 {
@@ -40,9 +38,9 @@ abstract class Validator
     /**
      * Validates the configuration value.
      *
-     * @return bool
-     *
      * @throws \Adldap\Configuration\ConfigurationException When the value given fails validation.
+     *
+     * @return bool
      */
     abstract public function validate();
 }

+ 21 - 8
api/vendor/adldap2/adldap2/src/Connections/ConnectionInterface.php

@@ -41,7 +41,7 @@ interface ConnectionInterface
 
     /**
      * Constructor.
-     * 
+     *
      * @param string|null $name The connection name.
      */
     public function __construct($name = null);
@@ -103,7 +103,7 @@ interface ConnectionInterface
 
     /**
      * Returns the connections name.
-     * 
+     *
      * @return string|null
      */
     public function getName();
@@ -264,6 +264,8 @@ interface ConnectionInterface
      *
      * @link http://php.net/manual/en/function.ldap-start-tls.php
      *
+     * @throws ConnectionException If starting TLS fails.
+     *
      * @return mixed
      */
     public function startTLS();
@@ -278,7 +280,7 @@ interface ConnectionInterface
      * @param string $password
      * @param bool   $sasl
      *
-     * @throws ConnectionException If connecting over TLS fails.
+     * @throws ConnectionException If starting TLS fails.
      *
      * @return bool
      */
@@ -319,9 +321,9 @@ interface ConnectionInterface
      * @param string $dn
      * @param $filter
      * @param array $fields
-     * @param bool   $onlyAttributes
-     * @param int    $size
-     * @param int    $time
+     * @param bool  $onlyAttributes
+     * @param int   $size
+     * @param int   $time
      *
      * @return mixed
      */
@@ -406,7 +408,7 @@ interface ConnectionInterface
 
     /**
      * Add attribute values to current attributes.
-     * 
+     *
      * @link http://php.net/manual/en/function.ldap-mod-add.php
      *
      * @param string $dn
@@ -454,7 +456,7 @@ interface ConnectionInterface
     public function controlPagedResult($pageSize = 1000, $isCritical = false, $cookie = '');
 
     /**
-     * Retrieve a paginated result response.
+     * Retrieve the LDAP pagination cookie.
      *
      * @link http://php.net/manual/en/function.ldap-control-paged-result-response.php
      *
@@ -465,6 +467,17 @@ interface ConnectionInterface
      */
     public function controlPagedResultResponse($result, &$cookie);
 
+    /**
+     * Frees up the memory allocated internally to store the result.
+     *
+     * @link https://www.php.net/manual/en/function.ldap-free-result.php
+     *
+     * @param resource $result
+     *
+     * @return bool
+     */
+    public function freeResult($result);
+
     /**
      * Returns the error number of the last command
      * executed on the current connection.

+ 74 - 54
api/vendor/adldap2/adldap2/src/Connections/Ldap.php

@@ -3,17 +3,15 @@
 namespace Adldap\Connections;
 
 /**
- * Class Ldap
+ * Class Ldap.
  *
  * A class that abstracts PHP's LDAP functions and stores the bound connection.
- *
- * @package Adldap\Connections
  */
 class Ldap implements ConnectionInterface
 {
     /**
      * The connection name.
-     * 
+     *
      * @var string|null
      */
     protected $name;
@@ -33,29 +31,21 @@ class Ldap implements ConnectionInterface
     protected $connection;
 
     /**
-     * Stores the bool whether or not
-     * the current connection is bound.
+     * The bound status of the connection.
      *
      * @var bool
      */
     protected $bound = false;
 
     /**
-     * Stores the bool to tell the connection
-     * whether or not to use SSL.
-     *
-     * To use SSL, your server must support LDAP over SSL.
-     * http://adldap.sourceforge.net/wiki/doku.php?id=ldap_over_ssl
+     * Whether the connection must be bound over SSL.
      *
      * @var bool
      */
     protected $useSSL = false;
 
     /**
-     * Stores the bool to tell the connection
-     * whether or not to use TLS.
-     *
-     * If you wish to use TLS you should ensure that $useSSL is set to false and vice-versa
+     * Whether the connection must be bound over TLS.
      *
      * @var bool
      */
@@ -150,7 +140,7 @@ class Ldap implements ConnectionInterface
      */
     public function getEntries($searchResults)
     {
-        return ldap_get_entries($this->getConnection(), $searchResults);
+        return ldap_get_entries($this->connection, $searchResults);
     }
 
     /**
@@ -158,7 +148,7 @@ class Ldap implements ConnectionInterface
      */
     public function getFirstEntry($searchResults)
     {
-        return ldap_first_entry($this->getConnection(), $searchResults);
+        return ldap_first_entry($this->connection, $searchResults);
     }
 
     /**
@@ -166,7 +156,7 @@ class Ldap implements ConnectionInterface
      */
     public function getNextEntry($entry)
     {
-        return ldap_next_entry($this->getConnection(), $entry);
+        return ldap_next_entry($this->connection, $entry);
     }
 
     /**
@@ -174,7 +164,7 @@ class Ldap implements ConnectionInterface
      */
     public function getAttributes($entry)
     {
-        return ldap_get_attributes($this->getConnection(), $entry);
+        return ldap_get_attributes($this->connection, $entry);
     }
 
     /**
@@ -182,7 +172,7 @@ class Ldap implements ConnectionInterface
      */
     public function countEntries($searchResults)
     {
-        return ldap_count_entries($this->getConnection(), $searchResults);
+        return ldap_count_entries($this->connection, $searchResults);
     }
 
     /**
@@ -190,7 +180,7 @@ class Ldap implements ConnectionInterface
      */
     public function compare($dn, $attribute, $value)
     {
-        return ldap_compare($this->getConnection(), $dn, $attribute, $value);
+        return ldap_compare($this->connection, $dn, $attribute, $value);
     }
 
     /**
@@ -198,7 +188,7 @@ class Ldap implements ConnectionInterface
      */
     public function getLastError()
     {
-        return ldap_error($this->getConnection());
+        return ldap_error($this->connection);
     }
 
     /**
@@ -209,12 +199,10 @@ class Ldap implements ConnectionInterface
         // If the returned error number is zero, the last LDAP operation
         // succeeded. We won't return a detailed error.
         if ($number = $this->errNo()) {
-            ldap_get_option($this->getConnection(), LDAP_OPT_DIAGNOSTIC_MESSAGE, $message);
+            ldap_get_option($this->connection, LDAP_OPT_DIAGNOSTIC_MESSAGE, $message);
 
             return new DetailedError($number, $this->err2Str($number), $message);
         }
-
-        return;
     }
 
     /**
@@ -222,7 +210,7 @@ class Ldap implements ConnectionInterface
      */
     public function getValuesLen($entry, $attribute)
     {
-        return ldap_get_values_len($this->getConnection(), $entry, $attribute);
+        return ldap_get_values_len($this->connection, $entry, $attribute);
     }
 
     /**
@@ -230,7 +218,7 @@ class Ldap implements ConnectionInterface
      */
     public function setOption($option, $value)
     {
-        return ldap_set_option($this->getConnection(), $option, $value);
+        return ldap_set_option($this->connection, $option, $value);
     }
 
     /**
@@ -248,7 +236,7 @@ class Ldap implements ConnectionInterface
      */
     public function setRebindCallback(callable $callback)
     {
-        return ldap_set_rebind_proc($this->getConnection(), $callback);
+        return ldap_set_rebind_proc($this->connection, $callback);
     }
 
     /**
@@ -256,16 +244,23 @@ class Ldap implements ConnectionInterface
      */
     public function startTLS()
     {
-        return ldap_start_tls($this->getConnection());
+        try {
+            return ldap_start_tls($this->connection);
+        } catch (\ErrorException $e) {
+            throw new ConnectionException($e->getMessage(), $e->getCode(), $e);
+        }
     }
 
     /**
      * {@inheritdoc}
      */
-    public function connect($hosts = [], $port = '389')
+    public function connect($hosts = [], $port = 389)
     {
         $this->host = $this->getConnectionString($hosts, $this->getProtocol(), $port);
 
+        // Reset the bound status if reinitializing the connection.
+        $this->bound = false;
+
         return $this->connection = ldap_connect($this->host);
     }
 
@@ -274,9 +269,13 @@ class Ldap implements ConnectionInterface
      */
     public function close()
     {
-        $connection = $this->getConnection();
+        $connection = $this->connection;
+
+        $result = is_resource($connection) ? ldap_close($connection) : false;
+
+        $this->bound = false;
 
-        return is_resource($connection) ? ldap_close($connection) : false;
+        return $result;
     }
 
     /**
@@ -284,7 +283,7 @@ class Ldap implements ConnectionInterface
      */
     public function search($dn, $filter, array $fields, $onlyAttributes = false, $size = 0, $time = 0)
     {
-        return ldap_search($this->getConnection(), $dn, $filter, $fields, $onlyAttributes, $size, $time);
+        return ldap_search($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time);
     }
 
     /**
@@ -292,7 +291,7 @@ class Ldap implements ConnectionInterface
      */
     public function listing($dn, $filter, array $fields, $onlyAttributes = false, $size = 0, $time = 0)
     {
-        return ldap_list($this->getConnection(), $dn, $filter, $fields, $onlyAttributes, $size, $time);
+        return ldap_list($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time);
     }
 
     /**
@@ -300,7 +299,7 @@ class Ldap implements ConnectionInterface
      */
     public function read($dn, $filter, array $fields, $onlyAttributes = false, $size = 0, $time = 0)
     {
-        return ldap_read($this->getConnection(), $dn, $filter, $fields, $onlyAttributes, $size, $time);
+        return ldap_read($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time);
     }
 
     /**
@@ -308,15 +307,22 @@ class Ldap implements ConnectionInterface
      */
     public function bind($username, $password, $sasl = false)
     {
-        if ($this->isUsingTLS() && $this->startTLS() === false) {
-            throw new ConnectionException("Unable to connect to LDAP server over TLS.");
+        // Prior to binding, we will upgrade our connectivity to TLS on our current
+        // connection and ensure we are not already bound before upgrading.
+        // This is to prevent subsequent upgrading on several binds.
+        if ($this->isUsingTLS() && !$this->isBound()) {
+            $this->startTLS();
         }
 
         if ($sasl) {
-            return $this->bound = ldap_sasl_bind($this->getConnection(), null, null, 'GSSAPI');
+            return $this->bound = ldap_sasl_bind($this->connection, null, null, 'GSSAPI');
         }
 
-        return $this->bound = ldap_bind($this->getConnection(), $username, $password);
+        return $this->bound = ldap_bind(
+            $this->connection,
+            $username,
+            html_entity_decode($password)
+        );
     }
 
     /**
@@ -324,7 +330,7 @@ class Ldap implements ConnectionInterface
      */
     public function add($dn, array $entry)
     {
-        return ldap_add($this->getConnection(), $dn, $entry);
+        return ldap_add($this->connection, $dn, $entry);
     }
 
     /**
@@ -332,7 +338,7 @@ class Ldap implements ConnectionInterface
      */
     public function delete($dn)
     {
-        return ldap_delete($this->getConnection(), $dn);
+        return ldap_delete($this->connection, $dn);
     }
 
     /**
@@ -340,7 +346,7 @@ class Ldap implements ConnectionInterface
      */
     public function rename($dn, $newRdn, $newParent, $deleteOldRdn = false)
     {
-        return ldap_rename($this->getConnection(), $dn, $newRdn, $newParent, $deleteOldRdn);
+        return ldap_rename($this->connection, $dn, $newRdn, $newParent, $deleteOldRdn);
     }
 
     /**
@@ -348,7 +354,7 @@ class Ldap implements ConnectionInterface
      */
     public function modify($dn, array $entry)
     {
-        return ldap_modify($this->getConnection(), $dn, $entry);
+        return ldap_modify($this->connection, $dn, $entry);
     }
 
     /**
@@ -356,7 +362,7 @@ class Ldap implements ConnectionInterface
      */
     public function modifyBatch($dn, array $values)
     {
-        return ldap_modify_batch($this->getConnection(), $dn, $values);
+        return ldap_modify_batch($this->connection, $dn, $values);
     }
 
     /**
@@ -364,7 +370,7 @@ class Ldap implements ConnectionInterface
      */
     public function modAdd($dn, array $entry)
     {
-        return ldap_mod_add($this->getConnection(), $dn, $entry);
+        return ldap_mod_add($this->connection, $dn, $entry);
     }
 
     /**
@@ -372,7 +378,7 @@ class Ldap implements ConnectionInterface
      */
     public function modReplace($dn, array $entry)
     {
-        return ldap_mod_replace($this->getConnection(), $dn, $entry);
+        return ldap_mod_replace($this->connection, $dn, $entry);
     }
 
     /**
@@ -380,7 +386,7 @@ class Ldap implements ConnectionInterface
      */
     public function modDelete($dn, array $entry)
     {
-        return ldap_mod_del($this->getConnection(), $dn, $entry);
+        return ldap_mod_del($this->connection, $dn, $entry);
     }
 
     /**
@@ -388,7 +394,7 @@ class Ldap implements ConnectionInterface
      */
     public function controlPagedResult($pageSize = 1000, $isCritical = false, $cookie = '')
     {
-        return ldap_control_paged_result($this->getConnection(), $pageSize, $isCritical, $cookie);
+        return ldap_control_paged_result($this->connection, $pageSize, $isCritical, $cookie);
     }
 
     /**
@@ -396,7 +402,15 @@ class Ldap implements ConnectionInterface
      */
     public function controlPagedResultResponse($result, &$cookie)
     {
-        return ldap_control_paged_result_response($this->getConnection(), $result, $cookie);
+        return ldap_control_paged_result_response($this->connection, $result, $cookie);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function freeResult($result)
+    {
+        return ldap_free_result($result);
     }
 
     /**
@@ -404,7 +418,7 @@ class Ldap implements ConnectionInterface
      */
     public function errNo()
     {
-        return ldap_errno($this->getConnection());
+        return ldap_errno($this->connection);
     }
 
     /**
@@ -446,7 +460,7 @@ class Ldap implements ConnectionInterface
      */
     public function getDiagnosticMessage()
     {
-        ldap_get_option($this->getConnection(), LDAP_OPT_ERROR_STRING, $message);
+        ldap_get_option($this->connection, LDAP_OPT_ERROR_STRING, $message);
 
         return $message;
     }
@@ -474,14 +488,20 @@ class Ldap implements ConnectionInterface
     /**
      * Generates an LDAP connection string for each host given.
      *
-     * @param string|array  $hosts
-     * @param string        $protocol
-     * @param string        $port
+     * @param string|array $hosts
+     * @param string       $protocol
+     * @param string       $port
      *
      * @return string
      */
     protected function getConnectionString($hosts, $protocol, $port)
     {
+        // If we are using SSL and using the default port, we
+        // will override it to use the default SSL port.
+        if ($this->isUsingSSL() && $port == 389) {
+            $port = self::PORT_SSL;
+        }
+
         // Normalize hosts into an array.
         $hosts = is_array($hosts) ? $hosts : [$hosts];
 

+ 43 - 16
api/vendor/adldap2/adldap2/src/Connections/Provider.php

@@ -3,23 +3,23 @@
 namespace Adldap\Connections;
 
 use Adldap\Adldap;
-use InvalidArgumentException;
 use Adldap\Auth\Guard;
+use Adldap\Query\Cache;
+use InvalidArgumentException;
 use Adldap\Auth\GuardInterface;
 use Adldap\Schemas\ActiveDirectory;
 use Adldap\Schemas\SchemaInterface;
-use Adldap\Query\Factory as SearchFactory;
+use Psr\SimpleCache\CacheInterface;
 use Adldap\Models\Factory as ModelFactory;
+use Adldap\Query\Factory as SearchFactory;
 use Adldap\Configuration\DomainConfiguration;
 
 /**
- * Class Provider
+ * Class Provider.
  *
  * Contains the LPAP connection and domain configuration to
  * instantiate factories for retrieving and creating
  * LDAP records as well as authentication (binding).
- *
- * @package Adldap\Connections
  */
 class Provider implements ProviderInterface
 {
@@ -51,6 +51,13 @@ class Provider implements ProviderInterface
      */
     protected $guard;
 
+    /**
+     * The providers cache instance.
+     *
+     * @var Cache|null
+     */
+    protected $cache;
+
     /**
      * {@inheritdoc}
      */
@@ -62,7 +69,7 @@ class Provider implements ProviderInterface
 
     /**
      * Close the LDAP connection (if bound) upon destruction.
-     * 
+     *
      * @return void
      */
     public function __destruct()
@@ -89,14 +96,14 @@ class Provider implements ProviderInterface
 
             $schema = $configuration->get('schema');
 
-            // We'll update our schema here when our configuration is set.
-            $this->setSchema(new $schema);
-            
+            // We will update our schema here when our configuration is set.
+            $this->setSchema(new $schema());
+
             return $this;
         }
 
         $class = DomainConfiguration::class;
-        
+
         throw new InvalidArgumentException(
             "Configuration must be array or instance of $class"
         );
@@ -107,7 +114,7 @@ class Provider implements ProviderInterface
      */
     public function setConnection(ConnectionInterface $connection = null)
     {
-        // We'll create a standard connection if one isn't given.
+        // We will create a standard connection if one isn't given.
         $this->connection = $connection ?: new Ldap();
 
         // Prepare the connection.
@@ -142,6 +149,20 @@ class Provider implements ProviderInterface
         return $this;
     }
 
+    /**
+     * Sets the cache store.
+     *
+     * @param CacheInterface $store
+     *
+     * @return $this
+     */
+    public function setCache(CacheInterface $store)
+    {
+        $this->cache = new Cache($store);
+
+        return $this;
+    }
+
     /**
      * {@inheritdoc}
      */
@@ -205,11 +226,17 @@ class Provider implements ProviderInterface
      */
     public function search()
     {
-        return new SearchFactory(
+        $factory = new SearchFactory(
             $this->connection,
             $this->schema,
             $this->configuration->get('base_dn')
         );
+
+        if ($this->cache) {
+            $factory->setCache($this->cache);
+        }
+
+        return $factory;
     }
 
     /**
@@ -243,9 +270,9 @@ class Provider implements ProviderInterface
     /**
      * Prepares the connection by setting configured parameters.
      *
-     * @return void
-     *
      * @throws \Adldap\Configuration\ConfigurationException When configuration options requested do not exist
+     *
+     * @return void
      */
     protected function prepareConnection()
     {
@@ -259,8 +286,8 @@ class Provider implements ProviderInterface
             $this->configuration->get('custom_options'),
             [
                 LDAP_OPT_PROTOCOL_VERSION => $this->configuration->get('version'),
-                LDAP_OPT_NETWORK_TIMEOUT => $this->configuration->get('timeout'),
-                LDAP_OPT_REFERRALS => $this->configuration->get('follow_referrals')
+                LDAP_OPT_NETWORK_TIMEOUT  => $this->configuration->get('timeout'),
+                LDAP_OPT_REFERRALS        => $this->configuration->get('follow_referrals'),
             ]
         );
 

+ 7 - 6
api/vendor/adldap2/adldap2/src/Connections/ProviderInterface.php

@@ -9,11 +9,11 @@ use Adldap\Configuration\DomainConfiguration;
 interface ProviderInterface
 {
     /**
-      * Constructor.
-      *
-      * @param DomainConfiguration|array $configuration
-      * @param ConnectionInterface|null  $connection
-      */
+     * Constructor.
+     *
+     * @param array|DomainConfiguration $configuration
+     * @param ConnectionInterface       $connection
+     */
     public function __construct($configuration, ConnectionInterface $connection);
 
     /**
@@ -120,7 +120,8 @@ interface ProviderInterface
      * @param string|null $username
      * @param string|null $password
      *
-     * @throws \Adldap\Auth\BindException When binding to your LDAP server fails.
+     * @throws \Adldap\Auth\BindException If binding to the LDAP server fails.
+     * @throws ConnectionException        If upgrading the connection to TLS fails
      *
      * @return ProviderInterface
      */

+ 5 - 6
api/vendor/adldap2/adldap2/src/Events/Dispatcher.php

@@ -5,7 +5,7 @@ namespace Adldap\Events;
 use Illuminate\Support\Arr;
 
 /**
- * Class Dispatcher
+ * Class Dispatcher.
  *
  * Handles event listening and dispatching.
  *
@@ -14,9 +14,8 @@ use Illuminate\Support\Arr;
  * an extra dependency that would be required.
  *
  * @author Taylor Otwell
- * @see https://github.com/laravel/framework
  *
- * @package Adldap\Events
+ * @see https://github.com/laravel/framework
  */
 class Dispatcher implements DispatcherInterface
 {
@@ -114,7 +113,7 @@ class Dispatcher implements DispatcherInterface
             // If a response is returned from the listener and event halting is enabled
             // we will just return this response, and not call the rest of the event
             // listeners. Otherwise we will add the response on the response list.
-            if ($halt && ! is_null($response)) {
+            if ($halt && !is_null($response)) {
                 return $response;
             }
 
@@ -250,8 +249,8 @@ class Dispatcher implements DispatcherInterface
     /**
      * Register an event listener with the dispatcher.
      *
-     * @param \Closure|string  $listener
-     * @param bool             $wildcard
+     * @param \Closure|string $listener
+     * @param bool            $wildcard
      *
      * @return \Closure
      */

+ 1 - 1
api/vendor/adldap2/adldap2/src/Events/DispatchesEvents.php

@@ -20,7 +20,7 @@ trait DispatchesEvents
     {
         // If no event dispatcher has been set, well instantiate and
         // set one here. This will be our singleton instance.
-        if (! isset(static::$dispatcher)) {
+        if (!isset(static::$dispatcher)) {
             static::setEventDispatcher(new Dispatcher());
         }
 

+ 66 - 12
api/vendor/adldap2/adldap2/src/Log/EventLogger.php

@@ -2,10 +2,12 @@
 
 namespace Adldap\Log;
 
+use ReflectionClass;
 use Psr\Log\LoggerInterface;
 use Adldap\Auth\Events\Failed;
 use Adldap\Auth\Events\Event as AuthEvent;
 use Adldap\Models\Events\Event as ModelEvent;
+use Adldap\Query\Events\QueryExecuted as QueryEvent;
 
 class EventLogger
 {
@@ -26,6 +28,22 @@ class EventLogger
         $this->logger = $logger;
     }
 
+    /**
+     * Logs the given event.
+     *
+     * @param mixed $event
+     */
+    public function log($event)
+    {
+        if ($event instanceof AuthEvent) {
+            $this->auth($event);
+        } elseif ($event instanceof ModelEvent) {
+            $this->model($event);
+        } elseif ($event instanceof QueryEvent) {
+            $this->query($event);
+        }
+    }
+
     /**
      * Logs an authentication event.
      *
@@ -36,14 +54,12 @@ class EventLogger
     public function auth(AuthEvent $event)
     {
         if (isset($this->logger)) {
-            $operation = get_class($event);
-
             $connection = $event->getConnection();
 
             $message = "LDAP ({$connection->getHost()})"
-                . " - Connection: {$connection->getName()}"
-                . " - Operation: {$operation}"
-                . " - Username: {$event->getUsername()}";
+                ." - Connection: {$connection->getName()}"
+                ." - Operation: {$this->getOperationName($event)}"
+                ." - Username: {$event->getUsername()}";
 
             $result = null;
             $type = 'info';
@@ -52,7 +68,7 @@ class EventLogger
                 $type = 'warning';
                 $result = " - Reason: {$connection->getLastError()}";
             }
-            
+
             $this->logger->$type($message.$result);
         }
     }
@@ -67,8 +83,6 @@ class EventLogger
     public function model(ModelEvent $event)
     {
         if (isset($this->logger)) {
-            $operation = get_class($event);
-
             $model = $event->getModel();
 
             $on = get_class($model);
@@ -76,12 +90,52 @@ class EventLogger
             $connection = $model->getQuery()->getConnection();
 
             $message = "LDAP ({$connection->getHost()})"
-                . " - Connection: {$connection->getName()}"
-                . " - Operation: {$operation}"
-                . " - On: {$on}"
-                . " - Distinguished Name: {$model->getDn()}";
+                ." - Connection: {$connection->getName()}"
+                ." - Operation: {$this->getOperationName($event)}"
+                ." - On: {$on}"
+                ." - Distinguished Name: {$model->getDn()}";
 
             $this->logger->info($message);
         }
     }
+
+    /**
+     * Logs a query event.
+     *
+     * @param QueryEvent $event
+     *
+     * @return void
+     */
+    public function query(QueryEvent $event)
+    {
+        if (isset($this->logger)) {
+            $query = $event->getQuery();
+
+            $connection = $query->getConnection();
+
+            $selected = implode(',', $query->getSelects());
+
+            $message = "LDAP ({$connection->getHost()})"
+                ." - Connection: {$connection->getName()}"
+                ." - Operation: {$this->getOperationName($event)}"
+                ." - Base DN: {$query->getDn()}"
+                ." - Filter: {$query->getUnescapedQuery()}"
+                ." - Selected: ({$selected})"
+                ." - Time Elapsed: {$event->getTime()}";
+
+            $this->logger->info($message);
+        }
+    }
+
+    /**
+     * Returns the operational name of the given event.
+     *
+     * @param mixed $event
+     *
+     * @return string
+     */
+    protected function getOperationName($event)
+    {
+        return (new ReflectionClass($event))->getShortName();
+    }
 }

+ 40 - 34
api/vendor/adldap2/adldap2/src/Models/Attributes/AccountControl.php

@@ -76,8 +76,7 @@ class AccountControl
     }
 
     /**
-     * Returns the account control integer as a string
-     * when the object is casted as a string.
+     * Get the value when casted to string.
      *
      * @return string
      */
@@ -87,8 +86,7 @@ class AccountControl
     }
 
     /**
-     * Returns the account control integer when
-     * the object is casted as an integer.
+     * Get the value when casted to int.
      *
      * @return int
      */
@@ -98,7 +96,37 @@ class AccountControl
     }
 
     /**
-     * Applies the specified flag.
+     * Add the value to the account control values.
+     *
+     * @param int $value
+     *
+     * @return AccountControl
+     */
+    public function add($value)
+    {
+        // Use the value as a key so if the same value
+        // is used, it will always be overwritten
+        $this->values[$value] = $value;
+
+        return $this;
+    }
+
+    /**
+     * Remove the value from the account control.
+     *
+     * @param int $value
+     *
+     * @return $this
+     */
+    public function remove($value)
+    {
+        unset($this->values[$value]);
+
+        return $this;
+    }
+
+    /**
+     * Extract and apply the flag.
      *
      * @param int $flag
      */
@@ -275,7 +303,7 @@ class AccountControl
      * The user cannot change the password. This is a permission on the user's object.
      *
      * For information about how to programmatically set this permission, visit the following link:
-     * 
+     *
      * @link http://msdn2.microsoft.com/en-us/library/aa746398.aspx
      *
      * @return AccountControl
@@ -369,23 +397,17 @@ class AccountControl
     }
 
     /**
-     * Returns the complete account control value.
+     * Get the account control value.
      *
      * @return int
      */
     public function getValue()
     {
-        $total = 0;
-
-        foreach ($this->values as $value) {
-            $total = $total + $value;
-        }
-
-        return $total;
+        return array_sum($this->values);
     }
 
     /**
-     * Returns the account control's values.
+     * Get the account control flag values.
      *
      * @return array
      */
@@ -395,7 +417,7 @@ class AccountControl
     }
 
     /**
-     * Sets the account control values.
+     * Set the account control values.
      *
      * @param array $flags
      */
@@ -405,7 +427,7 @@ class AccountControl
     }
 
     /**
-     * Returns an array containing all of the allowed user account control flags.
+     * Get all possible account control flags.
      *
      * @return array
      */
@@ -427,26 +449,10 @@ class AccountControl
 
         for ($i = 0; $i <= 26; $i++) {
             if ((int) $flag & (1 << $i)) {
-                array_push($flags, 1 << $i);
+                $flags[1 << $i] = 1 << $i;
             }
         }
 
         return $flags;
     }
-
-    /**
-     * Applies the inserted value to the values property array.
-     *
-     * @param int $value
-     *
-     * @return AccountControl
-     */
-    protected function add($value)
-    {
-        // Use the value as a key so if the same value
-        // is used, it will always be overwritten
-        $this->values[$value] = $value;
-
-        return $this;
-    }
 }

+ 4 - 4
api/vendor/adldap2/adldap2/src/Models/Attributes/DistinguishedName.php

@@ -12,11 +12,11 @@ class DistinguishedName
      * @var array
      */
     protected $components = [
-        'cn' => [],
+        'cn'  => [],
         'uid' => [],
-        'ou' => [],
-        'dc' => [],
-        'o' => [],
+        'ou'  => [],
+        'dc'  => [],
+        'o'   => [],
     ];
 
     /**

+ 7 - 4
api/vendor/adldap2/adldap2/src/Models/Attributes/Guid.php

@@ -18,6 +18,7 @@ class Guid
      * The guid structure in order by section to parse using substr().
      *
      * @author Chad Sikorra <Chad.Sikorra@gmail.com>
+     *
      * @link https://github.com/ldaptools/ldaptools
      *
      * @var array
@@ -34,15 +35,16 @@ class Guid
      * The hexadecimal octet order based on string position.
      *
      * @author Chad Sikorra <Chad.Sikorra@gmail.com>
+     *
      * @link https://github.com/ldaptools/ldaptools
      *
      * @var array
      */
     protected $octetSections = [
-        [6, 4, 2 ,0],
+        [6, 4, 2, 0],
         [10, 8],
         [14, 12],
-        [16, 18, 20, 22, 24, 26, 28, 30]
+        [16, 18, 20, 22, 24, 26, 28, 30],
     ];
 
     /**
@@ -68,10 +70,10 @@ class Guid
     {
         if (static::isValid($value)) {
             $this->value = $value;
-        } else if ($value = $this->binaryGuidToString($value)) {
+        } elseif ($value = $this->binaryGuidToString($value)) {
             $this->value = $value;
         } else {
-            throw new InvalidArgumentException("Invalid Binary / String GUID.");
+            throw new InvalidArgumentException('Invalid Binary / String GUID.');
         }
     }
 
@@ -129,6 +131,7 @@ class Guid
      * Return the specified section of the hexadecimal string.
      *
      * @author Chad Sikorra <Chad.Sikorra@gmail.com>
+     *
      * @link https://github.com/ldaptools/ldaptools
      *
      * @param string $hex      The full hex string.

+ 2 - 2
api/vendor/adldap2/adldap2/src/Models/Attributes/Sid.php

@@ -37,10 +37,10 @@ class Sid
     {
         if (static::isValid($value)) {
             $this->value = $value;
-        } else if ($value = $this->binarySidToString($value)) {
+        } elseif ($value = $this->binarySidToString($value)) {
             $this->value = $value;
         } else {
-            throw new InvalidArgumentException("Invalid Binary / String SID.");
+            throw new InvalidArgumentException('Invalid Binary / String SID.');
         }
     }
 

+ 2 - 2
api/vendor/adldap2/adldap2/src/Models/Attributes/TSProperty.php

@@ -175,7 +175,7 @@ class TSProperty
     {
         $nameLength = hexdec(substr($tsProperty, 0, 2));
 
-        # 1 data byte is 3 encoded bytes
+        // 1 data byte is 3 encoded bytes
         $valueLength = hexdec(substr($tsProperty, 2, 2)) * 3;
 
         $this->valueType = hexdec(substr($tsProperty, 4, 2));
@@ -393,4 +393,4 @@ class TSProperty
     {
         return str_pad(dechex($int), $padLength, 0, STR_PAD_LEFT);
     }
-}
+}

+ 17 - 16
api/vendor/adldap2/adldap2/src/Models/Attributes/TSPropertyArray.php

@@ -17,22 +17,22 @@ class TSPropertyArray
      * @var array
      */
     const DEFAULTS = [
-        'CtxCfgPresent' => 2953518677,
-        'CtxWFProfilePath' => '',
-        'CtxWFProfilePathW' => '',
-        'CtxWFHomeDir' => '',
-        'CtxWFHomeDirW' => '',
-        'CtxWFHomeDirDrive' => '',
-        'CtxWFHomeDirDriveW' => '',
-        'CtxShadow' => 1,
+        'CtxCfgPresent'           => 2953518677,
+        'CtxWFProfilePath'        => '',
+        'CtxWFProfilePathW'       => '',
+        'CtxWFHomeDir'            => '',
+        'CtxWFHomeDirW'           => '',
+        'CtxWFHomeDirDrive'       => '',
+        'CtxWFHomeDirDriveW'      => '',
+        'CtxShadow'               => 1,
         'CtxMaxDisconnectionTime' => 0,
-        'CtxMaxConnectionTime' => 0,
-        'CtxMaxIdleTime' => 0,
-        'CtxWorkDirectory' => '',
-        'CtxWorkDirectoryW' => '',
-        'CtxCfgFlags1' => 2418077696,
-        'CtxInitialProgram' => '',
-        'CtxInitialProgramW' => '',
+        'CtxMaxConnectionTime'    => 0,
+        'CtxMaxIdleTime'          => 0,
+        'CtxWorkDirectory'        => '',
+        'CtxWorkDirectoryW'       => '',
+        'CtxCfgFlags1'            => 2418077696,
+        'CtxInitialProgram'       => '',
+        'CtxInitialProgramW'      => '',
     ];
 
     /**
@@ -65,7 +65,7 @@ class TSPropertyArray
     protected $postBinary = '';
 
     /**
-     * Construct in one of the following ways:
+     * Construct in one of the following ways:.
      *
      *   - Pass an array of TSProperty key => value pairs (See DEFAULTS constant).
      *   - Pass the userParameters binary value. The object representation of that will be decoded and constructed.
@@ -120,6 +120,7 @@ class TSPropertyArray
      * Add a TSProperty object. If it already exists, it will be overwritten.
      *
      * @param TSProperty $tsProperty
+     *
      * @return $this
      */
     public function add(TSProperty $tsProperty)

+ 11 - 13
api/vendor/adldap2/adldap2/src/Models/BatchModification.php

@@ -5,12 +5,10 @@ namespace Adldap\Models;
 use InvalidArgumentException;
 
 /**
- * Class BatchModification
+ * Class BatchModification.
  *
  * A utility class to assist in the creation of LDAP
  * batch modifications and ensure their validity.
- *
- * @package Adldap\Models
  */
 class BatchModification
 {
@@ -52,9 +50,9 @@ class BatchModification
     /**
      * Constructor.
      *
-     * @param string|null      $attribute
-     * @param string|int|null  $type
-     * @param array            $values
+     * @param string|null     $attribute
+     * @param string|int|null $type
+     * @param array           $values
      */
     public function __construct($attribute = null, $type = null, $values = [])
     {
@@ -120,7 +118,7 @@ class BatchModification
      */
     public function setValues(array $values = [])
     {
-        $this->values = array_map(function($value) {
+        $this->values = array_map(function ($value) {
             // We need to make sure all values given to a batch modification are
             // strings, otherwise we'll receive an LDAP exception when
             // we try to process the modification.
@@ -150,7 +148,7 @@ class BatchModification
     public function setType($type = null)
     {
         if (!is_null($type) && !$this->isValidType($type)) {
-            throw new InvalidArgumentException("Given batch modification type is invalid.");
+            throw new InvalidArgumentException('Given batch modification type is invalid.');
         }
 
         $this->type = $type;
@@ -176,7 +174,7 @@ class BatchModification
      */
     public function isValid()
     {
-        return ! is_null($this->get());
+        return !is_null($this->get());
     }
 
     /**
@@ -234,8 +232,8 @@ class BatchModification
                 // A values key cannot be provided when
                 // a remove all type is selected.
                 return [
-                    static::KEY_ATTRIB => $this->attribute,
-                    static::KEY_MODTYPE => $this->type
+                    static::KEY_ATTRIB  => $this->attribute,
+                    static::KEY_MODTYPE => $this->type,
                 ];
             case LDAP_MODIFY_BATCH_REMOVE:
                 // Fallthrough.
@@ -243,9 +241,9 @@ class BatchModification
                 // Fallthrough.
             case LDAP_MODIFY_BATCH_REPLACE:
                 return [
-                    static::KEY_ATTRIB => $this->attribute,
+                    static::KEY_ATTRIB  => $this->attribute,
                     static::KEY_MODTYPE => $this->type,
-                    static::KEY_VALUES => $this->values,
+                    static::KEY_VALUES  => $this->values,
                 ];
             default:
                 // If the modtype isn't recognized, we'll return null.

+ 8 - 14
api/vendor/adldap2/adldap2/src/Models/Computer.php

@@ -2,24 +2,18 @@
 
 namespace Adldap\Models;
 
-use Adldap\Models\Concerns\HasDescription;
-use Adldap\Models\Concerns\HasUserAccountControl;
-use Adldap\Models\Concerns\HasLastLogonAndLogOff;
-use Adldap\Models\Concerns\HasCriticalSystemObject;
-
 /**
- * Class Computer
+ * Class Computer.
  *
  * Represents an LDAP computer / server.
- *
- * @package Adldap\Models
  */
 class Computer extends Entry
 {
-    use HasCriticalSystemObject,
-        HasDescription,
-        HasLastLogonAndLogOff,
-        HasUserAccountControl;
+    use Concerns\HasMemberOf,
+        Concerns\HasDescription,
+        Concerns\HasLastLogonAndLogOff,
+        Concerns\HasUserAccountControl,
+        Concerns\HasCriticalSystemObject;
 
     /**
      * Returns the computers operating system.
@@ -72,7 +66,7 @@ class Computer extends Entry
      *
      * @link https://msdn.microsoft.com/en-us/library/ms675243(v=vs.85).aspx
      *
-     * @return string
+     * @return int
      */
     public function getBadPasswordTime()
     {
@@ -84,7 +78,7 @@ class Computer extends Entry
      *
      * @link https://msdn.microsoft.com/en-us/library/ms675098(v=vs.85).aspx
      *
-     * @return string
+     * @return int
      */
     public function getAccountExpiry()
     {

+ 5 - 5
api/vendor/adldap2/adldap2/src/Models/Concerns/HasAttributes.php

@@ -30,7 +30,7 @@ trait HasAttributes
      * @var array
      */
     protected $attributes = [];
-    
+
     /**
      * The models original attributes.
      *
@@ -89,7 +89,7 @@ trait HasAttributes
      */
     public function getAttribute($key, $subKey = null)
     {
-        if (! $key) {
+        if (!$key) {
             return;
         }
 
@@ -256,7 +256,7 @@ trait HasAttributes
     {
         // Normalize key.
         $key = $this->normalizeAttributeKey($key);
-        
+
         if (is_null($subKey)) {
             return Arr::has($this->attributes, $key);
         }
@@ -295,7 +295,7 @@ trait HasAttributes
         $dirty = [];
 
         foreach ($this->attributes as $key => $value) {
-            if (! $this->originalIsEquivalent($key)) {
+            if (!$this->originalIsEquivalent($key)) {
                 // We need to reset the array's indices using array_values due to
                 // LDAP requiring consecutive indices (0, 1, 2 etc.)
                 $dirty[$key] = array_values($value);
@@ -326,7 +326,7 @@ trait HasAttributes
      */
     protected function originalIsEquivalent($key)
     {
-        if (! array_key_exists($key, $this->original)) {
+        if (!array_key_exists($key, $this->original)) {
             return false;
         }
 

+ 3 - 3
api/vendor/adldap2/adldap2/src/Models/Concerns/HasMemberOf.php

@@ -5,7 +5,7 @@ namespace Adldap\Models\Concerns;
 use Adldap\Utilities;
 use Adldap\Models\User;
 use Adldap\Models\Group;
-use Illuminate\Support\Collection;
+use Adldap\Query\Collection;
 
 trait HasMemberOf
 {
@@ -103,7 +103,7 @@ trait HasMemberOf
      * @param bool  $recursive
      * @param array $visited
      *
-     * @return \Illuminate\Support\Collection
+     * @return Collection
      */
     public function getGroups(array $fields = ['*'], $recursive = false, array $visited = [])
     {
@@ -223,7 +223,7 @@ trait HasMemberOf
         $query = $this->query->newInstance();
 
         return $query->newCollection($dns)->map(function ($dn) use ($query, $fields) {
-            return $query->select($fields)->findByDn($dn);
+            return $query->select($fields)->clearFilters()->findByDn($dn);
         })->filter(function ($group) {
             return $group instanceof Group;
         });

+ 18 - 16
api/vendor/adldap2/adldap2/src/Models/Concerns/HasUserProperties.php

@@ -7,7 +7,7 @@ trait HasUserProperties
     /**
      * Returns the users country.
      *
-     * @return string
+     * @return string|null
      */
     public function getCountry()
     {
@@ -31,7 +31,7 @@ trait HasUserProperties
      *
      * @link https://msdn.microsoft.com/en-us/library/ms675490(v=vs.85).aspx
      *
-     * @return string
+     * @return string|null
      */
     public function getDepartment()
     {
@@ -55,7 +55,7 @@ trait HasUserProperties
      *
      * @link https://msdn.microsoft.com/en-us/library/ms676855(v=vs.85).aspx
      *
-     * @return string
+     * @return string|null
      */
     public function getEmail()
     {
@@ -82,7 +82,7 @@ trait HasUserProperties
      *
      * @link https://msdn.microsoft.com/en-us/library/ms675675(v=vs.85).aspx
      *
-     * @return string
+     * @return string|null
      */
     public function getFacsimileNumber()
     {
@@ -112,6 +112,7 @@ trait HasUserProperties
     {
         return $this->getFirstAttribute($this->schema->firstName());
     }
+
     /**
      * Sets the users first name.
      *
@@ -127,7 +128,7 @@ trait HasUserProperties
     /**
      * Returns the users initials.
      *
-     * @return string
+     * @return string|null
      */
     public function getInitials()
     {
@@ -148,7 +149,7 @@ trait HasUserProperties
 
     /**
      * Returns the users IP Phone.
-     * 
+     *
      * @return string|null
      */
     public function getIpPhone()
@@ -179,6 +180,7 @@ trait HasUserProperties
     {
         return $this->getFirstAttribute($this->schema->lastName());
     }
+
     /**
      * Sets the users last name.
      *
@@ -194,7 +196,7 @@ trait HasUserProperties
     /**
      * Returns the users postal code.
      *
-     * @return string
+     * @return string|null
      */
     public function getPostalCode()
     {
@@ -276,13 +278,13 @@ trait HasUserProperties
      */
     public function getProxyAddresses()
     {
-        return $this->getAttribute($this->schema->proxyAddresses());
+        return $this->getAttribute($this->schema->proxyAddresses()) ?? [];
     }
 
     /**
      * Returns the users street address.
      *
-     * @return $this
+     * @return string|null
      */
     public function getStreetAddress()
     {
@@ -306,7 +308,7 @@ trait HasUserProperties
      *
      * @link https://msdn.microsoft.com/en-us/library/ms680037(v=vs.85).aspx
      *
-     * @return string
+     * @return string|null
      */
     public function getTitle()
     {
@@ -330,7 +332,7 @@ trait HasUserProperties
      *
      * @link https://msdn.microsoft.com/en-us/library/ms680027(v=vs.85).aspx
      *
-     * @return string
+     * @return string|null
      */
     public function getTelephoneNumber()
     {
@@ -351,8 +353,8 @@ trait HasUserProperties
 
     /**
      * Returns the users primary mobile phone number.
-     * 
-     * @return string
+     *
+     * @return string|null
      */
     public function getMobileNumber()
     {
@@ -373,8 +375,8 @@ trait HasUserProperties
 
     /**
      * Returns the users secondary (other) mobile phone number.
-     * 
-     * @return string
+     *
+     * @return string|null
      */
     public function getOtherMobileNumber()
     {
@@ -420,7 +422,7 @@ trait HasUserProperties
     /**
      * Returns the distinguished name of the user who is the user's manager.
      *
-     * @return string
+     * @return string|null
      */
     public function getManager()
     {

+ 1 - 3
api/vendor/adldap2/adldap2/src/Models/Contact.php

@@ -3,11 +3,9 @@
 namespace Adldap\Models;
 
 /**
- * Class Contact
+ * Class Contact.
  *
  * Represents an LDAP contact.
- *
- * @package Adldap\Models
  */
 class Contact extends Entry
 {

+ 3 - 7
api/vendor/adldap2/adldap2/src/Models/Container.php

@@ -2,19 +2,15 @@
 
 namespace Adldap\Models;
 
-use Adldap\Models\Concerns\HasDescription;
-use Adldap\Models\Concerns\HasCriticalSystemObject;
-
 /**
- * Class Container
+ * Class Container.
  *
  * Represents an LDAP container.
- *
- * @package Adldap\Models
  */
 class Container extends Entry
 {
-    use HasDescription, HasCriticalSystemObject;
+    use Concerns\HasDescription,
+        Concerns\HasCriticalSystemObject;
 
     /**
      * Returns the containers system flags integer.

+ 1 - 3
api/vendor/adldap2/adldap2/src/Models/Entry.php

@@ -3,11 +3,9 @@
 namespace Adldap\Models;
 
 /**
- * Class Entry
+ * Class Entry.
  *
  * Represents an LDAP record that could not be identified as another type of model.
- *
- * @package Adldap\Models
  */
 class Entry extends Model
 {

+ 11 - 12
api/vendor/adldap2/adldap2/src/Models/Factory.php

@@ -7,20 +7,22 @@ use Adldap\Schemas\ActiveDirectory;
 use Adldap\Schemas\SchemaInterface;
 
 /**
- * Class Factory
+ * Class Factory.
  *
- * Constructs and scopes LDAP queries.
- *
- * @package Adldap\Models
+ * Creates new LDAP models.
  */
 class Factory
 {
     /**
+     * The LDAP query builder.
+     *
      * @var Builder
      */
     protected $query;
 
     /**
+     * The LDAP schema.
+     *
      * @var SchemaInterface
      */
     protected $schema;
@@ -53,6 +55,8 @@ class Factory
     /**
      * Sets the current schema.
      *
+     * If null is given, a default ActiveDirectory schema is set.
+     *
      * @param SchemaInterface|null $schema
      *
      * @return $this
@@ -75,7 +79,7 @@ class Factory
     {
         $model = $this->schema->entryModel();
 
-        return (new $model($attributes, $this->query));
+        return new $model($attributes, $this->query);
     }
 
     /**
@@ -90,12 +94,7 @@ class Factory
         $model = $this->schema->userModel();
 
         return (new $model($attributes, $this->query))
-            ->setAttribute($this->schema->objectClass(), [
-                $this->schema->top(),
-                $this->schema->person(),
-                $this->schema->organizationalPerson(),
-                $this->schema->objectClassUser(),
-            ]);
+            ->setAttribute($this->schema->objectClass(), $this->schema->userObjectClasses());
     }
 
     /**
@@ -146,7 +145,7 @@ class Factory
         $model = $this->schema->containerModel();
 
         return (new $model($attributes, $this->query))
-            ->setAttribute($this->schema->objectClass(), $this->schema->organizationalUnit());
+            ->setAttribute($this->schema->objectClass(), $this->schema->objectClassContainer());
     }
 
     /**

+ 3 - 6
api/vendor/adldap2/adldap2/src/Models/ForeignSecurityPrincipal.php

@@ -1,16 +1,13 @@
 <?php
-namespace Adldap\Models;
 
-use Adldap\Models\Concerns\HasMemberOf;
+namespace Adldap\Models;
 
 /**
- * Class ForeignSecurityPrincipal
+ * Class ForeignSecurityPrincipal.
  *
  * Represents an LDAP ForeignSecurityPrincipal.
- *
- * @package Adldap\Models
  */
 class ForeignSecurityPrincipal extends Entry
 {
-    use HasMemberOf;
+    use Concerns\HasMemberOf;
 }

+ 12 - 15
api/vendor/adldap2/adldap2/src/Models/Group.php

@@ -2,34 +2,31 @@
 
 namespace Adldap\Models;
 
-use InvalidArgumentException;
 use Adldap\Utilities;
-use Adldap\Models\Concerns\HasMemberOf;
-use Adldap\Models\Concerns\HasDescription;
+use InvalidArgumentException;
 
 /**
- * Class Group
+ * Class Group.
  *
  * Represents an LDAP group (security / distribution).
- *
- * @package Adldap\Models
  */
 class Group extends Entry
 {
-    use HasDescription, HasMemberOf;
+    use Concerns\HasMemberOf,
+        Concerns\HasDescription;
 
     /**
      * Returns all users apart of the current group.
      *
      * @link https://msdn.microsoft.com/en-us/library/ms677097(v=vs.85).aspx
      *
-     * @return \Illuminate\Support\Collection
+     * @return \Adldap\Query\Collection
      */
     public function getMembers()
     {
         $members = $this->getMembersFromAttribute($this->schema->member());
 
-        if(count($members) === 0) {
+        if (count($members) === 0) {
             $members = $this->getPaginatedMembers();
         }
 
@@ -67,9 +64,7 @@ class Group extends Entry
      */
     public function setMembers(array $entries)
     {
-        $this->setAttribute($this->schema->member(), $entries);
-
-        return $this;
+        return $this->setAttribute($this->schema->member(), $entries);
     }
 
     /**
@@ -205,7 +200,9 @@ class Group extends Entry
             if ($identifier == 'dn' || $identifier == 'distinguishedname') {
                 $member = $query->findByDn($entry);
             } else {
-                $member = $query->findBy($identifier, $entry);
+                // We'll ensure we clear our filters when retrieving each member,
+                // so we can continue fetching the next one in line.
+                $member = $query->clearFilters()->findBy($identifier, $entry);
             }
 
             // We'll double check that we've received a model from
@@ -232,7 +229,7 @@ class Group extends Entry
         // We need to filter out the model attributes so
         // we only retrieve the member range.
         $attributes = array_values(array_filter($keys, function ($key) {
-            return strpos($key,'member;range') !== false;
+            return strpos($key, 'member;range') !== false;
         }));
 
         // We'll grab the member range key so we can run a
@@ -256,7 +253,7 @@ class Group extends Entry
             // If the query already included all member results (indicated
             // by the '*'), then we can return here. Otherwise we need
             // to continue on and retrieve the rest.
-            if($to === '*') {
+            if ($to === '*') {
                 return $members;
             }
 

+ 121 - 42
api/vendor/adldap2/adldap2/src/Models/Model.php

@@ -4,33 +4,30 @@ namespace Adldap\Models;
 
 use DateTime;
 use ArrayAccess;
+use Adldap\Utilities;
 use JsonSerializable;
+use Adldap\Query\Builder;
+use Illuminate\Support\Arr;
+use Adldap\Query\Collection;
 use InvalidArgumentException;
 use UnexpectedValueException;
-use Illuminate\Support\Arr;
-use Illuminate\Support\Collection;
-use Adldap\Utilities;
-use Adldap\Query\Builder;
-use Adldap\Schemas\SchemaInterface;
 use Adldap\Models\Attributes\Sid;
 use Adldap\Models\Attributes\Guid;
+use Adldap\Schemas\SchemaInterface;
 use Adldap\Models\Attributes\MbString;
-use Adldap\Models\Attributes\DistinguishedName;
-use Adldap\Models\Concerns\HasEvents;
-use Adldap\Models\Concerns\HasAttributes;
 use Adldap\Connections\ConnectionException;
+use Adldap\Models\Attributes\DistinguishedName;
 
 /**
- * Class Model
+ * Class Model.
  *
  * Represents an LDAP record and provides the ability
  * to modify / retrieve data from the record.
- *
- * @package Adldap\Models
  */
 abstract class Model implements ArrayAccess, JsonSerializable
 {
-    use HasAttributes, HasEvents;
+    use Concerns\HasEvents,
+        Concerns\HasAttributes;
 
     /**
      * Indicates if the model exists.
@@ -66,7 +63,7 @@ abstract class Model implements ArrayAccess, JsonSerializable
      * @param array   $attributes
      * @param Builder $builder
      */
-    public function __construct(array $attributes = [], Builder $builder)
+    public function __construct(array $attributes, Builder $builder)
     {
         $this->setQuery($builder)
             ->setSchema($builder->getSchema())
@@ -136,7 +133,7 @@ abstract class Model implements ArrayAccess, JsonSerializable
      *
      * @param mixed $items
      *
-     * @return \Illuminate\Support\Collection
+     * @return Collection
      */
     public function newCollection($items = [])
     {
@@ -176,7 +173,7 @@ abstract class Model implements ArrayAccess, JsonSerializable
      */
     public function offsetExists($offset)
     {
-        return isset($this->{$offset});
+        return !is_null($this->getAttribute($offset));
     }
 
     /**
@@ -188,7 +185,7 @@ abstract class Model implements ArrayAccess, JsonSerializable
      */
     public function offsetGet($offset)
     {
-        return $this->{$offset};
+        return $this->getAttribute($offset);
     }
 
     /**
@@ -201,7 +198,7 @@ abstract class Model implements ArrayAccess, JsonSerializable
      */
     public function offsetSet($offset, $value)
     {
-        $this->{$offset} = $value;
+        $this->setAttribute($offset, $value);
     }
 
     /**
@@ -213,7 +210,19 @@ abstract class Model implements ArrayAccess, JsonSerializable
      */
     public function offsetUnset($offset)
     {
-        unset($this->{$offset});
+        unset($this->attributes[$offset]);
+    }
+
+    /**
+     * Determine if an attribute exists on the model.
+     *
+     * @param string $key
+     *
+     * @return bool
+     */
+    public function __isset($key)
+    {
+        return $this->offsetExists($key);
     }
 
     /**
@@ -225,12 +234,12 @@ abstract class Model implements ArrayAccess, JsonSerializable
     {
         $attributes = $this->getAttributes();
 
-        array_walk_recursive($attributes, function(&$val) {
+        array_walk_recursive($attributes, function (&$val) {
             if (MbString::isLoaded()) {
                 // If we're able to detect the attribute
                 // encoding, we'll encode only the
                 // attributes that need to be.
-                if (! MbString::isUtf8($val)) {
+                if (!MbString::isUtf8($val)) {
                     $val = utf8_encode($val);
                 }
             } else {
@@ -245,7 +254,7 @@ abstract class Model implements ArrayAccess, JsonSerializable
         // their string equivalents for convenience.
         return array_replace($attributes, [
             $this->schema->objectGuid() => $this->getConvertedGuid(),
-            $this->schema->objectSid() => $this->getConvertedSid(),
+            $this->schema->objectSid()  => $this->getConvertedSid(),
         ]);
     }
 
@@ -258,7 +267,7 @@ abstract class Model implements ArrayAccess, JsonSerializable
     {
         $model = $this->query->newInstance()->findByDn($this->getDn());
 
-        return $model instanceof Model ? $model : null;
+        return $model instanceof self ? $model : null;
     }
 
     /**
@@ -383,6 +392,40 @@ abstract class Model implements ArrayAccess, JsonSerializable
         return $this->getNewDnBuilder($dn);
     }
 
+    /**
+     * Returns the models distinguished name components.
+     *
+     * @param bool $removeAttributePrefixes
+     *
+     * @return array
+     */
+    public function getDnComponents($removeAttributePrefixes = true)
+    {
+        if ($components = Utilities::explodeDn($this->getDn(), $removeAttributePrefixes)) {
+            unset($components['count']);
+
+            return $components;
+        }
+
+        return [];
+    }
+
+    /**
+     * Returns the distinguished name that the model is a leaf of.
+     *
+     * @return string
+     */
+    public function getDnRoot()
+    {
+        $components = $this->getDnComponents(false);
+
+        // Shift off the beginning of the array;
+        // This contains the models RDN.
+        array_shift($components);
+
+        return implode(',', $components);
+    }
+
     /**
      * Returns a new DistinguishedName object for building onto.
      *
@@ -555,6 +598,30 @@ abstract class Model implements ArrayAccess, JsonSerializable
         return $this->setFirstAttribute($this->schema->accountName(), $accountName);
     }
 
+    /**
+     * Returns the model's userPrincipalName.
+     *
+     * @link https://docs.microsoft.com/en-us/windows/win32/adschema/a-userprincipalname
+     *
+     * @return string
+     */
+    public function getUserPrincipalName()
+    {
+        return $this->getFirstAttribute($this->schema->userPrincipalName());
+    }
+
+    /**
+     * Sets the model's userPrincipalName.
+     *
+     * @param string $upn
+     *
+     * @return Model
+     */
+    public function setUserPrincipalName($upn)
+    {
+        return $this->setFirstAttribute($this->schema->userPrincipalName(), $upn);
+    }
+
     /**
      * Returns the model's samaccounttype.
      *
@@ -596,7 +663,7 @@ abstract class Model implements ArrayAccess, JsonSerializable
      */
     public function getCreatedAtTimestamp()
     {
-        return DateTime::createFromFormat('YmdHis.0Z', $this->getCreatedAt())->getTimestamp();
+        return DateTime::createFromFormat($this->timestampFormat, $this->getCreatedAt())->getTimestamp();
     }
 
     /**
@@ -736,7 +803,7 @@ abstract class Model implements ArrayAccess, JsonSerializable
      */
     public function setManagedBy($dn)
     {
-        if ($dn instanceof Model) {
+        if ($dn instanceof self) {
             $dn = $dn->getDn();
         }
 
@@ -777,7 +844,7 @@ abstract class Model implements ArrayAccess, JsonSerializable
      */
     public function inOu($ou, $strict = false)
     {
-        if ($ou instanceof Model) {
+        if ($ou instanceof self) {
             // If we've been given an OU model, we can
             // just check if the OU's DN is inside
             // the current models DN.
@@ -964,7 +1031,7 @@ abstract class Model implements ArrayAccess, JsonSerializable
      * Delete specific values in attributes:
      *
      *     ["memberuid" => "username"]
-     * 
+     *
      * Delete an entire attribute:
      *
      *     ["memberuid" => []]
@@ -998,11 +1065,13 @@ abstract class Model implements ArrayAccess, JsonSerializable
      * Throws a ModelNotFoundException if the current model does
      * not exist or does not contain a distinguished name.
      *
+     * @param bool $recursive Whether to recursively delete leaf nodes (models that are children).
+     *
      * @throws ModelDoesNotExistException
      *
      * @return bool
      */
-    public function delete()
+    public function delete($recursive = false)
     {
         $dn = $this->getDn();
 
@@ -1014,9 +1083,17 @@ abstract class Model implements ArrayAccess, JsonSerializable
 
         $this->fireModelEvent(new Events\Deleting($this));
 
+        if ($recursive) {
+            // If recursive is requested, we'll retrieve all direct leaf nodes
+            // by executing a 'listing' and delete each resulting model.
+            $this->newQuery()->listing()->in($this->getDn())->get()->each(function (self $model) use ($recursive) {
+                $model->delete($recursive);
+            });
+        }
+
         if ($this->query->getConnection()->delete($dn)) {
-            // We'll set the exists property to false on delete
-            // so the dev can run create operations.
+            // If the deletion was successful, we'll mark the model
+            // as non-existing and fire the deleted event.
             $this->exists = false;
 
             $this->fireModelEvent(new Events\Deleted($this));
@@ -1030,12 +1107,10 @@ abstract class Model implements ArrayAccess, JsonSerializable
     /**
      * Moves the current model into the given new parent.
      *
-     * For example:
-     *
-     *      $user->move($ou);
+     * For example: $user->move($ou);
      *
-     * @param string|Model $newParentDn The new parent of the current Model.
-     * @param bool         $deleteOldRdn
+     * @param Model|string $newParentDn  The new parent of the current model.
+     * @param bool         $deleteOldRdn Whether to delete the old models relative distinguished name once renamed / moved.
      *
      * @return bool
      */
@@ -1046,7 +1121,7 @@ abstract class Model implements ArrayAccess, JsonSerializable
 
         // If the current model has an empty RDN, we can't move it.
         if ((int) Arr::first($parts) === 0) {
-            throw new UnexpectedValueException("Current model does not contain an RDN to move.");
+            throw new UnexpectedValueException('Current model does not contain an RDN to move.');
         }
 
         // Looks like we have a DN. We'll retrieve the leftmost RDN (the identifier).
@@ -1058,15 +1133,19 @@ abstract class Model implements ArrayAccess, JsonSerializable
     /**
      * Renames the current model to a new RDN and new parent.
      *
-     * @param string      $rdn          The models new relative distinguished name. Example: "cn=JohnDoe"
-     * @param string|null $newParentDn  The models new parent distinguished name (if moving). Leave this null if you are only renaming. Example: "ou=MovedUsers,dc=acme,dc=org"
-     * @param bool|true   $deleteOldRdn Whether to delete the old models relative distinguished name onced renamed / moved.
+     * @param string            $rdn          The models new relative distinguished name. Example: "cn=JohnDoe"
+     * @param Model|string|null $newParentDn  The models new parent distinguished name (if moving). Leave this null if you are only renaming. Example: "ou=MovedUsers,dc=acme,dc=org"
+     * @param bool|true         $deleteOldRdn Whether to delete the old models relative distinguished name once renamed / moved.
      *
      * @return bool
      */
-    public function rename($rdn, $newParentDn, $deleteOldRdn = true)
+    public function rename($rdn, $newParentDn = null, $deleteOldRdn = true)
     {
-        $moved = $this->query->getConnection()->rename($this->getDn(), $rdn, (string) $newParentDn, $deleteOldRdn);
+        if ($newParentDn instanceof self) {
+            $newParentDn = $newParentDn->getDn();
+        }
+
+        $moved = $this->query->getConnection()->rename($this->getDn(), $rdn, $newParentDn, $deleteOldRdn);
 
         if ($moved) {
             // If the model was successfully moved, we'll set its
@@ -1160,11 +1239,11 @@ abstract class Model implements ArrayAccess, JsonSerializable
     {
         if (!$this->query->getConnection()->canChangePasswords()) {
             throw new ConnectionException(
-                "You must be connected to your LDAP server with TLS or SSL to perform this operation."
+                'You must be connected to your LDAP server with TLS or SSL to perform this operation.'
             );
         }
     }
-    
+
     /**
      * Converts the inserted string boolean to a PHP boolean.
      *

+ 1 - 3
api/vendor/adldap2/adldap2/src/Models/ModelDoesNotExistException.php

@@ -5,11 +5,9 @@ namespace Adldap\Models;
 use Adldap\AdldapException;
 
 /**
- * Class ModelDoesNotExistException
+ * Class ModelDoesNotExistException.
  *
  * Thrown when a model being saved / updated does not actually exist.
- *
- * @package Adldap\Models
  */
 class ModelDoesNotExistException extends AdldapException
 {

+ 1 - 3
api/vendor/adldap2/adldap2/src/Models/ModelNotFoundException.php

@@ -5,11 +5,9 @@ namespace Adldap\Models;
 use Adldap\AdldapException;
 
 /**
- * Class ModelNotFoundException
+ * Class ModelNotFoundException.
  *
  * Thrown when an LDAP record is not found.
- *
- * @package Adldap\Models
  */
 class ModelNotFoundException extends AdldapException
 {

+ 2 - 6
api/vendor/adldap2/adldap2/src/Models/OrganizationalUnit.php

@@ -2,18 +2,14 @@
 
 namespace Adldap\Models;
 
-use Adldap\Models\Concerns\HasDescription;
-
 /**
- * Class OrganizationalUnit
+ * Class OrganizationalUnit.
  *
  * Represents an LDAP organizational unit.
- *
- * @package Adldap\Models
  */
 class OrganizationalUnit extends Entry
 {
-    use HasDescription;
+    use Concerns\HasDescription;
 
     /**
      * Retrieves the organization units OU attribute.

+ 2 - 4
api/vendor/adldap2/adldap2/src/Models/Printer.php

@@ -3,11 +3,9 @@
 namespace Adldap\Models;
 
 /**
- * Class Printer
+ * Class Printer.
  *
  * Represents an LDAP printer.
- *
- * @package Adldap\Models
  */
 class Printer extends Entry
 {
@@ -283,6 +281,6 @@ class Printer extends Entry
      */
     public function getPrintRateUnit()
     {
-        return $this->getFirstAttribute($this->schema->printerPrintRate());
+        return $this->getFirstAttribute($this->schema->printerPrintRateUnit());
     }
 }

+ 1 - 3
api/vendor/adldap2/adldap2/src/Models/RootDse.php

@@ -5,11 +5,9 @@ namespace Adldap\Models;
 use DateTime;
 
 /**
- * Class RootDse
+ * Class RootDse.
  *
  * Represents the LDAP connections Root DSE record.
- *
- * @package Adldap\Models
  */
 class RootDse extends Model
 {

+ 111 - 28
api/vendor/adldap2/adldap2/src/Models/User.php

@@ -11,11 +11,9 @@ use Adldap\Models\Attributes\TSPropertyArray;
 use Illuminate\Contracts\Auth\Authenticatable;
 
 /**
- * Class User
+ * Class User.
  *
  * Represents an LDAP user.
- *
- * @package Adldap\Models
  */
 class User extends Entry implements Authenticatable
 {
@@ -25,6 +23,31 @@ class User extends Entry implements Authenticatable
         Concerns\HasLastLogonAndLogOff,
         Concerns\HasUserAccountControl;
 
+    /** @var callable|null */
+    private static $passwordStrategy;
+
+    /**
+     * Password will be processed using given callback before saving.
+     *
+     * @param callable $strategy
+     */
+    public static function usePasswordStrategy(callable $strategy)
+    {
+        static::$passwordStrategy = $strategy;
+    }
+
+    /**
+     * Will return user set password strategy or default one.
+     *
+     * @return callable
+     */
+    public static function getPasswordStrategy(): callable
+    {
+        return static::$passwordStrategy ?? function ($password) {
+            return Utilities::encodePassword($password);
+        };
+    }
+
     /**
      * Get the name of the unique identifier for the user.
      *
@@ -52,7 +75,6 @@ class User extends Entry implements Authenticatable
      */
     public function getAuthPassword()
     {
-        return;
     }
 
     /**
@@ -62,7 +84,6 @@ class User extends Entry implements Authenticatable
      */
     public function getRememberToken()
     {
-        return;
     }
 
     /**
@@ -74,7 +95,6 @@ class User extends Entry implements Authenticatable
      */
     public function setRememberToken($value)
     {
-        return;
     }
 
     /**
@@ -84,7 +104,6 @@ class User extends Entry implements Authenticatable
      */
     public function getRememberTokenName()
     {
-        return;
     }
 
     /**
@@ -261,6 +280,18 @@ class User extends Entry implements Authenticatable
         return $this->getFirstAttribute($this->schema->homeDirectory());
     }
 
+    /**
+     * The user's main home phone number.
+     *
+     * @link https://docs.microsoft.com/en-us/windows/desktop/ADSchema/a-homephone
+     *
+     * @return string|null
+     */
+    public function getHomePhone()
+    {
+        return $this->getFirstAttribute($this->schema->homePhone());
+    }
+
     /**
      * Returns the users principal name.
      *
@@ -362,19 +393,41 @@ class User extends Entry implements Authenticatable
     }
 
     /**
-     * Returns the formatted timestamp of the password last set date.
+     * Returns the bad password time unix timestamp.
      *
-     * @return string|null
+     * @return float|null
+     */
+    public function getBadPasswordTimestamp()
+    {
+        if ($time = $this->getBadPasswordTime()) {
+            return Utilities::convertWindowsTimeToUnixTime($time);
+        }
+    }
+
+    /**
+     * Returns the formatted timestamp of the bad password date.
      *
      * @throws \Exception
+     *
+     * @return string|null
      */
-    public function getPasswordLastSetDate()
+    public function getBadPasswordDate()
     {
-        if ($timestamp = $this->getPasswordLastSetTimestamp()) {
+        if ($timestamp = $this->getBadPasswordTimestamp()) {
             return (new DateTime())->setTimestamp($timestamp)->format($this->dateFormat);
         }
     }
 
+    /**
+     * Returns the time when the users password was set last.
+     *
+     * @return string
+     */
+    public function getPasswordLastSet()
+    {
+        return $this->getFirstAttribute($this->schema->passwordLastSet());
+    }
+
     /**
      * Returns the password last set unix timestamp.
      *
@@ -388,13 +441,17 @@ class User extends Entry implements Authenticatable
     }
 
     /**
-     * Returns the time when the users password was set last.
+     * Returns the formatted timestamp of the password last set date.
      *
-     * @return string
+     * @throws \Exception
+     *
+     * @return string|null
      */
-    public function getPasswordLastSet()
+    public function getPasswordLastSetDate()
     {
-        return $this->getFirstAttribute($this->schema->passwordLastSet());
+        if ($timestamp = $this->getPasswordLastSetTimestamp()) {
+            return (new DateTime())->setTimestamp($timestamp)->format($this->dateFormat);
+        }
     }
 
     /**
@@ -407,6 +464,32 @@ class User extends Entry implements Authenticatable
         return $this->getFirstAttribute($this->schema->lockoutTime());
     }
 
+    /**
+     * Returns the users lockout unix timestamp.
+     *
+     * @return float|null
+     */
+    public function getLockoutTimestamp()
+    {
+        if ($time = $this->getLockoutTime()) {
+            return Utilities::convertWindowsTimeToUnixTime($time);
+        }
+    }
+
+    /**
+     * Returns the formatted timestamp of the lockout date.
+     *
+     * @throws \Exception
+     *
+     * @return string|null
+     */
+    public function getLockoutDate()
+    {
+        if ($timestamp = $this->getLockoutTimestamp()) {
+            return (new DateTime())->setTimestamp($timestamp)->format($this->dateFormat);
+        }
+    }
+
     /**
      * Clears the accounts lockout time, unlocking the account.
      *
@@ -520,7 +603,7 @@ class User extends Entry implements Authenticatable
      * Sets the users thumbnail photo.
      *
      * @param string $data
-     * @param bool $encode
+     * @param bool   $encode
      *
      * @return $this
      */
@@ -544,7 +627,7 @@ class User extends Entry implements Authenticatable
     {
         $jpeg = $this->getJpegPhoto();
 
-        return is_null($jpeg) ? $jpeg : 'data:image/jpeg;base64,' . base64_encode($jpeg);
+        return is_null($jpeg) ? $jpeg : 'data:image/jpeg;base64,'.base64_encode($jpeg);
     }
 
     /**
@@ -730,7 +813,7 @@ class User extends Entry implements Authenticatable
     {
         $this->validateSecureConnection();
 
-        $encodedPassword = Utilities::encodePassword($password);
+        $encodedPassword = call_user_func(static::getPasswordStrategy(), $password);
 
         if ($this->exists) {
             // If the record exists, we need to add a batch replace
@@ -780,14 +863,14 @@ class User extends Entry implements Authenticatable
      *
      * Throws an exception on failure.
      *
-     * @param string $oldPassword The new password
-     * @param string $newPassword The old password
-     * @param bool $replaceNotRemove Alternative password change method. Set to true if you're receiving 'CONSTRAINT'
+     * @param string $oldPassword      The new password
+     * @param string $newPassword      The old password
+     * @param bool   $replaceNotRemove Alternative password change method. Set to true if you're receiving 'CONSTRAINT'
      *                                 errors.
      *
-     * @throws UserPasswordPolicyException When the new password does not match your password policy.
+     * @throws UserPasswordPolicyException    When the new password does not match your password policy.
      * @throws UserPasswordIncorrectException When the old password is incorrect.
-     * @throws AdldapException When an unknown cause of failure occurs.
+     * @throws AdldapException                When an unknown cause of failure occurs.
      *
      * @return true
      */
@@ -803,21 +886,21 @@ class User extends Entry implements Authenticatable
             $modifications[] = $this->newBatchModification(
                 $attribute,
                 LDAP_MODIFY_BATCH_REPLACE,
-                [Utilities::encodePassword($newPassword)]
+                [call_user_func(static::getPasswordStrategy(), $newPassword)]
             );
         } else {
             // Create batch modification for removing the old password.
             $modifications[] = $this->newBatchModification(
                 $attribute,
                 LDAP_MODIFY_BATCH_REMOVE,
-                [Utilities::encodePassword($oldPassword)]
+                [call_user_func(static::getPasswordStrategy(), $oldPassword)]
             );
 
             // Create batch modification for adding the new password.
             $modifications[] = $this->newBatchModification(
                 $attribute,
                 LDAP_MODIFY_BATCH_ADD,
-                [Utilities::encodePassword($newPassword)]
+                [call_user_func(static::getPasswordStrategy(), $newPassword)]
             );
         }
 
@@ -884,9 +967,9 @@ class User extends Entry implements Authenticatable
     /**
      * Return the expiration date of the user account.
      *
-     * @return DateTime|null
-     *
      * @throws \Exception
+     *
+     * @return DateTime|null
      */
     public function expirationDate()
     {

+ 1 - 3
api/vendor/adldap2/adldap2/src/Models/UserPasswordIncorrectException.php

@@ -5,12 +5,10 @@ namespace Adldap\Models;
 use Adldap\AdldapException;
 
 /**
- * Class UserPasswordIncorrectException
+ * Class UserPasswordIncorrectException.
  *
  * Thrown when a users password is being changed
  * and their current password given is incorrect.
- *
- * @package Adldap\Models
  */
 class UserPasswordIncorrectException extends AdldapException
 {

+ 1 - 3
api/vendor/adldap2/adldap2/src/Models/UserPasswordPolicyException.php

@@ -5,12 +5,10 @@ namespace Adldap\Models;
 use Adldap\AdldapException;
 
 /**
- * Class UserPasswordPolicyException
+ * Class UserPasswordPolicyException.
  *
  * Thrown when a users password is being changed but their new password
  * does not conform to the LDAP servers password policy.
- *
- * @package Adldap\Models
  */
 class UserPasswordPolicyException extends AdldapException
 {

+ 345 - 39
api/vendor/adldap2/adldap2/src/Query/Builder.php

@@ -3,12 +3,14 @@
 namespace Adldap\Query;
 
 use Closure;
-use InvalidArgumentException;
-use Illuminate\Support\Arr;
+use Adldap\Adldap;
 use Adldap\Utilities;
 use Adldap\Models\Model;
-use Adldap\Schemas\SchemaInterface;
+use Illuminate\Support\Arr;
+use InvalidArgumentException;
 use Adldap\Schemas\ActiveDirectory;
+use Adldap\Schemas\SchemaInterface;
+use Adldap\Query\Events\QueryExecuted;
 use Adldap\Models\ModelNotFoundException;
 use Adldap\Connections\ConnectionInterface;
 
@@ -28,7 +30,7 @@ class Builder
      */
     public $filters = [
         'and' => [],
-        'or' => [],
+        'or'  => [],
         'raw' => [],
     ];
 
@@ -95,6 +97,27 @@ class Builder
      */
     protected $nested = false;
 
+    /**
+     * Determines whether the query should be cached.
+     *
+     * @var bool
+     */
+    protected $caching = false;
+
+    /**
+     * How long the query should be cached until.
+     *
+     * @var \DateTimeInterface|null
+     */
+    protected $cacheUntil = null;
+
+    /**
+     * Determines whether the query cache must be flushed.
+     *
+     * @var bool
+     */
+    protected $flushCache = false;
+
     /**
      * The current connection instance.
      *
@@ -116,6 +139,13 @@ class Builder
      */
     protected $schema;
 
+    /**
+     * The current cache instance.
+     *
+     * @var Cache|null
+     */
+    protected $cache;
+
     /**
      * Constructor.
      *
@@ -182,6 +212,18 @@ class Builder
         return $this->schema;
     }
 
+    /**
+     * Sets the cache to store query results.
+     *
+     * @param Cache|null $cache
+     */
+    public function setCache(Cache $cache = null)
+    {
+        $this->cache = $cache;
+
+        return $this;
+    }
+
     /**
      * Returns a new Query Builder instance.
      *
@@ -220,7 +262,7 @@ class Builder
     /**
      * Returns the current query.
      *
-     * @return \Illuminate\Support\Collection|array
+     * @return Collection|array
      */
     public function get()
     {
@@ -236,6 +278,12 @@ class Builder
      */
     public function getQuery()
     {
+        // We need to ensure we have at least one filter, as
+        // no query results will be returned otherwise.
+        if (count(array_filter($this->filters)) === 0) {
+            $this->whereHas($this->schema->objectClass());
+        }
+
         return $this->grammar->compile($this);
     }
 
@@ -324,18 +372,32 @@ class Builder
      *
      * @param string $query
      *
-     * @return \Illuminate\Support\Collection|array
+     * @return \Adldap\Query\Collection|array
      */
     public function query($query)
     {
-        $results = $this->connection->{$this->type}(
-            $this->getDn(),
-            $query,
-            $this->getSelects(),
-            $onlyAttributes = false,
-            $this->limit
-        );
+        $start = microtime(true);
+
+        // Here we will create the execution callback. This allows us
+        // to only execute an LDAP request if caching is disabled
+        // or if no cache of the given query exists yet.
+        $callback = function () use ($query) {
+            return $this->parse($this->run($query));
+        };
+
+        // If caching is enabled and we have a cache instance available,
+        // we will try to retrieve the cached results instead.
+        // Otherwise, we will simply execute the callback.
+        if ($this->caching && $this->cache) {
+            $results = $this->getCachedResponse($this->getCacheKey($query), $callback);
+        } else {
+            $results = $callback();
+        }
+
+        // Log the query.
+        $this->logQuery($this, $this->type, $this->getElapsedTime($start));
 
+        // Process & return the results.
         return $this->newProcessor()->process($results);
     }
 
@@ -348,10 +410,82 @@ class Builder
      *
      * @return Paginator
      */
-    public function paginate($perPage = 50, $currentPage = 0, $isCritical = true)
+    public function paginate($perPage = 1000, $currentPage = 0, $isCritical = true)
     {
         $this->paginated = true;
 
+        $start = microtime(true);
+
+        $query = $this->getQuery();
+
+        // Here we will create the pagination callback. This allows us
+        // to only execute an LDAP request if caching is disabled
+        // or if no cache of the given query exists yet.
+        $callback = function () use ($query, $perPage, $isCritical) {
+            return $this->runPaginate($query, $perPage, $isCritical);
+        };
+
+        // If caching is enabled and we have a cache instance available,
+        // we will try to retrieve the cached results instead.
+        if ($this->caching && $this->cache) {
+            $pages = $this->getCachedResponse($this->getCacheKey($query), $callback);
+        } else {
+            $pages = $callback();
+        }
+
+        // Log the query.
+        $this->logQuery($this, 'paginate', $this->getElapsedTime($start));
+
+        // Process & return the results.
+        return $this->newProcessor()->processPaginated($pages, $perPage, $currentPage);
+    }
+
+    /**
+     * Get the cached response or execute and cache the callback value.
+     *
+     * @param string  $key
+     * @param Closure $callback
+     *
+     * @return mixed
+     */
+    protected function getCachedResponse($key, Closure $callback)
+    {
+        if ($this->flushCache) {
+            $this->cache->delete($key);
+        }
+
+        return $this->cache->remember($key, $this->cacheUntil, $callback);
+    }
+
+    /**
+     * Runs the query operation with the given filter.
+     *
+     * @param string $filter
+     *
+     * @return resource
+     */
+    protected function run($filter)
+    {
+        return $this->connection->{$this->type}(
+            $this->getDn(),
+            $filter,
+            $this->getSelects(),
+            $onlyAttributes = false,
+            $this->limit
+        );
+    }
+
+    /**
+     * Runs the paginate operation with the given filter.
+     *
+     * @param string $filter
+     * @param int    $perPage
+     * @param bool   $isCritical
+     *
+     * @return array
+     */
+    protected function runPaginate($filter, $perPage, $isCritical)
+    {
         $pages = [];
 
         $cookie = '';
@@ -360,25 +494,65 @@ class Builder
             $this->connection->controlPagedResult($perPage, $isCritical, $cookie);
 
             // Run the search.
-            $resource = @$this->connection->search($this->getDn(), $this->getQuery(), $this->getSelects());
+            $resource = $this->run($filter);
 
             if ($resource) {
+                // If we have been given a valid resource, we will retrieve the next
+                // pagination cookie to send for our next pagination request.
                 $this->connection->controlPagedResultResponse($resource, $cookie);
 
-                // We'll collect each resource result into the pages array.
-                $pages[] = $resource;
+                $pages[] = $this->parse($resource);
             }
         } while (!empty($cookie));
 
-        $paginator = $this->newProcessor()->processPaginated($pages, $perPage, $currentPage);
-
         // Reset paged result on the current connection. We won't pass in the current $perPage
         // parameter since we want to reset the page size to the default '1000'. Sending '0'
         // eliminates any further opportunity for running queries in the same request,
         // even though that is supposed to be the correct usage.
         $this->connection->controlPagedResult();
 
-        return $paginator;
+        return $pages;
+    }
+
+    /**
+     * Parses the given LDAP resource by retrieving its entries.
+     *
+     * @param resource $resource
+     *
+     * @return array
+     */
+    protected function parse($resource)
+    {
+        // Normalize entries. Get entries returns false on failure.
+        // We'll always want an array in this situation.
+        $entries = $this->connection->getEntries($resource) ?: [];
+
+        // Free up memory.
+        if (is_resource($resource)) {
+            $this->connection->freeResult($resource);
+        }
+
+        return $entries;
+    }
+
+    /**
+     * Returns the cache key.
+     *
+     * @param string $query
+     *
+     * @return string
+     */
+    protected function getCacheKey($query)
+    {
+        $key = $this->connection->getHost()
+            .$this->type
+            .$this->getDn()
+            .$query
+            .implode('', $this->getSelects())
+            .$this->limit
+            .$this->paginated;
+
+        return md5($key);
     }
 
     /**
@@ -435,7 +609,7 @@ class Builder
         try {
             return $this->findByOrFail($attribute, $value, $columns);
         } catch (ModelNotFoundException $e) {
-            return false;
+            return;
         }
     }
 
@@ -472,7 +646,7 @@ class Builder
         }
 
         // If we're not using ActiveDirectory, we can't use ANR. We'll make our own query.
-        if (! is_a($this->schema, ActiveDirectory::class)) {
+        if (!is_a($this->schema, ActiveDirectory::class)) {
             return $this->prepareAnrEquivalentQuery($value)->first($columns);
         }
 
@@ -485,13 +659,13 @@ class Builder
      * @param array $values
      * @param array $columns
      *
-     * @return \Illuminate\Support\Collection|array
+     * @return \Adldap\Query\Collection|array
      */
     public function findMany(array $values = [], $columns = [])
     {
         $this->select($columns);
 
-        if (! is_a($this->schema, ActiveDirectory::class)) {
+        if (!is_a($this->schema, ActiveDirectory::class)) {
             $query = $this;
 
             foreach ($values as $value) {
@@ -513,7 +687,7 @@ class Builder
      */
     protected function prepareAnrEquivalentQuery($value)
     {
-        return $this->orFilter(function (Builder $query) use ($value) {
+        return $this->orFilter(function (self $query) use ($value) {
             $locateBy = [
                 $this->schema->name(),
                 $this->schema->email(),
@@ -537,7 +711,7 @@ class Builder
      * @param array  $values
      * @param array  $columns
      *
-     * @return \Illuminate\Support\Collection|array
+     * @return \Adldap\Query\Collection|array
      */
     public function findManyBy($attribute, array $values = [], $columns = [])
     {
@@ -589,7 +763,7 @@ class Builder
         try {
             return $this->findByDnOrFail($dn, $columns);
         } catch (ModelNotFoundException $e) {
-            return false;
+            return;
         }
     }
 
@@ -639,7 +813,7 @@ class Builder
         try {
             return $this->findByGuidOrFail($guid, $columns);
         } catch (ModelNotFoundException $e) {
-            return false;
+            return;
         }
     }
 
@@ -662,7 +836,7 @@ class Builder
         }
 
         return $this->select($columns)->whereRaw([
-            $this->schema->objectGuid() => $guid
+            $this->schema->objectGuid() => $guid,
         ])->firstOrFail();
     }
 
@@ -679,7 +853,7 @@ class Builder
         try {
             return $this->findBySidOrFail($sid, $columns);
         } catch (ModelNotFoundException $e) {
-            return false;
+            return;
         }
     }
 
@@ -849,7 +1023,7 @@ class Builder
 
         $field = $this->escape($field, $ignore = null, 3);
 
-        $this->filters[$boolean][] = compact('field', 'operator', 'value');
+        $this->addFilter($boolean, compact('field', 'operator', 'value'));
 
         return $this;
     }
@@ -959,6 +1133,23 @@ class Builder
         return $this->where($field, Operator::$notContains, $value);
     }
 
+    /**
+     * Query for entries that match any of the values provided for the given field.
+     *
+     * @param string $field
+     * @param array  $values
+     *
+     * @return Builder
+     */
+    public function whereIn($field, array $values)
+    {
+        return $this->orFilter(function (self $query) use ($field, $values) {
+            foreach ($values as $value) {
+                $query->whereEquals($field, $value);
+            }
+        });
+    }
+
     /**
      * Adds a 'between' clause to the current query.
      *
@@ -1242,6 +1433,53 @@ class Builder
         return $this->orWhereEquals($this->schema->memberOfRecursive(), $dn);
     }
 
+    /**
+     * Adds a filter onto the current query.
+     *
+     * @param string $type     The type of filter to add.
+     * @param array  $bindings The bindings of the filter.
+     *
+     * @throws InvalidArgumentException
+     *
+     * @return $this
+     */
+    public function addFilter($type, array $bindings)
+    {
+        // Here we will ensure we have been given a proper filter type.
+        if (!array_key_exists($type, $this->filters)) {
+            throw new InvalidArgumentException("Invalid filter type: {$type}.");
+        }
+
+        // The required filter key bindings.
+        $required = ['field', 'operator', 'value'];
+
+        // Here we will ensure the proper key bindings are given.
+        if (count(array_intersect_key(array_flip($required), $bindings)) !== count($required)) {
+            // Retrieve the keys that are missing in the bindings array.
+            $missing = implode(', ', array_diff($required, array_flip($bindings)));
+
+            throw new InvalidArgumentException("Invalid filter bindings. Missing: {$missing} keys.");
+        }
+
+        $this->filters[$type][] = $bindings;
+
+        return $this;
+    }
+
+    /**
+     * Clear the query builders filters.
+     *
+     * @return $this
+     */
+    public function clearFilters()
+    {
+        foreach ($this->filters as $type => $filters) {
+            $this->filters[$type] = [];
+        }
+
+        return $this;
+    }
+
     /**
      * Returns true / false depending if the current object
      * contains selects.
@@ -1340,8 +1578,7 @@ class Builder
     }
 
     /**
-     * Sets the recursive property to tell the search whether or
-     * not to return the LDAP results in their raw format.
+     * Whether to return the LDAP results in their raw format.
      *
      * @param bool $raw
      *
@@ -1355,8 +1592,7 @@ class Builder
     }
 
     /**
-     * Sets the nested property to tell the Grammar instance whether
-     * or not the current query is already nested.
+     * Whether the current query is nested.
      *
      * @param bool $nested
      *
@@ -1370,13 +1606,22 @@ class Builder
     }
 
     /**
-     * Returns true / false if the current query is nested.
+     * Enables caching on the current query until the given date.
      *
-     * @return bool
+     * If flushing is enabled, the query cache will be flushed and then re-cached.
+     *
+     * @param \DateTimeInterface $until When to expire the query cache.
+     * @param bool               $flush Whether to force-flush the query cache.
+     *
+     * @return $this
      */
-    public function isNested()
+    public function cache(\DateTimeInterface $until = null, $flush = false)
     {
-        return $this->nested === true;
+        $this->caching = true;
+        $this->cacheUntil = $until;
+        $this->flushCache = $flush;
+
+        return $this;
     }
 
     /**
@@ -1423,6 +1668,16 @@ class Builder
         return $this->sortByFlags;
     }
 
+    /**
+     * Returns true / false if the current query is nested.
+     *
+     * @return bool
+     */
+    public function isNested()
+    {
+        return $this->nested === true;
+    }
+
     /**
      * Returns bool that determines whether the current
      * query builder will return raw results.
@@ -1568,6 +1823,57 @@ class Builder
         $this->where($field, '=', $parameters[$index], $bool);
     }
 
+    /**
+     * Logs the given executed query information by firing its query event.
+     *
+     * @param Builder    $query
+     * @param string     $type
+     * @param null|float $time
+     */
+    protected function logQuery($query, $type, $time = null)
+    {
+        $args = [$query, $time];
+
+        switch ($type) {
+            case 'listing':
+                $event = new Events\Listing(...$args);
+                break;
+            case 'read':
+                $event = new Events\Read(...$args);
+                break;
+            case 'paginate':
+                $event = new Events\Paginate(...$args);
+                break;
+            default:
+                $event = new Events\Search(...$args);
+                break;
+        }
+
+        $this->fireQueryEvent($event);
+    }
+
+    /**
+     * Fires the given query event.
+     *
+     * @param QueryExecuted $event
+     */
+    protected function fireQueryEvent(QueryExecuted $event)
+    {
+        Adldap::getEventDispatcher()->fire($event);
+    }
+
+    /**
+     * Get the elapsed time since a given starting point.
+     *
+     * @param int $start
+     *
+     * @return float
+     */
+    protected function getElapsedTime($start)
+    {
+        return round((microtime(true) - $start) * 1000, 2);
+    }
+
     /**
      * Returns a new query Processor instance.
      *

+ 95 - 0
api/vendor/adldap2/adldap2/src/Query/Cache.php

@@ -0,0 +1,95 @@
+<?php
+
+namespace Adldap\Query;
+
+use Closure;
+use Psr\SimpleCache\CacheInterface;
+
+class Cache
+{
+    /**
+     * The cache driver.
+     *
+     * @var CacheInterface
+     */
+    protected $store;
+
+    /**
+     * Constructor.
+     *
+     * @param CacheInterface $store
+     */
+    public function __construct(CacheInterface $store)
+    {
+        $this->store = $store;
+    }
+
+    /**
+     * Get an item from the cache.
+     *
+     * @param string $key
+     *
+     * @throws \Psr\SimpleCache\InvalidArgumentException
+     *
+     * @return mixed
+     */
+    public function get($key)
+    {
+        return $this->store->get($key);
+    }
+
+    /**
+     * Store an item in the cache.
+     *
+     * @param string                                    $key
+     * @param mixed                                     $value
+     * @param \DateTimeInterface|\DateInterval|int|null $ttl
+     *
+     * @throws \Psr\SimpleCache\InvalidArgumentException
+     *
+     * @return bool
+     */
+    public function put($key, $value, $ttl = null)
+    {
+        return $this->store->set($key, $value, $ttl);
+    }
+
+    /**
+     * Get an item from the cache, or execute the given Closure and store the result.
+     *
+     * @param string                                    $key
+     * @param \DateTimeInterface|\DateInterval|int|null $ttl
+     * @param Closure                                   $callback
+     *
+     * @throws \Psr\SimpleCache\InvalidArgumentException
+     *
+     * @return mixed
+     */
+    public function remember($key, $ttl, Closure $callback)
+    {
+        $value = $this->get($key);
+
+        if (!is_null($value)) {
+            return $value;
+        }
+
+        $this->put($key, $value = $callback(), $ttl);
+
+        return $value;
+    }
+
+    /**
+     * Delete an item from the cache.
+     *
+     * @param string $key
+     *
+     * @throws \Psr\Cache\InvalidArgumentException
+     * @throws \Psr\SimpleCache\InvalidArgumentException
+     *
+     * @return bool
+     */
+    public function delete($key)
+    {
+        return $this->store->delete($key);
+    }
+}

+ 27 - 0
api/vendor/adldap2/adldap2/src/Query/Collection.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace Adldap\Query;
+
+use Adldap\Models\Model;
+use Illuminate\Support\Collection as BaseCollection;
+
+class Collection extends BaseCollection
+{
+    /**
+     * {@inheritdoc}
+     */
+    protected function valueRetriever($value)
+    {
+        if ($this->useAsCallable($value)) {
+            return $value;
+        }
+
+        return function ($item) use ($value) {
+            if ($item instanceof Model) {
+                return $item->getFirstAttribute($value);
+            }
+
+            return data_get($item, $value);
+        };
+    }
+}

+ 8 - 0
api/vendor/adldap2/adldap2/src/Query/Events/Listing.php

@@ -0,0 +1,8 @@
+<?php
+
+namespace Adldap\Query\Events;
+
+class Listing extends QueryExecuted
+{
+    //
+}

+ 8 - 0
api/vendor/adldap2/adldap2/src/Query/Events/Paginate.php

@@ -0,0 +1,8 @@
+<?php
+
+namespace Adldap\Query\Events;
+
+class Paginate extends QueryExecuted
+{
+    //
+}

+ 54 - 0
api/vendor/adldap2/adldap2/src/Query/Events/QueryExecuted.php

@@ -0,0 +1,54 @@
+<?php
+
+namespace Adldap\Query\Events;
+
+use Adldap\Query\Builder;
+
+class QueryExecuted
+{
+    /**
+     * The LDAP filter that was used for the query.
+     *
+     * @var string
+     */
+    protected $query;
+
+    /**
+     * The number of milliseconds it took to execute the query.
+     *
+     * @var float
+     */
+    protected $time;
+
+    /**
+     * Constructor.
+     *
+     * @param Builder    $query
+     * @param null|float $time
+     */
+    public function __construct(Builder $query, $time = null)
+    {
+        $this->query = $query;
+        $this->time = $time;
+    }
+
+    /**
+     * Returns the LDAP filter that was used for the query.
+     *
+     * @return Builder
+     */
+    public function getQuery()
+    {
+        return $this->query;
+    }
+
+    /**
+     * Returns the number of milliseconds it took to execute the query.
+     *
+     * @return float|null
+     */
+    public function getTime()
+    {
+        return $this->time;
+    }
+}

+ 8 - 0
api/vendor/adldap2/adldap2/src/Query/Events/Read.php

@@ -0,0 +1,8 @@
+<?php
+
+namespace Adldap\Query\Events;
+
+class Read extends QueryExecuted
+{
+    //
+}

+ 8 - 0
api/vendor/adldap2/adldap2/src/Query/Events/Search.php

@@ -0,0 +1,8 @@
+<?php
+
+namespace Adldap\Query\Events;
+
+class Search extends QueryExecuted
+{
+    //
+}

+ 30 - 6
api/vendor/adldap2/adldap2/src/Query/Factory.php

@@ -12,7 +12,6 @@ use Adldap\Connections\ConnectionInterface;
  *
  * Constructs new LDAP queries.
  *
- * @package Adldap\Search
  *
  * @mixin Builder
  */
@@ -37,12 +36,19 @@ class Factory
      */
     protected $base;
 
+    /**
+     * The query cache.
+     *
+     * @var Cache
+     */
+    protected $cache;
+
     /**
      * Constructor.
      *
      * @param ConnectionInterface  $connection The connection to use when constructing a new query.
-     * @param SchemaInterface|null $schema The schema to use for the query and models located.
-     * @param string               $baseDn The base DN to use for all searches.
+     * @param SchemaInterface|null $schema     The schema to use for the query and models located.
+     * @param string               $baseDn     The base DN to use for all searches.
      */
     public function __construct(ConnectionInterface $connection, SchemaInterface $schema = null, $baseDn = '')
     {
@@ -93,6 +99,20 @@ class Factory
         return $this;
     }
 
+    /**
+     * Sets the cache for storing query results.
+     *
+     * @param Cache $cache
+     *
+     * @return $this
+     */
+    public function setCache(Cache $cache)
+    {
+        $this->cache = $cache;
+
+        return $this;
+    }
+
     /**
      * Returns a new query builder instance.
      *
@@ -108,7 +128,7 @@ class Factory
      * connection by performing a search for all entries
      * that contain a common name attribute.
      *
-     * @return \Illuminate\Support\Collection|array
+     * @return \Adldap\Query\Collection|array
      */
     public function get()
     {
@@ -124,7 +144,7 @@ class Factory
     {
         $wheres = [
             [$this->schema->objectClass(), Operator::$equals, $this->schema->objectClassUser()],
-            [$this->schema->objectCategory(), Operator::$equals, $this->schema->objectCategoryPerson()]
+            [$this->schema->objectCategory(), Operator::$equals, $this->schema->objectCategoryPerson()],
         ];
 
         // OpenLDAP doesn't like specifying the omission of user objectclasses
@@ -256,6 +276,10 @@ class Factory
      */
     protected function newBuilder()
     {
-        return new Builder($this->connection, $this->newGrammar(), $this->schema);
+        $builder = new Builder($this->connection, $this->newGrammar(), $this->schema);
+
+        $builder->setCache($this->cache);
+
+        return $builder;
     }
 }

+ 1 - 1
api/vendor/adldap2/adldap2/src/Query/Operator.php

@@ -35,7 +35,7 @@ class Operator
     public static $doesNotEqual = '!';
 
     /**
-     * The does not equal operator (alias)
+     * The does not equal operator (alias).
      *
      * @var string
      */

+ 23 - 23
api/vendor/adldap2/adldap2/src/Query/Processor.php

@@ -2,11 +2,9 @@
 
 namespace Adldap\Query;
 
-use InvalidArgumentException;
-use Illuminate\Support\Arr;
-use Illuminate\Support\Collection;
 use Adldap\Models\Entry;
 use Adldap\Models\Model;
+use InvalidArgumentException;
 use Adldap\Schemas\SchemaInterface;
 use Adldap\Connections\ConnectionInterface;
 
@@ -35,23 +33,19 @@ class Processor
     public function __construct(Builder $builder)
     {
         $this->builder = $builder;
-        $this->connection = $builder->getConnection();
         $this->schema = $builder->getSchema();
+        $this->connection = $builder->getConnection();
     }
 
     /**
      * Processes LDAP search results and constructs their model instances.
      *
-     * @param resource $results
+     * @param array $entries The LDAP entries to process.
      *
-     * @return array
+     * @return Collection|array
      */
-    public function process($results)
+    public function process($entries)
     {
-        // Normalize entries. Get entries returns false on failure.
-        // We'll always want an array in this situation.
-        $entries = $this->connection->getEntries($results) ?: [];
-
         if ($this->builder->isRaw()) {
             // If the builder is asking for a raw
             // LDAP result, we can return here.
@@ -60,7 +54,7 @@ class Processor
 
         $models = [];
 
-        if (Arr::has($entries, 'count')) {
+        if (array_key_exists('count', $entries)) {
             for ($i = 0; $i < $entries['count']; $i++) {
                 // We'll go through each entry and construct a new
                 // model instance with the raw LDAP attributes.
@@ -68,13 +62,19 @@ class Processor
             }
         }
 
-        if (!$this->builder->isPaginated()) {
-            // If the current query isn't paginated,
-            // we'll sort the models array here.
-            $models = $this->processSort($models);
+        // If the query contains paginated results, we'll return them here.
+        if ($this->builder->isPaginated()) {
+            return $models;
+        }
+
+        // If the query is requested to be sorted, we'll perform
+        // that here and return the resulting collection.
+        if ($this->builder->isSorted()) {
+            return $this->processSort($models);
         }
 
-        return $models;
+        // Otherwise, we'll return a regular unsorted collection.
+        return $this->newCollection($models);
     }
 
     /**
@@ -90,9 +90,9 @@ class Processor
     {
         $models = [];
 
-        foreach ($pages as $results) {
+        foreach ($pages as $entries) {
             // Go through each page and process the results into an objects array.
-            $models = array_merge($models, $this->process($results));
+            $models = array_merge($models, $this->process($entries));
         }
 
         $models = $this->processSort($models)->toArray();
@@ -111,6 +111,8 @@ class Processor
     {
         $objectClass = $this->schema->objectClass();
 
+        // We need to ensure the record contains an object class to be able to
+        // determine its type. Otherwise, we create a default Entry model.
         if (array_key_exists($objectClass, $attributes) && array_key_exists(0, $attributes[$objectClass])) {
             // Retrieve all of the object classes from the LDAP
             // entry and lowercase them for comparisons.
@@ -176,7 +178,7 @@ class Processor
     }
 
     /**
-     * Returns a new doctrine array collection instance.
+     * Returns a new collection instance.
      *
      * @param array $items
      *
@@ -204,8 +206,6 @@ class Processor
 
         $desc = ($direction === 'desc' ? true : false);
 
-        return $this->newCollection($models)->sortBy(function (Model $model) use ($field) {
-            return $model->getFirstAttribute($field);
-        }, $flags, $desc);
+        return $this->newCollection($models)->sortBy($field, $flags, $desc);
     }
 }

+ 26 - 2
api/vendor/adldap2/adldap2/src/Schemas/FreeIPA.php

@@ -4,6 +4,14 @@ namespace Adldap\Schemas;
 
 class FreeIPA extends Schema
 {
+    /**
+     * {@inheritdoc}
+     */
+    public function accountName()
+    {
+        return 'uid';
+    }
+
     /**
      * {@inheritdoc}
      */
@@ -28,6 +36,14 @@ class FreeIPA extends Schema
         return 'ipausergroup';
     }
 
+    /**
+     * {@inheritdoc}
+     */
+    public function userPrincipalName()
+    {
+        return 'krbCanonicalName';
+    }
+
     /**
      * {@inheritdoc}
      */
@@ -60,6 +76,14 @@ class FreeIPA extends Schema
         return 'lockouttime';
     }
 
+    /**
+     * {@inheritdoc}
+     */
+    public function passwordLastSet()
+    {
+        return 'krbLastPwdChange';
+    }
+
     /**
      * {@inheritdoc}
      */
@@ -89,7 +113,7 @@ class FreeIPA extends Schema
      */
     public function objectGuid()
     {
-        return 'objectguid';
+        return 'ipaUniqueID';
     }
 
     /**
@@ -97,6 +121,6 @@ class FreeIPA extends Schema
      */
     public function objectGuidRequiresConversion()
     {
-        return true;
+        return false;
     }
 }

+ 8 - 0
api/vendor/adldap2/adldap2/src/Schemas/OpenLDAP.php

@@ -4,6 +4,14 @@ namespace Adldap\Schemas;
 
 class OpenLDAP extends Schema
 {
+    /**
+     * {@inheritdoc}
+     */
+    public function accountName()
+    {
+        return 'uid';
+    }
+
     /**
      * {@inheritdoc}
      */

+ 32 - 30
api/vendor/adldap2/adldap2/src/Schemas/Schema.php

@@ -95,9 +95,7 @@ abstract class Schema implements SchemaInterface
     }
 
     /**
-     * The class name of the Computer model.
-     *
-     * @return string
+     * {@inheritdoc}
      */
     public function computerModel()
     {
@@ -121,9 +119,7 @@ abstract class Schema implements SchemaInterface
     }
 
     /**
-     * The class name of the Contact model.
-     *
-     * @return string
+     * {@inheritdoc}
      */
     public function contactModel()
     {
@@ -131,9 +127,7 @@ abstract class Schema implements SchemaInterface
     }
 
     /**
-     * The class name of the Container model.
-     *
-     * @return string
+     * {@inheritdoc}
      */
     public function containerModel()
     {
@@ -277,9 +271,7 @@ abstract class Schema implements SchemaInterface
     }
 
     /**
-     * The class name of the Entry model.
-     *
-     * @return string
+     * {@inheritdoc}
      */
     public function entryModel()
     {
@@ -294,7 +286,6 @@ abstract class Schema implements SchemaInterface
         return 'FALSE';
     }
 
-
     /**
      * {@inheritdoc}
      */
@@ -304,9 +295,7 @@ abstract class Schema implements SchemaInterface
     }
 
     /**
-     * The class name of the Group model.
-     *
-     * @return string
+     * {@inheritdoc}
      */
     public function groupModel()
     {
@@ -353,6 +342,14 @@ abstract class Schema implements SchemaInterface
         return 'homedirectory';
     }
 
+    /**
+     * {@inheritdoc}
+     */
+    public function homePhone()
+    {
+        return 'homephone';
+    }
+
     /**
      * {@inheritdoc}
      */
@@ -518,7 +515,7 @@ abstract class Schema implements SchemaInterface
      */
     public function memberRange($from, $to)
     {
-        return $this->member() . ";range={$from}-{$to}";
+        return $this->member().";range={$from}-{$to}";
     }
 
     /**
@@ -694,7 +691,7 @@ abstract class Schema implements SchemaInterface
             $this->objectClassContainer()                   => $this->containerModel(),
             $this->objectClassPrinter()                     => $this->printerModel(),
             $this->objectClassOu()                          => $this->organizationalUnitModel(),
-            $this->objectClassForeignSecurityPrincipal()    => $this->foreignSecurityPrincipalModel()
+            $this->objectClassForeignSecurityPrincipal()    => $this->foreignSecurityPrincipalModel(),
         ];
     }
 
@@ -763,9 +760,7 @@ abstract class Schema implements SchemaInterface
     }
 
     /**
-     * The class name of the Organizational Unit model.
-     *
-     * @return string
+     * {@inheritdoc}
      */
     public function organizationalUnitModel()
     {
@@ -909,9 +904,7 @@ abstract class Schema implements SchemaInterface
     }
 
     /**
-     * The class name of the Printer model.
-     *
-     * @return string
+     * {@inheritdoc}
      */
     public function printerModel()
     {
@@ -1191,15 +1184,26 @@ abstract class Schema implements SchemaInterface
     }
 
     /**
-     * The class name of the User model.
-     *
-     * @return string
+     * {@inheritdoc}
      */
     public function userModel()
     {
         return User::class;
     }
 
+    /**
+     * {@inheritdoc}
+     */
+    public function userObjectClasses() : array
+    {
+        return [
+            $this->top(),
+            $this->person(),
+            $this->organizationalPerson(),
+            $this->objectClassUser(),
+        ];
+    }
+
     /**
      * {@inheritdoc}
      */
@@ -1225,9 +1229,7 @@ abstract class Schema implements SchemaInterface
     }
 
     /**
-     * The class name of the foreignSecurityPrincipal model.
-     *
-     * @return string
+     * {@inheritdoc}
      */
     public function foreignSecurityPrincipalModel()
     {

+ 27 - 9
api/vendor/adldap2/adldap2/src/Schemas/SchemaInterface.php

@@ -237,6 +237,8 @@ interface SchemaInterface
      * value to be the first element in an array, however OpenLDAP expects
      * the dn attribute to contain the value, not an array.
      *
+     * @deprecated since 10.0.0
+     *
      * @return int|null
      */
     public function distinguishedNameSubKey();
@@ -391,7 +393,7 @@ interface SchemaInterface
 
     /**
      * Specifies the drive letter to which to map the UNC path specified by homeDirectory.
-     * 
+     *
      * @link https://msdn.microsoft.com/en-us/library/ms676191(v=vs.85).aspx
      *
      * @return string|null
@@ -400,13 +402,22 @@ interface SchemaInterface
 
     /**
      * The home directory for the account.
-     * 
+     *
      * @link https://msdn.microsoft.com/en-us/library/ms676190(v=vs.85).aspx
      *
      * @return string|null
      */
     public function homeDirectory();
 
+    /**
+     * The user's main home phone number.
+     *
+     * @link https://docs.microsoft.com/en-us/windows/desktop/ADSchema/a-homephone
+     *
+     * @return string|null
+     */
+    public function homePhone();
+
     /**
      * The users extra notable information.
      *
@@ -438,9 +449,9 @@ interface SchemaInterface
 
     /**
      * Specifies the TCP/IP address for the phone. Used by telephony.
-     * 
+     *
      * @link https://msdn.microsoft.com/en-us/library/cc221092.aspx
-     * 
+     *
      * @return string
      */
     public function ipPhone();
@@ -621,7 +632,7 @@ interface SchemaInterface
     /**
      * The range limited list of users that belong to the group. See range limit in Active Directory
      * (Range Retrieval of Attribute Values https://msdn.microsoft.com/en-us/library/cc223242.aspx)
-     * Issue #342
+     * Issue #342.
      *
      * @link https://msdn.microsoft.com/en-us/library/ms677097(v=vs.85).aspx
      *
@@ -1261,18 +1272,18 @@ interface SchemaInterface
 
     /**
      * The primary mobile phone number.
-     * 
+     *
      * @link https://docs.microsoft.com/en-us/windows/desktop/adschema/a-mobile
-     * 
+     *
      * @return string
      */
     public function mobile();
 
     /**
      * The secondary mobile phone number.
-     * 
+     *
      * @link https://docs.microsoft.com/en-us/windows/desktop/ADSchema/a-othermobile
-     * 
+     *
      * @return string
      */
     public function otherMobile();
@@ -1368,6 +1379,13 @@ interface SchemaInterface
      */
     public function userModel();
 
+    /**
+     * The object classes that User models must be constructed with.
+     *
+     * @return array
+     */
+    public function userObjectClasses() : array;
+
     /**
      * This attribute contains the UPN that is an Internet-style login name for
      * a user based on the Internet standard RFC 822.

+ 20 - 5
api/vendor/adldap2/adldap2/src/Utilities.php

@@ -131,11 +131,11 @@ class Utilities
      */
     public static function stringGuidToHex($string)
     {
-        $hex = '\\' . substr($string, 6, 2) . '\\' . substr($string, 4, 2) . '\\' . substr($string, 2, 2) . '\\' . substr($string, 0, 2);
-        $hex = $hex . '\\' . substr($string, 11, 2) . '\\' . substr($string, 9, 2);
-        $hex = $hex . '\\' . substr($string, 16, 2) . '\\' . substr($string, 14, 2);
-        $hex = $hex . '\\' . substr($string, 19, 2) . '\\' . substr($string, 21, 2);
-        $hex = $hex . '\\' . substr($string, 24, 2) . '\\' . substr($string, 26, 2) . '\\' . substr($string, 28, 2) . '\\' . substr($string, 30, 2) . '\\' . substr($string, 32, 2) . '\\' . substr($string, 34, 2);
+        $hex = '\\'.substr($string, 6, 2).'\\'.substr($string, 4, 2).'\\'.substr($string, 2, 2).'\\'.substr($string, 0, 2);
+        $hex = $hex.'\\'.substr($string, 11, 2).'\\'.substr($string, 9, 2);
+        $hex = $hex.'\\'.substr($string, 16, 2).'\\'.substr($string, 14, 2);
+        $hex = $hex.'\\'.substr($string, 19, 2).'\\'.substr($string, 21, 2);
+        $hex = $hex.'\\'.substr($string, 24, 2).'\\'.substr($string, 26, 2).'\\'.substr($string, 28, 2).'\\'.substr($string, 30, 2).'\\'.substr($string, 32, 2).'\\'.substr($string, 34, 2);
 
         return $hex;
     }
@@ -152,6 +152,21 @@ class Utilities
         return iconv('UTF-8', 'UTF-16LE', '"'.$password.'"');
     }
 
+    /**
+     * Salt and hash a password to make its SSHA OpenLDAP version.
+     *
+     * @param string $password The password to create
+     *
+     * @return string
+     */
+    public static function makeSSHAPassword($password)
+    {
+        mt_srand((float) microtime() * 1000000);
+        $salt = pack('CCCC', mt_rand(), mt_rand(), mt_rand(), mt_rand());
+
+        return '{SSHA}'.base64_encode(pack('H*', sha1($password.$salt)).$salt);
+    }
+
     /**
      * Round a Windows timestamp down to seconds and remove
      * the seconds between 1601-01-01 and 1970-01-01.

+ 11 - 9
api/vendor/composer/installed.json

@@ -1,25 +1,27 @@
 [
     {
         "name": "adldap2/adldap2",
-        "version": "v10.0.2",
-        "version_normalized": "10.0.2.0",
+        "version": "v10.2.2",
+        "version_normalized": "10.2.2.0",
         "source": {
             "type": "git",
             "url": "https://github.com/Adldap2/Adldap2.git",
-            "reference": "f38a58161c07a295f67d3e8877c4236cdd9170e6"
+            "reference": "f09ca4ae3a65dbf123b56dc7e4ace8682ea16cdb"
         },
         "dist": {
             "type": "zip",
-            "url": "https://api.github.com/repos/Adldap2/Adldap2/zipball/f38a58161c07a295f67d3e8877c4236cdd9170e6",
-            "reference": "f38a58161c07a295f67d3e8877c4236cdd9170e6",
+            "url": "https://api.github.com/repos/Adldap2/Adldap2/zipball/f09ca4ae3a65dbf123b56dc7e4ace8682ea16cdb",
+            "reference": "f09ca4ae3a65dbf123b56dc7e4ace8682ea16cdb",
             "shasum": ""
         },
         "require": {
+            "ext-json": "*",
             "ext-ldap": "*",
-            "illuminate/contracts": "~5.0",
+            "illuminate/contracts": "~5.0|~6.0",
             "php": ">=7.0",
-            "psr/log": "~1.1",
-            "tightenco/collect": "~5.0"
+            "psr/log": "~1.0",
+            "psr/simple-cache": "~1.0",
+            "tightenco/collect": "~5.0|~6.0"
         },
         "require-dev": {
             "mockery/mockery": "~1.0",
@@ -28,7 +30,7 @@
         "suggest": {
             "ext-fileinfo": "fileinfo is required when retrieving user encoded thumbnails"
         },
-        "time": "2019-02-16T04:26:37+00:00",
+        "time": "2019-12-18T15:07:31+00:00",
         "type": "library",
         "installation-source": "dist",
         "autoload": {