diff --git a/apps/user_ldap/lib/Command/TestUserSettings.php b/apps/user_ldap/lib/Command/TestUserSettings.php index 2cd059455ca2b..3252b57c32059 100644 --- a/apps/user_ldap/lib/Command/TestUserSettings.php +++ b/apps/user_ldap/lib/Command/TestUserSettings.php @@ -111,6 +111,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int 'ldapExpertUUIDUserAttr', 'ldapQuotaAttribute', 'ldapEmailAttribute', + 'ldapUserActiveState', 'ldapUserDisplayName', 'ldapUserDisplayName2', 'ldapExtStorageHomeAttribute', diff --git a/apps/user_ldap/lib/Configuration.php b/apps/user_ldap/lib/Configuration.php index b2e22f1b007ca..04745b6f46e92 100644 --- a/apps/user_ldap/lib/Configuration.php +++ b/apps/user_ldap/lib/Configuration.php @@ -27,6 +27,7 @@ * @property string $ldapTLS * @property string $turnOffCertCheck * @property string $ldapIgnoreNamingRules + * @property string $ldapUserActiveState * @property string $ldapUserDisplayName * @property string $ldapUserDisplayName2 * @property string $ldapUserAvatarRule @@ -121,6 +122,7 @@ class Configuration { 'ldapTLS' => null, 'turnOffCertCheck' => null, 'ldapIgnoreNamingRules' => null, + 'ldapUserActiveState' => null, 'ldapUserDisplayName' => null, 'ldapUserDisplayName2' => null, 'ldapUserAvatarRule' => null, @@ -503,6 +505,7 @@ public function getDefaults(): array { 'ldap_base_users' => '', 'ldap_base_groups' => '', 'ldap_userlist_filter' => '', + 'ldap_user_active_state' => '', 'ldap_user_filter_mode' => 0, 'ldap_userfilter_objectclass' => '', 'ldap_userfilter_groups' => '', @@ -586,6 +589,7 @@ public function getConfigTranslationArray(): array { 'ldap_userfilter_objectclass' => 'ldapUserFilterObjectclass', 'ldap_userfilter_groups' => 'ldapUserFilterGroups', 'ldap_userlist_filter' => 'ldapUserFilter', + 'ldap_user_active_state' => 'ldapUserActiveState', 'ldap_user_filter_mode' => 'ldapUserFilterMode', 'ldap_user_avatar_rule' => 'ldapUserAvatarRule', 'ldap_login_filter' => 'ldapLoginFilter', diff --git a/apps/user_ldap/lib/Connection.php b/apps/user_ldap/lib/Connection.php index ea4d766fe0e84..28973e27f5233 100644 --- a/apps/user_ldap/lib/Connection.php +++ b/apps/user_ldap/lib/Connection.php @@ -35,6 +35,7 @@ * @property string $ldapTLS * @property string $turnOffCertCheck * @property string $ldapIgnoreNamingRules + * @property string $ldapUserActiveState * @property string $ldapUserDisplayName * @property string $ldapUserDisplayName2 * @property string $ldapUserAvatarRule diff --git a/apps/user_ldap/lib/Controller/ConfigAPIController.php b/apps/user_ldap/lib/Controller/ConfigAPIController.php index 56dde01b3c71d..a2005a32748d5 100644 --- a/apps/user_ldap/lib/Controller/ConfigAPIController.php +++ b/apps/user_ldap/lib/Controller/ConfigAPIController.php @@ -156,6 +156,7 @@ public function modify($configID, $configData) { * 1 * 0 * + * active * displayname * uid * inetOrgPerson diff --git a/apps/user_ldap/lib/User/Manager.php b/apps/user_ldap/lib/User/Manager.php index c6892312b0ae7..00efcb94f21cd 100644 --- a/apps/user_ldap/lib/User/Manager.php +++ b/apps/user_ldap/lib/User/Manager.php @@ -117,6 +117,7 @@ public function getAttributes($minimal = false) { $this->access->getConnection()->ldapExpertUsernameAttr, $this->access->getConnection()->ldapQuotaAttribute, $this->access->getConnection()->ldapEmailAttribute, + $this->access->getConnection()->ldapUserActiveState, $this->access->getConnection()->ldapUserDisplayName, $this->access->getConnection()->ldapUserDisplayName2, $this->access->getConnection()->ldapExtStorageHomeAttribute, diff --git a/apps/user_ldap/lib/User/User.php b/apps/user_ldap/lib/User/User.php index c1f21a0eb13de..692f1f820ae5f 100644 --- a/apps/user_ldap/lib/User/User.php +++ b/apps/user_ldap/lib/User/User.php @@ -170,6 +170,13 @@ public function processAttributes(array $ldapEntry): void { } unset($attr); + // active attribute + $attr = strtolower($this->connection->ldapUserActiveState); + if (isset($ldapEntry[$attr])) { + $this->updateUserActiveState($ldapEntry[$attr][0]); + } + unset($attr); + // check for cached profile data $username = $this->getUsername(); // buffer variable, to save resource $cacheKey = 'getUserProfile-' . $username; @@ -730,4 +737,9 @@ public function updateExtStorageHome(?string $valueFromLDAP = null):string { return ''; } } + + public function updateUserActiveState(string $valueFromLDAP): void { + $user = $this->userManager->get($this->uid); + $user->setEnabled($valueFromLDAP === 'TRUE'); + } } diff --git a/apps/user_ldap/openapi.json b/apps/user_ldap/openapi.json index 98afc0c3932f3..86ae47b79a173 100644 --- a/apps/user_ldap/openapi.json +++ b/apps/user_ldap/openapi.json @@ -538,7 +538,7 @@ "get": { "operationId": "configapi-show", "summary": "Get a configuration", - "description": "Output can look like this: ok 200 OK ldaps://my.ldap.server 7770 ou=small,dc=my,dc=ldap,dc=server ou=users,ou=small,dc=my,dc=ldap,dc=server ou=small,dc=my,dc=ldap,dc=server cn=root,dc=my,dc=ldap,dc=server clearTextWithShowPassword=1 1 0 displayname uid inetOrgPerson (&(objectclass=nextcloudUser)(nextcloudEnabled=TRUE)) 1 (&(|(objectclass=nextcloudGroup))) 0 nextcloudGroup cn memberUid (&(|(objectclass=inetOrgPerson))(uid=%uid)) 0 0 1 mail 20 auto auto 1 uid;sn;givenname 0 1 uid uid 0 0 500 1 \nThis endpoint requires admin access", + "description": "Output can look like this: ok 200 OK ldaps://my.ldap.server 7770 ou=small,dc=my,dc=ldap,dc=server ou=users,ou=small,dc=my,dc=ldap,dc=server ou=small,dc=my,dc=ldap,dc=server cn=root,dc=my,dc=ldap,dc=server clearTextWithShowPassword=1 1 0 active displayname uid inetOrgPerson (&(objectclass=nextcloudUser)(nextcloudEnabled=TRUE)) 1 (&(|(objectclass=nextcloudGroup))) 0 nextcloudGroup cn memberUid (&(|(objectclass=inetOrgPerson))(uid=%uid)) 0 0 1 mail 20 auto auto 1 uid;sn;givenname 0 1 uid uid 0 0 500 1 \nThis endpoint requires admin access", "tags": [ "configapi" ], diff --git a/apps/user_ldap/src/components/SettingsTabs/AdvancedTab.vue b/apps/user_ldap/src/components/SettingsTabs/AdvancedTab.vue index 4c8ad7ebd6e5a..e9d9658e0d7c9 100644 --- a/apps/user_ldap/src/components/SettingsTabs/AdvancedTab.vue +++ b/apps/user_ldap/src/components/SettingsTabs/AdvancedTab.vue @@ -72,6 +72,13 @@ :label="t('user_ldap', 'User Search Attributes')" @change="(event) => ldapConfigProxy.ldapAttributesForUserSearch = event.target.value" /> + + + ldapUserActiveState: string // Example: active ldapUserDisplayName: string // Example: displayname ldapUserDisplayName2: string // Example: uid ldapUserFilterObjectclass?: string // Example: inetOrgPerson diff --git a/apps/user_ldap/tests/User/UserTest.php b/apps/user_ldap/tests/User/UserTest.php index ee32320e06364..9e48c10978d9f 100644 --- a/apps/user_ldap/tests/User/UserTest.php +++ b/apps/user_ldap/tests/User/UserTest.php @@ -787,6 +787,48 @@ public static function extStorageHomeDataProvider(): array { ]; } + public function testActivateUser(): void { + $coreUser = $this->createMock(IUser::class); + $coreUser->expects($this->once()) + ->method('setEnabled') + ->with(true); + + $this->userManager->expects($this->once()) + ->method('get') + ->with($this->uid) + ->willReturn($coreUser); + + $this->user->updateUserActiveState('TRUE'); + } + + public function testDeactivateUserCorrect(): void { + $coreUser = $this->createMock(IUser::class); + $coreUser->expects($this->once()) + ->method('setEnabled') + ->with(false); + + $this->userManager->expects($this->once()) + ->method('get') + ->with($this->uid) + ->willReturn($coreUser); + + $this->user->updateUserActiveState('FALSE'); + } + + public function testDeactivateUserFallback(): void { + $coreUser = $this->createMock(IUser::class); + $coreUser->expects($this->once()) + ->method('setEnabled') + ->with(false); + + $this->userManager->expects($this->once()) + ->method('get') + ->with($this->uid) + ->willReturn($coreUser); + + $this->user->updateUserActiveState('weird'); + } + #[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'extStorageHomeDataProvider')] public function testUpdateExtStorageHome(string $expected, ?string $valueFromLDAP = null, bool $isSet = true): void { if ($valueFromLDAP === null) { diff --git a/openapi.json b/openapi.json index 11a1c5a527e6b..7a62cc1a2edc1 100644 --- a/openapi.json +++ b/openapi.json @@ -42976,7 +42976,7 @@ "get": { "operationId": "user_ldap-configapi-show", "summary": "Get a configuration", - "description": "Output can look like this: ok 200 OK ldaps://my.ldap.server 7770 ou=small,dc=my,dc=ldap,dc=server ou=users,ou=small,dc=my,dc=ldap,dc=server ou=small,dc=my,dc=ldap,dc=server cn=root,dc=my,dc=ldap,dc=server clearTextWithShowPassword=1 1 0 displayname uid inetOrgPerson (&(objectclass=nextcloudUser)(nextcloudEnabled=TRUE)) 1 (&(|(objectclass=nextcloudGroup))) 0 nextcloudGroup cn memberUid (&(|(objectclass=inetOrgPerson))(uid=%uid)) 0 0 1 mail 20 auto auto 1 uid;sn;givenname 0 1 uid uid 0 0 500 1 \nThis endpoint requires admin access", + "description": "Output can look like this: ok 200 OK ldaps://my.ldap.server 7770 ou=small,dc=my,dc=ldap,dc=server ou=users,ou=small,dc=my,dc=ldap,dc=server ou=small,dc=my,dc=ldap,dc=server cn=root,dc=my,dc=ldap,dc=server clearTextWithShowPassword=1 1 0 active displayname uid inetOrgPerson (&(objectclass=nextcloudUser)(nextcloudEnabled=TRUE)) 1 (&(|(objectclass=nextcloudGroup))) 0 nextcloudGroup cn memberUid (&(|(objectclass=inetOrgPerson))(uid=%uid)) 0 0 1 mail 20 auto auto 1 uid;sn;givenname 0 1 uid uid 0 0 500 1 \nThis endpoint requires admin access", "tags": [ "user_ldap/configapi" ],