Completed
Push — stable8.2 ( e9036a...6707df )
by
unknown
59:39
created

USER_LDAP::implementsActions()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1
Metric Value
dl 0
loc 8
ccs 6
cts 6
cp 1
rs 9.4286
cc 1
eloc 7
nc 1
nop 1
crap 1
1
<?php
2
/**
3
 * @author Arthur Schiwon <[email protected]>
4
 * @author Bart Visscher <[email protected]>
5
 * @author Dominik Schmidt <[email protected]>
6
 * @author Jörn Friedrich Dreyer <[email protected]>
7
 * @author Lukas Reschke <[email protected]>
8
 * @author Morris Jobke <[email protected]>
9
 * @author Robin Appelman <[email protected]>
10
 * @author Robin McCorkell <[email protected]>
11
 * @author Thomas Müller <[email protected]>
12
 * @author Tom Needham <[email protected]>
13
 *
14
 * @copyright Copyright (c) 2015, ownCloud, Inc.
15
 * @license AGPL-3.0
16
 *
17
 * This code is free software: you can redistribute it and/or modify
18
 * it under the terms of the GNU Affero General Public License, version 3,
19
 * as published by the Free Software Foundation.
20
 *
21
 * This program is distributed in the hope that it will be useful,
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24
 * GNU Affero General Public License for more details.
25
 *
26
 * You should have received a copy of the GNU Affero General Public License, version 3,
27
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
28
 *
29
 */
30
31
namespace OCA\user_ldap;
32
33
use OC\User\NoUserException;
34
use OCA\user_ldap\lib\BackendUtility;
35
use OCA\user_ldap\lib\Access;
36
use OCA\user_ldap\lib\user\OfflineUser;
37
use OCA\User_LDAP\lib\User\User;
38
use OCP\IConfig;
39
40
class USER_LDAP extends BackendUtility implements \OCP\IUserBackend, \OCP\UserInterface {
41
	/** @var string[] $homesToKill */
42
	protected $homesToKill = array();
43
44
	/** @var \OCP\IConfig */
45
	protected $ocConfig;
46
47
	/**
48
	 * @param \OCA\user_ldap\lib\Access $access
49
	 * @param \OCP\IConfig $ocConfig
50
	 */
51 34
	public function __construct(Access $access, IConfig $ocConfig) {
52 34
		parent::__construct($access);
53 34
		$this->ocConfig = $ocConfig;
54 34
	}
55
56
	/**
57
	 * checks whether the user is allowed to change his avatar in ownCloud
58
	 * @param string $uid the ownCloud user name
59
	 * @return boolean either the user can or cannot
60
	 */
61
	public function canChangeAvatar($uid) {
62
		$user = $this->access->userManager->get($uid);
63
		if(!$user instanceof User) {
64
			return false;
65
		}
66
		if($user->getAvatarImage() === false) {
67
			return true;
68
		}
69
70
		return false;
71
	}
72
73
	/**
74
	 * returns the username for the given login name, if available
75
	 *
76
	 * @param string $loginName
77
	 * @return string|false
78
	 */
79
	public function loginName2UserName($loginName) {
80
		try {
81
			$ldapRecord = $this->getLDAPUserByLoginName($loginName);
82
			$user = $this->access->userManager->get($ldapRecord['dn'][0]);
83
			if($user instanceof OfflineUser) {
84
				return false;
85
			}
86
			return $user->getUsername();
87
		} catch (\Exception $e) {
88
			return false;
89
		}
90
	}
91
92
	/**
93
	 * returns an LDAP record based on a given login name
94
	 *
95
	 * @param string $loginName
96
	 * @return array
97
	 * @throws \Exception
98
	 */
99 7
	public function getLDAPUserByLoginName($loginName) {
100
		//find out dn of the user name
101 7
		$attrs = $this->access->userManager->getAttributes();
102 7
		$users = $this->access->fetchUsersByLoginName($loginName, $attrs, 1);
0 ignored issues
show
Unused Code introduced by
The call to Access::fetchUsersByLoginName() has too many arguments starting with 1.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
103 7
		if(count($users) < 1) {
104 2
			throw new \Exception('No user available for the given login name.');
105
		}
106 5
		return $users[0];
107
	}
108
109
	/**
110
	 * Check if the password is correct
111
	 * @param string $uid The username
112
	 * @param string $password The password
113
	 * @return false|string
114
	 *
115
	 * Check if the password is correct without logging in the user
116
	 */
117 17
	public function checkPassword($uid, $password) {
118
		try {
119 7
			$ldapRecord = $this->getLDAPUserByLoginName($uid);
120 7
		} catch(\Exception $e) {
121 2
			return false;
122
		}
123 5
		$dn = $ldapRecord['dn'][0];
124 5
		$user = $this->access->userManager->get($dn);
125
126 5
		if(!$user instanceof User) {
127 1
			\OCP\Util::writeLog('user_ldap',
128 1
				'LDAP Login: Could not get user object for DN ' . $dn .
129 1
				'. Maybe the LDAP entry has no set display name attribute?',
130 1
				\OCP\Util::WARN);
131 1
			return false;
132
		}
133 4
		if($user->getUsername() !== false) {
134
			//are the credentials OK?
135 4
			if(!$this->access->areCredentialsValid($dn, $password)) {
136 2
				return false;
137
			}
138
139 17
			$this->access->cacheUserExists($user->getUsername());
140 17
			$user->processAttributes($ldapRecord);
141 17
			$user->markLogin();
142
143 2
			return $user->getUsername();
144
		}
145
146
		return false;
147
	}
148
149
	/**
150
	 * Get a list of all users
151
	 *
152
	 * @param string $search
153
	 * @param null|int $limit
154
	 * @param null|int $offset
155
	 * @return string[] an array of all uids
156
	 */
157 12
	public function getUsers($search = '', $limit = 10, $offset = 0) {
158 10
		$search = $this->access->escapeFilterPart($search, true);
159 10
		$cachekey = 'getUsers-'.$search.'-'.$limit.'-'.$offset;
160
161
		//check if users are cached, if so return
162 12
		$ldap_users = $this->access->connection->getFromCache($cachekey);
163 10
		if(!is_null($ldap_users)) {
164
			return $ldap_users;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $ldap_users; (object|integer|double|string|array|boolean) is incompatible with the return type declared by the interface OC_User_Interface::getUsers of type string[].

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
165
		}
166
167
		// if we'd pass -1 to LDAP search, we'd end up in a Protocol
168
		// error. With a limit of 0, we get 0 results. So we pass null.
169 10
		if($limit <= 0) {
170 3
			$limit = null;
171 3
		}
172 10
		$filter = $this->access->combineFilterWithAnd(array(
173 10
			$this->access->connection->ldapUserFilter,
174 10
			$this->access->getFilterPartForUserSearch($search)
175 10
		));
176
177 10
		\OCP\Util::writeLog('user_ldap',
178 10
			'getUsers: Options: search '.$search.' limit '.$limit.' offset '.$offset.' Filter: '.$filter,
179 10
			\OCP\Util::DEBUG);
180
		//do the search and translate results to owncloud names
181 10
		$ldap_users = $this->access->fetchListOfUsers(
182 10
			$filter,
183 10
			$this->access->userManager->getAttributes(true),
184 10
			$limit, $offset);
185 10
		$ldap_users = $this->access->ownCloudUserNames($ldap_users);
186 10
		\OCP\Util::writeLog('user_ldap', 'getUsers: '.count($ldap_users). ' Users found', \OCP\Util::DEBUG);
187
188 10
		$this->access->connection->writeToCache($cachekey, $ldap_users);
189 10
		return $ldap_users;
190
	}
191
192
	/**
193
	 * checks whether a user is still available on LDAP
194
	 *
195
	 * @param string|\OCA\User_LDAP\lib\user\User $user either the ownCloud user
196
	 * name or an instance of that user
197
	 * @return bool
198
	 * @throws \Exception
199
	 * @throws \OC\ServerNotAvailableException
200
	 */
201 10
	public function userExistsOnLDAP($user) {
202 10
		if(is_string($user)) {
203
			$user = $this->access->userManager->get($user);
204
		}
205 10
		if(is_null($user)) {
206 1
			return false;
207
		}
208
209 9
		$dn = $user->getDN();
210
		//check if user really still exists by reading its entry
211 9
		if(!is_array($this->access->readAttribute($dn, ''))) {
212 5
			$lcr = $this->access->connection->getConnectionResource();
213 5
			if(is_null($lcr)) {
214 3
				throw new \Exception('No LDAP Connection to server ' . $this->access->connection->ldapHost);
0 ignored issues
show
Documentation introduced by
The property ldapHost does not exist on object<OCA\user_ldap\lib\Connection>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
215
			}
216
217
			try {
218 2
				$uuid = $this->access->getUserMapper()->getUUIDByDN($dn);
219 2
				if(!$uuid) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $uuid of type string|false is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
220 2
					return false;
221
				}
222
				$newDn = $this->access->getUserDnByUuid($uuid);
223
				$this->access->getUserMapper()->setDNbyUUID($newDn, $uuid);
224
				return true;
225
			} catch (\Exception $e) {
226
				return false;
227
			}
228
		}
229
230 6
		if($user instanceof OfflineUser) {
231
			$user->unmark();
232
		}
233
234 6
		return true;
235 2
	}
236
237
	/**
238
	 * check if a user exists
239
	 * @param string $uid the username
240
	 * @return boolean
241
	 * @throws \Exception when connection could not be established
242
	 */
243 12
	public function userExists($uid) {
244 12 View Code Duplication
		if($this->access->connection->isCached('userExists'.$uid)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
245
			return $this->access->connection->getFromCache('userExists'.$uid);
246
		}
247
		//getting dn, if false the user does not exist. If dn, he may be mapped only, requires more checking.
248 12
		$user = $this->access->userManager->get($uid);
249
250 12
		if(is_null($user)) {
251 2
			\OCP\Util::writeLog('user_ldap', 'No DN found for '.$uid.' on '.
252 2
				$this->access->connection->ldapHost, \OCP\Util::DEBUG);
0 ignored issues
show
Documentation introduced by
The property ldapHost does not exist on object<OCA\user_ldap\lib\Connection>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
253 2
			$this->access->connection->writeToCache('userExists'.$uid, false);
254 2
			return false;
255 10
		} else if($user instanceof OfflineUser) {
256
			//express check for users marked as deleted. Returning true is
257
			//necessary for cleanup
258 1
			return true;
259
		}
260
261 9
		$result = $this->userExistsOnLDAP($user);
262 6
		$this->access->connection->writeToCache('userExists'.$uid, $result);
263 6
		if($result === true) {
264 6
			$user->update();
265 6
		}
266 6
		return $result;
267
	}
268
269
	/**
270
	* returns whether a user was deleted in LDAP
271
	*
272
	* @param string $uid The username of the user to delete
273
	* @return bool
274
	*/
275 3
	public function deleteUser($uid) {
276 3
		$marked = $this->ocConfig->getUserValue($uid, 'user_ldap', 'isDeleted', 0);
277 3 View Code Duplication
		if(intval($marked) === 0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
278 2
			\OC::$server->getLogger()->notice(
279 2
				'User '.$uid . ' is not marked as deleted, not cleaning up.',
280 2
				array('app' => 'user_ldap'));
281 2
			return false;
282
		}
283 1
		\OC::$server->getLogger()->info('Cleaning up after user ' . $uid,
284 1
			array('app' => 'user_ldap'));
285
286
		//Get Home Directory out of user preferences so we can return it later,
287
		//necessary for removing directories as done by OC_User.
288 1
		$home = $this->ocConfig->getUserValue($uid, 'user_ldap', 'homePath', '');
289 1
		$this->homesToKill[$uid] = $home;
290 1
		$this->access->getUserMapper()->unmap($uid);
291
292 1
		return true;
293
	}
294
295
	/**
296
	 * get the user's home directory
297
	 *
298
	 * @param string $uid the username
299
	 * @return bool|string
300
	 * @throws NoUserException
301
	 * @throws \Exception
302
	 */
303 5
	public function getHome($uid) {
304 5
		if(isset($this->homesToKill[$uid]) && !empty($this->homesToKill[$uid])) {
305
			//a deleted user who needs some clean up
306 1
			return $this->homesToKill[$uid];
307
		}
308
309
		// user Exists check required as it is not done in user proxy!
310 4
		if(!$this->userExists($uid)) {
311
			return false;
312
		}
313
314 3
		$cacheKey = 'getHome'.$uid;
315 3
		if($this->access->connection->isCached($cacheKey)) {
316
			return $this->access->connection->getFromCache($cacheKey);
317
		}
318
319 3
		$user = $this->access->userManager->get($uid);
320 3
		if(is_null($user) || ($user instanceof OfflineUser && !$this->userExistsOnLDAP($user->getOCName()))) {
321 1
			throw new NoUserException($uid . ' is not a valid user anymore');
322
		}
323 2
		if($user instanceof OfflineUser) {
324
			// apparently this user survived the userExistsOnLDAP check,
325
			// we request the user instance again in order to retrieve a User
326
			// instance instead
327
			$user = $this->access->userManager->get($uid);
328
		}
329 2
		$path = $user->getHomePath();
330 2
		$this->access->cacheUserHome($uid, $path);
331
332 2
		return $path;
333
	}
334
335
	/**
336
	 * get display name of the user
337
	 * @param string $uid user ID of the user
338
	 * @return string|false display name
339
	 */
340 2
	public function getDisplayName($uid) {
341 2
		if(!$this->userExists($uid)) {
342 1
			return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type declared by the interface OC_User_Interface::getDisplayName of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
343
		}
344
345 2
		$cacheKey = 'getDisplayName'.$uid;
346 2
		if(!is_null($displayName = $this->access->connection->getFromCache($cacheKey))) {
347
			return $displayName;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $displayName; (object|integer|double|string|array|boolean) is incompatible with the return type declared by the interface OC_User_Interface::getDisplayName of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
348
		}
349
350 2
		$displayName = $this->access->readAttribute(
351 2
			$this->access->username2dn($uid),
0 ignored issues
show
Security Bug introduced by
It seems like $this->access->username2dn($uid) targeting OCA\user_ldap\lib\Access::username2dn() can also be of type false; however, OCA\user_ldap\lib\Access::readAttribute() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
352 2
			$this->access->connection->ldapUserDisplayName);
353
354 2
		if($displayName && (count($displayName) > 0)) {
355 2
			$this->access->connection->writeToCache($cacheKey, $displayName[0]);
356 2
			return $displayName[0];
357
		}
358
359
		return null;
360
	}
361
362
	/**
363
	 * Get a list of all display names
364
	 *
365
	 * @param string $search
366
	 * @param string|null $limit
367
	 * @param string|null $offset
368
	 * @return array an array of all displayNames (value) and the corresponding uids (key)
369
	 */
370
	public function getDisplayNames($search = '', $limit = null, $offset = null) {
371
		$cacheKey = 'getDisplayNames-'.$search.'-'.$limit.'-'.$offset;
372
		if(!is_null($displayNames = $this->access->connection->getFromCache($cacheKey))) {
373
			return $displayNames;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $displayNames; (object|integer|double|string|array|boolean) is incompatible with the return type declared by the interface OC_User_Interface::getDisplayNames of type array.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
374
		}
375
376
		$displayNames = array();
377
		$users = $this->getUsers($search, $limit, $offset);
378
		foreach ($users as $user) {
0 ignored issues
show
Bug introduced by
The expression $users of type object|integer|double|string|array|boolean is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
379
			$displayNames[$user] = $this->getDisplayName($user);
380
		}
381
		$this->access->connection->writeToCache($cacheKey, $displayNames);
382
		return $displayNames;
383
	}
384
385
	/**
386
	* Check if backend implements actions
387
	* @param int $actions bitwise-or'ed actions
388
	* @return boolean
389
	*
390
	* Returns the supported actions as int to be
391
	* compared with OC_USER_BACKEND_CREATE_USER etc.
392
	*/
393 4
	public function implementsActions($actions) {
394
		return (bool)((\OC_User_Backend::CHECK_PASSWORD
395 4
			| \OC_User_Backend::GET_HOME
396 4
			| \OC_User_Backend::GET_DISPLAYNAME
397 4
			| \OC_User_Backend::PROVIDE_AVATAR
398 4
			| \OC_User_Backend::COUNT_USERS)
399 4
			& $actions);
400
	}
401
402
	/**
403
	 * @return bool
404
	 */
405
	public function hasUserListings() {
406
		return true;
407
	}
408
409
	/**
410
	 * counts the users in LDAP
411
	 *
412
	 * @return int|bool
413
	 */
414 2
	public function countUsers() {
415 2
		$filter = $this->access->getFilterForUserCount();
416 2
		$cacheKey = 'countUsers-'.$filter;
417 2
		if(!is_null($entries = $this->access->connection->getFromCache($cacheKey))) {
418
			return $entries;
419
		}
420 2
		$entries = $this->access->countUsers($filter);
421 2
		$this->access->connection->writeToCache($cacheKey, $entries);
422 2
		return $entries;
423
	}
424
425
	/**
426
	 * Backend name to be shown in user management
427
	 * @return string the name of the backend to be shown
428
	 */
429
	public function getBackendName(){
430
		return 'LDAP';
431
	}
432
433
}
434