Added support for LDAP user photo profile
This commit is contained in:
parent
94989663ec
commit
300dabe6b4
|
|
@ -5,6 +5,7 @@ New features:
|
|||
|
||||
* Added automated action to change task color based on the priority
|
||||
* Added support for LDAP Posix Groups (OpenLDAP with memberUid)
|
||||
* Added support for LDAP user photo attribute (Avatar image)
|
||||
* Search in activity stream
|
||||
* Search in comments
|
||||
* Search by task creator
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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.'));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ class BaseSubscriber extends Base
|
|||
}
|
||||
|
||||
$this->called[$key] = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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', '');
|
||||
|
|
|
|||
|
|
@ -114,6 +114,9 @@ define('LDAP_USER_ATTRIBUTE_EMAIL', 'mail');
|
|||
// LDAP attribute to find groups in user profile
|
||||
define('LDAP_USER_ATTRIBUTE_GROUPS', 'memberof');
|
||||
|
||||
// LDAP attribute for user avatar image: thumbnailPhoto or jpegPhoto
|
||||
define('LDAP_USER_ATTRIBUTE_PHOTO', '');
|
||||
|
||||
// Allow automatic LDAP user creation
|
||||
define('LDAP_USER_CREATION', true);
|
||||
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ Technical details
|
|||
|
||||
- [LDAP authentication](ldap-authentication.markdown)
|
||||
- [LDAP group synchronization](ldap-group-sync.markdown)
|
||||
- [LDAP profile picture](ldap-profile-picture.markdown)
|
||||
- [LDAP parameters](ldap-parameters.markdown)
|
||||
- [Reverse proxy authentication](reverse-proxy-authentication.markdown)
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ Here is the list of available LDAP parameters:
|
|||
| `LDAP_USER_ATTRIBUTE_FULLNAME` | cn | LDAP attribute for user full name (Example: "displayname") |
|
||||
| `LDAP_USER_ATTRIBUTE_EMAIL` | mail | LDAP attribute for user email |
|
||||
| `LDAP_USER_ATTRIBUTE_GROUPS` | memberof | LDAP attribute to find groups in user profile |
|
||||
| `LDAP_USER_ATTRIBUTE_PHOTO` | Empty | LDAP attribute to find user photo (jpegPhoto or thumbnailPhoto |
|
||||
| `LDAP_USER_CREATION` | true | Enable automatic LDAP user creation |
|
||||
| `LDAP_GROUP_ADMIN_DN` | Empty | LDAP DN for administrators (Example: "CN=Kanboard-Admins,CN=Users,DC=kanboard,DC=local") |
|
||||
| `LDAP_GROUP_MANAGER_DN` | Empty | LDAP DN for managers (Example: "CN=Kanboard Managers,CN=Users,DC=kanboard,DC=local") |
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
LDAP User Profile Photo
|
||||
=======================
|
||||
|
||||
Kanboard can download automatically user pictures from the LDAP server.
|
||||
|
||||
This feature is enabled only if LDAP authentication is activated and the parameter `LDAP_USER_ATTRIBUTE_PHOTO` is defined.
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
In your `config.php`, you have to set the LDAP attribute used to store the image.
|
||||
|
||||
```php
|
||||
define('LDAP_USER_ATTRIBUTE_PHOTO', 'jpegPhoto');
|
||||
```
|
||||
|
||||
Usually, the attributes `jpegPhoto` or `thumbnailPhoto` are used.
|
||||
The image can be stored in JPEG or PNG format.
|
||||
|
||||
To upload the image in the user profile, Active Directory administrators may use software like [AD Photo Edit](http://www.cjwdev.co.uk/Software/ADPhotoEdit/Info.html).
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
The profile image is **downloaded at login time only if the user do not already have uploaded an image previously**.
|
||||
|
||||
To change the user photo, the previous one have to be removed manually in the user profile.
|
||||
|
|
@ -52,6 +52,7 @@ class LdapUserTest extends Base
|
|||
'getAttributeEmail',
|
||||
'getAttributeName',
|
||||
'getAttributeGroup',
|
||||
'getAttributePhoto',
|
||||
'getGroupUserFilter',
|
||||
'getGroupAdminDn',
|
||||
'getGroupManagerDn',
|
||||
|
|
@ -136,10 +137,79 @@ class LdapUserTest extends Base
|
|||
$this->assertEquals('My LDAP user', $user->getName());
|
||||
$this->assertEquals('user1@localhost', $user->getEmail());
|
||||
$this->assertEquals(Role::APP_USER, $user->getRole());
|
||||
$this->assertSame('', $user->getPhoto());
|
||||
$this->assertEquals(array(), $user->getExternalGroupIds());
|
||||
$this->assertEquals(array('is_ldap_user' => 1), $user->getExtraAttributes());
|
||||
}
|
||||
|
||||
public function testGetUserWithPhoto()
|
||||
{
|
||||
$entries = new Entries(array(
|
||||
'count' => 1,
|
||||
0 => array(
|
||||
'count' => 2,
|
||||
'dn' => 'uid=my_ldap_user,ou=People,dc=kanboard,dc=local',
|
||||
'displayname' => array(
|
||||
'count' => 1,
|
||||
0 => 'My LDAP user',
|
||||
),
|
||||
'mail' => array(
|
||||
'count' => 2,
|
||||
0 => 'user1@localhost',
|
||||
1 => 'user2@localhost',
|
||||
),
|
||||
'samaccountname' => array(
|
||||
'count' => 1,
|
||||
0 => 'my_ldap_user',
|
||||
),
|
||||
'jpegPhoto' => array(
|
||||
'count' => 1,
|
||||
0 => 'my photo',
|
||||
),
|
||||
0 => 'displayname',
|
||||
1 => 'mail',
|
||||
2 => 'samaccountname',
|
||||
)
|
||||
));
|
||||
|
||||
$this->client
|
||||
->expects($this->any())
|
||||
->method('getConnection')
|
||||
->will($this->returnValue('my_ldap_resource'));
|
||||
|
||||
$this->query
|
||||
->expects($this->once())
|
||||
->method('execute')
|
||||
->with(
|
||||
$this->equalTo('ou=People,dc=kanboard,dc=local'),
|
||||
$this->equalTo('(uid=my_ldap_user)')
|
||||
);
|
||||
|
||||
$this->query
|
||||
->expects($this->once())
|
||||
->method('hasResult')
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$this->query
|
||||
->expects($this->once())
|
||||
->method('getEntries')
|
||||
->will($this->returnValue($entries));
|
||||
|
||||
$this->user
|
||||
->expects($this->any())
|
||||
->method('getAttributePhoto')
|
||||
->will($this->returnValue('jpegPhoto'));
|
||||
|
||||
$this->user
|
||||
->expects($this->any())
|
||||
->method('getBasDn')
|
||||
->will($this->returnValue('ou=People,dc=kanboard,dc=local'));
|
||||
|
||||
$user = $this->user->find('(uid=my_ldap_user)');
|
||||
$this->assertInstanceOf('Kanboard\User\LdapUserProvider', $user);
|
||||
$this->assertEquals('my photo', $user->getPhoto());
|
||||
}
|
||||
|
||||
public function testGetUserWithAdminRole()
|
||||
{
|
||||
$entries = new Entries(array(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
|
||||
use Kanboard\Core\Security\Role;
|
||||
use Kanboard\Event\UserProfileSyncEvent;
|
||||
use Kanboard\Model\User;
|
||||
use Kanboard\Subscriber\LdapUserPhotoSubscriber;
|
||||
use Kanboard\User\DatabaseUserProvider;
|
||||
use Kanboard\User\LdapUserProvider;
|
||||
|
||||
require_once __DIR__.'/../Base.php';
|
||||
|
||||
class LdapUserPhotoSubscriberTest extends Base
|
||||
{
|
||||
public function testWhenTheProviderIsNotLdap()
|
||||
{
|
||||
$userProvider = new DatabaseUserProvider(array());
|
||||
$subscriber = new LdapUserPhotoSubscriber($this->container);
|
||||
$userModel = new User($this->container);
|
||||
|
||||
$userModel->update(array('id' => 1, 'avatar_path' => 'my avatar'));
|
||||
$user = $userModel->getById(1);
|
||||
|
||||
$subscriber->syncUserPhoto(new UserProfileSyncEvent($user, $userProvider));
|
||||
|
||||
$user = $userModel->getById(1);
|
||||
$this->assertEquals('my avatar', $user['avatar_path']);
|
||||
}
|
||||
|
||||
public function testWhenTheUserHaveLdapPhoto()
|
||||
{
|
||||
$userProvider = new LdapUserProvider('dn', 'admin', 'Admin', 'admin@localhost', Role::APP_ADMIN, array(), 'my photo');
|
||||
$subscriber = new LdapUserPhotoSubscriber($this->container);
|
||||
$userModel = new User($this->container);
|
||||
$user = $userModel->getById(1);
|
||||
|
||||
$this->container['objectStorage']
|
||||
->expects($this->once())
|
||||
->method('put')
|
||||
->with($this->anything(), 'my photo');
|
||||
|
||||
|
||||
$subscriber->syncUserPhoto(new UserProfileSyncEvent($user, $userProvider));
|
||||
|
||||
$user = $userModel->getById(1);
|
||||
$this->assertStringStartsWith('avatars', $user['avatar_path']);
|
||||
}
|
||||
|
||||
public function testWhenTheUserDoNotHaveLdapPhoto()
|
||||
{
|
||||
$userProvider = new LdapUserProvider('dn', 'admin', 'Admin', 'admin@localhost', Role::APP_ADMIN, array());
|
||||
$subscriber = new LdapUserPhotoSubscriber($this->container);
|
||||
$userModel = new User($this->container);
|
||||
$user = $userModel->getById(1);
|
||||
|
||||
$this->container['objectStorage']
|
||||
->expects($this->never())
|
||||
->method('put');
|
||||
|
||||
$subscriber->syncUserPhoto(new UserProfileSyncEvent($user, $userProvider));
|
||||
|
||||
$user = $userModel->getById(1);
|
||||
$this->assertEmpty($user['avatar_path']);
|
||||
}
|
||||
|
||||
public function testWhenTheUserAlreadyHaveAvatar()
|
||||
{
|
||||
$userProvider = new LdapUserProvider('dn', 'admin', 'Admin', 'admin@localhost', Role::APP_ADMIN, array(), 'my photo');
|
||||
$subscriber = new LdapUserPhotoSubscriber($this->container);
|
||||
$userModel = new User($this->container);
|
||||
|
||||
$userModel->update(array('id' => 1, 'avatar_path' => 'my avatar'));
|
||||
$user = $userModel->getById(1);
|
||||
|
||||
$this->container['objectStorage']
|
||||
->expects($this->never())
|
||||
->method('put');
|
||||
|
||||
$subscriber->syncUserPhoto(new UserProfileSyncEvent($user, $userProvider));
|
||||
|
||||
$user = $userModel->getById(1);
|
||||
$this->assertEquals('my avatar', $user['avatar_path']);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue