Added support for LDAP user photo profile

This commit is contained in:
Frederic Guillot
2016-05-07 12:59:35 -04:00
parent 94989663ec
commit 300dabe6b4
19 changed files with 377 additions and 13 deletions

View File

@@ -76,7 +76,7 @@ class LdapAuth extends Base implements PasswordAuthenticationProviderInterface
throw new LogicException('Username not found in LDAP profile, check the parameter LDAP_USER_ATTRIBUTE_USERNAME');
}
$this->logger->info('Authenticate user: '.$user->getDn());
$this->logger->info('Authenticate this user: '.$user->getDn());
if ($client->authenticate($user->getDn(), $this->password)) {
$this->userInfo = $user;

View File

@@ -32,7 +32,7 @@ class AvatarFile extends Base
{
$user = $this->getUser();
if (! $this->avatarFile->uploadFile($user['id'], $this->request->getFileInfo('avatar'))) {
if (! $this->avatarFile->uploadImageFile($user['id'], $this->request->getFileInfo('avatar'))) {
$this->flash->failure(t('Unable to upload the file.'));
}

View File

@@ -145,7 +145,8 @@ class User
$entry->getFirstValue($this->getAttributeName()),
$entry->getFirstValue($this->getAttributeEmail()),
$this->getRole($groupIds),
$groupIds
$groupIds,
$entry->getFirstValue($this->getAttributePhoto())
);
}
@@ -164,6 +165,7 @@ class User
$this->getAttributeName(),
$this->getAttributeEmail(),
$this->getAttributeGroup(),
$this->getAttributePhoto(),
)));
}
@@ -223,6 +225,17 @@ class User
return strtolower(LDAP_USER_ATTRIBUTE_GROUPS);
}
/**
* Get LDAP profile photo attribute
*
* @access public
* @return string
*/
public function getAttributePhoto()
{
return strtolower(LDAP_USER_ATTRIBUTE_PHOTO);
}
/**
* Get LDAP Group User filter
*

View File

@@ -3,6 +3,7 @@
namespace Kanboard\Core\User;
use Kanboard\Core\Base;
use Kanboard\Event\UserProfileSyncEvent;
/**
* User Profile
@@ -12,6 +13,8 @@ use Kanboard\Core\Base;
*/
class UserProfile extends Base
{
const EVENT_USER_PROFILE_AFTER_SYNC = 'user_profile.after.sync';
/**
* Assign provider data to the local user
*
@@ -54,6 +57,7 @@ class UserProfile extends Base
if (! empty($profile) && $profile['is_active'] == 1) {
$this->userSession->initialize($profile);
$this->dispatcher->dispatch(self::EVENT_USER_PROFILE_AFTER_SYNC, new UserProfileSyncEvent($profile, $user));
return true;
}

View File

@@ -64,13 +64,13 @@ class UserSync extends Base
*/
private function createUser(UserProviderInterface $user, array $properties)
{
$id = $this->user->create($properties);
$userId = $this->user->create($properties);
if ($id === false) {
if ($userId === false) {
$this->logger->error('Unable to create user profile: '.$user->getExternalId());
return array();
}
return $this->user->getById($id);
return $this->user->getById($userId);
}
}

View File

@@ -0,0 +1,64 @@
<?php
namespace Kanboard\Event;
use Kanboard\Core\User\UserProviderInterface;
use Kanboard\User\LdapUserProvider;
use Symfony\Component\EventDispatcher\Event;
/**
* Class UserProfileSyncEvent
*
* @package Kanboard\Event
* @author Fredic Guillot
*/
class UserProfileSyncEvent extends Event
{
/**
* User profile
*
* @var array
*/
private $profile;
/**
* User provider
*
* @var UserProviderInterface
*/
private $user;
/**
* UserProfileSyncEvent constructor.
*
* @param array $profile
* @param UserProviderInterface $user
*/
public function __construct(array $profile, UserProviderInterface $user)
{
$this->profile = $profile;
$this->user = $user;
}
/**
* Get user profile
*
* @access public
* @return array
*/
public function getProfile()
{
return $this->profile;
}
/**
* Get user provider object
*
* @access public
* @return UserProviderInterface|LdapUserProvider
*/
public function getUser()
{
return $this->user;
}
}

View File

@@ -75,20 +75,20 @@ class AvatarFile extends Base
}
/**
* Upload avatar image
* Upload avatar image file
*
* @access public
* @param integer $user_id
* @param array $file
* @return boolean
*/
public function uploadFile($user_id, array $file)
public function uploadImageFile($user_id, array $file)
{
try {
if ($file['error'] == UPLOAD_ERR_OK && $file['size'] > 0) {
$destination_filename = $this->generatePath($user_id, $file['name']);
$this->objectStorage->moveUploadedFile($file['tmp_name'], $destination_filename);
$this->create($user_id, $destination_filename);
$destinationFilename = $this->generatePath($user_id, $file['name']);
$this->objectStorage->moveUploadedFile($file['tmp_name'], $destinationFilename);
$this->create($user_id, $destinationFilename);
} else {
throw new Exception('File not uploaded: '.var_export($file['error'], true));
}
@@ -101,6 +101,28 @@ class AvatarFile extends Base
return true;
}
/**
* Upload avatar image content
*
* @access public
* @param integer $user_id
* @param string $blob
* @return boolean
*/
public function uploadImageContent($user_id, &$blob)
{
try {
$destinationFilename = $this->generatePath($user_id, 'imageContent');
$this->objectStorage->put($destinationFilename, $blob);
$this->create($user_id, $destinationFilename);
} catch (Exception $e) {
$this->logger->error($e->getMessage());
return false;
}
return true;
}
/**
* Generate the path for a new filename
*

View File

@@ -2,6 +2,7 @@
namespace Kanboard\ServiceProvider;
use Kanboard\Subscriber\LdapUserPhotoSubscriber;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;
@@ -28,6 +29,10 @@ class EventDispatcherProvider implements ServiceProviderInterface
$container['dispatcher']->addSubscriber(new TransitionSubscriber($container));
$container['dispatcher']->addSubscriber(new RecurringTaskSubscriber($container));
if (LDAP_AUTH && LDAP_USER_ATTRIBUTE_PHOTO !== '') {
$container['dispatcher']->addSubscriber(new LdapUserPhotoSubscriber($container));
}
return $container;
}
}

View File

@@ -34,7 +34,6 @@ class BaseSubscriber extends Base
}
$this->called[$key] = true;
return false;
}
}

View File

@@ -0,0 +1,49 @@
<?php
namespace Kanboard\Subscriber;
use Kanboard\Core\User\UserProfile;
use Kanboard\Event\UserProfileSyncEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Class LdapUserPhotoSubscriber
*
* @package Kanboard\Subscriber
* @author Frederic Guillot
*/
class LdapUserPhotoSubscriber extends BaseSubscriber implements EventSubscriberInterface
{
/**
* Get event listeners
*
* @static
* @access public
* @return array
*/
public static function getSubscribedEvents()
{
return array(
UserProfile::EVENT_USER_PROFILE_AFTER_SYNC => 'syncUserPhoto',
);
}
/**
* Save the user profile photo from LDAP to the object storage
*
* @access public
* @param UserProfileSyncEvent $event
*/
public function syncUserPhoto(UserProfileSyncEvent $event)
{
if (is_a($event->getUser(), 'Kanboard\User\LdapUserProvider')) {
$profile = $event->getProfile();
$photo = $event->getUser()->getPhoto();
if (empty($profile['avatar_path']) && ! empty($photo)) {
$this->logger->info('Saving user photo from LDAP profile');
$this->avatarFile->uploadImageContent($profile['id'], $photo);
}
}
}
}

View File

@@ -60,6 +60,14 @@ class LdapUserProvider implements UserProviderInterface
*/
protected $groupIds;
/**
* User photo
*
* @access protected
* @var string
*/
protected $photo = '';
/**
* Constructor
*
@@ -70,8 +78,9 @@ class LdapUserProvider implements UserProviderInterface
* @param string $email
* @param string $role
* @param string[] $groupIds
* @param string $photo
*/
public function __construct($dn, $username, $name, $email, $role, array $groupIds)
public function __construct($dn, $username, $name, $email, $role, array $groupIds, $photo = '')
{
$this->dn = $dn;
$this->username = $username;
@@ -79,6 +88,7 @@ class LdapUserProvider implements UserProviderInterface
$this->email = $email;
$this->role = $role;
$this->groupIds = $groupIds;
$this->photo = $photo;
}
/**
@@ -203,4 +213,15 @@ class LdapUserProvider implements UserProviderInterface
{
return $this->dn;
}
/**
* Get user photo
*
* @access public
* @return string
*/
public function getPhoto()
{
return $this->photo;
}
}

View File

@@ -59,6 +59,7 @@ defined('LDAP_USER_ATTRIBUTE_USERNAME') or define('LDAP_USER_ATTRIBUTE_USERNAME'
defined('LDAP_USER_ATTRIBUTE_FULLNAME') or define('LDAP_USER_ATTRIBUTE_FULLNAME', 'cn');
defined('LDAP_USER_ATTRIBUTE_EMAIL') or define('LDAP_USER_ATTRIBUTE_EMAIL', 'mail');
defined('LDAP_USER_ATTRIBUTE_GROUPS') or define('LDAP_USER_ATTRIBUTE_GROUPS', 'memberof');
defined('LDAP_USER_ATTRIBUTE_PHOTO') or define('LDAP_USER_ATTRIBUTE_PHOTO', '');
defined('LDAP_USER_CREATION') or define('LDAP_USER_CREATION', true);
defined('LDAP_GROUP_ADMIN_DN') or define('LDAP_GROUP_ADMIN_DN', '');