Merge pull request #34443 from nextcloud/feat/add-enabled-user-backend

Add IProvideEnabledStateBackend interface
pull/39120/head
Côme Chilliet 2023-07-03 10:19:32 +07:00 committed by GitHub
commit b2f01b72fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 355 additions and 179 deletions

@ -67,6 +67,10 @@ OCA = OCA || {};
$element: $('#ldap_attributes_for_user_search'),
setMethod: 'setSearchAttributesUsers'
},
ldap_mark_remnants_as_disabled: {
$element: $('#ldap_mark_remnants_as_disabled'),
setMethod: 'setMarkRemnantsAsDisabled'
},
ldap_group_display_name: {
$element: $('#ldap_group_display_name'),
setMethod: 'setGroupDisplayName'
@ -275,6 +279,15 @@ OCA = OCA || {};
this.setElementValue(this.managedItems.ldap_attributes_for_user_search.$element, attributes);
},
/**
* enables or disables marking remnants as disabled
*
* @param {string} markRemnantsAsDisabled contains an int
*/
setMarkRemnantsAsDisabled: function(markRemnantsAsDisabled) {
this.setElementValue(this.managedItems.ldap_mark_remnants_as_disabled.$element, markRemnantsAsDisabled);
},
/**
* sets the display name attribute for groups
*

@ -115,6 +115,7 @@ class Configuration {
'ldapExpertUsernameAttr' => null,
'ldapExpertUUIDUserAttr' => null,
'ldapExpertUUIDGroupAttr' => null,
'markRemnantsAsDisabled' => false,
'lastJpegPhotoLookup' => null,
'ldapNestedGroups' => false,
'ldapPagingSize' => null,
@ -468,6 +469,7 @@ class Configuration {
'ldap_expert_uuid_group_attr' => '',
'has_memberof_filter_support' => 0,
'use_memberof_to_detect_membership' => 1,
'ldap_mark_remnants_as_disabled' => 0,
'last_jpegPhoto_lookup' => 0,
'ldap_nested_groups' => 0,
'ldap_paging_size' => 500,
@ -543,6 +545,7 @@ class Configuration {
'ldap_expert_uuid_group_attr' => 'ldapExpertUUIDGroupAttr',
'has_memberof_filter_support' => 'hasMemberOfFilterSupport',
'use_memberof_to_detect_membership' => 'useMemberOfToDetectMembership',
'ldap_mark_remnants_as_disabled' => 'markRemnantsAsDisabled',
'last_jpegPhoto_lookup' => 'lastJpegPhotoLookup',
'ldap_nested_groups' => 'ldapNestedGroups',
'ldap_paging_size' => 'ldapPagingSize',

@ -63,6 +63,7 @@ use Psr\Log\LoggerInterface;
* @property string ldapEmailAttribute
* @property string ldapExtStorageHomeAttribute
* @property string homeFolderNamingRule
* @property bool|string markRemnantsAsDisabled
* @property bool|string ldapNestedGroups
* @property string[] ldapBaseGroups
* @property string ldapGroupFilter

@ -24,6 +24,7 @@
namespace OCA\User_LDAP\User;
use OCA\User_LDAP\Mapping\UserMapping;
use OCP\IConfig;
use OCP\Share\IManager;
/**
@ -31,24 +32,16 @@ use OCP\Share\IManager;
* @package OCA\User_LDAP
*/
class DeletedUsersIndex {
/**
* @var \OCP\IConfig $config
*/
protected $config;
/**
* @var \OCA\User_LDAP\Mapping\UserMapping $mapping
*/
protected $mapping;
protected IConfig $config;
protected UserMapping $mapping;
protected ?array $deletedUsers = null;
private IManager $shareManager;
/**
* @var array $deletedUsers
*/
protected $deletedUsers;
/** @var IManager */
private $shareManager;
public function __construct(\OCP\IConfig $config, UserMapping $mapping, IManager $shareManager) {
public function __construct(
IConfig $config,
UserMapping $mapping,
IManager $shareManager
) {
$this->config = $config;
$this->mapping = $mapping;
$this->shareManager = $shareManager;
@ -56,11 +49,10 @@ class DeletedUsersIndex {
/**
* reads LDAP users marked as deleted from the database
* @return \OCA\User_LDAP\User\OfflineUser[]
* @return OfflineUser[]
*/
private function fetchDeletedUsers() {
$deletedUsers = $this->config->getUsersForUserValue(
'user_ldap', 'isDeleted', '1');
private function fetchDeletedUsers(): array {
$deletedUsers = $this->config->getUsersForUserValue('user_ldap', 'isDeleted', '1');
$userObjects = [];
foreach ($deletedUsers as $user) {
@ -73,9 +65,9 @@ class DeletedUsersIndex {
/**
* returns all LDAP users that are marked as deleted
* @return \OCA\User_LDAP\User\OfflineUser[]
* @return OfflineUser[]
*/
public function getUsers() {
public function getUsers(): array {
if (is_array($this->deletedUsers)) {
return $this->deletedUsers;
}
@ -84,9 +76,8 @@ class DeletedUsersIndex {
/**
* whether at least one user was detected as deleted
* @return bool
*/
public function hasUsers() {
public function hasUsers(): bool {
if (!is_array($this->deletedUsers)) {
$this->fetchDeletedUsers();
}
@ -96,12 +87,10 @@ class DeletedUsersIndex {
/**
* marks a user as deleted
*
* @param string $ocName
* @throws \OCP\PreConditionNotMetException
*/
public function markUser($ocName) {
$curValue = $this->config->getUserValue($ocName, 'user_ldap', 'isDeleted', '0');
if ($curValue === '1') {
public function markUser(string $ocName): void {
if ($this->isUserMarked($ocName)) {
// the user is already marked, do not write to DB again
return;
}
@ -109,4 +98,8 @@ class DeletedUsersIndex {
$this->config->setUserValue($ocName, 'user_ldap', 'foundDeleted', (string)time());
$this->deletedUsers = null;
}
public function isUserMarked(string $ocName): bool {
return ($this->config->getUserValue($ocName, 'user_ldap', 'isDeleted', '0') === '1');
}
}

@ -42,6 +42,7 @@ use OC\ServerNotAvailableException;
use OC\User\Backend;
use OC\User\NoUserException;
use OCA\User_LDAP\Exceptions\NotOnLDAP;
use OCA\User_LDAP\User\DeletedUsersIndex;
use OCA\User_LDAP\User\OfflineUser;
use OCA\User_LDAP\User\User;
use OCP\IConfig;
@ -50,34 +51,32 @@ use OCP\IUserSession;
use OCP\Notification\IManager as INotificationManager;
use OCP\User\Backend\ICountMappedUsersBackend;
use OCP\User\Backend\ICountUsersBackend;
use OCP\User\Backend\IProvideEnabledStateBackend;
use OCP\UserInterface;
use Psr\Log\LoggerInterface;
class User_LDAP extends BackendUtility implements IUserBackend, UserInterface, IUserLDAP, ICountUsersBackend, ICountMappedUsersBackend {
/** @var \OCP\IConfig */
protected $ocConfig;
/** @var INotificationManager */
protected $notificationManager;
/** @var UserPluginManager */
protected $userPluginManager;
/** @var LoggerInterface */
protected $logger;
/**
* @param Access $access
* @param \OCP\IConfig $ocConfig
* @param \OCP\Notification\IManager $notificationManager
* @param IUserSession $userSession
*/
public function __construct(Access $access, IConfig $ocConfig, INotificationManager $notificationManager, IUserSession $userSession, UserPluginManager $userPluginManager) {
class User_LDAP extends BackendUtility implements IUserBackend, UserInterface, IUserLDAP, ICountUsersBackend, ICountMappedUsersBackend, IProvideEnabledStateBackend {
protected IConfig $ocConfig;
protected INotificationManager $notificationManager;
protected UserPluginManager $userPluginManager;
protected LoggerInterface $logger;
protected DeletedUsersIndex $deletedUsersIndex;
public function __construct(
Access $access,
IConfig $ocConfig,
INotificationManager $notificationManager,
IUserSession $userSession,
UserPluginManager $userPluginManager,
LoggerInterface $logger,
DeletedUsersIndex $deletedUsersIndex,
) {
parent::__construct($access);
$this->ocConfig = $ocConfig;
$this->notificationManager = $notificationManager;
$this->userPluginManager = $userPluginManager;
$this->logger = \OC::$server->get(LoggerInterface::class);
$this->logger = $logger;
$this->deletedUsersIndex = $deletedUsersIndex;
}
/**
@ -392,13 +391,13 @@ class User_LDAP extends BackendUtility implements IUserBackend, UserInterface, I
}
}
$marked = (int)$this->ocConfig->getUserValue($uid, 'user_ldap', 'isDeleted', 0);
if ($marked === 0) {
$marked = $this->deletedUsersIndex->isUserMarked($uid);
if (!$marked) {
try {
$user = $this->access->userManager->get($uid);
if (($user instanceof User) && !$this->userExistsOnLDAP($uid, true)) {
$user->markUser();
$marked = 1;
$marked = true;
}
} catch (\Exception $e) {
$this->logger->debug(
@ -406,7 +405,7 @@ class User_LDAP extends BackendUtility implements IUserBackend, UserInterface, I
['app' => 'user_ldap', 'exception' => $e]
);
}
if ($marked === 0) {
if (!$marked) {
$this->logger->notice(
'User '.$uid . ' is not marked as deleted, not cleaning up.',
['app' => 'user_ldap']
@ -669,4 +668,21 @@ class User_LDAP extends BackendUtility implements IUserBackend, UserInterface, I
}
return false;
}
public function isUserEnabled(string $uid, callable $queryDatabaseValue): bool {
if ($this->deletedUsersIndex->isUserMarked($uid) && ((int)$this->access->connection->markRemnantsAsDisabled === 1)) {
return false;
} else {
return $queryDatabaseValue();
}
}
public function setUserEnabled(string $uid, bool $enabled, callable $queryDatabaseValue, callable $setDatabaseValue): bool {
$setDatabaseValue($enabled);
return $enabled;
}
public function getDisabledUserList(int $offset = 0, ?int $limit = null): array {
throw new \Exception('This is implemented directly in User_Proxy');
}
}

@ -31,20 +31,23 @@
*/
namespace OCA\User_LDAP;
use OCA\User_LDAP\User\DeletedUsersIndex;
use OCA\User_LDAP\User\OfflineUser;
use OCA\User_LDAP\User\User;
use OCP\IConfig;
use OCP\IUserBackend;
use OCP\IUserSession;
use OCP\Notification\IManager as INotificationManager;
use OCP\UserInterface;
use OCP\User\Backend\ICountMappedUsersBackend;
use OCP\User\Backend\ICountUsersBackend;
use OCP\UserInterface;
use OCP\User\Backend\IProvideEnabledStateBackend;
use Psr\Log\LoggerInterface;
class User_Proxy extends Proxy implements IUserBackend, UserInterface, IUserLDAP, ICountUsersBackend, ICountMappedUsersBackend {
/** @var array<string,User_LDAP> */
private $backends = [];
/** @var ?User_LDAP */
private $refBackend = null;
class User_Proxy extends Proxy implements IUserBackend, UserInterface, IUserLDAP, ICountUsersBackend, ICountMappedUsersBackend, IProvideEnabledStateBackend {
/** @var User_LDAP[] */
private array $backends = [];
private ?User_LDAP $refBackend = null;
private bool $isSetUp = false;
private Helper $helper;
@ -52,6 +55,8 @@ class User_Proxy extends Proxy implements IUserBackend, UserInterface, IUserLDAP
private INotificationManager $notificationManager;
private IUserSession $userSession;
private UserPluginManager $userPluginManager;
private LoggerInterface $logger;
private DeletedUsersIndex $deletedUsersIndex;
public function __construct(
Helper $helper,
@ -60,7 +65,9 @@ class User_Proxy extends Proxy implements IUserBackend, UserInterface, IUserLDAP
IConfig $ocConfig,
INotificationManager $notificationManager,
IUserSession $userSession,
UserPluginManager $userPluginManager
UserPluginManager $userPluginManager,
LoggerInterface $logger,
DeletedUsersIndex $deletedUsersIndex,
) {
parent::__construct($ldap, $accessFactory);
$this->helper = $helper;
@ -68,6 +75,8 @@ class User_Proxy extends Proxy implements IUserBackend, UserInterface, IUserLDAP
$this->notificationManager = $notificationManager;
$this->userSession = $userSession;
$this->userPluginManager = $userPluginManager;
$this->logger = $logger;
$this->deletedUsersIndex = $deletedUsersIndex;
}
protected function setup(): void {
@ -77,8 +86,15 @@ class User_Proxy extends Proxy implements IUserBackend, UserInterface, IUserLDAP
$serverConfigPrefixes = $this->helper->getServerConfigurationPrefixes(true);
foreach ($serverConfigPrefixes as $configPrefix) {
$this->backends[$configPrefix] =
new User_LDAP($this->getAccess($configPrefix), $this->ocConfig, $this->notificationManager, $this->userSession, $this->userPluginManager);
$this->backends[$configPrefix] = new User_LDAP(
$this->getAccess($configPrefix),
$this->ocConfig,
$this->notificationManager,
$this->userSession,
$this->userPluginManager,
$this->logger,
$this->deletedUsersIndex,
);
if (is_null($this->refBackend)) {
$this->refBackend = &$this->backends[$configPrefix];
@ -438,4 +454,23 @@ class User_Proxy extends Proxy implements IUserBackend, UserInterface, IUserLDAP
public function createUser($username, $password) {
return $this->handleRequest($username, 'createUser', [$username, $password]);
}
public function isUserEnabled(string $uid, callable $queryDatabaseValue): bool {
return $this->handleRequest($uid, 'isUserEnabled', [$uid, $queryDatabaseValue]);
}
public function setUserEnabled(string $uid, bool $enabled, callable $queryDatabaseValue, callable $setDatabaseValue): bool {
return $this->handleRequest($uid, 'setUserEnabled', [$uid, $enabled, $queryDatabaseValue, $setDatabaseValue]);
}
public function getDisabledUserList(int $offset = 0, ?int $limit = null): array {
return array_map(
fn (OfflineUser $user) => $user->getOCName(),
array_slice(
$this->deletedUsersIndex->getUsers(),
$offset,
$limit
)
);
}
}

@ -1,6 +1,6 @@
<?php
style('user_ldap', 'vendor/ui-multiselect/jquery.multiselect');
style('user_ldap', 'vendor/ui-multiselect/jquery.multiselect');
script('user_ldap', [
'vendor/ui-multiselect/src/jquery.multiselect',
@ -69,7 +69,7 @@ style('user_ldap', 'settings');
if (!function_exists('ldap_connect')) {
print_unescaped('<p class="ldapwarning">'.$l->t('<b>Warning:</b> The PHP LDAP module is not installed, the backend will not work. Please ask your system administrator to install it.').'</p>');
}
?>
?>
<?php require_once __DIR__ . '/part.wizard-server.php'; ?>
<?php require_once __DIR__ . '/part.wizard-userfilter.php'; ?>
<?php require_once __DIR__ . '/part.wizard-loginfilter.php'; ?>
@ -91,20 +91,21 @@ style('user_ldap', 'settings');
<p><label for="ldap_user_display_name_2"><?php p($l->t('2nd User Display Name Field'));?></label><input type="text" id="ldap_user_display_name_2" name="ldap_user_display_name_2" data-default="<?php p($_['ldap_user_display_name_2_default']); ?>" aria-describedby="ldap_user_display_name_2_instructions" title="<?php p($l->t('Optional. An LDAP attribute to be added to the display name in brackets. Results in e.g. »John Doe (john.doe@example.org)«.'));?>" /><p class="hidden-visually" id="ldap_user_display_name_2_instructions"><?php p($l->t('Optional. An LDAP attribute to be added to the display name in brackets. Results in e.g. »John Doe (john.doe@example.org)«.'));?></p></p>
<p><label for="ldap_base_users"><?php p($l->t('Base User Tree'));?></label><textarea id="ldap_base_users" name="ldap_base_users" placeholder="<?php p($l->t('One User Base DN per line'));?>" data-default="<?php p($_['ldap_base_users_default']); ?>" aria-describedby="ldap_base_users_instructions" title="<?php p($l->t('Base User Tree'));?>"></textarea><p class="hidden-visually" id="ldap_base_users_instructions"><?php p($l->t('Base User Tree'));?></p></p>
<p><label for="ldap_attributes_for_user_search"><?php p($l->t('User Search Attributes'));?></label><textarea id="ldap_attributes_for_user_search" name="ldap_attributes_for_user_search" placeholder="<?php p($l->t('Optional; one attribute per line'));?>" data-default="<?php p($_['ldap_attributes_for_user_search_default']); ?>" aria-describedby="ldap_attributes_for_user_search_instructions" title="<?php p($l->t('User Search Attributes'));?>"></textarea><p class="hidden-visually" id="ldap_attributes_for_user_search_instructions"><?php p($l->t('User Search Attributes'));?></p></p>
<p><label for="ldap_mark_remnants_as_disabled"><?php p($l->t('Disable users missing from LDAP'));?></label><input type="checkbox" id="ldap_mark_remnants_as_disabled" name="ldap_mark_remnants_as_disabled" value="1" data-default="<?php p($_['ldap_mark_remnants_as_disabled_default']); ?>" aria-describedby="ldap_mark_remnants_as_disabled_instructions" title="<?php p($l->t('When switched on, users imported from LDAP which are then missing will be disabled'));?>" /><p class="hidden-visually" id="ldap_mark_remnants_as_disabled_instructions"><?php p($l->t('When switched on, users imported from LDAP which are then missing will be disabled'));?></p></p>
<p><label for="ldap_group_display_name"><?php p($l->t('Group Display Name Field'));?></label><input type="text" id="ldap_group_display_name" name="ldap_group_display_name" data-default="<?php p($_['ldap_group_display_name_default']); ?>" aria-describedby="ldap_group_display_name_instructions" title="<?php p($l->t('The LDAP attribute to use to generate the groups\'s display name.'));?>" /><p class="hidden-visually" id="ldap_group_display_name_instructions"><?php p($l->t('The LDAP attribute to use to generate the groups\'s display name.'));?></p></p>
<p><label for="ldap_base_groups"><?php p($l->t('Base Group Tree'));?></label><textarea id="ldap_base_groups" name="ldap_base_groups" placeholder="<?php p($l->t('One Group Base DN per line'));?>" data-default="<?php p($_['ldap_base_groups_default']); ?>" aria-describedby="ldap_base_groups_instructions" title="<?php p($l->t('Base Group Tree'));?>"></textarea><p class="hidden-visually" id="ldap_base_groups_instructions"><?php p($l->t('Base Group Tree'));?></p></p>
<p><label for="ldap_attributes_for_group_search"><?php p($l->t('Group Search Attributes'));?></label><textarea id="ldap_attributes_for_group_search" name="ldap_attributes_for_group_search" placeholder="<?php p($l->t('Optional; one attribute per line'));?>" data-default="<?php p($_['ldap_attributes_for_group_search_default']); ?>" aria-describedby="ldap_attributes_for_group_search_instructions" title="<?php p($l->t('Group Search Attributes'));?>"></textarea><p class="hidden-visually" id="ldap_attributes_for_group_search_instructions"><?php p($l->t('Group Search Attributes'));?></p></p>
<p><label for="ldap_group_member_assoc_attribute"><?php p($l->t('Group-Member association'));?></label><select id="ldap_group_member_assoc_attribute" name="ldap_group_member_assoc_attribute" data-default="<?php p($_['ldap_group_member_assoc_attribute_default']); ?>" ><option value="uniqueMember"<?php if (isset($_['ldap_group_member_assoc_attribute']) && ($_['ldap_group_member_assoc_attribute'] === 'uniqueMember')) {
p(' selected');
} ?>>uniqueMember</option><option value="memberUid"<?php if (isset($_['ldap_group_member_assoc_attribute']) && ($_['ldap_group_member_assoc_attribute'] === 'memberUid')) {
p(' selected');
} ?>>memberUid</option><option value="member"<?php if (isset($_['ldap_group_member_assoc_attribute']) && ($_['ldap_group_member_assoc_attribute'] === 'member')) {
p(' selected');
} ?>>member (AD)</option><option value="gidNumber"<?php if (isset($_['ldap_group_member_assoc_attribute']) && ($_['ldap_group_member_assoc_attribute'] === 'gidNumber')) {
p(' selected');
} ?>>gidNumber</option><option value="zimbraMailForwardingAddress"<?php if (isset($_['ldap_group_member_assoc_attribute']) && ($_['ldap_group_member_assoc_attribute'] === 'zimbraMailForwardingAddress')) {
p(' selected');
} ?>>zimbraMailForwardingAddress</option></select></p>
p(' selected');
} ?>>uniqueMember</option><option value="memberUid"<?php if (isset($_['ldap_group_member_assoc_attribute']) && ($_['ldap_group_member_assoc_attribute'] === 'memberUid')) {
p(' selected');
} ?>>memberUid</option><option value="member"<?php if (isset($_['ldap_group_member_assoc_attribute']) && ($_['ldap_group_member_assoc_attribute'] === 'member')) {
p(' selected');
} ?>>member (AD)</option><option value="gidNumber"<?php if (isset($_['ldap_group_member_assoc_attribute']) && ($_['ldap_group_member_assoc_attribute'] === 'gidNumber')) {
p(' selected');
} ?>>gidNumber</option><option value="zimbraMailForwardingAddress"<?php if (isset($_['ldap_group_member_assoc_attribute']) && ($_['ldap_group_member_assoc_attribute'] === 'zimbraMailForwardingAddress')) {
p(' selected');
} ?>>zimbraMailForwardingAddress</option></select></p>
<p><label for="ldap_dynamic_group_member_url"><?php p($l->t('Dynamic Group Member URL'));?></label><input type="text" id="ldap_dynamic_group_member_url" name="ldap_dynamic_group_member_url" aria-describedby="ldap_dynamic_group_member_url_instructions" title="<?php p($l->t('The LDAP attribute that on group objects contains an LDAP search URL that determines what objects belong to the group. (An empty setting disables dynamic group membership functionality.)'));?>" data-default="<?php p($_['ldap_dynamic_group_member_url_default']); ?>" /><p class="hidden-visually" id="ldap_dynamic_group_member_url_instructions"><?php p($l->t('The LDAP attribute that on group objects contains an LDAP search URL that determines what objects belong to the group. (An empty setting disables dynamic group membership functionality.)'));?></p></p>
<p><label for="ldap_nested_groups"><?php p($l->t('Nested Groups'));?></label><input type="checkbox" id="ldap_nested_groups" name="ldap_nested_groups" value="1" data-default="<?php p($_['ldap_nested_groups_default']); ?>" aria-describedby="ldap_nested_groups_instructions" title="<?php p($l->t('When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)'));?>" /><p class="hidden-visually" id="ldap_nested_groups_instructions"><?php p($l->t('When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)'));?></p></p>
<p><label for="ldap_paging_size"><?php p($l->t('Paging chunksize'));?></label><input type="number" id="ldap_paging_size" name="ldap_paging_size" aria-describedby="ldap_paging_size_instructions" title="<?php p($l->t('Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)'));?>" data-default="<?php p($_['ldap_paging_size_default']); ?>" /><p class="hidden-visually" id="ldap_paging_size_instructions"><?php p($l->t('Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)'));?></p></p>

@ -28,8 +28,10 @@ use OCA\User_LDAP\GroupPluginManager;
use OCA\User_LDAP\Mapping\GroupMapping;
use OCA\User_LDAP\Mapping\UserMapping;
use OCA\User_LDAP\Tests\Integration\AbstractIntegrationTest;
use OCA\User_LDAP\User\DeletedUsersIndex;
use OCA\User_LDAP\User_LDAP;
use OCA\User_LDAP\UserPluginManager;
use Psr\Log\LoggerInterface;
require_once __DIR__ . '/../Bootstrap.php';
@ -51,7 +53,7 @@ class IntegrationTestAttributeDetection extends AbstractIntegrationTest {
$groupMapper->clear();
$this->access->setGroupMapper($groupMapper);
$userBackend = new User_LDAP($this->access, \OC::$server->getConfig(), \OC::$server->getNotificationManager(), \OC::$server->getUserSession(), \OC::$server->query(UserPluginManager::class));
$userBackend = new User_LDAP($this->access, \OC::$server->getConfig(), \OC::$server->getNotificationManager(), \OC::$server->getUserSession(), \OC::$server->get(UserPluginManager::class), \OC::$server->get(LoggerInterface::class), \OC::$server->get(DeletedUsersIndex::class));
$userManager = \OC::$server->getUserManager();
$userManager->clearBackends();
$userManager->registerBackend($userBackend);

@ -26,8 +26,10 @@ namespace OCA\User_LDAP\Tests\Integration\Lib;
use OCA\User_LDAP\Mapping\UserMapping;
use OCA\User_LDAP\Tests\Integration\AbstractIntegrationTest;
use OCA\User_LDAP\User\DeletedUsersIndex;
use OCA\User_LDAP\User_LDAP;
use OCA\User_LDAP\UserPluginManager;
use Psr\Log\LoggerInterface;
require_once __DIR__ . '/../Bootstrap.php';
@ -49,7 +51,7 @@ class IntegrationTestFetchUsersByLoginName extends AbstractIntegrationTest {
$this->mapping = new UserMapping(\OC::$server->getDatabaseConnection());
$this->mapping->clear();
$this->access->setUserMapper($this->mapping);
$this->backend = new User_LDAP($this->access, \OC::$server->getConfig(), \OC::$server->getNotificationManager(), \OC::$server->getUserSession(), \OC::$server->query(UserPluginManager::class));
$this->backend = new User_LDAP($this->access, \OC::$server->getConfig(), \OC::$server->getNotificationManager(), \OC::$server->getUserSession(), \OC::$server->get(UserPluginManager::class), \OC::$server->get(LoggerInterface::class), \OC::$server->get(DeletedUsersIndex::class));
}
/**

@ -27,8 +27,10 @@ namespace OCA\User_LDAP\Tests\Integration\Lib;
use OCA\User_LDAP\Mapping\UserMapping;
use OCA\User_LDAP\Tests\Integration\AbstractIntegrationTest;
use OCA\User_LDAP\User\DeletedUsersIndex;
use OCA\User_LDAP\User_LDAP;
use OCA\User_LDAP\UserPluginManager;
use Psr\Log\LoggerInterface;
require_once __DIR__ . '/../Bootstrap.php';
@ -50,7 +52,7 @@ class IntegrationTestPaging extends AbstractIntegrationTest {
require(__DIR__ . '/../setup-scripts/createExplicitUsers.php');
parent::init();
$this->backend = new User_LDAP($this->access, \OC::$server->getConfig(), \OC::$server->getNotificationManager(), \OC::$server->getUserSession(), \OC::$server->query(UserPluginManager::class));
$this->backend = new User_LDAP($this->access, \OC::$server->getConfig(), \OC::$server->getNotificationManager(), \OC::$server->getUserSession(), \OC::$server->get(UserPluginManager::class), \OC::$server->get(LoggerInterface::class), \OC::$server->get(DeletedUsersIndex::class));
}
public function initConnection() {

@ -30,6 +30,7 @@ namespace OCA\User_LDAP\Tests\Integration\Lib\User;
use OCA\User_LDAP\FilesystemHelper;
use OCA\User_LDAP\Mapping\UserMapping;
use OCA\User_LDAP\Tests\Integration\AbstractIntegrationTest;
use OCA\User_LDAP\User\DeletedUsersIndex;
use OCA\User_LDAP\User\Manager;
use OCA\User_LDAP\User\User;
use OCA\User_LDAP\User_LDAP;
@ -53,7 +54,7 @@ class IntegrationTestUserAvatar extends AbstractIntegrationTest {
$this->mapping = new UserMapping(\OC::$server->getDatabaseConnection());
$this->mapping->clear();
$this->access->setUserMapper($this->mapping);
$userBackend = new User_LDAP($this->access, \OC::$server->getConfig(), \OC::$server->getNotificationManager(), \OC::$server->getUserSession(), \OC::$server->query(UserPluginManager::class));
$userBackend = new User_LDAP($this->access, \OC::$server->getConfig(), \OC::$server->getNotificationManager(), \OC::$server->getUserSession(), \OC::$server->get(UserPluginManager::class), \OC::$server->get(LoggerInterface::class), \OC::$server->get(DeletedUsersIndex::class));
\OC_User::useBackend($userBackend);
}

@ -26,8 +26,10 @@ namespace OCA\User_LDAP\Tests\Integration\Lib\User;
use OCA\User_LDAP\Jobs\CleanUp;
use OCA\User_LDAP\Mapping\UserMapping;
use OCA\User_LDAP\Tests\Integration\AbstractIntegrationTest;
use OCA\User_LDAP\User\DeletedUsersIndex;
use OCA\User_LDAP\User_LDAP;
use OCA\User_LDAP\UserPluginManager;
use Psr\Log\LoggerInterface;
require_once __DIR__ . '/../../Bootstrap.php';
@ -46,7 +48,7 @@ class IntegrationTestUserCleanUp extends AbstractIntegrationTest {
$this->mapping->clear();
$this->access->setUserMapper($this->mapping);
$userBackend = new User_LDAP($this->access, \OC::$server->getConfig(), \OC::$server->getNotificationManager(), \OC::$server->getUserSession(), \OC::$server->query(UserPluginManager::class));
$userBackend = new User_LDAP($this->access, \OC::$server->getConfig(), \OC::$server->getNotificationManager(), \OC::$server->getUserSession(), \OC::$server->get(UserPluginManager::class), \OC::$server->get(LoggerInterface::class), \OC::$server->get(DeletedUsersIndex::class));
\OC_User::useBackend($userBackend);
}

@ -26,8 +26,10 @@ namespace OCA\User_LDAP\Tests\Integration\Lib\User;
use OCA\User_LDAP\Mapping\UserMapping;
use OCA\User_LDAP\Tests\Integration\AbstractIntegrationTest;
use OCA\User_LDAP\User\DeletedUsersIndex;
use OCA\User_LDAP\User_LDAP;
use OCA\User_LDAP\UserPluginManager;
use Psr\Log\LoggerInterface;
require_once __DIR__ . '/../../Bootstrap.php';
@ -45,7 +47,7 @@ class IntegrationTestUserDisplayName extends AbstractIntegrationTest {
$this->mapping = new UserMapping(\OC::$server->getDatabaseConnection());
$this->mapping->clear();
$this->access->setUserMapper($this->mapping);
$userBackend = new User_LDAP($this->access, \OC::$server->getConfig(), \OC::$server->getNotificationManager(), \OC::$server->getUserSession(), \OC::$server->query(UserPluginManager::class));
$userBackend = new User_LDAP($this->access, \OC::$server->getConfig(), \OC::$server->getNotificationManager(), \OC::$server->getUserSession(), \OC::$server->get(UserPluginManager::class), \OC::$server->get(LoggerInterface::class), \OC::$server->get(DeletedUsersIndex::class));
\OC_User::useBackend($userBackend);
}

@ -37,6 +37,7 @@ use OCA\User_LDAP\Access;
use OCA\User_LDAP\Connection;
use OCA\User_LDAP\Mapping\AbstractMapping;
use OCA\User_LDAP\Mapping\UserMapping;
use OCA\User_LDAP\User\DeletedUsersIndex;
use OCA\User_LDAP\User\Manager;
use OCA\User_LDAP\User\OfflineUser;
use OCA\User_LDAP\User\User;
@ -48,6 +49,8 @@ use OCP\IConfig;
use OCP\IUser;
use OCP\Notification\IManager as INotificationManager;
use Test\TestCase;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
/**
* Class Test_User_Ldap_Direct
@ -59,22 +62,26 @@ use Test\TestCase;
class User_LDAPTest extends TestCase {
/** @var User_LDAP */
protected $backend;
/** @var Access|\PHPUnit\Framework\MockObject\MockObject */
/** @var Access|MockObject */
protected $access;
/** @var OfflineUser|\PHPUnit\Framework\MockObject\MockObject */
/** @var OfflineUser|MockObject */
protected $offlineUser;
/** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */
/** @var IConfig|MockObject */
protected $config;
/** @var INotificationManager|\PHPUnit\Framework\MockObject\MockObject */
/** @var INotificationManager|MockObject */
protected $notificationManager;
/** @var Session|\PHPUnit\Framework\MockObject\MockObject */
/** @var Session|MockObject */
protected $session;
/** @var UserPluginManager|\PHPUnit\Framework\MockObject\MockObject */
/** @var UserPluginManager|MockObject */
protected $pluginManager;
/** @var Connection|\PHPUnit\Framework\MockObject\MockObject */
/** @var Connection|MockObject */
protected $connection;
/** @var Manager|\PHPUnit\Framework\MockObject\MockObject */
/** @var Manager|MockObject */
protected $userManager;
/** @var LoggerInterface|MockObject */
protected $logger;
/** @var DeletedUsersIndex|MockObject */
protected $deletedUsersIndex;
protected function setUp(): void {
parent::setUp();
@ -95,12 +102,18 @@ class User_LDAPTest extends TestCase {
$this->session = $this->createMock(Session::class);
$this->pluginManager = $this->createMock(UserPluginManager::class);
$this->logger = $this->createMock(LoggerInterface::class);
$this->deletedUsersIndex = $this->createMock(DeletedUsersIndex::class);
$this->backend = new User_LDAP(
$this->access,
$this->config,
$this->notificationManager,
$this->session,
$this->pluginManager
$this->pluginManager,
$this->logger,
$this->deletedUsersIndex,
);
}
@ -109,21 +122,21 @@ class User_LDAPTest extends TestCase {
->method('username2dn')
->willReturnCallback(function ($uid) {
switch ($uid) {
case 'gunslinger':
return 'dnOfRoland,dc=test';
break;
case 'formerUser':
return 'dnOfFormerUser,dc=test';
break;
case 'newyorker':
return 'dnOfNewYorker,dc=test';
break;
case 'ladyofshadows':
return 'dnOfLadyOfShadows,dc=test';
break;
default:
return false;
}
case 'gunslinger':
return 'dnOfRoland,dc=test';
break;
case 'formerUser':
return 'dnOfFormerUser,dc=test';
break;
case 'newyorker':
return 'dnOfNewYorker,dc=test';
break;
case 'ladyofshadows':
return 'dnOfLadyOfShadows,dc=test';
break;
default:
return false;
}
});
$this->access->method('fetchUsersByLoginName')
@ -199,7 +212,7 @@ class User_LDAPTest extends TestCase {
->method('get')
->willReturn($user);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
\OC_User::useBackend($backend);
@ -209,7 +222,7 @@ class User_LDAPTest extends TestCase {
public function testCheckPasswordWrongPassword() {
$this->prepareAccessForCheckPassword();
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
\OC_User::useBackend($backend);
$result = $backend->checkPassword('roland', 'wrong');
@ -218,7 +231,7 @@ class User_LDAPTest extends TestCase {
public function testCheckPasswordWrongUser() {
$this->prepareAccessForCheckPassword();
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
\OC_User::useBackend($backend);
$result = $backend->checkPassword('mallory', 'evil');
@ -233,7 +246,7 @@ class User_LDAPTest extends TestCase {
->method('get')
->willReturn(null);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
\OC_User::useBackend($backend);
$result = $backend->checkPassword('roland', 'dt19');
@ -251,7 +264,7 @@ class User_LDAPTest extends TestCase {
->method('get')
->willReturn($user);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
\OC_User::useBackend($backend);
$user = \OC::$server->getUserManager()->checkPassword('roland', 'dt19');
@ -264,7 +277,7 @@ class User_LDAPTest extends TestCase {
public function testCheckPasswordPublicAPIWrongPassword() {
$this->prepareAccessForCheckPassword();
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
\OC_User::useBackend($backend);
$user = \OC::$server->getUserManager()->checkPassword('roland', 'wrong');
@ -277,7 +290,7 @@ class User_LDAPTest extends TestCase {
public function testCheckPasswordPublicAPIWrongUser() {
$this->prepareAccessForCheckPassword();
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
\OC_User::useBackend($backend);
$user = \OC::$server->getUserManager()->checkPassword('mallory', 'evil');
@ -289,7 +302,7 @@ class User_LDAPTest extends TestCase {
}
public function testDeleteUserCancel() {
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
$result = $backend->deleteUser('notme');
$this->assertFalse($result);
}
@ -309,10 +322,10 @@ class User_LDAPTest extends TestCase {
->method('getConnectionResource')
->willReturn('this is an ldap link');
$this->config->expects($this->any())
->method('getUserValue')
->with($uid, 'user_ldap', 'isDeleted')
->willReturn('1');
$this->deletedUsersIndex->expects($this->once())
->method('isUserMarked')
->with($uid)
->willReturn(true);
$offlineUser = $this->createMock(OfflineUser::class);
$offlineUser->expects($this->once())
@ -322,7 +335,7 @@ class User_LDAPTest extends TestCase {
->method('get')
->willReturn($offlineUser);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
$result = $backend->deleteUser($uid);
$this->assertTrue($result);
@ -339,10 +352,10 @@ class User_LDAPTest extends TestCase {
->with('uid')
->willReturn(true);
$this->config->expects($this->once())
->method('getUserValue')
->with('uid', 'user_ldap', 'isDeleted', 0)
->willReturn(1);
$this->deletedUsersIndex->expects($this->once())
->method('isUserMarked')
->with('uid')
->willReturn(true);
$mapper = $this->createMock(UserMapping::class);
$mapper->expects($this->once())
@ -388,7 +401,7 @@ class User_LDAPTest extends TestCase {
} else {
$result = [];
foreach ($users as $user) {
if (stripos($user, $search) !== false) {
if (stripos($user, $search) !== false) {
$result[] = $user;
}
}
@ -411,7 +424,7 @@ class User_LDAPTest extends TestCase {
public function testGetUsersNoParam() {
$this->prepareAccessForGetUsers();
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
$result = $backend->getUsers();
$this->assertEquals(3, count($result));
@ -419,7 +432,7 @@ class User_LDAPTest extends TestCase {
public function testGetUsersLimitOffset() {
$this->prepareAccessForGetUsers();
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
$result = $backend->getUsers('', 1, 2);
$this->assertEquals(1, count($result));
@ -427,7 +440,7 @@ class User_LDAPTest extends TestCase {
public function testGetUsersLimitOffset2() {
$this->prepareAccessForGetUsers();
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
$result = $backend->getUsers('', 2, 1);
$this->assertEquals(2, count($result));
@ -435,7 +448,7 @@ class User_LDAPTest extends TestCase {
public function testGetUsersSearchWithResult() {
$this->prepareAccessForGetUsers();
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
$result = $backend->getUsers('yo');
$this->assertEquals(2, count($result));
@ -443,7 +456,7 @@ class User_LDAPTest extends TestCase {
public function testGetUsersSearchEmptyResult() {
$this->prepareAccessForGetUsers();
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
$result = $backend->getUsers('nix');
$this->assertEquals(0, count($result));
@ -459,7 +472,7 @@ class User_LDAPTest extends TestCase {
public function testGetUsersViaAPINoParam() {
$this->prepareAccessForGetUsers();
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
\OC_User::useBackend($backend);
$result = $this->getUsers();
@ -468,7 +481,7 @@ class User_LDAPTest extends TestCase {
public function testGetUsersViaAPILimitOffset() {
$this->prepareAccessForGetUsers();
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
\OC_User::useBackend($backend);
$result = $this->getUsers('', 1, 2);
@ -477,7 +490,7 @@ class User_LDAPTest extends TestCase {
public function testGetUsersViaAPILimitOffset2() {
$this->prepareAccessForGetUsers();
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
\OC_User::useBackend($backend);
$result = $this->getUsers('', 2, 1);
@ -486,7 +499,7 @@ class User_LDAPTest extends TestCase {
public function testGetUsersViaAPISearchWithResult() {
$this->prepareAccessForGetUsers();
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
\OC_User::useBackend($backend);
$result = $this->getUsers('yo');
@ -495,7 +508,7 @@ class User_LDAPTest extends TestCase {
public function testGetUsersViaAPISearchEmptyResult() {
$this->prepareAccessForGetUsers();
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
\OC_User::useBackend($backend);
$result = $this->getUsers('nix');
@ -503,7 +516,7 @@ class User_LDAPTest extends TestCase {
}
public function testUserExists() {
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
$this->prepareMockForUserExists();
$user = $this->createMock(User::class);
@ -522,7 +535,7 @@ class User_LDAPTest extends TestCase {
}
public function testUserExistsForDeleted() {
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
$this->prepareMockForUserExists();
$mapper = $this->createMock(UserMapping::class);
@ -546,7 +559,7 @@ class User_LDAPTest extends TestCase {
}
public function testUserExistsForNeverExisting() {
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
$this->prepareMockForUserExists();
$this->access->expects($this->any())
@ -565,7 +578,7 @@ class User_LDAPTest extends TestCase {
}
public function testUserExistsPublicAPI() {
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
$this->prepareMockForUserExists();
\OC_User::useBackend($backend);
@ -595,7 +608,7 @@ class User_LDAPTest extends TestCase {
}
public function testDeleteUserExisting() {
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
//we do not support deleting existing users at all
$result = $backend->deleteUser('gunslinger');
@ -603,7 +616,7 @@ class User_LDAPTest extends TestCase {
}
public function testGetHomeAbsolutePath() {
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
$this->prepareMockForUserExists();
$this->connection->expects($this->any())
@ -652,7 +665,7 @@ class User_LDAPTest extends TestCase {
}
public function testGetHomeRelative() {
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
$this->prepareMockForUserExists();
$dataDir = \OC::$server->getConfig()->getSystemValue(
@ -706,7 +719,7 @@ class User_LDAPTest extends TestCase {
public function testGetHomeNoPath() {
$this->expectException(\Exception::class);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
$this->prepareMockForUserExists();
$this->connection->expects($this->any())
@ -754,7 +767,7 @@ class User_LDAPTest extends TestCase {
public function testGetHomeDeletedUser() {
$uid = 'newyorker';
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
$this->prepareMockForUserExists();
$this->connection->expects($this->any())
@ -810,7 +823,7 @@ class User_LDAPTest extends TestCase {
});
/** @noinspection PhpUnhandledExceptionInspection */
$this->assertEquals($this->backend->getHome('uid'),'result');
$this->assertEquals($this->backend->getHome('uid'), 'result');
}
private function prepareAccessForGetDisplayName() {
@ -829,16 +842,16 @@ class User_LDAPTest extends TestCase {
->method('readAttribute')
->willReturnCallback(function ($dn, $attr) {
switch ($dn) {
case 'dnOfRoland,dc=test':
if ($attr === 'displayname') {
return ['Roland Deschain'];
}
return [];
break;
default:
return false;
}
case 'dnOfRoland,dc=test':
if ($attr === 'displayname') {
return ['Roland Deschain'];
}
return [];
break;
default:
return false;
}
});
$this->access->method('fetchUsersByLoginName')
->willReturn([]);
@ -846,7 +859,7 @@ class User_LDAPTest extends TestCase {
public function testGetDisplayName() {
$this->prepareAccessForGetDisplayName();
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
$this->prepareMockForUserExists();
$this->connection->expects($this->any())
@ -927,7 +940,7 @@ class User_LDAPTest extends TestCase {
}
});
$this->prepareAccessForGetDisplayName();
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
$this->prepareMockForUserExists();
$this->connection->expects($this->any())
@ -998,7 +1011,7 @@ class User_LDAPTest extends TestCase {
->with('uid')
->willReturn('result');
$this->assertEquals($this->backend->getDisplayName('uid'),'result');
$this->assertEquals($this->backend->getDisplayName('uid'), 'result');
}
//no test for getDisplayNames, because it just invokes getUsers and
@ -1009,7 +1022,7 @@ class User_LDAPTest extends TestCase {
->method('countUsers')
->willReturn(5);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
$result = $backend->countUsers();
$this->assertEquals(5, $result);
@ -1020,7 +1033,7 @@ class User_LDAPTest extends TestCase {
->method('countUsers')
->willReturn(false);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
$result = $backend->countUsers();
$this->assertFalse($result);
@ -1035,7 +1048,7 @@ class User_LDAPTest extends TestCase {
->method('countUsers')
->willReturn(42);
$this->assertEquals($this->backend->countUsers(),42);
$this->assertEquals($this->backend->countUsers(), 42);
}
public function testLoginName2UserNameSuccess() {
@ -1064,7 +1077,7 @@ class User_LDAPTest extends TestCase {
->method('writeToCache')
->with($this->equalTo('loginName2UserName-'.$loginName), $this->equalTo($username));
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
$user = $this->createMock(User::class);
$user->expects($this->any())
->method('getUsername')
@ -1109,7 +1122,7 @@ class User_LDAPTest extends TestCase {
->method('getAttributes')
->willReturn(['dn', 'uid', 'mail', 'displayname']);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
$name = $backend->loginName2UserName($loginName);
$this->assertSame(false, $name);
@ -1146,7 +1159,7 @@ class User_LDAPTest extends TestCase {
->method('getAttributes')
->willReturn(['dn', 'uid', 'mail', 'displayname']);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
$name = $backend->loginName2UserName($loginName);
$this->assertSame(false, $name);
@ -1223,7 +1236,7 @@ class User_LDAPTest extends TestCase {
$this->userManager->expects($this->atLeastOnce())
->method('get')
->willReturn($this->createMock(User::class));
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
\OC_User::useBackend($backend);
$this->assertTrue(\OC_User::setPassword('roland', 'dt'));
@ -1236,7 +1249,7 @@ class User_LDAPTest extends TestCase {
->method('get')
->willReturn($this->createMock(User::class));
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
$this->userManager->expects($this->any())
->method('get')
->willReturn($this->createMock(User::class));
@ -1252,7 +1265,7 @@ class User_LDAPTest extends TestCase {
->willReturn($this->createMock(User::class));
$this->prepareAccessForSetPassword(false);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager);
$backend = new UserLDAP($this->access, $this->config, $this->notificationManager, $this->session, $this->pluginManager, $this->logger, $this->deletedUsersIndex);
\OC_User::useBackend($backend);
$this->assertFalse(\OC_User::setPassword('roland', 'dt12234$'));
@ -1295,11 +1308,11 @@ class User_LDAPTest extends TestCase {
->willReturn(true);
$this->pluginManager->expects($this->once())
->method('setPassword')
->with('uid','password')
->with('uid', 'password')
->willReturn('result');
/** @noinspection PhpUnhandledExceptionInspection */
$this->assertEquals($this->backend->setPassword('uid', 'password'),'result');
$this->assertEquals($this->backend->setPassword('uid', 'password'), 'result');
}
public function avatarDataProvider() {
@ -1340,7 +1353,7 @@ class User_LDAPTest extends TestCase {
->with('uid')
->willReturn('result');
$this->assertEquals($this->backend->canChangeAvatar('uid'),'result');
$this->assertEquals($this->backend->canChangeAvatar('uid'), 'result');
}
public function testSetDisplayNameWithPlugin() {
@ -1413,7 +1426,7 @@ class User_LDAPTest extends TestCase {
->method('getUserMapper')
->willReturn($this->createMock(UserMapping::class));
$this->assertEquals($this->backend->createUser($uid, $pwd),true);
$this->assertEquals($this->backend->createUser($uid, $pwd), true);
}
public function testCreateUserFailing() {

@ -31,12 +31,14 @@ namespace OCA\User_LDAP\Tests;
use OCA\User_LDAP\AccessFactory;
use OCA\User_LDAP\Helper;
use OCA\User_LDAP\ILDAPWrapper;
use OCA\User_LDAP\User\DeletedUsersIndex;
use OCA\User_LDAP\User_Proxy;
use OCA\User_LDAP\UserPluginManager;
use OCP\IConfig;
use OCP\IUserSession;
use OCP\Notification\IManager as INotificationManager;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Test\TestCase;
class User_ProxyTest extends TestCase {
@ -56,6 +58,10 @@ class User_ProxyTest extends TestCase {
private $proxy;
/** @var UserPluginManager|MockObject */
private $userPluginManager;
/** @var LoggerInterface|MockObject */
protected $logger;
/** @var DeletedUsersIndex|MockObject */
protected $deletedUsersIndex;
protected function setUp(): void {
parent::setUp();
@ -67,6 +73,8 @@ class User_ProxyTest extends TestCase {
$this->notificationManager = $this->createMock(INotificationManager::class);
$this->userSession = $this->createMock(IUserSession::class);
$this->userPluginManager = $this->createMock(UserPluginManager::class);
$this->logger = $this->createMock(LoggerInterface::class);
$this->deletedUsersIndex = $this->createMock(DeletedUsersIndex::class);
$this->proxy = $this->getMockBuilder(User_Proxy::class)
->setConstructorArgs([
$this->helper,
@ -75,7 +83,9 @@ class User_ProxyTest extends TestCase {
$this->config,
$this->notificationManager,
$this->userSession,
$this->userPluginManager
$this->userPluginManager,
$this->logger,
$this->deletedUsersIndex,
])
->setMethods(['handleRequest'])
->getMock();

@ -644,6 +644,7 @@ return array(
'OCP\\User\\Backend\\IGetRealUIDBackend' => $baseDir . '/lib/public/User/Backend/IGetRealUIDBackend.php',
'OCP\\User\\Backend\\IPasswordConfirmationBackend' => $baseDir . '/lib/public/User/Backend/IPasswordConfirmationBackend.php',
'OCP\\User\\Backend\\IProvideAvatarBackend' => $baseDir . '/lib/public/User/Backend/IProvideAvatarBackend.php',
'OCP\\User\\Backend\\IProvideEnabledStateBackend' => $baseDir . '/lib/public/User/Backend/IProvideEnabledStateBackend.php',
'OCP\\User\\Backend\\ISearchKnownUsersBackend' => $baseDir . '/lib/public/User/Backend/ISearchKnownUsersBackend.php',
'OCP\\User\\Backend\\ISetDisplayNameBackend' => $baseDir . '/lib/public/User/Backend/ISetDisplayNameBackend.php',
'OCP\\User\\Backend\\ISetPasswordBackend' => $baseDir . '/lib/public/User/Backend/ISetPasswordBackend.php',

@ -677,6 +677,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\User\\Backend\\IGetRealUIDBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IGetRealUIDBackend.php',
'OCP\\User\\Backend\\IPasswordConfirmationBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IPasswordConfirmationBackend.php',
'OCP\\User\\Backend\\IProvideAvatarBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IProvideAvatarBackend.php',
'OCP\\User\\Backend\\IProvideEnabledStateBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IProvideEnabledStateBackend.php',
'OCP\\User\\Backend\\ISearchKnownUsersBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/ISearchKnownUsersBackend.php',
'OCP\\User\\Backend\\ISetDisplayNameBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/ISetDisplayNameBackend.php',
'OCP\\User\\Backend\\ISetPasswordBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/ISetPasswordBackend.php',

@ -55,6 +55,7 @@ use OCP\User\GetQuotaEvent;
use OCP\User\Backend\ISetDisplayNameBackend;
use OCP\User\Backend\ISetPasswordBackend;
use OCP\User\Backend\IProvideAvatarBackend;
use OCP\User\Backend\IProvideEnabledStateBackend;
use OCP\User\Backend\IGetHomeBackend;
use OCP\UserInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
@ -432,25 +433,46 @@ class User implements IUser {
* @return bool
*/
public function isEnabled() {
if ($this->enabled === null) {
$enabled = $this->config->getUserValue($this->uid, 'core', 'enabled', 'true');
$this->enabled = $enabled === 'true';
$queryDatabaseValue = function (): bool {
if ($this->enabled === null) {
$enabled = $this->config->getUserValue($this->uid, 'core', 'enabled', 'true');
$this->enabled = $enabled === 'true';
}
return $this->enabled;
};
if ($this->backend instanceof IProvideEnabledStateBackend) {
return $this->backend->isUserEnabled($this->uid, $queryDatabaseValue);
} else {
return $queryDatabaseValue();
}
return (bool) $this->enabled;
}
/**
* set the enabled status for the user
*
* @param bool $enabled
* @return void
*/
public function setEnabled(bool $enabled = true) {
$oldStatus = $this->isEnabled();
$this->enabled = $enabled;
if ($oldStatus !== $this->enabled) {
// TODO: First change the value, then trigger the event as done for all other properties.
$this->triggerChange('enabled', $enabled, $oldStatus);
$setDatabaseValue = function (bool $enabled): void {
$this->config->setUserValue($this->uid, 'core', 'enabled', $enabled ? 'true' : 'false');
$this->enabled = $enabled;
};
if ($this->backend instanceof IProvideEnabledStateBackend) {
$queryDatabaseValue = function (): bool {
if ($this->enabled === null) {
$enabled = $this->config->getUserValue($this->uid, 'core', 'enabled', 'true');
$this->enabled = $enabled === 'true';
}
return $this->enabled;
};
$enabled = $this->backend->setUserEnabled($this->uid, $enabled, $queryDatabaseValue, $setDatabaseValue);
if ($oldStatus !== $enabled) {
$this->triggerChange('enabled', $enabled, $oldStatus);
}
} elseif ($oldStatus !== $enabled) {
$setDatabaseValue($enabled);
$this->triggerChange('enabled', $enabled, $oldStatus);
}
}

@ -0,0 +1,56 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2022 Côme Chilliet <come.chilliet@nextcloud.com>
*
* @author Côme Chilliet <come.chilliet@nextcloud.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCP\User\Backend;
/**
* @since 28.0.0
*/
interface IProvideEnabledStateBackend {
/**
* @since 28.0.0
*
* @param callable():bool $queryDatabaseValue A callable to query the enabled state from database
*/
public function isUserEnabled(string $uid, callable $queryDatabaseValue): bool;
/**
* @since 28.0.0
*
* @param callable():bool $queryDatabaseValue A callable to query the enabled state from database
* @param callable(bool):void $setDatabaseValue A callable to set the enabled state in the database.
*/
public function setUserEnabled(string $uid, bool $enabled, callable $queryDatabaseValue, callable $setDatabaseValue): bool;
/**
* Get the list of disabled users, to merge with the ones disabled in database
*
* @since 28.0.0
*
* @return string[]
*/
public function getDisabledUserList(int $offset = 0, ?int $limit = null): array;
}