summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorblizzz <blizzz@owncloud.com>2013-11-26 12:05:32 -0800
committerblizzz <blizzz@owncloud.com>2013-11-26 12:05:32 -0800
commit4f15282bc998bb68896b5df67f4f749dd435897d (patch)
treed30a978ee443343541cfc9f825bba229da107296
parent1fef97f6a535cd79d0aea600634ec54c5f87bcea (diff)
parent69518b901326617a2a80986df0e250038684563b (diff)
downloadnextcloud-server-4f15282bc998bb68896b5df67f4f749dd435897d.tar.gz
nextcloud-server-4f15282bc998bb68896b5df67f4f749dd435897d.zip
Merge pull request #6058 from owncloud/ldap2avatar
Set Avatar for LDAP users automatically (if a picture is available)
-rw-r--r--apps/user_ldap/group_proxy.php5
-rw-r--r--apps/user_ldap/lib/access.php4
-rw-r--r--apps/user_ldap/lib/configuration.php3
-rw-r--r--apps/user_ldap/lib/proxy.php7
-rw-r--r--apps/user_ldap/user_ldap.php76
-rw-r--r--apps/user_ldap/user_proxy.php15
-rw-r--r--lib/private/avatar.php10
-rw-r--r--lib/private/user.php16
-rw-r--r--lib/private/user/backend.php15
-rw-r--r--lib/private/user/user.php12
-rw-r--r--settings/personal.php1
-rw-r--r--settings/templates/personal.php4
-rw-r--r--tests/lib/user/avataruserdummy.php27
-rw-r--r--tests/lib/user/user.php69
14 files changed, 245 insertions, 19 deletions
diff --git a/apps/user_ldap/group_proxy.php b/apps/user_ldap/group_proxy.php
index acc563c9532..4404bd7fe3a 100644
--- a/apps/user_ldap/group_proxy.php
+++ b/apps/user_ldap/group_proxy.php
@@ -67,16 +67,17 @@ class Group_Proxy extends lib\Proxy implements \OCP\GroupInterface {
* @param $gid string, the gid connected to the request
* @param $method string, the method of the group backend that shall be called
* @param $parameters an array of parameters to be passed
+ * @param $passOnWhen the result matches this variable
* @return mixed, the result of the method or false
*/
- protected function callOnLastSeenOn($gid, $method, $parameters) {
+ protected function callOnLastSeenOn($gid, $method, $parameters, $passOnWhen) {
$cacheKey = $this->getGroupCacheKey($gid);;
$prefix = $this->getFromCache($cacheKey);
//in case the uid has been found in the past, try this stored connection first
if(!is_null($prefix)) {
if(isset($this->backends[$prefix])) {
$result = call_user_func_array(array($this->backends[$prefix], $method), $parameters);
- if(!$result) {
+ if($result === $passOnWhen) {
//not found here, reset cache to null if group vanished
//because sometimes methods return false with a reason
$groupExists = call_user_func_array(
diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php
index a07bd3fa11f..ecc74b6cf54 100644
--- a/apps/user_ldap/lib/access.php
+++ b/apps/user_ldap/lib/access.php
@@ -199,7 +199,9 @@ class Access extends LDAPUtility {
*/
public function username2dn($name) {
$dn = $this->ocname2dn($name, true);
- if($dn) {
+ //Check whether the DN belongs to the Base, to avoid issues on multi-
+ //server setups
+ if($dn && $this->isDNPartOfBase($dn, $this->connection->ldapBaseUsers)) {
return $dn;
}
diff --git a/apps/user_ldap/lib/configuration.php b/apps/user_ldap/lib/configuration.php
index e14ed824a74..58f4b11e690 100644
--- a/apps/user_ldap/lib/configuration.php
+++ b/apps/user_ldap/lib/configuration.php
@@ -72,6 +72,7 @@ class Configuration {
'ldapExpertUsernameAttr' => null,
'ldapExpertUUIDUserAttr' => null,
'ldapExpertUUIDGroupAttr' => null,
+ 'lastJpegPhotoLookup' => null,
);
public function __construct($configPrefix, $autoread = true) {
@@ -330,6 +331,7 @@ class Configuration {
'ldap_expert_uuid_user_attr' => '',
'ldap_expert_uuid_group_attr' => '',
'has_memberof_filter_support' => 0,
+ 'last_jpegPhoto_lookup' => 0,
);
}
@@ -377,6 +379,7 @@ class Configuration {
'ldap_expert_uuid_user_attr' => 'ldapExpertUUIDUserAttr',
'ldap_expert_uuid_group_attr' => 'ldapExpertUUIDGroupAttr',
'has_memberof_filter_support' => 'hasMemberOfFilterSupport',
+ 'last_jpegPhoto_lookup' => 'lastJpegPhotoLookup',
);
return $array;
}
diff --git a/apps/user_ldap/lib/proxy.php b/apps/user_ldap/lib/proxy.php
index c74b357bdd2..30e1875901c 100644
--- a/apps/user_ldap/lib/proxy.php
+++ b/apps/user_ldap/lib/proxy.php
@@ -54,7 +54,7 @@ abstract class Proxy {
return 'group-'.$gid.'-lastSeenOn';
}
- abstract protected function callOnLastSeenOn($id, $method, $parameters);
+ abstract protected function callOnLastSeenOn($id, $method, $parameters, $passOnWhen);
abstract protected function walkBackends($id, $method, $parameters);
/**
@@ -64,8 +64,9 @@ abstract class Proxy {
* @param $parameters an array of parameters to be passed
* @return mixed, the result of the specified method
*/
- protected function handleRequest($id, $method, $parameters) {
- if(!$result = $this->callOnLastSeenOn($id, $method, $parameters)) {
+ protected function handleRequest($id, $method, $parameters, $passOnWhen = false) {
+ $result = $this->callOnLastSeenOn($id, $method, $parameters, $passOnWhen);
+ if($result === $passOnWhen) {
$result = $this->walkBackends($id, $method, $parameters);
}
return $result;
diff --git a/apps/user_ldap/user_ldap.php b/apps/user_ldap/user_ldap.php
index 6f52bbdf233..527a5c10b85 100644
--- a/apps/user_ldap/user_ldap.php
+++ b/apps/user_ldap/user_ldap.php
@@ -70,6 +70,74 @@ class USER_LDAP extends BackendUtility implements \OCP\UserInterface {
}
/**
+ * @brief reads jpegPhoto and set is as avatar if available
+ * @param $uid string ownCloud user name
+ * @param $dn string the user's LDAP DN
+ * @return void
+ */
+ private function updateAvatar($uid, $dn) {
+ $hasLoggedIn = \OCP\Config::getUserValue($uid, 'user_ldap',
+ 'firstLoginAccomplished', 0);
+ $lastChecked = \OCP\Config::getUserValue($uid, 'user_ldap',
+ 'lastJpegPhotoLookup', 0);
+ if(($hasLoggedIn !== '1') || (time() - intval($lastChecked)) < 86400 ) {
+ //update only once a day
+ return;
+ }
+
+ $jpegPhoto = $this->access->readAttribute($dn, 'jpegPhoto');
+ \OCP\Config::setUserValue($uid, 'user_ldap', 'lastJpegPhotoLookup', time());
+ if(!$jpegPhoto || !is_array($jpegPhoto) || !isset($jpegPhoto[0])) {
+ //not set, nothing left to do;
+ return;
+ }
+
+ $image = new \OCP\Image();
+ $image->loadFromBase64(base64_encode($jpegPhoto[0]));
+
+ if(!$image->valid()) {
+ \OCP\Util::writeLog('user_ldap', 'jpegPhoto data invalid for '.$dn,
+ \OCP\Util::ERROR);
+ return;
+ }
+ //make sure it is a square and not bigger than 128x128
+ $size = min(array($image->width(), $image->height(), 128));
+ if(!$image->centerCrop($size)) {
+ \OCP\Util::writeLog('user_ldap',
+ 'croping image for avatar failed for '.$dn,
+ \OCP\Util::ERROR);
+ return;
+ }
+
+ if(!\OC\Files\Filesystem::$loaded) {
+ \OC_Util::setupFS($uid);
+ }
+
+ $avatarManager = \OC::$server->getAvatarManager();
+ $avatar = $avatarManager->getAvatar($uid);
+ $avatar->set($image);
+ }
+
+ /**
+ * @brief checks whether the user is allowed to change his avatar in ownCloud
+ * @param $uid string the ownCloud user name
+ * @return boolean either the user can or cannot
+ */
+ public function canChangeAvatar($uid) {
+ $dn = $this->access->username2dn($uid);
+ if(!$dn) {
+ return false;
+ }
+ $jpegPhoto = $this->access->readAttribute($dn, 'jpegPhoto');
+ if(!$jpegPhoto || !is_array($jpegPhoto) || !isset($jpegPhoto[0])) {
+ //The user is allowed to change his avatar in ownCloud only if no
+ //avatar is provided by LDAP
+ return true;
+ }
+ return false;
+ }
+
+ /**
* @brief Check if the password is correct
* @param $uid The username
* @param $password The password
@@ -100,6 +168,10 @@ class USER_LDAP extends BackendUtility implements \OCP\UserInterface {
return false;
}
+ \OCP\Config::setUserValue($ocname, 'user_ldap',
+ 'firstLoginAccomplished', 1);
+
+ $this->updateAvatar($ocname, $dn);
//give back the display name
return $ocname;
}
@@ -173,6 +245,7 @@ class USER_LDAP extends BackendUtility implements \OCP\UserInterface {
$this->access->connection->writeToCache('userExists'.$uid, true);
$this->updateQuota($dn);
+ $this->updateAvatar($uid, $dn);
return true;
}
@@ -289,7 +362,8 @@ class USER_LDAP extends BackendUtility implements \OCP\UserInterface {
public function implementsActions($actions) {
return (bool)((OC_USER_BACKEND_CHECK_PASSWORD
| OC_USER_BACKEND_GET_HOME
- | OC_USER_BACKEND_GET_DISPLAYNAME)
+ | OC_USER_BACKEND_GET_DISPLAYNAME
+ | OC_USER_BACKEND_PROVIDE_AVATAR)
& $actions);
}
diff --git a/apps/user_ldap/user_proxy.php b/apps/user_ldap/user_proxy.php
index 092fdbf7c78..b073b143e74 100644
--- a/apps/user_ldap/user_proxy.php
+++ b/apps/user_ldap/user_proxy.php
@@ -54,6 +54,7 @@ class User_Proxy extends lib\Proxy implements \OCP\UserInterface {
protected function walkBackends($uid, $method, $parameters) {
$cacheKey = $this->getUserCacheKey($uid);
foreach($this->backends as $configPrefix => $backend) {
+// print("walkBackend '$configPrefix'<br/>");
if($result = call_user_func_array(array($backend, $method), $parameters)) {
$this->writeToCache($cacheKey, $configPrefix);
return $result;
@@ -67,16 +68,17 @@ class User_Proxy extends lib\Proxy implements \OCP\UserInterface {
* @param $uid string, the uid connected to the request
* @param $method string, the method of the user backend that shall be called
* @param $parameters an array of parameters to be passed
+ * @param $passOnWhen the result matches this variable
* @return mixed, the result of the method or false
*/
- protected function callOnLastSeenOn($uid, $method, $parameters) {
+ protected function callOnLastSeenOn($uid, $method, $parameters, $passOnWhen) {
$cacheKey = $this->getUserCacheKey($uid);
$prefix = $this->getFromCache($cacheKey);
//in case the uid has been found in the past, try this stored connection first
if(!is_null($prefix)) {
if(isset($this->backends[$prefix])) {
$result = call_user_func_array(array($this->backends[$prefix], $method), $parameters);
- if(!$result) {
+ if($result === $passOnWhen) {
//not found here, reset cache to null if user vanished
//because sometimes methods return false with a reason
$userExists = call_user_func_array(
@@ -164,6 +166,15 @@ class User_Proxy extends lib\Proxy implements \OCP\UserInterface {
}
/**
+ * @brief checks whether the user is allowed to change his avatar in ownCloud
+ * @param $uid string the ownCloud user name
+ * @return boolean either the user can or cannot
+ */
+ public function canChangeAvatar($uid) {
+ return $this->handleRequest($uid, 'canChangeAvatar', array($uid), true);
+ }
+
+ /**
* @brief Get a list of all display names
* @returns array with all displayNames (value) and the corresponding uids (key)
*
diff --git a/lib/private/avatar.php b/lib/private/avatar.php
index 814a9b22bed..e97f55eecaf 100644
--- a/lib/private/avatar.php
+++ b/lib/private/avatar.php
@@ -44,15 +44,19 @@ class OC_Avatar implements \OCP\IAvatar {
/**
* @brief sets the users avatar
- * @param $data mixed imagedata or path to set a new avatar
+ * @param $data mixed OC_Image, imagedata or path to set a new avatar
* @throws Exception if the provided file is not a jpg or png image
* @throws Exception if the provided image is not valid
* @throws \OC\NotSquareException if the image is not square
* @return void
*/
public function set ($data) {
-
- $img = new OC_Image($data);
+ if($data instanceOf OC_Image) {
+ $img = $data;
+ $data = $img->data();
+ } else {
+ $img = new OC_Image($data);
+ }
$type = substr($img->mimeType(), -3);
if ($type === 'peg') {
$type = 'jpg';
diff --git a/lib/private/user.php b/lib/private/user.php
index 5bd36006750..210e5ed3f02 100644
--- a/lib/private/user.php
+++ b/lib/private/user.php
@@ -425,6 +425,22 @@ class OC_User {
}
/**
+ * @brief Check whether user can change his avatar
+ * @param string $uid The username
+ * @return bool
+ *
+ * Check whether a specified user can change his avatar
+ */
+ public static function canUserChangeAvatar($uid) {
+ $user = self::getManager()->get($uid);
+ if ($user) {
+ return $user->canChangeAvatar();
+ } else {
+ return false;
+ }
+ }
+
+ /**
* @brief Check whether user can change his password
* @param string $uid The username
* @return bool
diff --git a/lib/private/user/backend.php b/lib/private/user/backend.php
index e9be08e429c..02c93d13bdf 100644
--- a/lib/private/user/backend.php
+++ b/lib/private/user/backend.php
@@ -31,13 +31,13 @@ define('OC_USER_BACKEND_NOT_IMPLEMENTED', -501);
/**
* actions that user backends can define
*/
-define('OC_USER_BACKEND_CREATE_USER', 0x000001);
-define('OC_USER_BACKEND_SET_PASSWORD', 0x000010);
-define('OC_USER_BACKEND_CHECK_PASSWORD', 0x000100);
-define('OC_USER_BACKEND_GET_HOME', 0x001000);
-define('OC_USER_BACKEND_GET_DISPLAYNAME', 0x010000);
-define('OC_USER_BACKEND_SET_DISPLAYNAME', 0x100000);
-
+define('OC_USER_BACKEND_CREATE_USER', 0x0000001);
+define('OC_USER_BACKEND_SET_PASSWORD', 0x0000010);
+define('OC_USER_BACKEND_CHECK_PASSWORD', 0x0000100);
+define('OC_USER_BACKEND_GET_HOME', 0x0001000);
+define('OC_USER_BACKEND_GET_DISPLAYNAME', 0x0010000);
+define('OC_USER_BACKEND_SET_DISPLAYNAME', 0x0100000);
+define('OC_USER_BACKEND_PROVIDE_AVATAR', 0x1000000);
/**
* Abstract base class for user management. Provides methods for querying backend
@@ -54,6 +54,7 @@ abstract class OC_User_Backend implements OC_User_Interface {
OC_USER_BACKEND_GET_HOME => 'getHome',
OC_USER_BACKEND_GET_DISPLAYNAME => 'getDisplayName',
OC_USER_BACKEND_SET_DISPLAYNAME => 'setDisplayName',
+ OC_USER_BACKEND_PROVIDE_AVATAR => 'canChangeAvatar',
);
/**
diff --git a/lib/private/user/user.php b/lib/private/user/user.php
index e5f842944f1..e773473ec41 100644
--- a/lib/private/user/user.php
+++ b/lib/private/user/user.php
@@ -140,6 +140,18 @@ class User {
}
/**
+ * check if the backend allows the user to change his avatar on Personal page
+ *
+ * @return bool
+ */
+ public function canChangeAvatar() {
+ if($this->backend->implementsActions(\OC_USER_BACKEND_PROVIDE_AVATAR)) {
+ return $this->backend->canChangeAvatar($this->uid);
+ }
+ return true;
+ }
+
+ /**
* check if the backend supports changing passwords
*
* @return bool
diff --git a/settings/personal.php b/settings/personal.php
index 670e18e20ef..44e1048941b 100644
--- a/settings/personal.php
+++ b/settings/personal.php
@@ -90,6 +90,7 @@ $tmpl->assign('displayNameChangeSupported', OC_User::canUserChangeDisplayName(OC
$tmpl->assign('displayName', OC_User::getDisplayName());
$tmpl->assign('enableDecryptAll' , $enableDecryptAll);
$tmpl->assign('enableAvatars', \OC_Config::getValue('enable_avatars', true));
+$tmpl->assign('avatarChangeSupported', OC_User::canUserChangeAvatar(OC_User::getUser()));
$forms=OC_App::getForms('personal');
$tmpl->assign('forms', array());
diff --git a/settings/templates/personal.php b/settings/templates/personal.php
index a79eeefa796..3eb864655bb 100644
--- a/settings/templates/personal.php
+++ b/settings/templates/personal.php
@@ -87,11 +87,15 @@ if($_['passwordChangeSupported']) {
<div id="displayavatar">
<div class="avatardiv"></div><br>
<div class="warning hidden"></div>
+ <?php if ($_['avatarChangeSupported']): ?>
<div class="inlineblock button" id="uploadavatarbutton"><?php p($l->t('Upload new')); ?></div>
<input type="file" class="hidden" name="files[]" id="uploadavatar">
<div class="inlineblock button" id="selectavatar"><?php p($l->t('Select new from Files')); ?></div>
<div class="inlineblock button" id="removeavatar"><?php p($l->t('Remove image')); ?></div><br>
<?php p($l->t('Either png or jpg. Ideally square but you will be able to crop it.')); ?>
+ <?php else: ?>
+ <?php p($l->t('Your avatar is provided by your original account.')); ?>
+ <?php endif; ?>
</div>
<div id="cropper" class="hidden">
<div class="inlineblock button" id="abortcropperbutton"><?php p($l->t('Abort')); ?></div>
diff --git a/tests/lib/user/avataruserdummy.php b/tests/lib/user/avataruserdummy.php
new file mode 100644
index 00000000000..738b10492ea
--- /dev/null
+++ b/tests/lib/user/avataruserdummy.php
@@ -0,0 +1,27 @@
+<?php
+/**
+* ownCloud
+*
+* @author Arthur Schiwon
+* @copyright 2013 Arthur Schiwon blizzz@owncloud.com
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the License, or any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+class Avatar_User_Dummy extends \OC_User_Dummy {
+ public function canChangeAvatar($uid) {
+ return true;
+ }
+} \ No newline at end of file
diff --git a/tests/lib/user/user.php b/tests/lib/user/user.php
index de5ccbf38c1..0bbcda013ce 100644
--- a/tests/lib/user/user.php
+++ b/tests/lib/user/user.php
@@ -87,6 +87,75 @@ class User extends \PHPUnit_Framework_TestCase {
$this->assertFalse($user->setPassword('bar',''));
}
+ public function testChangeAvatarSupportedYes() {
+ /**
+ * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend
+ */
+ require_once 'avataruserdummy.php';
+ $backend = $this->getMock('Avatar_User_Dummy');
+ $backend->expects($this->once())
+ ->method('canChangeAvatar')
+ ->with($this->equalTo('foo'))
+ ->will($this->returnValue(true));
+
+ $backend->expects($this->any())
+ ->method('implementsActions')
+ ->will($this->returnCallback(function ($actions) {
+ if ($actions === \OC_USER_BACKEND_PROVIDE_AVATAR) {
+ return true;
+ } else {
+ return false;
+ }
+ }));
+
+ $user = new \OC\User\User('foo', $backend);
+ $this->assertTrue($user->canChangeAvatar());
+ }
+
+ public function testChangeAvatarSupportedNo() {
+ /**
+ * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend
+ */
+ require_once 'avataruserdummy.php';
+ $backend = $this->getMock('Avatar_User_Dummy');
+ $backend->expects($this->once())
+ ->method('canChangeAvatar')
+ ->with($this->equalTo('foo'))
+ ->will($this->returnValue(false));
+
+ $backend->expects($this->any())
+ ->method('implementsActions')
+ ->will($this->returnCallback(function ($actions) {
+ if ($actions === \OC_USER_BACKEND_PROVIDE_AVATAR) {
+ return true;
+ } else {
+ return false;
+ }
+ }));
+
+ $user = new \OC\User\User('foo', $backend);
+ $this->assertFalse($user->canChangeAvatar());
+ }
+
+ public function testChangeAvatarNotSupported() {
+ /**
+ * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend
+ */
+ require_once 'avataruserdummy.php';
+ $backend = $this->getMock('Avatar_User_Dummy');
+ $backend->expects($this->never())
+ ->method('canChangeAvatar');
+
+ $backend->expects($this->any())
+ ->method('implementsActions')
+ ->will($this->returnCallback(function ($actions) {
+ return false;
+ }));
+
+ $user = new \OC\User\User('foo', $backend);
+ $this->assertTrue($user->canChangeAvatar());
+ }
+
public function testDelete() {
/**
* @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend