1 | <?php |
||||
2 | |||||
3 | namespace SilverStripe\LDAP\Tests\Services; |
||||
4 | |||||
5 | use SilverStripe\Assets\Image; |
||||
6 | use SilverStripe\Core\Config\Config; |
||||
7 | use SilverStripe\Core\Injector\Injector; |
||||
8 | use SilverStripe\Dev\SapphireTest; |
||||
9 | use SilverStripe\LDAP\Extensions\LDAPGroupExtension; |
||||
10 | use SilverStripe\LDAP\Extensions\LDAPMemberExtension; |
||||
11 | use SilverStripe\LDAP\Model\LDAPGateway; |
||||
12 | use SilverStripe\LDAP\Services\LDAPService; |
||||
13 | use SilverStripe\LDAP\Tests\Model\LDAPFakeGateway; |
||||
14 | use SilverStripe\LDAP\Tests\Model\LDAPFakeMember; |
||||
15 | use SilverStripe\Security\Group; |
||||
16 | use SilverStripe\Security\Member; |
||||
17 | use Silverstripe\Assets\Dev\TestAssetStore; |
||||
18 | use SilverStripe\ORM\DataQuery; |
||||
19 | |||||
20 | class LDAPServiceTest extends SapphireTest |
||||
21 | { |
||||
22 | protected $usesDatabase = true; |
||||
23 | |||||
24 | protected static $fixture_file = 'LDAPServiceTest.yml'; |
||||
25 | |||||
26 | |||||
27 | /** |
||||
28 | * @var LDAPService |
||||
29 | */ |
||||
30 | private $service; |
||||
31 | |||||
32 | protected function setUp() |
||||
33 | { |
||||
34 | parent::setUp(); |
||||
35 | |||||
36 | $gateway = new LDAPFakeGateway(); |
||||
37 | Injector::inst()->registerService($gateway, LDAPGateway::class); |
||||
38 | |||||
39 | $service = Injector::inst()->get(LDAPService::class); |
||||
40 | $service->setGateway($gateway); |
||||
41 | |||||
42 | $this->service = $service; |
||||
43 | |||||
44 | Config::modify()->set(LDAPGateway::class, 'options', ['host' => '1.2.3.4']); |
||||
45 | Config::modify()->set(LDAPService::class, 'groups_search_locations', [ |
||||
46 | 'CN=Users,DC=playpen,DC=local', |
||||
47 | 'CN=Others,DC=playpen,DC=local' |
||||
48 | ]); |
||||
49 | // Prevent other module extension hooks from executing during write() etc. |
||||
50 | Config::modify()->remove(Member::class, 'extensions'); |
||||
51 | Config::modify()->remove(Group::class, 'extensions'); |
||||
52 | Config::modify()->set(Member::class, 'update_ldap_from_local', false); |
||||
53 | Config::modify()->set(Member::class, 'create_users_in_ldap', false); |
||||
54 | Config::modify()->set( |
||||
55 | Group::class, |
||||
56 | 'extensions', |
||||
57 | [LDAPGroupExtension::class] |
||||
58 | ); |
||||
59 | Config::modify()->set( |
||||
60 | Member::class, |
||||
61 | 'extensions', |
||||
62 | [LDAPMemberExtension::class] |
||||
63 | ); |
||||
64 | |||||
65 | // Disable Monolog logging to stderr by default if you don't give it a handler |
||||
66 | $this->service->getLogger()->pushHandler(new \Monolog\Handler\NullHandler()); |
||||
67 | } |
||||
68 | |||||
69 | public function testGroups() |
||||
70 | { |
||||
71 | $expected = [ |
||||
72 | 'CN=Group1,CN=Users,DC=playpen,DC=local' => ['dn' => 'CN=Group1,CN=Users,DC=playpen,DC=local'], |
||||
73 | 'CN=Group2,CN=Users,DC=playpen,DC=local' => ['dn' => 'CN=Group2,CN=Users,DC=playpen,DC=local'], |
||||
74 | 'CN=Group3,CN=Users,DC=playpen,DC=local' => ['dn' => 'CN=Group3,CN=Users,DC=playpen,DC=local'], |
||||
75 | 'CN=Group4,CN=Users,DC=playpen,DC=local' => ['dn' => 'CN=Group4,CN=Users,DC=playpen,DC=local'], |
||||
76 | 'CN=Group5,CN=Users,DC=playpen,DC=local' => ['dn' => 'CN=Group5,CN=Users,DC=playpen,DC=local'], |
||||
77 | 'CN=Group6,CN=Others,DC=playpen,DC=local' => ['dn' => 'CN=Group6,CN=Others,DC=playpen,DC=local'], |
||||
78 | 'CN=Group7,CN=Others,DC=playpen,DC=local' => ['dn' => 'CN=Group7,CN=Others,DC=playpen,DC=local'], |
||||
79 | 'CN=Group8,CN=Others,DC=playpen,DC=local' => ['dn' => 'CN=Group8,CN=Others,DC=playpen,DC=local'] |
||||
80 | ]; |
||||
81 | |||||
82 | $results = $this->service->getGroups(); |
||||
83 | |||||
84 | $this->assertEquals($expected, $results); |
||||
85 | } |
||||
86 | |||||
87 | public function testUpdateMemberFromLDAP() |
||||
88 | { |
||||
89 | Config::modify()->set( |
||||
90 | Member::class, |
||||
91 | 'ldap_field_mappings', |
||||
92 | [ |
||||
93 | 'givenname' => 'FirstName', |
||||
94 | 'sn' => 'Surname', |
||||
95 | 'mail' => 'Email', |
||||
96 | ] |
||||
97 | ); |
||||
98 | |||||
99 | $member = new Member(); |
||||
100 | $member->GUID = '123'; |
||||
101 | |||||
102 | $this->service->updateMemberFromLDAP($member); |
||||
103 | |||||
104 | $this->assertTrue($member->ID > 0, 'updateMemberFromLDAP writes the member'); |
||||
105 | $this->assertEquals('123', $member->GUID, 'GUID remains the same'); |
||||
106 | $this->assertEquals('Joe', $member->FirstName, 'FirstName updated from LDAP'); |
||||
107 | $this->assertEquals('Bloggs', $member->Surname, 'Surname updated from LDAP'); |
||||
108 | $this->assertEquals('[email protected]', $member->Email, 'Email updated from LDAP'); |
||||
109 | } |
||||
110 | |||||
111 | /** |
||||
112 | * LDAP should correctly assign a member to the groups, if there's a mapping between LDAPGroupMapping and Group |
||||
113 | * and LDAP returns the mapping via 'memberof' |
||||
114 | */ |
||||
115 | public function testAssignGroupMember() |
||||
116 | { |
||||
117 | Config::modify()->set( |
||||
118 | Member::class, |
||||
119 | 'ldap_field_mappings', |
||||
120 | [ |
||||
121 | 'givenname' => 'FirstName', |
||||
122 | 'sn' => 'Surname', |
||||
123 | 'mail' => 'Email', |
||||
124 | ] |
||||
125 | ); |
||||
126 | |||||
127 | $member = new Member(); |
||||
128 | $member->GUID = '789'; |
||||
129 | |||||
130 | $this->service->updateMemberFromLDAP($member); |
||||
131 | $this->assertCount(4, $member->Groups()); |
||||
132 | } |
||||
133 | |||||
134 | /** |
||||
135 | * LDAP should correctly assign a member to the groups, if there's a mapping between LDAPGroupMapping and Group |
||||
136 | * and LDAP returns the mapping via 'memberof' |
||||
137 | */ |
||||
138 | public function testAssignRemovedGroupMember() |
||||
139 | { |
||||
140 | Config::modify()->set( |
||||
141 | Member::class, |
||||
142 | 'ldap_field_mappings', |
||||
143 | [ |
||||
144 | 'givenname' => 'FirstName', |
||||
145 | 'sn' => 'Surname', |
||||
146 | 'mail' => 'Email', |
||||
147 | ] |
||||
148 | ); |
||||
149 | |||||
150 | $member = new Member(); |
||||
151 | $member->GUID = '789'; |
||||
152 | $member->write(); |
||||
153 | |||||
154 | // Pretend we're the module, and generate some mappings. |
||||
155 | Group::get()->each(function ($group) use ($member) { |
||||
156 | $group->Members()->add($member, [ |
||||
157 | 'IsImportedFromLDAP' => '1' |
||||
158 | ]); |
||||
159 | }); |
||||
160 | |||||
161 | $this->assertCount(Group::get()->count(), $member->Groups()); |
||||
162 | |||||
163 | // There should only be 4 groups assigned from LDAP for this user, two should be removed. |
||||
164 | $this->service->updateMemberFromLDAP($member); |
||||
165 | $this->assertCount(4, $member->Groups()); |
||||
166 | } |
||||
167 | |||||
168 | /** |
||||
169 | * If the LDAPService setting reset_missing_attributes is true, reset fields if the attribute isn't present |
||||
170 | * in the response information. |
||||
171 | */ |
||||
172 | public function testUpdateMemberResetAttributesFromLDAP() |
||||
173 | { |
||||
174 | Config::modify()->set( |
||||
175 | Member::class, |
||||
176 | 'ldap_field_mappings', |
||||
177 | [ |
||||
178 | 'givenname' => 'FirstName', |
||||
179 | 'sn' => 'Surname', |
||||
180 | 'mail' => 'Email', |
||||
181 | 'specialattribute' => 'specialattribute' |
||||
182 | ] |
||||
183 | ); |
||||
184 | |||||
185 | Config::modify()->set(LDAPService::class, 'reset_missing_attributes', true); |
||||
186 | |||||
187 | $member = new Member(); |
||||
188 | $member->GUID = '123'; |
||||
189 | $member->specialattribute = "I should be removed because LDAP said so"; |
||||
190 | |||||
191 | $this->service->updateMemberFromLDAP($member); |
||||
192 | |||||
193 | $this->assertTrue($member->ID > 0, 'updateMemberFromLDAP writes the member'); |
||||
194 | $this->assertEquals('123', $member->GUID, 'GUID remains the same'); |
||||
195 | $this->assertEquals('Joe', $member->FirstName, 'FirstName updated from LDAP'); |
||||
196 | $this->assertEquals('Bloggs', $member->Surname, 'Surname updated from LDAP'); |
||||
197 | $this->assertEquals('[email protected]', $member->Email, 'Email updated from LDAP'); |
||||
198 | $this->assertNull($member->specialattribute); |
||||
199 | } |
||||
200 | |||||
201 | /** |
||||
202 | * If the LDAPService setting reset_missing_attributes is true, delete the thumbnail (special case) |
||||
203 | * if it's not present in the response information. |
||||
204 | */ |
||||
205 | public function testUpdateMemberResetThumbnailFromLDAP() |
||||
206 | { |
||||
207 | Config::modify()->set( |
||||
208 | Member::class, |
||||
209 | 'ldap_field_mappings', |
||||
210 | [ |
||||
211 | 'givenname' => 'FirstName', |
||||
212 | 'sn' => 'Surname', |
||||
213 | 'mail' => 'Email', |
||||
214 | 'thumbnailphoto' => 'ProfileImage' |
||||
215 | ] |
||||
216 | ); |
||||
217 | |||||
218 | Config::modify()->set(LDAPService::class, 'reset_missing_attributes', true); |
||||
219 | |||||
220 | // Create a test 'image' for this member. |
||||
221 | /** @var File $file */ |
||||
222 | TestAssetStore::activate('FileTest'); |
||||
223 | $file = new Image(); |
||||
224 | $file->setFromString(str_repeat('x', 1000000), "test.jpg"); |
||||
225 | |||||
226 | $member = new LDAPFakeMember(); |
||||
227 | $member->GUID = '123'; |
||||
0 ignored issues
–
show
Bug
Best Practice
introduced
by
![]() |
|||||
228 | $member->setComponent("ProfileImage", $file); |
||||
229 | |||||
230 | // make sure our Profile image is there. |
||||
231 | $this->assertNotNull($member->ProfileImage); |
||||
0 ignored issues
–
show
The property
ProfileImage does not exist on SilverStripe\LDAP\Tests\Model\LDAPFakeMember . Since you implemented __get , consider adding a @property annotation.
![]() |
|||||
232 | $this->assertTrue($member->ProfileImage->exists()); |
||||
0 ignored issues
–
show
The method
exists() does not exist on null .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. ![]() |
|||||
233 | |||||
234 | $this->service->updateMemberFromLDAP($member); |
||||
235 | |||||
236 | // ensure the profile image was deleted, as it wasn't present in the attribute response from TestLDAP service |
||||
237 | $this->assertFalse($member->ProfileImage->exists()); |
||||
238 | } |
||||
239 | |||||
240 | /** |
||||
241 | * If the LDAPService setting reset_missing_attributes is true, delete the thumbnail (special case) |
||||
242 | * if it's not present in the response information. |
||||
243 | */ |
||||
244 | public function testUpdateMemberLeaveThumbnailIfSameFromLDAP() |
||||
245 | { |
||||
246 | Config::modify()->set( |
||||
247 | Member::class, |
||||
248 | 'ldap_field_mappings', |
||||
249 | [ |
||||
250 | 'givenname' => 'FirstName', |
||||
251 | 'sn' => 'Surname', |
||||
252 | 'mail' => 'Email', |
||||
253 | 'thumbnailphoto' => 'ProfileImage' |
||||
254 | ] |
||||
255 | ); |
||||
256 | |||||
257 | Config::modify()->set(LDAPService::class, 'reset_missing_attributes', true); |
||||
258 | |||||
259 | // Create a test 'image' for this member. |
||||
260 | /** @var File $file */ |
||||
261 | TestAssetStore::activate('FileTest'); |
||||
262 | |||||
263 | $member = new LDAPFakeMember(); |
||||
264 | $member->GUID = '456'; |
||||
0 ignored issues
–
show
The property
GUID does not exist on SilverStripe\LDAP\Tests\Model\LDAPFakeMember . Since you implemented __set , consider adding a @property annotation.
![]() |
|||||
265 | |||||
266 | // make sure our Profile image is there. |
||||
267 | $this->assertNotNull($member->ProfileImage); |
||||
0 ignored issues
–
show
The property
ProfileImage does not exist on SilverStripe\LDAP\Tests\Model\LDAPFakeMember . Since you implemented __get , consider adding a @property annotation.
![]() |
|||||
268 | |||||
269 | $this->service->updateMemberFromLDAP($member); |
||||
270 | |||||
271 | // We have an image from the service. |
||||
272 | $this->assertTrue($member->ProfileImage->exists()); |
||||
273 | |||||
274 | // now make sure it doesn't change. |
||||
275 | $obj = $member->ProfileImage; |
||||
276 | |||||
277 | $this->service->updateMemberFromLDAP($member); |
||||
278 | |||||
279 | $this->assertSame($member->ProfileImage, $obj); |
||||
280 | } |
||||
281 | } |
||||
282 |