]>
Commit | Line | Data |
---|---|---|
aebd817b | 1 | diff --git a/.travis.yml b/.travis.yml |
a3d281ea | 2 | index 04cea258..56b1f576 100644 |
aebd817b IB |
3 | --- a/.travis.yml |
4 | +++ b/.travis.yml | |
a3d281ea | 5 | @@ -58,6 +58,7 @@ install: |
aebd817b IB |
6 | |
7 | before_script: | |
8 | - PHP=$TRAVIS_PHP_VERSION | |
9 | + - echo "extension=ldap.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini | |
10 | - if [[ ! $PHP = hhvm* ]]; then echo "memory_limit=-1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini; fi; | |
11 | # xdebug isn't enable for PHP 7.1 | |
12 | - if [[ ! $PHP = hhvm* ]]; then phpenv config-rm xdebug.ini || echo "xdebug not available"; fi | |
13 | diff --git a/app/AppKernel.php b/app/AppKernel.php | |
14 | index 40726f05..c4f465dc 100644 | |
15 | --- a/app/AppKernel.php | |
16 | +++ b/app/AppKernel.php | |
17 | @@ -42,6 +42,10 @@ class AppKernel extends Kernel | |
18 | new OldSound\RabbitMqBundle\OldSoundRabbitMqBundle(), | |
19 | ]; | |
20 | ||
21 | + if (class_exists('FR3D\\LdapBundle\\FR3DLdapBundle')) { | |
22 | + $bundles[] = new FR3D\LdapBundle\FR3DLdapBundle(); | |
23 | + } | |
24 | + | |
25 | if (in_array($this->getEnvironment(), ['dev', 'test'], true)) { | |
26 | $bundles[] = new Symfony\Bundle\DebugBundle\DebugBundle(); | |
27 | $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle(); | |
28 | diff --git a/app/DoctrineMigrations/Version20170710113900.php b/app/DoctrineMigrations/Version20170710113900.php | |
29 | new file mode 100644 | |
30 | index 00000000..7be83110 | |
31 | --- /dev/null | |
32 | +++ b/app/DoctrineMigrations/Version20170710113900.php | |
33 | @@ -0,0 +1,54 @@ | |
34 | +<?php | |
35 | + | |
36 | +namespace Application\Migrations; | |
37 | + | |
38 | +use Doctrine\DBAL\Migrations\AbstractMigration; | |
39 | +use Doctrine\DBAL\Schema\Schema; | |
40 | +use Symfony\Component\DependencyInjection\ContainerAwareInterface; | |
41 | +use Symfony\Component\DependencyInjection\ContainerInterface; | |
42 | + | |
43 | +/** | |
44 | + * Added dn field on wallabag_users | |
45 | + */ | |
46 | +class Version20170710113900 extends AbstractMigration implements ContainerAwareInterface | |
47 | +{ | |
48 | + /** | |
49 | + * @var ContainerInterface | |
50 | + */ | |
51 | + private $container; | |
52 | + | |
53 | + public function setContainer(ContainerInterface $container = null) | |
54 | + { | |
55 | + $this->container = $container; | |
56 | + } | |
57 | + | |
58 | + private function getTable($tableName) | |
59 | + { | |
60 | + return $this->container->getParameter('database_table_prefix').$tableName; | |
61 | + } | |
62 | + | |
63 | + /** | |
64 | + * @param Schema $schema | |
65 | + */ | |
66 | + public function up(Schema $schema) | |
67 | + { | |
68 | + $usersTable = $schema->getTable($this->getTable('user')); | |
69 | + | |
70 | + $this->skipIf($usersTable->hasColumn('dn'), 'It seems that you already played this migration.'); | |
71 | + | |
72 | + $usersTable->addColumn('dn', 'text', [ | |
73 | + 'default' => null, | |
74 | + 'notnull' => false, | |
75 | + ]); | |
76 | + } | |
77 | + | |
78 | + /** | |
79 | + * @param Schema $schema | |
80 | + */ | |
81 | + public function down(Schema $schema) | |
82 | + { | |
83 | + $usersTable = $schema->getTable($this->getTable('user')); | |
84 | + $usersTable->dropColumn('dn'); | |
85 | + } | |
86 | +} | |
87 | + | |
88 | diff --git a/app/config/parameters.yml.dist b/app/config/parameters.yml.dist | |
89 | index 6b0cb8e8..cfd41b69 100644 | |
90 | --- a/app/config/parameters.yml.dist | |
91 | +++ b/app/config/parameters.yml.dist | |
92 | @@ -62,3 +62,23 @@ parameters: | |
93 | redis_port: 6379 | |
94 | redis_path: null | |
95 | redis_password: null | |
96 | + | |
97 | + # ldap configuration | |
98 | + # To enable, you need to require fr3d/ldap-bundle | |
99 | + ldap_enabled: false | |
100 | + ldap_host: localhost | |
101 | + ldap_port: 389 | |
102 | + ldap_tls: false | |
103 | + ldap_ssl: false | |
104 | + ldap_bind_requires_dn: true | |
105 | + ldap_base: dc=example,dc=com | |
106 | + ldap_manager_dn: ou=Manager,dc=example,dc=com | |
107 | + ldap_manager_pw: password | |
108 | + ldap_filter: (&(ObjectClass=Person)) | |
109 | + # optional (if null: no ldap user is admin) | |
110 | + ldap_admin_filter: (&(memberOf=ou=admins,dc=example,dc=com)(uid=%s)) | |
111 | + ldap_username_attribute: uid | |
112 | + ldap_email_attribute: mail | |
113 | + ldap_name_attribute: cn | |
114 | + # optional (default sets user as enabled unconditionally) | |
115 | + ldap_enabled_attribute: ~ | |
116 | diff --git a/app/config/security.yml b/app/config/security.yml | |
a3d281ea | 117 | index 02afc9ea..48fbb553 100644 |
aebd817b IB |
118 | --- a/app/config/security.yml |
119 | +++ b/app/config/security.yml | |
120 | @@ -6,6 +6,7 @@ security: | |
121 | ROLE_ADMIN: ROLE_USER | |
122 | ROLE_SUPER_ADMIN: [ ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH ] | |
123 | ||
124 | + # /!\ This list is modified in WallabagUserBundle when LDAP is enabled | |
125 | providers: | |
126 | administrators: | |
127 | entity: | |
128 | @@ -36,6 +37,7 @@ security: | |
129 | pattern: ^/login$ | |
130 | anonymous: ~ | |
131 | ||
132 | + # /!\ This section is modified in WallabagUserBundle when LDAP is enabled | |
133 | secured_area: | |
134 | pattern: ^/ | |
135 | form_login: | |
136 | diff --git a/composer.json b/composer.json | |
46c99b57 | 137 | index 0483da1d..e3e47bdc 100644 |
aebd817b IB |
138 | --- a/composer.json |
139 | +++ b/composer.json | |
46c99b57 | 140 | @@ -87,7 +87,11 @@ |
a3d281ea | 141 | "bdunogier/guzzle-site-authenticator": "^1.0.0", |
aebd817b | 142 | "defuse/php-encryption": "^2.1", |
46c99b57 IB |
143 | "html2text/html2text": "^4.1", |
144 | - "sulu/symfony-intl-fix": "^1.0" | |
145 | + "sulu/symfony-intl-fix": "^1.0", | |
a3d281ea IB |
146 | + "fr3d/ldap-bundle": "^3.0" |
147 | + }, | |
aebd817b IB |
148 | + "suggest": { |
149 | + "fr3d/ldap-bundle": "If you want to authenticate via LDAP" | |
a3d281ea | 150 | }, |
aebd817b IB |
151 | "require-dev": { |
152 | "doctrine/doctrine-fixtures-bundle": "~2.2", | |
a3d281ea | 153 | diff --git a/composer.lock b/composer.lock |
46c99b57 | 154 | index b3b0a4c6..8c8a87ee 100644 |
a3d281ea IB |
155 | --- a/composer.lock |
156 | +++ b/composer.lock | |
a3d281ea IB |
157 | @@ -1346,6 +1346,65 @@ |
158 | ], | |
46c99b57 | 159 | "time": "2019-05-09T11:53:40+00:00" |
a3d281ea IB |
160 | }, |
161 | + { | |
162 | + "name": "fr3d/ldap-bundle", | |
163 | + "version": "v3.0.0", | |
164 | + "source": { | |
165 | + "type": "git", | |
166 | + "url": "https://github.com/Maks3w/FR3DLdapBundle.git", | |
167 | + "reference": "5a8927c11af45fa06331b97221c6da1a4a237475" | |
168 | + }, | |
169 | + "dist": { | |
170 | + "type": "zip", | |
171 | + "url": "https://api.github.com/repos/Maks3w/FR3DLdapBundle/zipball/5a8927c11af45fa06331b97221c6da1a4a237475", | |
172 | + "reference": "5a8927c11af45fa06331b97221c6da1a4a237475", | |
173 | + "shasum": "" | |
174 | + }, | |
175 | + "require": { | |
176 | + "php": ">=5.5", | |
177 | + "psr/log": "~1.0", | |
178 | + "symfony/config": "2.3 - 3", | |
179 | + "symfony/dependency-injection": "2.3 - 3", | |
180 | + "symfony/polyfill-php56": "^1.1", | |
181 | + "symfony/security": "2.3 - 3", | |
182 | + "symfony/security-bundle": "2.3 - 3", | |
183 | + "zendframework/zend-ldap": "2.5 - 3" | |
184 | + }, | |
185 | + "require-dev": { | |
186 | + "fabpot/php-cs-fixer": "1.11.*", | |
187 | + "fr3d/psr3-message-assertions": "0.1.*", | |
188 | + "friendsofsymfony/user-bundle": "~1.3", | |
189 | + "maks3w/phpunit-methods-trait": "^4.6", | |
190 | + "phpunit/phpunit": "^4.6", | |
191 | + "symfony/validator": "2.3 - 3" | |
192 | + }, | |
193 | + "suggest": { | |
194 | + "friendsofsymfony/user-bundle": "Integrate authentication and management for DB users, useful for unmanned LDAP servers", | |
195 | + "symfony/validator": "Allow pre-validate for existing users before register new ones" | |
196 | + }, | |
197 | + "type": "symfony-bundle", | |
198 | + "autoload": { | |
199 | + "psr-4": { | |
200 | + "FR3D\\LdapBundle\\": "" | |
201 | + } | |
202 | + }, | |
203 | + "notification-url": "https://packagist.org/downloads/", | |
204 | + "license": [ | |
205 | + "MIT" | |
206 | + ], | |
207 | + "authors": [ | |
208 | + { | |
209 | + "name": "Maks3w" | |
210 | + } | |
211 | + ], | |
212 | + "description": "This package provide users and authentication services based on LDAP directories for Symfony2 framework", | |
213 | + "homepage": "https://github.com/Maks3w/FR3DLdapBundle", | |
214 | + "keywords": [ | |
215 | + "Authentication", | |
216 | + "ldap" | |
217 | + ], | |
218 | + "time": "2016-02-12T17:45:14+00:00" | |
219 | + }, | |
220 | { | |
221 | "name": "friendsofsymfony/jsrouting-bundle", | |
222 | "version": "1.6.3", | |
46c99b57 | 223 | @@ -7069,6 +7128,59 @@ |
a3d281ea IB |
224 | "zf2" |
225 | ], | |
226 | "time": "2018-04-25T15:33:34+00:00" | |
227 | + }, | |
228 | + { | |
229 | + "name": "zendframework/zend-ldap", | |
230 | + "version": "2.10.0", | |
231 | + "source": { | |
232 | + "type": "git", | |
233 | + "url": "https://github.com/zendframework/zend-ldap.git", | |
234 | + "reference": "b63c7884a08d3a6bda60ebcf7d6238cf8ad89f49" | |
235 | + }, | |
236 | + "dist": { | |
237 | + "type": "zip", | |
238 | + "url": "https://api.github.com/repos/zendframework/zend-ldap/zipball/b63c7884a08d3a6bda60ebcf7d6238cf8ad89f49", | |
239 | + "reference": "b63c7884a08d3a6bda60ebcf7d6238cf8ad89f49", | |
240 | + "shasum": "" | |
241 | + }, | |
242 | + "require": { | |
243 | + "ext-ldap": "*", | |
244 | + "php": "^5.6 || ^7.0" | |
245 | + }, | |
246 | + "require-dev": { | |
247 | + "php-mock/php-mock-phpunit": "^1.1.2 || ^2.1.1", | |
248 | + "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2", | |
249 | + "zendframework/zend-coding-standard": "~1.0.0", | |
250 | + "zendframework/zend-config": "^2.5", | |
251 | + "zendframework/zend-eventmanager": "^2.6.3 || ^3.0.1", | |
252 | + "zendframework/zend-stdlib": "^2.7 || ^3.0" | |
253 | + }, | |
254 | + "suggest": { | |
255 | + "zendframework/zend-eventmanager": "Zend\\EventManager component" | |
256 | + }, | |
257 | + "type": "library", | |
258 | + "extra": { | |
259 | + "branch-alias": { | |
260 | + "dev-master": "2.10.x-dev", | |
261 | + "dev-develop": "2.11.x-dev" | |
262 | + } | |
263 | + }, | |
264 | + "autoload": { | |
265 | + "psr-4": { | |
266 | + "Zend\\Ldap\\": "src/" | |
267 | + } | |
268 | + }, | |
269 | + "notification-url": "https://packagist.org/downloads/", | |
270 | + "license": [ | |
271 | + "BSD-3-Clause" | |
272 | + ], | |
273 | + "description": "Provides support for LDAP operations including but not limited to binding, searching and modifying entries in an LDAP directory", | |
274 | + "keywords": [ | |
275 | + "ZendFramework", | |
276 | + "ldap", | |
277 | + "zf" | |
278 | + ], | |
279 | + "time": "2018-07-05T05:05:12+00:00" | |
280 | } | |
281 | ], | |
282 | "packages-dev": [ | |
aebd817b | 283 | diff --git a/scripts/install.sh b/scripts/install.sh |
46c99b57 | 284 | index affa715f..45254212 100755 |
aebd817b IB |
285 | --- a/scripts/install.sh |
286 | +++ b/scripts/install.sh | |
46c99b57 | 287 | @@ -37,5 +37,8 @@ fi |
aebd817b IB |
288 | TAG=$(git describe --tags $(git rev-list --tags --max-count=1)) |
289 | ||
290 | git checkout $TAG | |
291 | +if [ -n "$LDAP_ENABLED" ]; then | |
292 | + SYMFONY_ENV=$ENV $COMPOSER_COMMAND require --no-update fr3d/ldap-bundle | |
293 | +fi | |
294 | SYMFONY_ENV=$ENV $COMPOSER_COMMAND install --no-dev -o --prefer-dist | |
295 | php bin/console wallabag:install --env=$ENV | |
296 | diff --git a/scripts/update.sh b/scripts/update.sh | |
46c99b57 | 297 | index 3ef10439..eeee28d6 100755 |
aebd817b IB |
298 | --- a/scripts/update.sh |
299 | +++ b/scripts/update.sh | |
46c99b57 | 300 | @@ -42,6 +42,9 @@ git fetch origin |
aebd817b IB |
301 | git fetch --tags |
302 | TAG=$(git describe --tags $(git rev-list --tags --max-count=1)) | |
303 | git checkout $TAG --force | |
304 | +if [ -n "$LDAP_ENABLED" ]; then | |
305 | + SYMFONY_ENV=$ENV $COMPOSER_COMMAND require --no-update fr3d/ldap-bundle | |
306 | +fi | |
307 | SYMFONY_ENV=$ENV $COMPOSER_COMMAND install --no-dev -o --prefer-dist | |
308 | php bin/console doctrine:migrations:migrate --no-interaction --env=$ENV | |
309 | php bin/console cache:clear --env=$ENV | |
310 | diff --git a/src/Wallabag/UserBundle/DependencyInjection/WallabagUserExtension.php b/src/Wallabag/UserBundle/DependencyInjection/WallabagUserExtension.php | |
311 | index 5ca3482e..904a6af1 100644 | |
312 | --- a/src/Wallabag/UserBundle/DependencyInjection/WallabagUserExtension.php | |
313 | +++ b/src/Wallabag/UserBundle/DependencyInjection/WallabagUserExtension.php | |
314 | @@ -6,9 +6,34 @@ use Symfony\Component\Config\FileLocator; | |
315 | use Symfony\Component\DependencyInjection\ContainerBuilder; | |
316 | use Symfony\Component\DependencyInjection\Loader; | |
317 | use Symfony\Component\HttpKernel\DependencyInjection\Extension; | |
318 | +use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; | |
319 | ||
320 | -class WallabagUserExtension extends Extension | |
321 | +class WallabagUserExtension extends Extension implements PrependExtensionInterface | |
322 | { | |
323 | + public function prepend(ContainerBuilder $container) | |
324 | + { | |
325 | + $ldap = $container->getParameter('ldap_enabled'); | |
326 | + | |
327 | + if ($ldap) { | |
328 | + $container->prependExtensionConfig('security', array( | |
329 | + 'providers' => array( | |
330 | + 'chain_provider' => array(), | |
331 | + ), | |
332 | + )); | |
333 | + $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); | |
334 | + $loader->load('ldap.yml'); | |
335 | + } elseif ($container->hasExtension('fr3d_ldap')) { | |
336 | + $container->prependExtensionConfig('fr3_d_ldap', array( | |
337 | + 'driver' => array( | |
338 | + 'host' => 'localhost', | |
339 | + ), | |
340 | + 'user' => array( | |
341 | + 'baseDn' => 'dc=example,dc=com', | |
342 | + ), | |
343 | + )); | |
344 | + } | |
345 | + } | |
346 | + | |
347 | public function load(array $configs, ContainerBuilder $container) | |
348 | { | |
349 | $configuration = new Configuration(); | |
350 | @@ -16,6 +41,9 @@ class WallabagUserExtension extends Extension | |
351 | ||
352 | $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); | |
353 | $loader->load('services.yml'); | |
354 | + if ($container->getParameter('ldap_enabled')) { | |
355 | + $loader->load('ldap_services.yml'); | |
356 | + } | |
357 | $container->setParameter('wallabag_user.registration_enabled', $config['registration_enabled']); | |
358 | } | |
359 | ||
360 | diff --git a/src/Wallabag/UserBundle/Entity/User.php b/src/Wallabag/UserBundle/Entity/User.php | |
361 | index 48446e3c..f93c59c7 100644 | |
362 | --- a/src/Wallabag/UserBundle/Entity/User.php | |
363 | +++ b/src/Wallabag/UserBundle/Entity/User.php | |
364 | @@ -1,5 +1,15 @@ | |
365 | <?php | |
366 | ||
367 | +// This permits to have the LdapUserInterface even when fr3d/ldap-bundle is not | |
368 | +// in the packages | |
369 | +namespace FR3D\LdapBundle\Model; | |
370 | + | |
371 | +interface LdapUserInterface | |
372 | +{ | |
373 | + public function setDn($dn); | |
374 | + public function getDn(); | |
375 | +} | |
376 | + | |
377 | namespace Wallabag\UserBundle\Entity; | |
378 | ||
379 | use Doctrine\Common\Collections\ArrayCollection; | |
380 | @@ -16,6 +26,7 @@ use Wallabag\ApiBundle\Entity\Client; | |
381 | use Wallabag\CoreBundle\Entity\Config; | |
382 | use Wallabag\CoreBundle\Entity\Entry; | |
383 | use Wallabag\CoreBundle\Helper\EntityTimestampsTrait; | |
384 | +use FR3D\LdapBundle\Model\LdapUserInterface; | |
385 | ||
386 | /** | |
387 | * User. | |
388 | @@ -28,7 +39,7 @@ use Wallabag\CoreBundle\Helper\EntityTimestampsTrait; | |
389 | * @UniqueEntity("email") | |
390 | * @UniqueEntity("username") | |
391 | */ | |
392 | -class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterface | |
393 | +class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterface, LdapUserInterface | |
394 | { | |
395 | use EntityTimestampsTrait; | |
396 | ||
397 | @@ -67,6 +78,13 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf | |
398 | */ | |
399 | protected $email; | |
400 | ||
401 | + /** | |
402 | + * @var string | |
403 | + * | |
404 | + * @ORM\Column(name="dn", type="text", nullable=true) | |
405 | + */ | |
406 | + protected $dn; | |
407 | + | |
408 | /** | |
409 | * @var \DateTime | |
410 | * | |
411 | @@ -309,4 +327,33 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf | |
412 | return $this->clients->first(); | |
413 | } | |
414 | } | |
415 | + | |
416 | + /** | |
417 | + * Set dn. | |
418 | + * | |
419 | + * @param string $dn | |
420 | + * | |
421 | + * @return User | |
422 | + */ | |
423 | + public function setDn($dn) | |
424 | + { | |
425 | + $this->dn = $dn; | |
426 | + | |
427 | + return $this; | |
428 | + } | |
429 | + | |
430 | + /** | |
431 | + * Get dn. | |
432 | + * | |
433 | + * @return string | |
434 | + */ | |
435 | + public function getDn() | |
436 | + { | |
437 | + return $this->dn; | |
438 | + } | |
439 | + | |
440 | + public function isLdapUser() | |
441 | + { | |
442 | + return $this->dn !== null; | |
443 | + } | |
444 | } | |
445 | diff --git a/src/Wallabag/UserBundle/LdapHydrator.php b/src/Wallabag/UserBundle/LdapHydrator.php | |
446 | new file mode 100644 | |
447 | index 00000000..cea2450f | |
448 | --- /dev/null | |
449 | +++ b/src/Wallabag/UserBundle/LdapHydrator.php | |
450 | @@ -0,0 +1,103 @@ | |
451 | +<?php | |
452 | + | |
453 | +namespace Wallabag\UserBundle; | |
454 | + | |
455 | +use FR3D\LdapBundle\Hydrator\HydratorInterface; | |
456 | +use FOS\UserBundle\FOSUserEvents; | |
457 | +use FOS\UserBundle\Event\UserEvent; | |
458 | + | |
459 | +class LdapHydrator implements HydratorInterface | |
460 | +{ | |
461 | + private $userManager; | |
462 | + private $eventDispatcher; | |
463 | + private $attributesMap; | |
464 | + private $enabledAttribute; | |
465 | + private $ldapBaseDn; | |
466 | + private $ldapAdminFilter; | |
467 | + private $ldapDriver; | |
468 | + | |
469 | + public function __construct( | |
470 | + $user_manager, | |
471 | + $event_dispatcher, | |
472 | + array $attributes_map, | |
473 | + $ldap_base_dn, | |
474 | + $ldap_admin_filter, | |
475 | + $ldap_driver | |
476 | + ) { | |
477 | + $this->userManager = $user_manager; | |
478 | + $this->eventDispatcher = $event_dispatcher; | |
479 | + | |
480 | + $this->attributesMap = array( | |
481 | + 'setUsername' => $attributes_map[0], | |
482 | + 'setEmail' => $attributes_map[1], | |
483 | + 'setName' => $attributes_map[2], | |
484 | + ); | |
485 | + $this->enabledAttribute = $attributes_map[3]; | |
486 | + | |
487 | + $this->ldapBaseDn = $ldap_base_dn; | |
488 | + $this->ldapAdminFilter = $ldap_admin_filter; | |
489 | + $this->ldapDriver = $ldap_driver; | |
490 | + } | |
491 | + | |
492 | + public function hydrate(array $ldapEntry) | |
493 | + { | |
494 | + $user = $this->userManager->findUserBy(array('dn' => $ldapEntry['dn'])); | |
495 | + | |
496 | + if (!$user) { | |
497 | + $user = $this->userManager->createUser(); | |
498 | + $user->setDn($ldapEntry['dn']); | |
499 | + $user->setPassword(''); | |
500 | + $user->setSalt(''); | |
501 | + $this->updateUserFields($user, $ldapEntry); | |
502 | + | |
503 | + $event = new UserEvent($user); | |
504 | + $this->eventDispatcher->dispatch(FOSUserEvents::USER_CREATED, $event); | |
505 | + | |
506 | + $this->userManager->reloadUser($user); | |
507 | + } else { | |
508 | + $this->updateUserFields($user, $ldapEntry); | |
509 | + } | |
510 | + | |
511 | + return $user; | |
512 | + } | |
513 | + | |
514 | + private function updateUserFields($user, $ldapEntry) | |
515 | + { | |
516 | + foreach ($this->attributesMap as $key => $value) { | |
517 | + if (is_array($ldapEntry[$value])) { | |
518 | + $ldap_value = $ldapEntry[$value][0]; | |
519 | + } else { | |
520 | + $ldap_value = $ldapEntry[$value]; | |
521 | + } | |
522 | + | |
523 | + call_user_func([$user, $key], $ldap_value); | |
524 | + } | |
525 | + | |
526 | + if ($this->enabledAttribute !== null) { | |
527 | + $user->setEnabled($ldapEntry[$this->enabledAttribute]); | |
528 | + } else { | |
529 | + $user->setEnabled(true); | |
530 | + } | |
531 | + | |
532 | + if ($this->isAdmin($user)) { | |
533 | + $user->addRole('ROLE_SUPER_ADMIN'); | |
534 | + } else { | |
535 | + $user->removeRole('ROLE_SUPER_ADMIN'); | |
536 | + } | |
537 | + | |
538 | + $this->userManager->updateUser($user, true); | |
539 | + } | |
540 | + | |
541 | + private function isAdmin($user) | |
542 | + { | |
543 | + if ($this->ldapAdminFilter === null) { | |
544 | + return false; | |
545 | + } | |
546 | + | |
547 | + $escaped_username = ldap_escape($user->getUsername(), '', LDAP_ESCAPE_FILTER); | |
548 | + $filter = sprintf($this->ldapAdminFilter, $escaped_username); | |
549 | + $entries = $this->ldapDriver->search($this->ldapBaseDn, $filter); | |
550 | + | |
551 | + return $entries['count'] == 1; | |
552 | + } | |
553 | +} | |
554 | diff --git a/src/Wallabag/UserBundle/OAuthStorageLdapWrapper.php b/src/Wallabag/UserBundle/OAuthStorageLdapWrapper.php | |
555 | new file mode 100644 | |
556 | index 00000000..8a851f12 | |
557 | --- /dev/null | |
558 | +++ b/src/Wallabag/UserBundle/OAuthStorageLdapWrapper.php | |
559 | @@ -0,0 +1,43 @@ | |
560 | +<?php | |
561 | + | |
562 | +namespace Wallabag\UserBundle; | |
563 | + | |
564 | +use FOS\OAuthServerBundle\Storage\OAuthStorage; | |
565 | +use OAuth2\Model\IOAuth2Client; | |
566 | +use Symfony\Component\Security\Core\Exception\AuthenticationException; | |
567 | + | |
568 | +class OAuthStorageLdapWrapper extends OAuthStorage | |
569 | +{ | |
570 | + private $ldapManager; | |
571 | + | |
572 | + public function setLdapManager($ldap_manager) | |
573 | + { | |
574 | + $this->ldapManager = $ldap_manager; | |
575 | + } | |
576 | + | |
577 | + public function checkUserCredentials(IOAuth2Client $client, $username, $password) | |
578 | + { | |
579 | + try { | |
580 | + $user = $this->userProvider->loadUserByUsername($username); | |
581 | + } catch (AuthenticationException $e) { | |
582 | + return false; | |
583 | + } | |
584 | + | |
585 | + if ($user->isLdapUser()) { | |
586 | + return $this->checkLdapUserCredentials($user, $password); | |
587 | + } else { | |
588 | + return parent::checkUserCredentials($client, $username, $password); | |
589 | + } | |
590 | + } | |
591 | + | |
592 | + private function checkLdapUserCredentials($user, $password) | |
593 | + { | |
594 | + if ($this->ldapManager->bind($user, $password)) { | |
595 | + return array( | |
596 | + 'data' => $user, | |
597 | + ); | |
598 | + } else { | |
599 | + return false; | |
600 | + } | |
601 | + } | |
602 | +} | |
603 | diff --git a/src/Wallabag/UserBundle/Resources/config/ldap.yml b/src/Wallabag/UserBundle/Resources/config/ldap.yml | |
604 | new file mode 100644 | |
605 | index 00000000..5ec16088 | |
606 | --- /dev/null | |
607 | +++ b/src/Wallabag/UserBundle/Resources/config/ldap.yml | |
608 | @@ -0,0 +1,28 @@ | |
609 | +fr3d_ldap: | |
610 | + service: | |
611 | + user_hydrator: ldap_user_hydrator | |
612 | + driver: | |
613 | + host: "%ldap_host%" | |
614 | + port: "%ldap_port%" | |
615 | + useSsl: "%ldap_ssl%" | |
616 | + useStartTls: "%ldap_tls%" | |
617 | + bindRequiresDn: "%ldap_bind_requires_dn%" | |
618 | + username: "%ldap_manager_dn%" | |
619 | + password: "%ldap_manager_pw%" | |
620 | + user: | |
621 | + baseDn: "%ldap_base%" | |
622 | + filter: "%ldap_filter%" | |
623 | + usernameAttribute: "%ldap_username_attribute%" | |
624 | +security: | |
625 | + providers: | |
626 | + chain_provider: | |
627 | + chain: | |
628 | + providers: [ fr3d_ldapbundle, fos_userbundle ] | |
629 | + fr3d_ldapbundle: | |
630 | + id: fr3d_ldap.security.user.provider | |
631 | + firewalls: | |
632 | + secured_area: | |
633 | + fr3d_ldap: ~ | |
634 | + form_login: | |
635 | + provider: chain_provider | |
636 | + | |
637 | diff --git a/src/Wallabag/UserBundle/Resources/config/ldap_services.yml b/src/Wallabag/UserBundle/Resources/config/ldap_services.yml | |
638 | new file mode 100644 | |
639 | index 00000000..b3e3fd8a | |
640 | --- /dev/null | |
641 | +++ b/src/Wallabag/UserBundle/Resources/config/ldap_services.yml | |
642 | @@ -0,0 +1,22 @@ | |
643 | +services: | |
644 | + fos_oauth_server.server: | |
645 | + class: OAuth2\OAuth2 | |
646 | + arguments: | |
647 | + - "@oauth_storage_ldap_wrapper" | |
648 | + - "%fos_oauth_server.server.options%" | |
649 | + oauth_storage_ldap_wrapper: | |
650 | + class: Wallabag\UserBundle\OAuthStorageLdapWrapper | |
651 | + parent: fos_oauth_server.storage | |
652 | + calls: | |
653 | + - [setLdapManager, ["@fr3d_ldap.ldap_manager"]] | |
654 | + | |
655 | + ldap_user_hydrator: | |
656 | + class: Wallabag\UserBundle\LdapHydrator | |
657 | + arguments: | |
658 | + - "@fos_user.user_manager" | |
659 | + - "@event_dispatcher" | |
660 | + - [ "%ldap_username_attribute%", "%ldap_email_attribute%", "%ldap_name_attribute%", "%ldap_enabled_attribute%" ] | |
661 | + - "%ldap_base%" | |
662 | + - "%ldap_admin_filter%" | |
663 | + - "@fr3d_ldap.ldap_driver" | |
664 | + |