From 404d26aa4a950e246f11ce421c48faef764fce31 Mon Sep 17 00:00:00 2001
From: Marc Hefter
Date: Sat, 7 May 2022 16:27:20 +0200
Subject: [PATCH 01/23] feature addition: [user_ldap] update user profile from
LDAP; WIP work-in-progress; TODO update profile
Signed-off-by: Marc Hefter
---
apps/user_ldap/js/wizard/wizardTabAdvanced.js | 93 ++++++++++++++++++
apps/user_ldap/lib/Configuration.php | 22 +++++
apps/user_ldap/lib/Connection.php | 7 ++
apps/user_ldap/lib/User/Manager.php | 8 ++
apps/user_ldap/lib/User/User.php | 96 +++++++++++++++++++
5 files changed, 226 insertions(+)
diff --git a/apps/user_ldap/js/wizard/wizardTabAdvanced.js b/apps/user_ldap/js/wizard/wizardTabAdvanced.js
index be98072dcb3..26bcd15810e 100644
--- a/apps/user_ldap/js/wizard/wizardTabAdvanced.js
+++ b/apps/user_ldap/js/wizard/wizardTabAdvanced.js
@@ -125,6 +125,36 @@ OCA = OCA || {};
$element: $('#ldap_ext_storage_home_attribute'),
setMethod: 'setExternalStorageHomeAttribute'
},
+
+ //User Profile Attributes
+ ldap_attr_phone: {
+ $element: $('#ldap_attr_phone'),
+ setMethod: 'setPhoneAttribute'
+ },
+ ldap_attr_website: {
+ $element: $('#ldap_attr_website'),
+ setMethod: 'setWebsiteAttribute'
+ },
+ ldap_attr_address: {
+ $element: $('#ldap_attr_address'),
+ setMethod: 'setAddressAttribute'
+ },
+ ldap_attr_organisation: {
+ $element: $('#ldap_attr_organisation'),
+ setMethod: 'setOrganisationAttribute'
+ },
+ ldap_attr_role: {
+ $element: $('#ldap_attr_role'),
+ setMethod: 'setRoleAttribute'
+ },
+ ldap_attr_headline: {
+ $element: $('#ldap_attr_headline'),
+ setMethod: 'setHeadlineAttribute'
+ },
+ ldap_attr_biography: {
+ $element: $('#ldap_attr_biography'),
+ setMethod: 'setBiographyAttribute'
+ },
};
this.setManagedItems(items);
},
@@ -366,6 +396,69 @@ OCA = OCA || {};
this.setElementValue(this.managedItems.home_folder_naming_rule.$element, attribute);
},
+ /**
+ * sets the attribute for the Nextcloud user profile phone Number
+ *
+ * @param {string} attribute
+ */
+ setPhoneAttribute: function(attribute) {
+ this.setElementValue(this.managedItems.ldap_attr_phone.$element, attribute);
+ },
+
+ /**
+ * sets the attribute for the Nextcloud user profile website
+ *
+ * @param {string} attribute
+ */
+ setWebsiteAttribute: function(attribute) {
+ this.setElementValue(this.managedItems.ldap_attr_website.$element, attribute);
+ },
+
+ /**
+ * sets the attribute for the Nextcloud user profile postal address
+ *
+ * @param {string} attribute
+ */
+ setAddressAttribute: function(attribute) {
+ this.setElementValue(this.managedItems.ldap_attr_address.$element, attribute);
+ },
+
+ /**
+ * sets the attribute for the Nextcloud user profile organisation
+ *
+ * @param {string} attribute
+ */
+ setOrganisationAttribute: function(attribute) {
+ this.setElementValue(this.managedItems.ldap_attr_organisation.$element, attribute);
+ },
+
+ /**
+ * sets the attribute for the Nextcloud user profile role
+ *
+ * @param {string} attribute
+ */
+ setRoleAttribute: function(attribute) {
+ this.setElementValue(this.managedItems.ldap_attr_role.$element, attribute);
+ },
+
+ /**
+ * sets the attribute for the Nextcloud user profile headline
+ *
+ * @param {string} attribute
+ */
+ setHeadlineAttribute: function(attribute) {
+ this.setElementValue(this.managedItems.ldap_attr_headline.$element, attribute);
+ },
+
+ /**
+ * sets the attribute for the Nextcloud user profile biography
+ *
+ * @param {string} attribute
+ */
+ setBiographyAttribute: function(attribute) {
+ this.setElementValue(this.managedItems.ldap_attr_biography.$element, attribute);
+ },
+
/**
* deals with the result of the Test Connection test
*
diff --git a/apps/user_ldap/lib/Configuration.php b/apps/user_ldap/lib/Configuration.php
index 59fac50b90b..91780155251 100644
--- a/apps/user_ldap/lib/Configuration.php
+++ b/apps/user_ldap/lib/Configuration.php
@@ -10,6 +10,7 @@
* @author Jörn Friedrich Dreyer
* @author Lennart Rosam
* @author Lukas Reschke
+ * @author Marc Hefter
* @author Morris Jobke
* @author Robin McCorkell
* @author Roeland Jago Douma
@@ -123,6 +124,13 @@ class Configuration {
'ldapExtStorageHomeAttribute' => null,
'ldapMatchingRuleInChainState' => self::LDAP_SERVER_FEATURE_UNKNOWN,
'ldapConnectionTimeout' => 15,
+ 'ldapAttributePhone' => null,
+ 'ldapAttributeWebsite' => null,
+ 'ldapAttributeAddress' => null,
+ 'ldapAttributeOrganisation' => null,
+ 'ldapAttributeRole' => null,
+ 'ldapAttributeHeadline' => null,
+ 'ldapAttributeBiography' => null,
];
public function __construct(string $configPrefix, bool $autoRead = true) {
@@ -469,6 +477,13 @@ class Configuration {
'ldap_ext_storage_home_attribute' => '',
'ldap_matching_rule_in_chain_state' => self::LDAP_SERVER_FEATURE_UNKNOWN,
'ldap_connection_timeout' => 15,
+ 'ldap_attr_phone' => '',
+ 'ldap_attr_website' => '',
+ 'ldap_attr_address' => '',
+ 'ldap_attr_organisation' => '',
+ 'ldap_attr_role' => '',
+ 'ldap_attr_headline' => '',
+ 'ldap_attr_biography' => '',
];
}
@@ -535,6 +550,13 @@ class Configuration {
'ldap_matching_rule_in_chain_state' => 'ldapMatchingRuleInChainState',
'ldapIgnoreNamingRules' => 'ldapIgnoreNamingRules', // sysconfig
'ldap_connection_timeout' => 'ldapConnectionTimeout',
+ 'ldap_attr_phone' => 'ldapAttributePhone',
+ 'ldap_attr_website' => 'ldapAttributeWebsite',
+ 'ldap_attr_address' => 'ldapAttributeAddress',
+ 'ldap_attr_organisation' => 'ldapAttributeOrganisation',
+ 'ldap_attr_role' => 'ldapAttributeRole',
+ 'ldap_attr_headline' => 'ldapAttributeHeadline',
+ 'ldap_attr_biography' => 'ldapAttributeBiography',
];
return $array;
}
diff --git a/apps/user_ldap/lib/Connection.php b/apps/user_ldap/lib/Connection.php
index 6700890c8c7..85c8b5ceda3 100644
--- a/apps/user_ldap/lib/Connection.php
+++ b/apps/user_ldap/lib/Connection.php
@@ -73,6 +73,13 @@ use Psr\Log\LoggerInterface;
* @property int hasMemberOfFilterSupport
* @property int useMemberOfToDetectMembership
* @property string ldapMatchingRuleInChainState
+ * @property string ldapAttributePhone
+ * @property string ldapAttributeWebsite
+ * @property string ldapAttributeAddress
+ * @property string ldapAttributeOrganisation
+ * @property string ldapAttributeRole
+ * @property string ldapAttributeHeadline
+ * @property string ldapAttributeBiography
*/
class Connection extends LDAPUtility {
/**
diff --git a/apps/user_ldap/lib/User/Manager.php b/apps/user_ldap/lib/User/Manager.php
index b1915ab57b5..8e0ad9c5df9 100644
--- a/apps/user_ldap/lib/User/Manager.php
+++ b/apps/user_ldap/lib/User/Manager.php
@@ -6,6 +6,7 @@
* @author Christoph Wurst
* @author Joas Schilling
* @author Jörn Friedrich Dreyer
+ * @author Marc Hefter
* @author Morris Jobke
* @author Roeland Jago Douma
* @author Roger Szabo
@@ -152,6 +153,13 @@ class Manager {
$this->access->getConnection()->ldapUserDisplayName,
$this->access->getConnection()->ldapUserDisplayName2,
$this->access->getConnection()->ldapExtStorageHomeAttribute,
+ $this->access->getConnection()->ldapAttributePhone,
+ $this->access->getConnection()->ldapAttributeWebsite,
+ $this->access->getConnection()->ldapAttributeAddress,
+ $this->access->getConnection()->ldapAttributeOrganisation,
+ $this->access->getConnection()->ldapAttributeRole,
+ $this->access->getConnection()->ldapAttributeHeadline,
+ $this->access->getConnection()->ldapAttributeBiography,
];
$homeRule = (string)$this->access->getConnection()->homeFolderNamingRule;
diff --git a/apps/user_ldap/lib/User/User.php b/apps/user_ldap/lib/User/User.php
index edf43494777..81ced78dab9 100644
--- a/apps/user_ldap/lib/User/User.php
+++ b/apps/user_ldap/lib/User/User.php
@@ -7,6 +7,7 @@
* @author Joas Schilling
* @author Jörn Friedrich Dreyer
* @author Juan Pablo Villafáñez
+ * @author Marc Hefter
* @author Morris Jobke
* @author Philipp Staiger
* @author Roger Szabo
@@ -35,6 +36,7 @@ use OCA\User_LDAP\Access;
use OCA\User_LDAP\Connection;
use OCA\User_LDAP\Exceptions\AttributeNotSet;
use OCA\User_LDAP\FilesystemHelper;
+use OCP\Accounts\IAccountManager;
use OCP\IAvatarManager;
use OCP\IConfig;
use OCP\ILogger;
@@ -108,6 +110,17 @@ class User {
*/
public const USER_PREFKEY_FIRSTLOGIN = 'firstLoginAccomplished';
+ /**
+ * DB config keys for user profile
+ */
+ public const USER_PREFKEY_PHONE = 'profile_phone';
+ public const USER_PREFKEY_WEBSITE = 'profile_website';
+ public const USER_PREFKEY_ADDRESS = 'profile_address';
+ public const USER_PREFKEY_ORGANISATION = 'profile_organisation';
+ public const USER_PREFKEY_ROLE = 'profile_role';
+ public const USER_PREFKEY_HEADLINE = 'profile_headline';
+ public const USER_PREFKEY_BIOGRAPHY = 'profile_biography';
+
/**
* @brief constructor, make sure the subclasses call this one!
* @param string $username the internal username
@@ -231,6 +244,49 @@ class User {
}
unset($attr);
+ //User Profile Field - Phone number
+ $attr = strtolower($this->connection->ldapAttributePhone);
+ if (isset($ldapEntry[$attr])) {
+ $this->updateProfile(self::USER_PREFKEY_PHONE, $ldapEntry[$attr][0]);
+ }
+ unset($attr);
+ //User Profile Field - website
+ $attr = strtolower($this->connection->ldapAttributeWebsite);
+ if (isset($ldapEntry[$attr])) {
+ $this->updateProfile(self::USER_PREFKEY_WEBSITE, $ldapEntry[$attr][0]);
+ }
+ unset($attr);
+ //User Profile Field - Address
+ $attr = strtolower($this->connection->ldapAttributeAddress);
+ if (isset($ldapEntry[$attr])) {
+ $this->updateProfile(self::USER_PREFKEY_ADDRESS, $ldapEntry[$attr][0]);
+ }
+ unset($attr);
+ //User Profile Field - organisation
+ $attr = strtolower($this->connection->ldapAttributeAddress);
+ if (isset($ldapEntry[$attr])) {
+ $this->updateProfile(self::USER_PREFKEY_ORGANISATION, $ldapEntry[$attr][0]);
+ }
+ unset($attr);
+ //User Profile Field - role
+ $attr = strtolower($this->connection->ldapAttributeAddress);
+ if (isset($ldapEntry[$attr])) {
+ $this->updateProfile(self::USER_PREFKEY_ROLE, $ldapEntry[$attr][0]);
+ }
+ unset($attr);
+ //User Profile Field - headline
+ $attr = strtolower($this->connection->ldapAttributeAddress);
+ if (isset($ldapEntry[$attr])) {
+ $this->updateProfile(self::USER_PREFKEY_HEADLINE, $ldapEntry[$attr][0]);
+ }
+ unset($attr);
+ //User Profile Field - biography
+ $attr = strtolower($this->connection->ldapAttributeAddress);
+ if (isset($ldapEntry[$attr])) {
+ $this->updateProfile(self::USER_PREFKEY_BIOGRAPHY, $ldapEntry[$attr][0]);
+ }
+ unset($attr);
+
//Avatar
/** @var Connection $connection */
$connection = $this->access->getConnection();
@@ -512,6 +568,46 @@ class User {
return $quotaValue === 'none' || $quotaValue === 'default' || \OC_Helper::computerFileSize($quotaValue) !== false;
}
+/* user profile settings and LDAP attributes
+ * ***
+ * interface IAccountManager
+ * public const PROPERTY_PHONE = 'phone';
+ * public const PROPERTY_EMAIL = 'email';
+ * public const PROPERTY_WEBSITE = 'website';
+ * public const PROPERTY_ADDRESS = 'address';
+ * public const PROPERTY_TWITTER = 'twitter';
+ * public const PROPERTY_ORGANISATION = 'organisation';
+ * public const PROPERTY_ROLE = 'role';
+ * public const PROPERTY_HEADLINE = 'headline';
+ * public const PROPERTY_BIOGRAPHY = 'biography';
+ * public const PROPERTY_PROFILE_ENABLED = 'profile_enabled';
+ * public function getAccount(IUser $user): IAccount;
+ * public function updateAccount(IAccount $account): void;
+ */
+ /**
+ * fetches values from LDAP and stores it as Nextcloud user value
+ * @param string $valueFromLDAP if known, to save an LDAP read request
+ * @return null
+ */
+ public function updateProfile(string $property, $valueFromLDAP = null) {
+ if ($this->wasRefreshed($property)) {
+ return;
+ }
+ if ($valueFromLDAP !== null) {
+ //$propertyValue = (string)$valueFromLDAP;
+ $propertyValue = [$valueFromLDAP];
+ }
+ if ($propertyValue && isset($propertyValue[0])) {
+ $value = $propertyValue[0];
+ $this->config->setUserValue($this->getUsername(), 'user_ldap', $property, $value);
+ // TODO: update user profile data; call \OCP\Accounts\IAccount::setProperty
+ return $value;
+ } else {
+ $this->config->deleteUserValue($this->getUsername(), 'user_ldap', $property);
+ return '';
+ }
+ }
+
/**
* called by a post_login hook to save the avatar picture
*
From 7fa3c674de904b140575112f471c5753aa03a89c Mon Sep 17 00:00:00 2001
From: Marc Hefter
Date: Thu, 12 May 2022 07:46:22 +0200
Subject: [PATCH 02/23] feature addition: [user_ldap] update user profile from
LDAP; WIP; fixing some uggly copy-and-paste errors; testing functionality;
preparing and editing the documentation
Signed-off-by: Marc Hefter
Signed-off-by: Marc Hefter
---
apps/user_ldap/js/wizard/wizardTabAdvanced.js | 13 +++++++
apps/user_ldap/lib/Configuration.php | 3 ++
apps/user_ldap/lib/Connection.php | 1 +
apps/user_ldap/lib/User/Manager.php | 1 +
apps/user_ldap/lib/User/User.php | 39 +++++++++++++++++--
apps/user_ldap/templates/settings.php | 11 ++++++
6 files changed, 64 insertions(+), 4 deletions(-)
diff --git a/apps/user_ldap/js/wizard/wizardTabAdvanced.js b/apps/user_ldap/js/wizard/wizardTabAdvanced.js
index 26bcd15810e..d2c3b6d125d 100644
--- a/apps/user_ldap/js/wizard/wizardTabAdvanced.js
+++ b/apps/user_ldap/js/wizard/wizardTabAdvanced.js
@@ -139,6 +139,10 @@ OCA = OCA || {};
$element: $('#ldap_attr_address'),
setMethod: 'setAddressAttribute'
},
+ ldap_attr_twitter: {
+ $element: $('#ldap_attr_twitter'),
+ setMethod: 'setTwitterAttribute'
+ },
ldap_attr_organisation: {
$element: $('#ldap_attr_organisation'),
setMethod: 'setOrganisationAttribute'
@@ -423,6 +427,15 @@ OCA = OCA || {};
this.setElementValue(this.managedItems.ldap_attr_address.$element, attribute);
},
+ /**
+ * sets the attribute for the Nextcloud user profile twitter
+ *
+ * @param {string} attribute
+ */
+ setTwitterAttribute: function(attribute) {
+ this.setElementValue(this.managedItems.ldap_attr_twitter.$element, attribute);
+ },
+
/**
* sets the attribute for the Nextcloud user profile organisation
*
diff --git a/apps/user_ldap/lib/Configuration.php b/apps/user_ldap/lib/Configuration.php
index 91780155251..e29bff4b8c5 100644
--- a/apps/user_ldap/lib/Configuration.php
+++ b/apps/user_ldap/lib/Configuration.php
@@ -127,6 +127,7 @@ class Configuration {
'ldapAttributePhone' => null,
'ldapAttributeWebsite' => null,
'ldapAttributeAddress' => null,
+ 'ldapAttributeTwitter' => null,
'ldapAttributeOrganisation' => null,
'ldapAttributeRole' => null,
'ldapAttributeHeadline' => null,
@@ -480,6 +481,7 @@ class Configuration {
'ldap_attr_phone' => '',
'ldap_attr_website' => '',
'ldap_attr_address' => '',
+ 'ldap_attr_twitter' => '',
'ldap_attr_organisation' => '',
'ldap_attr_role' => '',
'ldap_attr_headline' => '',
@@ -553,6 +555,7 @@ class Configuration {
'ldap_attr_phone' => 'ldapAttributePhone',
'ldap_attr_website' => 'ldapAttributeWebsite',
'ldap_attr_address' => 'ldapAttributeAddress',
+ 'ldap_attr_twitter' => 'ldapAttributeTwitter',
'ldap_attr_organisation' => 'ldapAttributeOrganisation',
'ldap_attr_role' => 'ldapAttributeRole',
'ldap_attr_headline' => 'ldapAttributeHeadline',
diff --git a/apps/user_ldap/lib/Connection.php b/apps/user_ldap/lib/Connection.php
index 85c8b5ceda3..f899ee381c8 100644
--- a/apps/user_ldap/lib/Connection.php
+++ b/apps/user_ldap/lib/Connection.php
@@ -76,6 +76,7 @@ use Psr\Log\LoggerInterface;
* @property string ldapAttributePhone
* @property string ldapAttributeWebsite
* @property string ldapAttributeAddress
+ * @property string ldapAttributeTwitter
* @property string ldapAttributeOrganisation
* @property string ldapAttributeRole
* @property string ldapAttributeHeadline
diff --git a/apps/user_ldap/lib/User/Manager.php b/apps/user_ldap/lib/User/Manager.php
index 8e0ad9c5df9..8942563a0d5 100644
--- a/apps/user_ldap/lib/User/Manager.php
+++ b/apps/user_ldap/lib/User/Manager.php
@@ -156,6 +156,7 @@ class Manager {
$this->access->getConnection()->ldapAttributePhone,
$this->access->getConnection()->ldapAttributeWebsite,
$this->access->getConnection()->ldapAttributeAddress,
+ $this->access->getConnection()->ldapAttributeTwitter,
$this->access->getConnection()->ldapAttributeOrganisation,
$this->access->getConnection()->ldapAttributeRole,
$this->access->getConnection()->ldapAttributeHeadline,
diff --git a/apps/user_ldap/lib/User/User.php b/apps/user_ldap/lib/User/User.php
index 81ced78dab9..e9437d61ab3 100644
--- a/apps/user_ldap/lib/User/User.php
+++ b/apps/user_ldap/lib/User/User.php
@@ -116,6 +116,7 @@ class User {
public const USER_PREFKEY_PHONE = 'profile_phone';
public const USER_PREFKEY_WEBSITE = 'profile_website';
public const USER_PREFKEY_ADDRESS = 'profile_address';
+ public const USER_PREFKEY_TWITTER = 'profile_twitter';
public const USER_PREFKEY_ORGANISATION = 'profile_organisation';
public const USER_PREFKEY_ROLE = 'profile_role';
public const USER_PREFKEY_HEADLINE = 'profile_headline';
@@ -262,26 +263,32 @@ class User {
$this->updateProfile(self::USER_PREFKEY_ADDRESS, $ldapEntry[$attr][0]);
}
unset($attr);
+ //User Profile Field - Twitter
+ $attr = strtolower($this->connection->ldapAttributeTwitter);
+ if (isset($ldapEntry[$attr])) {
+ $this->updateProfile(self::USER_PREFKEY_TWITTER, $ldapEntry[$attr][0]);
+ }
+ unset($attr);
//User Profile Field - organisation
- $attr = strtolower($this->connection->ldapAttributeAddress);
+ $attr = strtolower($this->connection->ldapAttributeOrganisation);
if (isset($ldapEntry[$attr])) {
$this->updateProfile(self::USER_PREFKEY_ORGANISATION, $ldapEntry[$attr][0]);
}
unset($attr);
//User Profile Field - role
- $attr = strtolower($this->connection->ldapAttributeAddress);
+ $attr = strtolower($this->connection->ldapAttributeRole);
if (isset($ldapEntry[$attr])) {
$this->updateProfile(self::USER_PREFKEY_ROLE, $ldapEntry[$attr][0]);
}
unset($attr);
//User Profile Field - headline
- $attr = strtolower($this->connection->ldapAttributeAddress);
+ $attr = strtolower($this->connection->ldapAttributeHeadline);
if (isset($ldapEntry[$attr])) {
$this->updateProfile(self::USER_PREFKEY_HEADLINE, $ldapEntry[$attr][0]);
}
unset($attr);
//User Profile Field - biography
- $attr = strtolower($this->connection->ldapAttributeAddress);
+ $attr = strtolower($this->connection->ldapAttributeBiography);
if (isset($ldapEntry[$attr])) {
$this->updateProfile(self::USER_PREFKEY_BIOGRAPHY, $ldapEntry[$attr][0]);
}
@@ -590,6 +597,30 @@ class User {
* @return null
*/
public function updateProfile(string $property, $valueFromLDAP = null) {
+ // check for valid property and set corresponding profile property
+ $profileProperty = 'INVALID';
+ if (self::USER_PREFKEY_PHONE == $property) {
+ $profileProperty = \OCP\Accounts\IAccountManager::PROPERTY_PHONE;
+ } elseif (self::USER_PREFKEY_WEBSITE == $property) {
+ $profileProperty = \OCP\Accounts\IAccountManager::PROPERTY_WEBSITE;
+ } elseif (self::USER_PREFKEY_ADDRESS == $property) {
+ $profileProperty = \OCP\Accounts\IAccountManager::PROPERTY_ADDRESS;
+ } elseif (self::USER_PREFKEY_TWITTER == $property) {
+ $profileProperty = \OCP\Accounts\IAccountManager::PROPERTY_TWITTER;
+ } elseif (self::USER_PREFKEY_ORGANISATION == $property) {
+ $profileProperty = \OCP\Accounts\IAccountManager::PROPERTY_ORGANISATION;
+ } elseif (self::USER_PREFKEY_ROLE == $property) {
+ $profileProperty = \OCP\Accounts\IAccountManager::PROPERTY_ROLE;
+ } elseif (self::USER_PREFKEY_HEADLINE == $property) {
+ $profileProperty = \OCP\Accounts\IAccountManager::PROPERTY_HEADLINE;
+ } elseif (self::USER_PREFKEY_BIOGRAPHY == $property) {
+ $profileProperty = \OCP\Accounts\IAccountManager::PROPERTY_BIOGRAPHY;
+ } else {
+ // TODO: throw exception for invalid property specified
+ return;
+ }
+ $this->logger->info('user profile data from LDAP '.$this->dn.' ('.$profileProperty.')', ['app' => 'user_ldap']);
+ // check if this property was refreshed before
if ($this->wasRefreshed($property)) {
return;
}
diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php
index a28ef55a306..b779cc1f6e5 100644
--- a/apps/user_ldap/templates/settings.php
+++ b/apps/user_ldap/templates/settings.php
@@ -120,6 +120,17 @@ style('user_ldap', 'settings');
t('Leave empty for username (default). Otherwise, specify an LDAP/AD attribute.'));?>
t('$home in an external storage configuration will be replaced with the value of the specified attribute')); ?>
+ t('User Profile Attributes'));?>
+
From 2315c177261a03a2047f9ba3d11dd96da4fef840 Mon Sep 17 00:00:00 2001
From: Marc Hefter
Date: Tue, 17 May 2022 12:49:38 +0200
Subject: [PATCH 03/23] feature addition: [user_ldap] update user profile from
LDAP
Signed-off-by: Marc Hefter
Signed-off-by: Marc Hefter
---
apps/user_ldap/lib/User/User.php | 42 +++++++++++++++++---------------
lib/private/User/LazyUser.php | 10 ++++++++
lib/private/User/User.php | 41 +++++++++++++++++++++++++++++++
lib/public/IUser.php | 23 +++++++++++++++++
4 files changed, 96 insertions(+), 20 deletions(-)
diff --git a/apps/user_ldap/lib/User/User.php b/apps/user_ldap/lib/User/User.php
index e9437d61ab3..043f3b2d273 100644
--- a/apps/user_ldap/lib/User/User.php
+++ b/apps/user_ldap/lib/User/User.php
@@ -36,9 +36,12 @@ use OCA\User_LDAP\Access;
use OCA\User_LDAP\Connection;
use OCA\User_LDAP\Exceptions\AttributeNotSet;
use OCA\User_LDAP\FilesystemHelper;
+use OC\Accounts\AccountManager;
use OCP\Accounts\IAccountManager;
+use OCP\Accounts\PropertyDoesNotExistException;
use OCP\IAvatarManager;
use OCP\IConfig;
+use OCP\IDBConnection;
use OCP\ILogger;
use OCP\Image;
use OCP\IUser;
@@ -575,28 +578,12 @@ class User {
return $quotaValue === 'none' || $quotaValue === 'default' || \OC_Helper::computerFileSize($quotaValue) !== false;
}
-/* user profile settings and LDAP attributes
- * ***
- * interface IAccountManager
- * public const PROPERTY_PHONE = 'phone';
- * public const PROPERTY_EMAIL = 'email';
- * public const PROPERTY_WEBSITE = 'website';
- * public const PROPERTY_ADDRESS = 'address';
- * public const PROPERTY_TWITTER = 'twitter';
- * public const PROPERTY_ORGANISATION = 'organisation';
- * public const PROPERTY_ROLE = 'role';
- * public const PROPERTY_HEADLINE = 'headline';
- * public const PROPERTY_BIOGRAPHY = 'biography';
- * public const PROPERTY_PROFILE_ENABLED = 'profile_enabled';
- * public function getAccount(IUser $user): IAccount;
- * public function updateAccount(IAccount $account): void;
- */
/**
* fetches values from LDAP and stores it as Nextcloud user value
* @param string $valueFromLDAP if known, to save an LDAP read request
* @return null
*/
- public function updateProfile(string $property, $valueFromLDAP = null) {
+ private function updateProfile(string $property, $valueFromLDAP) {
// check for valid property and set corresponding profile property
$profileProperty = 'INVALID';
if (self::USER_PREFKEY_PHONE == $property) {
@@ -616,10 +603,9 @@ class User {
} elseif (self::USER_PREFKEY_BIOGRAPHY == $property) {
$profileProperty = \OCP\Accounts\IAccountManager::PROPERTY_BIOGRAPHY;
} else {
- // TODO: throw exception for invalid property specified
+ // FIXME: throw exception for invalid property specified
return;
}
- $this->logger->info('user profile data from LDAP '.$this->dn.' ('.$profileProperty.')', ['app' => 'user_ldap']);
// check if this property was refreshed before
if ($this->wasRefreshed($property)) {
return;
@@ -628,12 +614,28 @@ class User {
//$propertyValue = (string)$valueFromLDAP;
$propertyValue = [$valueFromLDAP];
}
+ $this->logger->debug('user profile data ('.$profileProperty.') from LDAP '.$this->dn.' ='.((string)$valueFromLDAP), ['app' => 'user_ldap']);
if ($propertyValue && isset($propertyValue[0])) {
$value = $propertyValue[0];
+ try {
+ $user = $this->userManager->get($this->uid);
+ if (!is_null($user)) {
+ $currentValue = (string)$user->getProfilePropertyValue($profileProperty);
+ if ($currentValue !== $value) {
+ $user->setProfilePropertyValue($profileProperty,$value);
+ }
+ // setScope(IAccountManager::SCOPE_FEDERATED);
+ // setVerified(IAccountManager::VERIFIED);
+ }
+ } catch (PropertyDoesNotExistException $e) {
+ $this->logger->error('property does not exist: '.$profileProperty.' for user '.$userName.'', ['app' => 'user_ldap']);
+ return;
+ }
+ $this->logger->debug('property updated: '.$profileProperty.'='.$propertyValue.' for user '.$userName.'', ['app' => 'user_ldap']);
$this->config->setUserValue($this->getUsername(), 'user_ldap', $property, $value);
- // TODO: update user profile data; call \OCP\Accounts\IAccount::setProperty
return $value;
} else {
+ // FIXME: I decided, to leave profile untouched, if attribute gets removed from LDAP
$this->config->deleteUserValue($this->getUsername(), 'user_ldap', $property);
return '';
}
diff --git a/lib/private/User/LazyUser.php b/lib/private/User/LazyUser.php
index 096578b8f37..577c937ee51 100644
--- a/lib/private/User/LazyUser.php
+++ b/lib/private/User/LazyUser.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
/**
* @copyright Copyright (c) 2022 Robin Appelman
*
+ * @author Marc Hefter
+ *
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
@@ -145,4 +147,12 @@ class LazyUser implements IUser {
public function setQuota($quota) {
$this->getUser()->setQuota($quota);
}
+
+ public function getProfilePropertyValue(string $property): ?string {
+ return $this->getUser()->getProfilePropertyValue($property);
+ }
+
+ public function setProfilePropertyValue(string $property, $value) {
+ $this->getUser()->setProfilePropertyValue($property, $value);
+ }
}
diff --git a/lib/private/User/User.php b/lib/private/User/User.php
index 2d80dbc7adf..d4f7effcf1d 100644
--- a/lib/private/User/User.php
+++ b/lib/private/User/User.php
@@ -12,6 +12,7 @@
* @author Julius Härtl
* @author Leon Klingele
* @author Lukas Reschke
+ * @author Marc Hefter
* @author Morris Jobke
* @author Robin Appelman
* @author Roeland Jago Douma
@@ -588,4 +589,44 @@ class User implements IUser {
$this->emitter->emit('\OC\User', 'changeUser', [$this, $feature, $value, $oldValue]);
}
}
+
+ /**
+ * @param string $property name of the AccountProperty
+ * @return string|null AccountProperty value
+ * @throws InvalidArgumentException when the property name is invalid or null
+ */
+ public function getProfilePropertyValue($property): ?string {
+ if ($property === null) {
+ throw new InvalidArgumentException('Property can not be null.');
+ }
+ // FIXME: check $property if it's one of the IAccountManager::PROPERTY_* public constants
+
+ // FIXME: I need to get the AccountProperty value to return
+ //return $this->config->getUserValue($this->uid, 'user_ldap', $property, null);
+ $this->ensureAccountManager();
+ $account = $this->accountManager->getAccount($this);
+ $property = $account->getProperty($property);
+ return $property->getValue();
+ }
+
+ /**
+ * @param string $property name of the AccountProperty
+ * @param string $value AccountProperty value
+ * @return void
+ * @throws InvalidArgumentException when the property name is invalid or null
+ */
+ public function setProfilePropertyValue($property, $value) {
+ if ($property === null) {
+ throw new InvalidArgumentException('Property can not be null.');
+ }
+ // FIXME: check $property if it's one of the IAccountManager::PROPERTY_* public constants
+ $this->ensureAccountManager();
+ $account = $this->accountManager->getAccount($this);
+ $property = $account->getProperty($property);
+ $property->setValue($value);
+ //$property->setScope(IAccountManager::SCOPE_FEDERATED);
+ //$property->setVerified(IAccountManager::VERIFIED);
+ $this->accountManager->updateAccount($account);
+ return;
+ }
}
diff --git a/lib/public/IUser.php b/lib/public/IUser.php
index 3a7e6ab1f11..fc732b47757 100644
--- a/lib/public/IUser.php
+++ b/lib/public/IUser.php
@@ -5,6 +5,7 @@
* @author Arthur Schiwon
* @author John Molakvoæ
* @author Lukas Reschke
+ * @author Marc Hefter
* @author Morris Jobke
* @author Robin Appelman
* @author Roeland Jago Douma
@@ -270,4 +271,26 @@ interface IUser {
* @since 9.0.0
*/
public function setQuota($quota);
+
+ /**
+ * get users' profile property value.
+ *
+ * @param string $property name see IAccountManager::PROPERTY_*
+ * @return string AccountProperty value
+ * @throws InvalidArgumentException when the property name is invalid or null
+ * @since 25.0.0
+ */
+ public function getProfilePropertyValue(string $property): ?string;
+
+ /**
+ * set users' profile property value.
+ * remove property, if null
+ *
+ * @param string $property name from IAccountManager::PROPERTY_*
+ * @param string $value AccountProperty value
+ * @return void
+ * @throws InvalidArgumentException when the property name is invalid or null
+ * @since 25.0.0
+ */
+ public function setProfilePropertyValue(string $property, $value);
}
From eee0275dc5b3cfec8f1470bf9efca357e7d3ca68 Mon Sep 17 00:00:00 2001
From: Marc Hefter
Date: Tue, 17 May 2022 18:05:37 +0200
Subject: [PATCH 04/23] added user profile scope setting
Signed-off-by: Marc Hefter
Signed-off-by: Marc Hefter
---
apps/user_ldap/js/wizard/wizardTabAdvanced.js | 13 ++++
apps/user_ldap/lib/Configuration.php | 3 +
apps/user_ldap/lib/Connection.php | 1 +
apps/user_ldap/lib/User/User.php | 25 ++++---
apps/user_ldap/templates/settings.php | 1 +
lib/private/User/LazyUser.php | 12 +++-
lib/private/User/User.php | 66 ++++++++++++++++++-
lib/public/IUser.php | 27 +++++++-
8 files changed, 130 insertions(+), 18 deletions(-)
diff --git a/apps/user_ldap/js/wizard/wizardTabAdvanced.js b/apps/user_ldap/js/wizard/wizardTabAdvanced.js
index d2c3b6d125d..031f2bf2a9d 100644
--- a/apps/user_ldap/js/wizard/wizardTabAdvanced.js
+++ b/apps/user_ldap/js/wizard/wizardTabAdvanced.js
@@ -159,6 +159,10 @@ OCA = OCA || {};
$element: $('#ldap_attr_biography'),
setMethod: 'setBiographyAttribute'
},
+ ldap_profile_scope: {
+ $element: $('#ldap_profile_scope'),
+ setMethod: 'setProfileScope'
+ },
};
this.setManagedItems(items);
},
@@ -472,6 +476,15 @@ OCA = OCA || {};
this.setElementValue(this.managedItems.ldap_attr_biography.$element, attribute);
},
+ /**
+ * sets the visibility scope for the Nextcloud user profile properties
+ *
+ * @param {string} scope
+ */
+ setProfileScope: function(scope) {
+ this.setElementValue(this.managedItems.ldap_profile_scope.$element, scope);
+ },
+
/**
* deals with the result of the Test Connection test
*
diff --git a/apps/user_ldap/lib/Configuration.php b/apps/user_ldap/lib/Configuration.php
index e29bff4b8c5..2b42dd9992b 100644
--- a/apps/user_ldap/lib/Configuration.php
+++ b/apps/user_ldap/lib/Configuration.php
@@ -132,6 +132,7 @@ class Configuration {
'ldapAttributeRole' => null,
'ldapAttributeHeadline' => null,
'ldapAttributeBiography' => null,
+ 'ldapProfileScope' => null,
];
public function __construct(string $configPrefix, bool $autoRead = true) {
@@ -486,6 +487,7 @@ class Configuration {
'ldap_attr_role' => '',
'ldap_attr_headline' => '',
'ldap_attr_biography' => '',
+ 'ldap_profile_scope' => '',
];
}
@@ -560,6 +562,7 @@ class Configuration {
'ldap_attr_role' => 'ldapAttributeRole',
'ldap_attr_headline' => 'ldapAttributeHeadline',
'ldap_attr_biography' => 'ldapAttributeBiography',
+ 'ldap_profile_scope' => 'ldapProfileScope',
];
return $array;
}
diff --git a/apps/user_ldap/lib/Connection.php b/apps/user_ldap/lib/Connection.php
index f899ee381c8..11aaaec13dd 100644
--- a/apps/user_ldap/lib/Connection.php
+++ b/apps/user_ldap/lib/Connection.php
@@ -81,6 +81,7 @@ use Psr\Log\LoggerInterface;
* @property string ldapAttributeRole
* @property string ldapAttributeHeadline
* @property string ldapAttributeBiography
+ * @property string ldapProfileScope
*/
class Connection extends LDAPUtility {
/**
diff --git a/apps/user_ldap/lib/User/User.php b/apps/user_ldap/lib/User/User.php
index 043f3b2d273..1f044c6ddd6 100644
--- a/apps/user_ldap/lib/User/User.php
+++ b/apps/user_ldap/lib/User/User.php
@@ -248,52 +248,57 @@ class User {
}
unset($attr);
+ //User profile visibility
+ $profileScope = $this->connection->ldapProfileScope;
+ if (is_null($profileScope) || '' === $profileScope || 'unset' === $profileScope) {
+ $profileScope = null;
+ }
//User Profile Field - Phone number
$attr = strtolower($this->connection->ldapAttributePhone);
if (isset($ldapEntry[$attr])) {
- $this->updateProfile(self::USER_PREFKEY_PHONE, $ldapEntry[$attr][0]);
+ $this->updateProfile(self::USER_PREFKEY_PHONE, $ldapEntry[$attr][0], $profileScope);
}
unset($attr);
//User Profile Field - website
$attr = strtolower($this->connection->ldapAttributeWebsite);
if (isset($ldapEntry[$attr])) {
- $this->updateProfile(self::USER_PREFKEY_WEBSITE, $ldapEntry[$attr][0]);
+ $this->updateProfile(self::USER_PREFKEY_WEBSITE, $ldapEntry[$attr][0], $profileScope);
}
unset($attr);
//User Profile Field - Address
$attr = strtolower($this->connection->ldapAttributeAddress);
if (isset($ldapEntry[$attr])) {
- $this->updateProfile(self::USER_PREFKEY_ADDRESS, $ldapEntry[$attr][0]);
+ $this->updateProfile(self::USER_PREFKEY_ADDRESS, $ldapEntry[$attr][0], $profileScope);
}
unset($attr);
//User Profile Field - Twitter
$attr = strtolower($this->connection->ldapAttributeTwitter);
if (isset($ldapEntry[$attr])) {
- $this->updateProfile(self::USER_PREFKEY_TWITTER, $ldapEntry[$attr][0]);
+ $this->updateProfile(self::USER_PREFKEY_TWITTER, $ldapEntry[$attr][0], $profileScope);
}
unset($attr);
//User Profile Field - organisation
$attr = strtolower($this->connection->ldapAttributeOrganisation);
if (isset($ldapEntry[$attr])) {
- $this->updateProfile(self::USER_PREFKEY_ORGANISATION, $ldapEntry[$attr][0]);
+ $this->updateProfile(self::USER_PREFKEY_ORGANISATION, $ldapEntry[$attr][0], $profileScope);
}
unset($attr);
//User Profile Field - role
$attr = strtolower($this->connection->ldapAttributeRole);
if (isset($ldapEntry[$attr])) {
- $this->updateProfile(self::USER_PREFKEY_ROLE, $ldapEntry[$attr][0]);
+ $this->updateProfile(self::USER_PREFKEY_ROLE, $ldapEntry[$attr][0], $profileScope);
}
unset($attr);
//User Profile Field - headline
$attr = strtolower($this->connection->ldapAttributeHeadline);
if (isset($ldapEntry[$attr])) {
- $this->updateProfile(self::USER_PREFKEY_HEADLINE, $ldapEntry[$attr][0]);
+ $this->updateProfile(self::USER_PREFKEY_HEADLINE, $ldapEntry[$attr][0], $profileScope);
}
unset($attr);
//User Profile Field - biography
$attr = strtolower($this->connection->ldapAttributeBiography);
if (isset($ldapEntry[$attr])) {
- $this->updateProfile(self::USER_PREFKEY_BIOGRAPHY, $ldapEntry[$attr][0]);
+ $this->updateProfile(self::USER_PREFKEY_BIOGRAPHY, $ldapEntry[$attr][0], $profileScope);
}
unset($attr);
@@ -583,7 +588,7 @@ class User {
* @param string $valueFromLDAP if known, to save an LDAP read request
* @return null
*/
- private function updateProfile(string $property, $valueFromLDAP) {
+ private function updateProfile(string $property, $valueFromLDAP, $scope=null) {
// check for valid property and set corresponding profile property
$profileProperty = 'INVALID';
if (self::USER_PREFKEY_PHONE == $property) {
@@ -622,7 +627,7 @@ class User {
if (!is_null($user)) {
$currentValue = (string)$user->getProfilePropertyValue($profileProperty);
if ($currentValue !== $value) {
- $user->setProfilePropertyValue($profileProperty,$value);
+ $user->setProfileProperty($profileProperty,$value,$scope,null);
}
// setScope(IAccountManager::SCOPE_FEDERATED);
// setVerified(IAccountManager::VERIFIED);
diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php
index b779cc1f6e5..aee48f85ed0 100644
--- a/apps/user_ldap/templates/settings.php
+++ b/apps/user_ldap/templates/settings.php
@@ -130,6 +130,7 @@ style('user_ldap', 'settings');
+
diff --git a/lib/private/User/LazyUser.php b/lib/private/User/LazyUser.php
index 577c937ee51..0645983979f 100644
--- a/lib/private/User/LazyUser.php
+++ b/lib/private/User/LazyUser.php
@@ -152,7 +152,15 @@ class LazyUser implements IUser {
return $this->getUser()->getProfilePropertyValue($property);
}
- public function setProfilePropertyValue(string $property, $value) {
- $this->getUser()->setProfilePropertyValue($property, $value);
+ public function getProfilePropertyScope(string $property): ?string {
+ return $this->getUser()->getProfilePropertyScope($property);
+ }
+
+ public function getProfilePropertyVerified(string $property): ?string {
+ return $this->getUser()->getProfilePropertyVerified($property);
+ }
+
+ public function setProfileProperty(string $property, $value=null, $scope=null, $verified=null) {
+ $this->getUser()->setProfileProperty($property, $value, $scope, $verified);
}
}
diff --git a/lib/private/User/User.php b/lib/private/User/User.php
index d4f7effcf1d..aaff2db8f5a 100644
--- a/lib/private/User/User.php
+++ b/lib/private/User/User.php
@@ -609,13 +609,47 @@ class User implements IUser {
return $property->getValue();
}
+ /**
+ * @param string $property name of the AccountProperty
+ * @return string|null AccountProperty scope
+ * @throws InvalidArgumentException when the property name is invalid or null
+ */
+ public function getProfilePropertyScope($property): ?string {
+ if ($property === null) {
+ throw new InvalidArgumentException('Property can not be null.');
+ }
+ $this->ensureAccountManager();
+ $account = $this->accountManager->getAccount($this);
+ // TODO: this should be stored locally, to reduce database overhead
+ $property = $account->getProperty($property);
+ return $property->getScope();
+ }
+
+ /**
+ * @param string $property name of the AccountProperty
+ * @return string|null AccountProperty verified
+ * @throws InvalidArgumentException when the property name is invalid or null
+ */
+ public function getProfilePropertyVerified($property): ?string {
+ if ($property === null) {
+ throw new InvalidArgumentException('Property can not be null.');
+ }
+ $this->ensureAccountManager();
+ $account = $this->accountManager->getAccount($this);
+ // TODO: this should be stored locally, to reduce database overhead
+ $property = $account->getProperty($property);
+ return $property->getVerified();
+ }
+
/**
* @param string $property name of the AccountProperty
* @param string $value AccountProperty value
+ * @param string $scope AccountProperty scope
+ * @param string $verified AccountProperty verified
* @return void
* @throws InvalidArgumentException when the property name is invalid or null
*/
- public function setProfilePropertyValue($property, $value) {
+ public function setProfileProperty($property, $value=null, $scope=null, $verified=null) {
if ($property === null) {
throw new InvalidArgumentException('Property can not be null.');
}
@@ -623,9 +657,35 @@ class User implements IUser {
$this->ensureAccountManager();
$account = $this->accountManager->getAccount($this);
$property = $account->getProperty($property);
+ if (null !== $value) {
+ $property->setValue($value);
+ }
+ if (null !== $scope) {
+ // FIXME: should I default to IAccountManager::SCOPE_FEDERATED
+ $property->setScope($scope);
+ }
+ if (null !== $verified) {
+ // FIXME: should I default to IAccountManager::VERIFIED
+ $property->setVerified($verified);
+ }
+ $this->accountManager->updateAccount($account);
+ return;
+ }
+
+ /**
+ * @param string $property name of the AccountProperty
+ * @param string $value AccountProperty value
+ * @return void
+ * @throws InvalidArgumentException when the property name is invalid or null
+ */
+ public function setProfilePropertyValue($property, $value) {
+ if ($property === null) {
+ throw new InvalidArgumentException('Property can not be null.');
+ }
+ $this->ensureAccountManager();
+ $account = $this->accountManager->getAccount($this);
+ $property = $account->getProperty($property);
$property->setValue($value);
- //$property->setScope(IAccountManager::SCOPE_FEDERATED);
- //$property->setVerified(IAccountManager::VERIFIED);
$this->accountManager->updateAccount($account);
return;
}
diff --git a/lib/public/IUser.php b/lib/public/IUser.php
index fc732b47757..7dc21a28b08 100644
--- a/lib/public/IUser.php
+++ b/lib/public/IUser.php
@@ -283,14 +283,35 @@ interface IUser {
public function getProfilePropertyValue(string $property): ?string;
/**
- * set users' profile property value.
- * remove property, if null
+ * get users' profile property scope.
+ *
+ * @param string $property name see IAccountManager::PROPERTY_*
+ * @return string AccountProperty scope IAccountManager::SCOPE_*
+ * @throws InvalidArgumentException when the property name is invalid or null
+ * @since 25.0.0
+ */
+ public function getProfilePropertyScope(string $property): ?string;
+
+ /**
+ * get users' profile property verified.
+ *
+ * @param string $property name see IAccountManager::PROPERTY_*
+ * @return string AccountProperty verification status IAccountManager::NOT_VERIFIED/VERIFICATION_IN_PROGRESS/VERIFIED
+ * @throws InvalidArgumentException when the property name is invalid or null
+ * @since 25.0.0
+ */
+ public function getProfilePropertyVerified(string $property): ?string;
+
+ /**
+ * set users' profile property value,scope,verified.
*
* @param string $property name from IAccountManager::PROPERTY_*
* @param string $value AccountProperty value
+ * @param string $scope AccountProperty scope
+ * @param string $verified AccountProperty verified
* @return void
* @throws InvalidArgumentException when the property name is invalid or null
* @since 25.0.0
*/
- public function setProfilePropertyValue(string $property, $value);
+ public function setProfileProperty(string $property, $value=null, $scope=null, $verified=null);
}
From c7623c7869729fca3b5c01054f69651018151efd Mon Sep 17 00:00:00 2001
From: Marc Hefter
Date: Fri, 20 May 2022 14:31:55 +0200
Subject: [PATCH 05/23] bugfix: changed forgotten userName, to getUsername
Signed-off-by: Marc Hefter
Signed-off-by: Marc Hefter
---
apps/user_ldap/lib/User/User.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/apps/user_ldap/lib/User/User.php b/apps/user_ldap/lib/User/User.php
index 1f044c6ddd6..dc6be6ba16d 100644
--- a/apps/user_ldap/lib/User/User.php
+++ b/apps/user_ldap/lib/User/User.php
@@ -633,10 +633,10 @@ class User {
// setVerified(IAccountManager::VERIFIED);
}
} catch (PropertyDoesNotExistException $e) {
- $this->logger->error('property does not exist: '.$profileProperty.' for user '.$userName.'', ['app' => 'user_ldap']);
+ $this->logger->error('property does not exist: '.$profileProperty.' for user '.$this->getUsername().'', ['app' => 'user_ldap']);
return;
}
- $this->logger->debug('property updated: '.$profileProperty.'='.$propertyValue.' for user '.$userName.'', ['app' => 'user_ldap']);
+ $this->logger->debug('property updated: '.$profileProperty.'='.$propertyValue.' for user '.$this->getUsername().'', ['app' => 'user_ldap']);
$this->config->setUserValue($this->getUsername(), 'user_ldap', $property, $value);
return $value;
} else {
From b72fbd58f61b40db40c2f9a61e47ef8985008dc2 Mon Sep 17 00:00:00 2001
From: Marc Hefter
Date: Sat, 21 May 2022 11:04:19 +0200
Subject: [PATCH 06/23] fixed error: Array to string conversion at
user_ldap/lib/User/User.php#639
Signed-off-by: Marc Hefter
Signed-off-by: Marc Hefter
---
apps/user_ldap/lib/User/User.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/apps/user_ldap/lib/User/User.php b/apps/user_ldap/lib/User/User.php
index dc6be6ba16d..a3d87c31541 100644
--- a/apps/user_ldap/lib/User/User.php
+++ b/apps/user_ldap/lib/User/User.php
@@ -636,7 +636,7 @@ class User {
$this->logger->error('property does not exist: '.$profileProperty.' for user '.$this->getUsername().'', ['app' => 'user_ldap']);
return;
}
- $this->logger->debug('property updated: '.$profileProperty.'='.$propertyValue.' for user '.$this->getUsername().'', ['app' => 'user_ldap']);
+ $this->logger->debug('property updated: '.$profileProperty.'='.$value.' for user '.$this->getUsername().'', ['app' => 'user_ldap']);
$this->config->setUserValue($this->getUsername(), 'user_ldap', $property, $value);
return $value;
} else {
From 240c57b94b274f157a4b7d38d168e06b48a8fafc Mon Sep 17 00:00:00 2001
From: Marc Hefter
Date: Sat, 21 May 2022 16:03:42 +0200
Subject: [PATCH 07/23] cleanup: removed unnecessary imports of
IAccountManager, AccountManager, IDBConnection
Signed-off-by: Marc Hefter
Signed-off-by: Marc Hefter
---
apps/user_ldap/lib/User/User.php | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/apps/user_ldap/lib/User/User.php b/apps/user_ldap/lib/User/User.php
index a3d87c31541..85cf3bde301 100644
--- a/apps/user_ldap/lib/User/User.php
+++ b/apps/user_ldap/lib/User/User.php
@@ -36,16 +36,13 @@ use OCA\User_LDAP\Access;
use OCA\User_LDAP\Connection;
use OCA\User_LDAP\Exceptions\AttributeNotSet;
use OCA\User_LDAP\FilesystemHelper;
-use OC\Accounts\AccountManager;
-use OCP\Accounts\IAccountManager;
-use OCP\Accounts\PropertyDoesNotExistException;
use OCP\IAvatarManager;
use OCP\IConfig;
-use OCP\IDBConnection;
use OCP\ILogger;
use OCP\Image;
use OCP\IUser;
use OCP\IUserManager;
+use OCP\Accounts\PropertyDoesNotExistException;
use OCP\Notification\IManager as INotificationManager;
use Psr\Log\LoggerInterface;
From 26aa1c3580374024d91184ddf50d1085c00a0288 Mon Sep 17 00:00:00 2001
From: Marc Hefter
Date: Tue, 14 Feb 2023 11:56:51 +0100
Subject: [PATCH 08/23] CleanUp: remove unneeded UNSET, to unclutter code
Signed-off-by: march42
Signed-off-by: Marc Hefter
---
apps/user_ldap/lib/User/User.php | 7 -------
1 file changed, 7 deletions(-)
diff --git a/apps/user_ldap/lib/User/User.php b/apps/user_ldap/lib/User/User.php
index 85cf3bde301..28d43b81f46 100644
--- a/apps/user_ldap/lib/User/User.php
+++ b/apps/user_ldap/lib/User/User.php
@@ -255,43 +255,36 @@ class User {
if (isset($ldapEntry[$attr])) {
$this->updateProfile(self::USER_PREFKEY_PHONE, $ldapEntry[$attr][0], $profileScope);
}
- unset($attr);
//User Profile Field - website
$attr = strtolower($this->connection->ldapAttributeWebsite);
if (isset($ldapEntry[$attr])) {
$this->updateProfile(self::USER_PREFKEY_WEBSITE, $ldapEntry[$attr][0], $profileScope);
}
- unset($attr);
//User Profile Field - Address
$attr = strtolower($this->connection->ldapAttributeAddress);
if (isset($ldapEntry[$attr])) {
$this->updateProfile(self::USER_PREFKEY_ADDRESS, $ldapEntry[$attr][0], $profileScope);
}
- unset($attr);
//User Profile Field - Twitter
$attr = strtolower($this->connection->ldapAttributeTwitter);
if (isset($ldapEntry[$attr])) {
$this->updateProfile(self::USER_PREFKEY_TWITTER, $ldapEntry[$attr][0], $profileScope);
}
- unset($attr);
//User Profile Field - organisation
$attr = strtolower($this->connection->ldapAttributeOrganisation);
if (isset($ldapEntry[$attr])) {
$this->updateProfile(self::USER_PREFKEY_ORGANISATION, $ldapEntry[$attr][0], $profileScope);
}
- unset($attr);
//User Profile Field - role
$attr = strtolower($this->connection->ldapAttributeRole);
if (isset($ldapEntry[$attr])) {
$this->updateProfile(self::USER_PREFKEY_ROLE, $ldapEntry[$attr][0], $profileScope);
}
- unset($attr);
//User Profile Field - headline
$attr = strtolower($this->connection->ldapAttributeHeadline);
if (isset($ldapEntry[$attr])) {
$this->updateProfile(self::USER_PREFKEY_HEADLINE, $ldapEntry[$attr][0], $profileScope);
}
- unset($attr);
//User Profile Field - biography
$attr = strtolower($this->connection->ldapAttributeBiography);
if (isset($ldapEntry[$attr])) {
From 44065c0fea21f554725d81d37cc0133717114119 Mon Sep 17 00:00:00 2001
From: Marc Hefter
Date: Tue, 14 Feb 2023 13:15:49 +0100
Subject: [PATCH 09/23] Fix: Parameter $scope has no provided type
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: Côme Chilliet <91878298+come-nc@users.noreply.github.com>
Signed-off-by: Marc Hefter
Signed-off-by: Marc Hefter
---
apps/user_ldap/lib/User/User.php | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/apps/user_ldap/lib/User/User.php b/apps/user_ldap/lib/User/User.php
index 28d43b81f46..c08847b9db8 100644
--- a/apps/user_ldap/lib/User/User.php
+++ b/apps/user_ldap/lib/User/User.php
@@ -576,9 +576,8 @@ class User {
/**
* fetches values from LDAP and stores it as Nextcloud user value
* @param string $valueFromLDAP if known, to save an LDAP read request
- * @return null
*/
- private function updateProfile(string $property, $valueFromLDAP, $scope=null) {
+ private function updateProfile(string $property, $valueFromLDAP, ?string $scope=null): void {
// check for valid property and set corresponding profile property
$profileProperty = 'INVALID';
if (self::USER_PREFKEY_PHONE == $property) {
@@ -628,11 +627,11 @@ class User {
}
$this->logger->debug('property updated: '.$profileProperty.'='.$value.' for user '.$this->getUsername().'', ['app' => 'user_ldap']);
$this->config->setUserValue($this->getUsername(), 'user_ldap', $property, $value);
- return $value;
+ return;
} else {
// FIXME: I decided, to leave profile untouched, if attribute gets removed from LDAP
$this->config->deleteUserValue($this->getUsername(), 'user_ldap', $property);
- return '';
+ return;
}
}
From 2f76b7a3d5b2d5712afb119db4f7af2e3bcf7bfc Mon Sep 17 00:00:00 2001
From: Marc Hefter
Date: Fri, 17 Feb 2023 10:25:08 +0100
Subject: [PATCH 10/23] CleanUp: tidy checking for empty profileScope
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: Côme Chilliet <91878298+come-nc@users.noreply.github.com>
Signed-off-by: Marc Hefter
---
apps/user_ldap/lib/User/User.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/apps/user_ldap/lib/User/User.php b/apps/user_ldap/lib/User/User.php
index c08847b9db8..cbe3101239e 100644
--- a/apps/user_ldap/lib/User/User.php
+++ b/apps/user_ldap/lib/User/User.php
@@ -247,7 +247,7 @@ class User {
//User profile visibility
$profileScope = $this->connection->ldapProfileScope;
- if (is_null($profileScope) || '' === $profileScope || 'unset' === $profileScope) {
+ if (empty($profileScope) || $profileScope === 'unset') {
$profileScope = null;
}
//User Profile Field - Phone number
From 651273808f7e40695539a4ac5b205b8aa46ff9ed Mon Sep 17 00:00:00 2001
From: Marc Hefter
Date: Fri, 17 Feb 2023 10:37:31 +0100
Subject: [PATCH 11/23] CleanUp: correct version to 27 and return value
specification
Co-authored-by: Pytal <24800714+Pytal@users.noreply.github.com>
Signed-off-by: Marc Hefter
Signed-off-by: Marc Hefter
---
lib/private/User/User.php | 6 +++---
lib/public/IUser.php | 8 ++++----
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/lib/private/User/User.php b/lib/private/User/User.php
index aaff2db8f5a..9449705358d 100644
--- a/lib/private/User/User.php
+++ b/lib/private/User/User.php
@@ -592,7 +592,7 @@ class User implements IUser {
/**
* @param string $property name of the AccountProperty
- * @return string|null AccountProperty value
+ * @return ?string AccountProperty value
* @throws InvalidArgumentException when the property name is invalid or null
*/
public function getProfilePropertyValue($property): ?string {
@@ -611,7 +611,7 @@ class User implements IUser {
/**
* @param string $property name of the AccountProperty
- * @return string|null AccountProperty scope
+ * @return ?string AccountProperty scope
* @throws InvalidArgumentException when the property name is invalid or null
*/
public function getProfilePropertyScope($property): ?string {
@@ -627,7 +627,7 @@ class User implements IUser {
/**
* @param string $property name of the AccountProperty
- * @return string|null AccountProperty verified
+ * @return ?string AccountProperty verified
* @throws InvalidArgumentException when the property name is invalid or null
*/
public function getProfilePropertyVerified($property): ?string {
diff --git a/lib/public/IUser.php b/lib/public/IUser.php
index 7dc21a28b08..f942e6f036f 100644
--- a/lib/public/IUser.php
+++ b/lib/public/IUser.php
@@ -278,7 +278,7 @@ interface IUser {
* @param string $property name see IAccountManager::PROPERTY_*
* @return string AccountProperty value
* @throws InvalidArgumentException when the property name is invalid or null
- * @since 25.0.0
+ * @since 27.0.0
*/
public function getProfilePropertyValue(string $property): ?string;
@@ -288,7 +288,7 @@ interface IUser {
* @param string $property name see IAccountManager::PROPERTY_*
* @return string AccountProperty scope IAccountManager::SCOPE_*
* @throws InvalidArgumentException when the property name is invalid or null
- * @since 25.0.0
+ * @since 27.0.0
*/
public function getProfilePropertyScope(string $property): ?string;
@@ -298,7 +298,7 @@ interface IUser {
* @param string $property name see IAccountManager::PROPERTY_*
* @return string AccountProperty verification status IAccountManager::NOT_VERIFIED/VERIFICATION_IN_PROGRESS/VERIFIED
* @throws InvalidArgumentException when the property name is invalid or null
- * @since 25.0.0
+ * @since 27.0.0
*/
public function getProfilePropertyVerified(string $property): ?string;
@@ -311,7 +311,7 @@ interface IUser {
* @param string $verified AccountProperty verified
* @return void
* @throws InvalidArgumentException when the property name is invalid or null
- * @since 25.0.0
+ * @since 27.0.0
*/
public function setProfileProperty(string $property, $value=null, $scope=null, $verified=null);
}
From 30202907516a8adb2bdc63a3d9d822752a0ae512 Mon Sep 17 00:00:00 2001
From: Marc Hefter
Date: Fri, 17 Feb 2023 10:50:46 +0100
Subject: [PATCH 12/23] CleanUp: removed redundant condition if block
Signed-off-by: Marc Hefter
---
apps/user_ldap/lib/User/User.php | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/apps/user_ldap/lib/User/User.php b/apps/user_ldap/lib/User/User.php
index cbe3101239e..f1be9b28cab 100644
--- a/apps/user_ldap/lib/User/User.php
+++ b/apps/user_ldap/lib/User/User.php
@@ -604,10 +604,7 @@ class User {
if ($this->wasRefreshed($property)) {
return;
}
- if ($valueFromLDAP !== null) {
- //$propertyValue = (string)$valueFromLDAP;
- $propertyValue = [$valueFromLDAP];
- }
+ $propertyValue = [$valueFromLDAP];
$this->logger->debug('user profile data ('.$profileProperty.') from LDAP '.$this->dn.' ='.((string)$valueFromLDAP), ['app' => 'user_ldap']);
if ($propertyValue && isset($propertyValue[0])) {
$value = $propertyValue[0];
From 5c4a05cfd68bb0397cb033f7c5d957ed6f9eabd0 Mon Sep 17 00:00:00 2001
From: Marc Hefter
Date: Fri, 17 Feb 2023 15:25:17 +0100
Subject: [PATCH 13/23] CleanUp: removed redundant storing profile attributes
in user settings
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: Côme Chilliet <91878298+come-nc@users.noreply.github.com
Signed-off-by: Marc Hefter
---
apps/user_ldap/lib/User/User.php | 2 --
1 file changed, 2 deletions(-)
diff --git a/apps/user_ldap/lib/User/User.php b/apps/user_ldap/lib/User/User.php
index f1be9b28cab..4807280dc40 100644
--- a/apps/user_ldap/lib/User/User.php
+++ b/apps/user_ldap/lib/User/User.php
@@ -623,11 +623,9 @@ class User {
return;
}
$this->logger->debug('property updated: '.$profileProperty.'='.$value.' for user '.$this->getUsername().'', ['app' => 'user_ldap']);
- $this->config->setUserValue($this->getUsername(), 'user_ldap', $property, $value);
return;
} else {
// FIXME: I decided, to leave profile untouched, if attribute gets removed from LDAP
- $this->config->deleteUserValue($this->getUsername(), 'user_ldap', $property);
return;
}
}
From f812b8757689edf7a3c1f2751bbd106196e9fafb Mon Sep 17 00:00:00 2001
From: Marc Hefter
Date: Sun, 26 Feb 2023 20:15:01 +0100
Subject: [PATCH 14/23] handling updateProfile with array of values
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
using an array to buffer profile updates, like suggested by @come-nc
clean some code and remove unneccessary redundancy
added the Fediverse profile property
Co-Authored-By: Côme Chilliet <91878298+come-nc@users.noreply.github.com>
Signed-off-by: Marc Hefter
---
apps/user_ldap/js/wizard/wizardTabAdvanced.js | 13 ++
apps/user_ldap/lib/Configuration.php | 3 +
apps/user_ldap/lib/Connection.php | 1 +
apps/user_ldap/lib/User/Manager.php | 1 +
apps/user_ldap/lib/User/User.php | 126 +++++++++---------
apps/user_ldap/templates/settings.php | 1 +
6 files changed, 79 insertions(+), 66 deletions(-)
diff --git a/apps/user_ldap/js/wizard/wizardTabAdvanced.js b/apps/user_ldap/js/wizard/wizardTabAdvanced.js
index 031f2bf2a9d..170625ce896 100644
--- a/apps/user_ldap/js/wizard/wizardTabAdvanced.js
+++ b/apps/user_ldap/js/wizard/wizardTabAdvanced.js
@@ -159,6 +159,10 @@ OCA = OCA || {};
$element: $('#ldap_attr_biography'),
setMethod: 'setBiographyAttribute'
},
+ ldap_attr_fediverse: {
+ $element: $('#ldap_attr_fediverse'),
+ setMethod: 'setFediverseAttribute'
+ },
ldap_profile_scope: {
$element: $('#ldap_profile_scope'),
setMethod: 'setProfileScope'
@@ -476,6 +480,15 @@ OCA = OCA || {};
this.setElementValue(this.managedItems.ldap_attr_biography.$element, attribute);
},
+ /**
+ * sets the attribute for the Nextcloud user profile fediverse
+ *
+ * @param {string} attribute
+ */
+ setFediverseAttribute: function(attribute) {
+ this.setElementValue(this.managedItems.ldap_attr_fediverse.$element, attribute);
+ },
+
/**
* sets the visibility scope for the Nextcloud user profile properties
*
diff --git a/apps/user_ldap/lib/Configuration.php b/apps/user_ldap/lib/Configuration.php
index 2b42dd9992b..1eb6c7986e5 100644
--- a/apps/user_ldap/lib/Configuration.php
+++ b/apps/user_ldap/lib/Configuration.php
@@ -132,6 +132,7 @@ class Configuration {
'ldapAttributeRole' => null,
'ldapAttributeHeadline' => null,
'ldapAttributeBiography' => null,
+ 'ldapAttributeFediverse' => null,
'ldapProfileScope' => null,
];
@@ -487,6 +488,7 @@ class Configuration {
'ldap_attr_role' => '',
'ldap_attr_headline' => '',
'ldap_attr_biography' => '',
+ 'ldap_attr_fediverse' => '',
'ldap_profile_scope' => '',
];
}
@@ -562,6 +564,7 @@ class Configuration {
'ldap_attr_role' => 'ldapAttributeRole',
'ldap_attr_headline' => 'ldapAttributeHeadline',
'ldap_attr_biography' => 'ldapAttributeBiography',
+ 'ldap_attr_fediverse' => 'ldapAttributeFediverse',
'ldap_profile_scope' => 'ldapProfileScope',
];
return $array;
diff --git a/apps/user_ldap/lib/Connection.php b/apps/user_ldap/lib/Connection.php
index 11aaaec13dd..8bf2904179a 100644
--- a/apps/user_ldap/lib/Connection.php
+++ b/apps/user_ldap/lib/Connection.php
@@ -81,6 +81,7 @@ use Psr\Log\LoggerInterface;
* @property string ldapAttributeRole
* @property string ldapAttributeHeadline
* @property string ldapAttributeBiography
+ * @property string ldapAttributeFediverse
* @property string ldapProfileScope
*/
class Connection extends LDAPUtility {
diff --git a/apps/user_ldap/lib/User/Manager.php b/apps/user_ldap/lib/User/Manager.php
index 8942563a0d5..d356a272f8c 100644
--- a/apps/user_ldap/lib/User/Manager.php
+++ b/apps/user_ldap/lib/User/Manager.php
@@ -161,6 +161,7 @@ class Manager {
$this->access->getConnection()->ldapAttributeRole,
$this->access->getConnection()->ldapAttributeHeadline,
$this->access->getConnection()->ldapAttributeBiography,
+ $this->access->getConnection()->ldapAttributeFediverse,
];
$homeRule = (string)$this->access->getConnection()->homeFolderNamingRule;
diff --git a/apps/user_ldap/lib/User/User.php b/apps/user_ldap/lib/User/User.php
index 4807280dc40..93f7ff5c332 100644
--- a/apps/user_ldap/lib/User/User.php
+++ b/apps/user_ldap/lib/User/User.php
@@ -110,18 +110,6 @@ class User {
*/
public const USER_PREFKEY_FIRSTLOGIN = 'firstLoginAccomplished';
- /**
- * DB config keys for user profile
- */
- public const USER_PREFKEY_PHONE = 'profile_phone';
- public const USER_PREFKEY_WEBSITE = 'profile_website';
- public const USER_PREFKEY_ADDRESS = 'profile_address';
- public const USER_PREFKEY_TWITTER = 'profile_twitter';
- public const USER_PREFKEY_ORGANISATION = 'profile_organisation';
- public const USER_PREFKEY_ROLE = 'profile_role';
- public const USER_PREFKEY_HEADLINE = 'profile_headline';
- public const USER_PREFKEY_BIOGRAPHY = 'profile_biography';
-
/**
* @brief constructor, make sure the subclasses call this one!
* @param string $username the internal username
@@ -245,6 +233,12 @@ class User {
}
unset($attr);
+ /**
+ * Additions to User_LDAP, for writing the User Profile
+ *
+ * @var string|null $profileScope the configured scope of visibility
+ * @var array $profileValues array of the LDAP data
+ */
//User profile visibility
$profileScope = $this->connection->ldapProfileScope;
if (empty($profileScope) || $profileScope === 'unset') {
@@ -253,43 +247,54 @@ class User {
//User Profile Field - Phone number
$attr = strtolower($this->connection->ldapAttributePhone);
if (isset($ldapEntry[$attr])) {
- $this->updateProfile(self::USER_PREFKEY_PHONE, $ldapEntry[$attr][0], $profileScope);
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_PHONE] = $ldapEntry[$attr][0];
}
//User Profile Field - website
$attr = strtolower($this->connection->ldapAttributeWebsite);
if (isset($ldapEntry[$attr])) {
- $this->updateProfile(self::USER_PREFKEY_WEBSITE, $ldapEntry[$attr][0], $profileScope);
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_WEBSITE] = $ldapEntry[$attr][0];
}
//User Profile Field - Address
$attr = strtolower($this->connection->ldapAttributeAddress);
if (isset($ldapEntry[$attr])) {
- $this->updateProfile(self::USER_PREFKEY_ADDRESS, $ldapEntry[$attr][0], $profileScope);
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_ADDRESS] = $ldapEntry[$attr][0];
}
//User Profile Field - Twitter
$attr = strtolower($this->connection->ldapAttributeTwitter);
if (isset($ldapEntry[$attr])) {
- $this->updateProfile(self::USER_PREFKEY_TWITTER, $ldapEntry[$attr][0], $profileScope);
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_TWITTER] = $ldapEntry[$attr][0];
}
//User Profile Field - organisation
$attr = strtolower($this->connection->ldapAttributeOrganisation);
if (isset($ldapEntry[$attr])) {
- $this->updateProfile(self::USER_PREFKEY_ORGANISATION, $ldapEntry[$attr][0], $profileScope);
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_ORGANISATION] = $ldapEntry[$attr][0];
}
//User Profile Field - role
$attr = strtolower($this->connection->ldapAttributeRole);
if (isset($ldapEntry[$attr])) {
- $this->updateProfile(self::USER_PREFKEY_ROLE, $ldapEntry[$attr][0], $profileScope);
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_ROLE] = $ldapEntry[$attr][0];
}
//User Profile Field - headline
$attr = strtolower($this->connection->ldapAttributeHeadline);
if (isset($ldapEntry[$attr])) {
- $this->updateProfile(self::USER_PREFKEY_HEADLINE, $ldapEntry[$attr][0], $profileScope);
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_HEADLINE] = $ldapEntry[$attr][0];
}
//User Profile Field - biography
$attr = strtolower($this->connection->ldapAttributeBiography);
if (isset($ldapEntry[$attr])) {
- $this->updateProfile(self::USER_PREFKEY_BIOGRAPHY, $ldapEntry[$attr][0], $profileScope);
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_BIOGRAPHY] = $ldapEntry[$attr][0];
+ }
+ //User Profile Field - fediverse
+ $attr = strtolower($this->connection->ldapAttributeFediverse);
+ if (isset($ldapEntry[$attr])) {
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_FEDIVERSE] = $ldapEntry[$attr][0];
+ }
+ // Update user profile
+ if(0 < count($profileValues)) {
+ $this->updateProfile($profileValues, $profileScope);
+ unset($profileValues);
}
+ unset($profileScope);
unset($attr);
//Avatar
@@ -574,59 +579,48 @@ class User {
}
/**
- * fetches values from LDAP and stores it as Nextcloud user value
- * @param string $valueFromLDAP if known, to save an LDAP read request
+ * takes values from LDAP and stores it as Nextcloud user profile value
+ *
+ * @param array $profileValues associaive array of property keys and values from LDAP
+ * @param string|null $profileScope the scope of visibility to set
+ * @var string $property the array key (property name from AccountManager class)
+ * @var string $valueFromLDAP the value as read from LDAP
+ * @var string $propertyValue
+ * @var string $value
+ * @var string $currentValue
*/
- private function updateProfile(string $property, $valueFromLDAP, ?string $scope=null): void {
- // check for valid property and set corresponding profile property
- $profileProperty = 'INVALID';
- if (self::USER_PREFKEY_PHONE == $property) {
- $profileProperty = \OCP\Accounts\IAccountManager::PROPERTY_PHONE;
- } elseif (self::USER_PREFKEY_WEBSITE == $property) {
- $profileProperty = \OCP\Accounts\IAccountManager::PROPERTY_WEBSITE;
- } elseif (self::USER_PREFKEY_ADDRESS == $property) {
- $profileProperty = \OCP\Accounts\IAccountManager::PROPERTY_ADDRESS;
- } elseif (self::USER_PREFKEY_TWITTER == $property) {
- $profileProperty = \OCP\Accounts\IAccountManager::PROPERTY_TWITTER;
- } elseif (self::USER_PREFKEY_ORGANISATION == $property) {
- $profileProperty = \OCP\Accounts\IAccountManager::PROPERTY_ORGANISATION;
- } elseif (self::USER_PREFKEY_ROLE == $property) {
- $profileProperty = \OCP\Accounts\IAccountManager::PROPERTY_ROLE;
- } elseif (self::USER_PREFKEY_HEADLINE == $property) {
- $profileProperty = \OCP\Accounts\IAccountManager::PROPERTY_HEADLINE;
- } elseif (self::USER_PREFKEY_BIOGRAPHY == $property) {
- $profileProperty = \OCP\Accounts\IAccountManager::PROPERTY_BIOGRAPHY;
- } else {
- // FIXME: throw exception for invalid property specified
+ private function updateProfile(array $profileValues, ?string $profileScope=null): void {
+ // check if user profile was refreshed before
+ if ($this->wasRefreshed('profile')) {
return;
}
- // check if this property was refreshed before
- if ($this->wasRefreshed($property)) {
+ // check if parameter array is empty
+ if(0 == count($profileValues)) {
return;
}
- $propertyValue = [$valueFromLDAP];
- $this->logger->debug('user profile data ('.$profileProperty.') from LDAP '.$this->dn.' ='.((string)$valueFromLDAP), ['app' => 'user_ldap']);
- if ($propertyValue && isset($propertyValue[0])) {
- $value = $propertyValue[0];
- try {
- $user = $this->userManager->get($this->uid);
- if (!is_null($user)) {
- $currentValue = (string)$user->getProfilePropertyValue($profileProperty);
- if ($currentValue !== $value) {
- $user->setProfileProperty($profileProperty,$value,$scope,null);
- }
- // setScope(IAccountManager::SCOPE_FEDERATED);
- // setVerified(IAccountManager::VERIFIED);
+ // fetch/prepare user
+ $user = $this->userManager->get($this->uid);
+ if (is_null($user)) {
+ return;
+ }
+ // loop through the properties and handle them
+ foreach($profileValues as $property => $valueFromLDAP) {
+ $this->logger->debug('user profile data ('.$property.') from LDAP '.$this->dn.' ='.((string)$valueFromLDAP), ['app' => 'user_ldap']);
+ // check and update profile properties
+ $propertyValue = [$valueFromLDAP];
+ if ($propertyValue && isset($propertyValue[0])) {
+ $value = $propertyValue[0];
+ try {
+ $currentValue = (string)$user->getProfilePropertyValue($property);
+ if ($currentValue !== $value) {
+ $user->setProfileProperty($property,$value,$scope,null);
+ $this->logger->debug('property updated: '.$property.'='.$value.' for user '.$this->getUsername().'', ['app' => 'user_ldap']);
+ }
+ } catch (PropertyDoesNotExistException $e) {
+ $this->logger->error('property does not exist: '.$property.' for user '.$this->getUsername().'', ['app' => 'user_ldap']);
+ return;
}
- } catch (PropertyDoesNotExistException $e) {
- $this->logger->error('property does not exist: '.$profileProperty.' for user '.$this->getUsername().'', ['app' => 'user_ldap']);
- return;
}
- $this->logger->debug('property updated: '.$profileProperty.'='.$value.' for user '.$this->getUsername().'', ['app' => 'user_ldap']);
- return;
- } else {
- // FIXME: I decided, to leave profile untouched, if attribute gets removed from LDAP
- return;
}
}
diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php
index aee48f85ed0..c0ff2b6a866 100644
--- a/apps/user_ldap/templates/settings.php
+++ b/apps/user_ldap/templates/settings.php
@@ -130,6 +130,7 @@ style('user_ldap', 'settings');
+
From c6408587ed12634e6d5067a385a7766f3306d894 Mon Sep 17 00:00:00 2001
From: Marc Hefter
Date: Mon, 27 Feb 2023 09:43:42 +0100
Subject: [PATCH 15/23] fixing Psalm messages
Signed-off-by: Marc Hefter
---
apps/user_ldap/lib/User/User.php | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/apps/user_ldap/lib/User/User.php b/apps/user_ldap/lib/User/User.php
index 93f7ff5c332..f327ec44e77 100644
--- a/apps/user_ldap/lib/User/User.php
+++ b/apps/user_ldap/lib/User/User.php
@@ -583,11 +583,6 @@ class User {
*
* @param array $profileValues associaive array of property keys and values from LDAP
* @param string|null $profileScope the scope of visibility to set
- * @var string $property the array key (property name from AccountManager class)
- * @var string $valueFromLDAP the value as read from LDAP
- * @var string $propertyValue
- * @var string $value
- * @var string $currentValue
*/
private function updateProfile(array $profileValues, ?string $profileScope=null): void {
// check if user profile was refreshed before
@@ -604,16 +599,21 @@ class User {
return;
}
// loop through the properties and handle them
+ /** @var string $property the array key (property name from AccountManager class) */
+ /** @var string $valueFromLDAP the value as read from LDAP */
foreach($profileValues as $property => $valueFromLDAP) {
- $this->logger->debug('user profile data ('.$property.') from LDAP '.$this->dn.' ='.((string)$valueFromLDAP), ['app' => 'user_ldap']);
+ $this->logger->debug('user profile data ('.$property.') from LDAP '.$this->dn, ['app' => 'user_ldap']);
// check and update profile properties
+ /** @var string $propertyValue */
$propertyValue = [$valueFromLDAP];
- if ($propertyValue && isset($propertyValue[0])) {
+ if (isset($propertyValue[0])) {
+ /** @var string $value */
$value = $propertyValue[0];
try {
+ /** @var string $currentValue */
$currentValue = (string)$user->getProfilePropertyValue($property);
if ($currentValue !== $value) {
- $user->setProfileProperty($property,$value,$scope,null);
+ $user->setProfileProperty($property,$value,$profileScope,null);
$this->logger->debug('property updated: '.$property.'='.$value.' for user '.$this->getUsername().'', ['app' => 'user_ldap']);
}
} catch (PropertyDoesNotExistException $e) {
From dd2bd6a925f0fb482a53eac61e46d680bb074c85 Mon Sep 17 00:00:00 2001
From: Marc Hefter
Date: Sun, 5 Mar 2023 12:01:52 +0100
Subject: [PATCH 16/23] refined code, to be independend from OCP\IUser
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
rework updateProfile in user_ldap/lib/User/User.php
some cleanup at processAttributes in user_ldap/lib/User/User.php
rearranged Fediverse attribute, to match profile layout
Co-authored-by: Côme Chilliet <91878298+come-nc@users.noreply.github.com>
Signed-off-by: Marc Hefter
---
apps/user_ldap/js/wizard/wizardTabAdvanced.js | 26 +++----
apps/user_ldap/lib/Configuration.php | 6 +-
apps/user_ldap/lib/Connection.php | 2 +-
apps/user_ldap/lib/User/Manager.php | 2 +-
apps/user_ldap/lib/User/User.php | 69 +++++++++----------
apps/user_ldap/templates/settings.php | 2 +-
6 files changed, 51 insertions(+), 56 deletions(-)
diff --git a/apps/user_ldap/js/wizard/wizardTabAdvanced.js b/apps/user_ldap/js/wizard/wizardTabAdvanced.js
index 170625ce896..5b247294473 100644
--- a/apps/user_ldap/js/wizard/wizardTabAdvanced.js
+++ b/apps/user_ldap/js/wizard/wizardTabAdvanced.js
@@ -143,6 +143,10 @@ OCA = OCA || {};
$element: $('#ldap_attr_twitter'),
setMethod: 'setTwitterAttribute'
},
+ ldap_attr_fediverse: {
+ $element: $('#ldap_attr_fediverse'),
+ setMethod: 'setFediverseAttribute'
+ },
ldap_attr_organisation: {
$element: $('#ldap_attr_organisation'),
setMethod: 'setOrganisationAttribute'
@@ -159,10 +163,6 @@ OCA = OCA || {};
$element: $('#ldap_attr_biography'),
setMethod: 'setBiographyAttribute'
},
- ldap_attr_fediverse: {
- $element: $('#ldap_attr_fediverse'),
- setMethod: 'setFediverseAttribute'
- },
ldap_profile_scope: {
$element: $('#ldap_profile_scope'),
setMethod: 'setProfileScope'
@@ -444,6 +444,15 @@ OCA = OCA || {};
this.setElementValue(this.managedItems.ldap_attr_twitter.$element, attribute);
},
+ /**
+ * sets the attribute for the Nextcloud user profile fediverse
+ *
+ * @param {string} attribute
+ */
+ setFediverseAttribute: function(attribute) {
+ this.setElementValue(this.managedItems.ldap_attr_fediverse.$element, attribute);
+ },
+
/**
* sets the attribute for the Nextcloud user profile organisation
*
@@ -480,15 +489,6 @@ OCA = OCA || {};
this.setElementValue(this.managedItems.ldap_attr_biography.$element, attribute);
},
- /**
- * sets the attribute for the Nextcloud user profile fediverse
- *
- * @param {string} attribute
- */
- setFediverseAttribute: function(attribute) {
- this.setElementValue(this.managedItems.ldap_attr_fediverse.$element, attribute);
- },
-
/**
* sets the visibility scope for the Nextcloud user profile properties
*
diff --git a/apps/user_ldap/lib/Configuration.php b/apps/user_ldap/lib/Configuration.php
index 1eb6c7986e5..3935da8fa89 100644
--- a/apps/user_ldap/lib/Configuration.php
+++ b/apps/user_ldap/lib/Configuration.php
@@ -128,11 +128,11 @@ class Configuration {
'ldapAttributeWebsite' => null,
'ldapAttributeAddress' => null,
'ldapAttributeTwitter' => null,
+ 'ldapAttributeFediverse' => null,
'ldapAttributeOrganisation' => null,
'ldapAttributeRole' => null,
'ldapAttributeHeadline' => null,
'ldapAttributeBiography' => null,
- 'ldapAttributeFediverse' => null,
'ldapProfileScope' => null,
];
@@ -484,11 +484,11 @@ class Configuration {
'ldap_attr_website' => '',
'ldap_attr_address' => '',
'ldap_attr_twitter' => '',
+ 'ldap_attr_fediverse' => '',
'ldap_attr_organisation' => '',
'ldap_attr_role' => '',
'ldap_attr_headline' => '',
'ldap_attr_biography' => '',
- 'ldap_attr_fediverse' => '',
'ldap_profile_scope' => '',
];
}
@@ -560,11 +560,11 @@ class Configuration {
'ldap_attr_website' => 'ldapAttributeWebsite',
'ldap_attr_address' => 'ldapAttributeAddress',
'ldap_attr_twitter' => 'ldapAttributeTwitter',
+ 'ldap_attr_fediverse' => 'ldapAttributeFediverse',
'ldap_attr_organisation' => 'ldapAttributeOrganisation',
'ldap_attr_role' => 'ldapAttributeRole',
'ldap_attr_headline' => 'ldapAttributeHeadline',
'ldap_attr_biography' => 'ldapAttributeBiography',
- 'ldap_attr_fediverse' => 'ldapAttributeFediverse',
'ldap_profile_scope' => 'ldapProfileScope',
];
return $array;
diff --git a/apps/user_ldap/lib/Connection.php b/apps/user_ldap/lib/Connection.php
index 8bf2904179a..1c365ef2afc 100644
--- a/apps/user_ldap/lib/Connection.php
+++ b/apps/user_ldap/lib/Connection.php
@@ -77,11 +77,11 @@ use Psr\Log\LoggerInterface;
* @property string ldapAttributeWebsite
* @property string ldapAttributeAddress
* @property string ldapAttributeTwitter
+ * @property string ldapAttributeFediverse
* @property string ldapAttributeOrganisation
* @property string ldapAttributeRole
* @property string ldapAttributeHeadline
* @property string ldapAttributeBiography
- * @property string ldapAttributeFediverse
* @property string ldapProfileScope
*/
class Connection extends LDAPUtility {
diff --git a/apps/user_ldap/lib/User/Manager.php b/apps/user_ldap/lib/User/Manager.php
index d356a272f8c..04c67a537b8 100644
--- a/apps/user_ldap/lib/User/Manager.php
+++ b/apps/user_ldap/lib/User/Manager.php
@@ -157,11 +157,11 @@ class Manager {
$this->access->getConnection()->ldapAttributeWebsite,
$this->access->getConnection()->ldapAttributeAddress,
$this->access->getConnection()->ldapAttributeTwitter,
+ $this->access->getConnection()->ldapAttributeFediverse,
$this->access->getConnection()->ldapAttributeOrganisation,
$this->access->getConnection()->ldapAttributeRole,
$this->access->getConnection()->ldapAttributeHeadline,
$this->access->getConnection()->ldapAttributeBiography,
- $this->access->getConnection()->ldapAttributeFediverse,
];
$homeRule = (string)$this->access->getConnection()->homeFolderNamingRule;
diff --git a/apps/user_ldap/lib/User/User.php b/apps/user_ldap/lib/User/User.php
index f327ec44e77..3dd8f05a07d 100644
--- a/apps/user_ldap/lib/User/User.php
+++ b/apps/user_ldap/lib/User/User.php
@@ -32,6 +32,8 @@
*/
namespace OCA\User_LDAP\User;
+use Exception;
+use OC\Accounts\AccountManager;
use OCA\User_LDAP\Access;
use OCA\User_LDAP\Connection;
use OCA\User_LDAP\Exceptions\AttributeNotSet;
@@ -42,6 +44,7 @@ use OCP\ILogger;
use OCP\Image;
use OCP\IUser;
use OCP\IUserManager;
+use OCP\Accounts\IAccountManager;
use OCP\Accounts\PropertyDoesNotExistException;
use OCP\Notification\IManager as INotificationManager;
use Psr\Log\LoggerInterface;
@@ -233,17 +236,12 @@ class User {
}
unset($attr);
- /**
- * Additions to User_LDAP, for writing the User Profile
- *
- * @var string|null $profileScope the configured scope of visibility
- * @var array $profileValues array of the LDAP data
- */
//User profile visibility
$profileScope = $this->connection->ldapProfileScope;
if (empty($profileScope) || $profileScope === 'unset') {
$profileScope = null;
}
+ $profileValues = array(); // empty array, to prevent unneccessary call to updateProfile
//User Profile Field - Phone number
$attr = strtolower($this->connection->ldapAttributePhone);
if (isset($ldapEntry[$attr])) {
@@ -264,6 +262,11 @@ class User {
if (isset($ldapEntry[$attr])) {
$profileValues[\OCP\Accounts\IAccountManager::PROPERTY_TWITTER] = $ldapEntry[$attr][0];
}
+ //User Profile Field - fediverse
+ $attr = strtolower($this->connection->ldapAttributeFediverse);
+ if (isset($ldapEntry[$attr])) {
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_FEDIVERSE] = $ldapEntry[$attr][0];
+ }
//User Profile Field - organisation
$attr = strtolower($this->connection->ldapAttributeOrganisation);
if (isset($ldapEntry[$attr])) {
@@ -284,17 +287,10 @@ class User {
if (isset($ldapEntry[$attr])) {
$profileValues[\OCP\Accounts\IAccountManager::PROPERTY_BIOGRAPHY] = $ldapEntry[$attr][0];
}
- //User Profile Field - fediverse
- $attr = strtolower($this->connection->ldapAttributeFediverse);
- if (isset($ldapEntry[$attr])) {
- $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_FEDIVERSE] = $ldapEntry[$attr][0];
- }
// Update user profile
- if(0 < count($profileValues)) {
+ if(!empty($profileValues)) {
$this->updateProfile($profileValues, $profileScope);
- unset($profileValues);
}
- unset($profileScope);
unset($attr);
//Avatar
@@ -589,39 +585,38 @@ class User {
if ($this->wasRefreshed('profile')) {
return;
}
- // check if parameter array is empty
- if(0 == count($profileValues)) {
- return;
- }
// fetch/prepare user
$user = $this->userManager->get($this->uid);
if (is_null($user)) {
return;
}
+ // prepare AccountManager and Account
+ $accountManager = \OC::$server->get(IAccountManager::class);
+ $account = $accountManager->getAccount($user); // get Account
+ if (is_null($account)) {
+ return;
+ }
// loop through the properties and handle them
- /** @var string $property the array key (property name from AccountManager class) */
- /** @var string $valueFromLDAP the value as read from LDAP */
foreach($profileValues as $property => $valueFromLDAP) {
- $this->logger->debug('user profile data ('.$property.') from LDAP '.$this->dn, ['app' => 'user_ldap']);
// check and update profile properties
- /** @var string $propertyValue */
- $propertyValue = [$valueFromLDAP];
- if (isset($propertyValue[0])) {
- /** @var string $value */
- $value = $propertyValue[0];
- try {
- /** @var string $currentValue */
- $currentValue = (string)$user->getProfilePropertyValue($property);
- if ($currentValue !== $value) {
- $user->setProfileProperty($property,$value,$profileScope,null);
- $this->logger->debug('property updated: '.$property.'='.$value.' for user '.$this->getUsername().'', ['app' => 'user_ldap']);
- }
- } catch (PropertyDoesNotExistException $e) {
- $this->logger->error('property does not exist: '.$property.' for user '.$this->getUsername().'', ['app' => 'user_ldap']);
- return;
- }
+ $value = (is_array($valueFromLDAP) ? $valueFromLDAP[0] : $valueFromLDAP); // take ONLY the first value, if multiple values specified
+ try {
+ $accountProperty = $account->getProperty($property);
+ $currentValue = $accountProperty->getValue();
+ $scope = ($profileScope ? $profileScope : ($accountProperty->getScope() ? $accountProperty->getScope() : AccountManager::DEFAULT_SCOPES[$property]));
+ }
+ catch (PropertyDoesNotExistException $e) { // thrown at getProperty
+ $this->logger->error('property does not exist: '.$property.' for uid='.$this->uid.'', ['app' => 'user_ldap', 'exception' => $e]);
+ $currentValue = '';
+ $scope = ($profileScope ? $profileScope : AccountManager::DEFAULT_SCOPES[$property]);
+ }
+ $verified = IAccountManager::VERIFIED; // trust the LDAP admin knew what he put there
+ if ($currentValue !== $value) {
+ $account->setProperty($property,$value,$scope,$verified);
+ $this->logger->debug('property updated: '.$property.'='.$value.' for uid='.$this->uid.'', ['app' => 'user_ldap']);
}
}
+ $accountManager->updateAccount($account);
}
/**
diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php
index c0ff2b6a866..805cfce7c23 100644
--- a/apps/user_ldap/templates/settings.php
+++ b/apps/user_ldap/templates/settings.php
@@ -126,11 +126,11 @@ style('user_ldap', 'settings');
+
-
From 0c6d440643414151add23d4bf7eb4cff326f7b98 Mon Sep 17 00:00:00 2001
From: Marc Hefter
Date: Tue, 7 Mar 2023 18:21:17 +0100
Subject: [PATCH 17/23] undoing the additions to OC\IUser
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
removed changes from lib/public/IUser.php
removed changes from lib/private/User/LazyUser.php
removed changes from lib/private/User/User.php
Co-authored-by: Côme Chilliet <91878298+come-nc@users.noreply.github.com>
Signed-off-by: Marc Hefter
---
lib/private/User/LazyUser.php | 18 ------
lib/private/User/User.php | 101 ----------------------------------
lib/public/IUser.php | 44 ---------------
3 files changed, 163 deletions(-)
diff --git a/lib/private/User/LazyUser.php b/lib/private/User/LazyUser.php
index 0645983979f..096578b8f37 100644
--- a/lib/private/User/LazyUser.php
+++ b/lib/private/User/LazyUser.php
@@ -4,8 +4,6 @@ declare(strict_types=1);
/**
* @copyright Copyright (c) 2022 Robin Appelman
*
- * @author Marc Hefter
- *
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
@@ -147,20 +145,4 @@ class LazyUser implements IUser {
public function setQuota($quota) {
$this->getUser()->setQuota($quota);
}
-
- public function getProfilePropertyValue(string $property): ?string {
- return $this->getUser()->getProfilePropertyValue($property);
- }
-
- public function getProfilePropertyScope(string $property): ?string {
- return $this->getUser()->getProfilePropertyScope($property);
- }
-
- public function getProfilePropertyVerified(string $property): ?string {
- return $this->getUser()->getProfilePropertyVerified($property);
- }
-
- public function setProfileProperty(string $property, $value=null, $scope=null, $verified=null) {
- $this->getUser()->setProfileProperty($property, $value, $scope, $verified);
- }
}
diff --git a/lib/private/User/User.php b/lib/private/User/User.php
index 9449705358d..2d80dbc7adf 100644
--- a/lib/private/User/User.php
+++ b/lib/private/User/User.php
@@ -12,7 +12,6 @@
* @author Julius Härtl
* @author Leon Klingele
* @author Lukas Reschke
- * @author Marc Hefter
* @author Morris Jobke
* @author Robin Appelman
* @author Roeland Jago Douma
@@ -589,104 +588,4 @@ class User implements IUser {
$this->emitter->emit('\OC\User', 'changeUser', [$this, $feature, $value, $oldValue]);
}
}
-
- /**
- * @param string $property name of the AccountProperty
- * @return ?string AccountProperty value
- * @throws InvalidArgumentException when the property name is invalid or null
- */
- public function getProfilePropertyValue($property): ?string {
- if ($property === null) {
- throw new InvalidArgumentException('Property can not be null.');
- }
- // FIXME: check $property if it's one of the IAccountManager::PROPERTY_* public constants
-
- // FIXME: I need to get the AccountProperty value to return
- //return $this->config->getUserValue($this->uid, 'user_ldap', $property, null);
- $this->ensureAccountManager();
- $account = $this->accountManager->getAccount($this);
- $property = $account->getProperty($property);
- return $property->getValue();
- }
-
- /**
- * @param string $property name of the AccountProperty
- * @return ?string AccountProperty scope
- * @throws InvalidArgumentException when the property name is invalid or null
- */
- public function getProfilePropertyScope($property): ?string {
- if ($property === null) {
- throw new InvalidArgumentException('Property can not be null.');
- }
- $this->ensureAccountManager();
- $account = $this->accountManager->getAccount($this);
- // TODO: this should be stored locally, to reduce database overhead
- $property = $account->getProperty($property);
- return $property->getScope();
- }
-
- /**
- * @param string $property name of the AccountProperty
- * @return ?string AccountProperty verified
- * @throws InvalidArgumentException when the property name is invalid or null
- */
- public function getProfilePropertyVerified($property): ?string {
- if ($property === null) {
- throw new InvalidArgumentException('Property can not be null.');
- }
- $this->ensureAccountManager();
- $account = $this->accountManager->getAccount($this);
- // TODO: this should be stored locally, to reduce database overhead
- $property = $account->getProperty($property);
- return $property->getVerified();
- }
-
- /**
- * @param string $property name of the AccountProperty
- * @param string $value AccountProperty value
- * @param string $scope AccountProperty scope
- * @param string $verified AccountProperty verified
- * @return void
- * @throws InvalidArgumentException when the property name is invalid or null
- */
- public function setProfileProperty($property, $value=null, $scope=null, $verified=null) {
- if ($property === null) {
- throw new InvalidArgumentException('Property can not be null.');
- }
- // FIXME: check $property if it's one of the IAccountManager::PROPERTY_* public constants
- $this->ensureAccountManager();
- $account = $this->accountManager->getAccount($this);
- $property = $account->getProperty($property);
- if (null !== $value) {
- $property->setValue($value);
- }
- if (null !== $scope) {
- // FIXME: should I default to IAccountManager::SCOPE_FEDERATED
- $property->setScope($scope);
- }
- if (null !== $verified) {
- // FIXME: should I default to IAccountManager::VERIFIED
- $property->setVerified($verified);
- }
- $this->accountManager->updateAccount($account);
- return;
- }
-
- /**
- * @param string $property name of the AccountProperty
- * @param string $value AccountProperty value
- * @return void
- * @throws InvalidArgumentException when the property name is invalid or null
- */
- public function setProfilePropertyValue($property, $value) {
- if ($property === null) {
- throw new InvalidArgumentException('Property can not be null.');
- }
- $this->ensureAccountManager();
- $account = $this->accountManager->getAccount($this);
- $property = $account->getProperty($property);
- $property->setValue($value);
- $this->accountManager->updateAccount($account);
- return;
- }
}
diff --git a/lib/public/IUser.php b/lib/public/IUser.php
index f942e6f036f..3a7e6ab1f11 100644
--- a/lib/public/IUser.php
+++ b/lib/public/IUser.php
@@ -5,7 +5,6 @@
* @author Arthur Schiwon
* @author John Molakvoæ
* @author Lukas Reschke
- * @author Marc Hefter
* @author Morris Jobke
* @author Robin Appelman
* @author Roeland Jago Douma
@@ -271,47 +270,4 @@ interface IUser {
* @since 9.0.0
*/
public function setQuota($quota);
-
- /**
- * get users' profile property value.
- *
- * @param string $property name see IAccountManager::PROPERTY_*
- * @return string AccountProperty value
- * @throws InvalidArgumentException when the property name is invalid or null
- * @since 27.0.0
- */
- public function getProfilePropertyValue(string $property): ?string;
-
- /**
- * get users' profile property scope.
- *
- * @param string $property name see IAccountManager::PROPERTY_*
- * @return string AccountProperty scope IAccountManager::SCOPE_*
- * @throws InvalidArgumentException when the property name is invalid or null
- * @since 27.0.0
- */
- public function getProfilePropertyScope(string $property): ?string;
-
- /**
- * get users' profile property verified.
- *
- * @param string $property name see IAccountManager::PROPERTY_*
- * @return string AccountProperty verification status IAccountManager::NOT_VERIFIED/VERIFICATION_IN_PROGRESS/VERIFIED
- * @throws InvalidArgumentException when the property name is invalid or null
- * @since 27.0.0
- */
- public function getProfilePropertyVerified(string $property): ?string;
-
- /**
- * set users' profile property value,scope,verified.
- *
- * @param string $property name from IAccountManager::PROPERTY_*
- * @param string $value AccountProperty value
- * @param string $scope AccountProperty scope
- * @param string $verified AccountProperty verified
- * @return void
- * @throws InvalidArgumentException when the property name is invalid or null
- * @since 27.0.0
- */
- public function setProfileProperty(string $property, $value=null, $scope=null, $verified=null);
}
From 5ea46d81bb5fff84e8676cf5d7a059edb6271bc1 Mon Sep 17 00:00:00 2001
From: Marc Hefter
Date: Fri, 10 Mar 2023 10:56:16 +0100
Subject: [PATCH 18/23] nice up the code handling AccountManager
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
merging defaultScopes from DEFAULT_SCOPES and account_manager.default_property_scope
removing unneccessary profileScope setting (using config.php instead)
honoring admin choice 'profile.enabled'=>false in config.php
moved checking for empty array to updateProfile function
corrected some typos and cleaned some comments
Co-authored-by: Côme Chilliet <91878298+come-nc@users.noreply.github.com>
Signed-off-by: Marc Hefter
---
apps/user_ldap/js/wizard/wizardTabAdvanced.js | 13 --
apps/user_ldap/lib/Configuration.php | 3 -
apps/user_ldap/lib/Connection.php | 1 -
apps/user_ldap/lib/User/User.php | 131 +++++++++---------
apps/user_ldap/templates/settings.php | 1 -
5 files changed, 66 insertions(+), 83 deletions(-)
diff --git a/apps/user_ldap/js/wizard/wizardTabAdvanced.js b/apps/user_ldap/js/wizard/wizardTabAdvanced.js
index 5b247294473..a438b847401 100644
--- a/apps/user_ldap/js/wizard/wizardTabAdvanced.js
+++ b/apps/user_ldap/js/wizard/wizardTabAdvanced.js
@@ -163,10 +163,6 @@ OCA = OCA || {};
$element: $('#ldap_attr_biography'),
setMethod: 'setBiographyAttribute'
},
- ldap_profile_scope: {
- $element: $('#ldap_profile_scope'),
- setMethod: 'setProfileScope'
- },
};
this.setManagedItems(items);
},
@@ -489,15 +485,6 @@ OCA = OCA || {};
this.setElementValue(this.managedItems.ldap_attr_biography.$element, attribute);
},
- /**
- * sets the visibility scope for the Nextcloud user profile properties
- *
- * @param {string} scope
- */
- setProfileScope: function(scope) {
- this.setElementValue(this.managedItems.ldap_profile_scope.$element, scope);
- },
-
/**
* deals with the result of the Test Connection test
*
diff --git a/apps/user_ldap/lib/Configuration.php b/apps/user_ldap/lib/Configuration.php
index 3935da8fa89..ef64f75a9ef 100644
--- a/apps/user_ldap/lib/Configuration.php
+++ b/apps/user_ldap/lib/Configuration.php
@@ -133,7 +133,6 @@ class Configuration {
'ldapAttributeRole' => null,
'ldapAttributeHeadline' => null,
'ldapAttributeBiography' => null,
- 'ldapProfileScope' => null,
];
public function __construct(string $configPrefix, bool $autoRead = true) {
@@ -489,7 +488,6 @@ class Configuration {
'ldap_attr_role' => '',
'ldap_attr_headline' => '',
'ldap_attr_biography' => '',
- 'ldap_profile_scope' => '',
];
}
@@ -565,7 +563,6 @@ class Configuration {
'ldap_attr_role' => 'ldapAttributeRole',
'ldap_attr_headline' => 'ldapAttributeHeadline',
'ldap_attr_biography' => 'ldapAttributeBiography',
- 'ldap_profile_scope' => 'ldapProfileScope',
];
return $array;
}
diff --git a/apps/user_ldap/lib/Connection.php b/apps/user_ldap/lib/Connection.php
index 1c365ef2afc..d8d00dd4d27 100644
--- a/apps/user_ldap/lib/Connection.php
+++ b/apps/user_ldap/lib/Connection.php
@@ -82,7 +82,6 @@ use Psr\Log\LoggerInterface;
* @property string ldapAttributeRole
* @property string ldapAttributeHeadline
* @property string ldapAttributeBiography
- * @property string ldapProfileScope
*/
class Connection extends LDAPUtility {
/**
diff --git a/apps/user_ldap/lib/User/User.php b/apps/user_ldap/lib/User/User.php
index 3dd8f05a07d..915bcae8289 100644
--- a/apps/user_ldap/lib/User/User.php
+++ b/apps/user_ldap/lib/User/User.php
@@ -47,6 +47,7 @@ use OCP\IUserManager;
use OCP\Accounts\IAccountManager;
use OCP\Accounts\PropertyDoesNotExistException;
use OCP\Notification\IManager as INotificationManager;
+use OCP\Server;
use Psr\Log\LoggerInterface;
/**
@@ -236,62 +237,58 @@ class User {
}
unset($attr);
- //User profile visibility
- $profileScope = $this->connection->ldapProfileScope;
- if (empty($profileScope) || $profileScope === 'unset') {
- $profileScope = null;
- }
- $profileValues = array(); // empty array, to prevent unneccessary call to updateProfile
- //User Profile Field - Phone number
- $attr = strtolower($this->connection->ldapAttributePhone);
- if (isset($ldapEntry[$attr])) {
- $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_PHONE] = $ldapEntry[$attr][0];
- }
- //User Profile Field - website
- $attr = strtolower($this->connection->ldapAttributeWebsite);
- if (isset($ldapEntry[$attr])) {
- $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_WEBSITE] = $ldapEntry[$attr][0];
- }
- //User Profile Field - Address
- $attr = strtolower($this->connection->ldapAttributeAddress);
- if (isset($ldapEntry[$attr])) {
- $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_ADDRESS] = $ldapEntry[$attr][0];
- }
- //User Profile Field - Twitter
- $attr = strtolower($this->connection->ldapAttributeTwitter);
- if (isset($ldapEntry[$attr])) {
- $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_TWITTER] = $ldapEntry[$attr][0];
- }
- //User Profile Field - fediverse
- $attr = strtolower($this->connection->ldapAttributeFediverse);
- if (isset($ldapEntry[$attr])) {
- $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_FEDIVERSE] = $ldapEntry[$attr][0];
- }
- //User Profile Field - organisation
- $attr = strtolower($this->connection->ldapAttributeOrganisation);
- if (isset($ldapEntry[$attr])) {
- $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_ORGANISATION] = $ldapEntry[$attr][0];
- }
- //User Profile Field - role
- $attr = strtolower($this->connection->ldapAttributeRole);
- if (isset($ldapEntry[$attr])) {
- $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_ROLE] = $ldapEntry[$attr][0];
- }
- //User Profile Field - headline
- $attr = strtolower($this->connection->ldapAttributeHeadline);
- if (isset($ldapEntry[$attr])) {
- $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_HEADLINE] = $ldapEntry[$attr][0];
- }
- //User Profile Field - biography
- $attr = strtolower($this->connection->ldapAttributeBiography);
- if (isset($ldapEntry[$attr])) {
- $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_BIOGRAPHY] = $ldapEntry[$attr][0];
- }
- // Update user profile
- if(!empty($profileValues)) {
- $this->updateProfile($profileValues, $profileScope);
+ // honoring profile disabled in config.php
+ if ($this->config->getSystemValueBool('profile.enabled', true)) {
+ $profileValues = array(); // empty array, to prevent unneccessary call to updateProfile
+ //User Profile Field - Phone number
+ $attr = strtolower($this->connection->ldapAttributePhone);
+ if (isset($ldapEntry[$attr])) {
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_PHONE] = $ldapEntry[$attr][0];
+ }
+ //User Profile Field - website
+ $attr = strtolower($this->connection->ldapAttributeWebsite);
+ if (isset($ldapEntry[$attr])) {
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_WEBSITE] = $ldapEntry[$attr][0];
+ }
+ //User Profile Field - Address
+ $attr = strtolower($this->connection->ldapAttributeAddress);
+ if (isset($ldapEntry[$attr])) {
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_ADDRESS] = $ldapEntry[$attr][0];
+ }
+ //User Profile Field - Twitter
+ $attr = strtolower($this->connection->ldapAttributeTwitter);
+ if (isset($ldapEntry[$attr])) {
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_TWITTER] = $ldapEntry[$attr][0];
+ }
+ //User Profile Field - fediverse
+ $attr = strtolower($this->connection->ldapAttributeFediverse);
+ if (isset($ldapEntry[$attr])) {
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_FEDIVERSE] = $ldapEntry[$attr][0];
+ }
+ //User Profile Field - organisation
+ $attr = strtolower($this->connection->ldapAttributeOrganisation);
+ if (isset($ldapEntry[$attr])) {
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_ORGANISATION] = $ldapEntry[$attr][0];
+ }
+ //User Profile Field - role
+ $attr = strtolower($this->connection->ldapAttributeRole);
+ if (isset($ldapEntry[$attr])) {
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_ROLE] = $ldapEntry[$attr][0];
+ }
+ //User Profile Field - headline
+ $attr = strtolower($this->connection->ldapAttributeHeadline);
+ if (isset($ldapEntry[$attr])) {
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_HEADLINE] = $ldapEntry[$attr][0];
+ }
+ //User Profile Field - biography
+ $attr = strtolower($this->connection->ldapAttributeBiography);
+ if (isset($ldapEntry[$attr])) {
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_BIOGRAPHY] = $ldapEntry[$attr][0];
+ }
+ // Update user profile
+ $this->updateProfile($profileValues);
+ unset($attr);
}
- unset($attr);
//Avatar
/** @var Connection $connection */
@@ -577,25 +574,29 @@ class User {
/**
* takes values from LDAP and stores it as Nextcloud user profile value
*
- * @param array $profileValues associaive array of property keys and values from LDAP
- * @param string|null $profileScope the scope of visibility to set
+ * @param array $profileValues associative array of property keys and values from LDAP
*/
- private function updateProfile(array $profileValues, ?string $profileScope=null): void {
+ private function updateProfile(array $profileValues): void {
+ // check if given array is empty
+ if (empty($profileValues)) {
+ return; // okay, nothing to do
+ }
// check if user profile was refreshed before
if ($this->wasRefreshed('profile')) {
- return;
+ return; // okay, updated before
}
// fetch/prepare user
$user = $this->userManager->get($this->uid);
if (is_null($user)) {
- return;
+ return; // FIXME: I guess userManager::get would never return null here
}
// prepare AccountManager and Account
- $accountManager = \OC::$server->get(IAccountManager::class);
+ $accountManager = Server::get(IAccountManager::class);
$account = $accountManager->getAccount($user); // get Account
if (is_null($account)) {
- return;
+ return; // FIXME: I guess getAccount would never return null here
}
+ $defaultScopes = array_merge(AccountManager::DEFAULT_SCOPES, $this->config->getSystemValue('account_manager.default_property_scope', []));
// loop through the properties and handle them
foreach($profileValues as $property => $valueFromLDAP) {
// check and update profile properties
@@ -603,17 +604,17 @@ class User {
try {
$accountProperty = $account->getProperty($property);
$currentValue = $accountProperty->getValue();
- $scope = ($profileScope ? $profileScope : ($accountProperty->getScope() ? $accountProperty->getScope() : AccountManager::DEFAULT_SCOPES[$property]));
+ $scope = ($accountProperty->getScope() ? $accountProperty->getScope() : $defaultScopes[$property]);
}
catch (PropertyDoesNotExistException $e) { // thrown at getProperty
$this->logger->error('property does not exist: '.$property.' for uid='.$this->uid.'', ['app' => 'user_ldap', 'exception' => $e]);
$currentValue = '';
- $scope = ($profileScope ? $profileScope : AccountManager::DEFAULT_SCOPES[$property]);
+ $scope = $defaultScopes[$property];
}
$verified = IAccountManager::VERIFIED; // trust the LDAP admin knew what he put there
if ($currentValue !== $value) {
$account->setProperty($property,$value,$scope,$verified);
- $this->logger->debug('property updated: '.$property.'='.$value.' for uid='.$this->uid.'', ['app' => 'user_ldap']);
+ $this->logger->debug('update property: '.$property.'='.$value.' for uid='.$this->uid.'', ['app' => 'user_ldap']);
}
}
$accountManager->updateAccount($account);
diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php
index 805cfce7c23..916ff84b82a 100644
--- a/apps/user_ldap/templates/settings.php
+++ b/apps/user_ldap/templates/settings.php
@@ -131,7 +131,6 @@ style('user_ldap', 'settings');
-
From 1e7bc93ec8b2c39f60993f42243bb8d7f3af2235 Mon Sep 17 00:00:00 2001
From: Marc Hefter
Date: Tue, 21 Mar 2023 22:55:48 +0100
Subject: [PATCH 19/23] handling, formatting of postalAddress attribute syntax
replace '$' with ', ' delimiter for address property
reformatted some code to 80 column
early check and return, if wasRefreshed('profile')
removed FIXMEs after digging and double checking
Signed-off-by: Marc Hefter
---
apps/user_ldap/lib/User/User.php | 63 ++++++++++++++++++++------------
1 file changed, 39 insertions(+), 24 deletions(-)
diff --git a/apps/user_ldap/lib/User/User.php b/apps/user_ldap/lib/User/User.php
index 915bcae8289..f44ea8f9084 100644
--- a/apps/user_ldap/lib/User/User.php
+++ b/apps/user_ldap/lib/User/User.php
@@ -237,53 +237,69 @@ class User {
}
unset($attr);
- // honoring profile disabled in config.php
- if ($this->config->getSystemValueBool('profile.enabled', true)) {
- $profileValues = array(); // empty array, to prevent unneccessary call to updateProfile
+ // honoring profile disabled in config.php and check if user profile was refreshed
+ if ($this->config->getSystemValueBool('profile.enabled', true) &&
+ !$this->wasRefreshed('profile')) {
+ $profileValues = array();
//User Profile Field - Phone number
$attr = strtolower($this->connection->ldapAttributePhone);
if (isset($ldapEntry[$attr])) {
- $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_PHONE] = $ldapEntry[$attr][0];
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_PHONE]
+ = $ldapEntry[$attr][0];
}
//User Profile Field - website
$attr = strtolower($this->connection->ldapAttributeWebsite);
if (isset($ldapEntry[$attr])) {
- $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_WEBSITE] = $ldapEntry[$attr][0];
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_WEBSITE]
+ = $ldapEntry[$attr][0];
}
//User Profile Field - Address
$attr = strtolower($this->connection->ldapAttributeAddress);
if (isset($ldapEntry[$attr])) {
- $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_ADDRESS] = $ldapEntry[$attr][0];
+ // basic format conversion from postalAddress syntax to comma delimited
+ if (str_contains($ldapEntry[$attr][0],'$')) {
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_ADDRESS]
+ = str_replace('$', ", ", $ldapEntry[$attr][0]);
+ } else {
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_ADDRESS]
+ = $ldapEntry[$attr][0];
+ }
}
//User Profile Field - Twitter
$attr = strtolower($this->connection->ldapAttributeTwitter);
if (isset($ldapEntry[$attr])) {
- $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_TWITTER] = $ldapEntry[$attr][0];
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_TWITTER]
+ = $ldapEntry[$attr][0];
}
//User Profile Field - fediverse
$attr = strtolower($this->connection->ldapAttributeFediverse);
if (isset($ldapEntry[$attr])) {
- $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_FEDIVERSE] = $ldapEntry[$attr][0];
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_FEDIVERSE]
+ = $ldapEntry[$attr][0];
}
//User Profile Field - organisation
$attr = strtolower($this->connection->ldapAttributeOrganisation);
if (isset($ldapEntry[$attr])) {
- $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_ORGANISATION] = $ldapEntry[$attr][0];
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_ORGANISATION]
+ = $ldapEntry[$attr][0];
}
//User Profile Field - role
$attr = strtolower($this->connection->ldapAttributeRole);
if (isset($ldapEntry[$attr])) {
- $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_ROLE] = $ldapEntry[$attr][0];
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_ROLE]
+ = $ldapEntry[$attr][0];
}
//User Profile Field - headline
$attr = strtolower($this->connection->ldapAttributeHeadline);
if (isset($ldapEntry[$attr])) {
- $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_HEADLINE] = $ldapEntry[$attr][0];
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_HEADLINE]
+ = $ldapEntry[$attr][0];
}
//User Profile Field - biography
$attr = strtolower($this->connection->ldapAttributeBiography);
if (isset($ldapEntry[$attr])) {
- $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_BIOGRAPHY] = $ldapEntry[$attr][0];
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_BIOGRAPHY]
+ = $ldapEntry[$attr][0];
}
// Update user profile
$this->updateProfile($profileValues);
@@ -581,22 +597,17 @@ class User {
if (empty($profileValues)) {
return; // okay, nothing to do
}
- // check if user profile was refreshed before
- if ($this->wasRefreshed('profile')) {
- return; // okay, updated before
- }
// fetch/prepare user
$user = $this->userManager->get($this->uid);
if (is_null($user)) {
- return; // FIXME: I guess userManager::get would never return null here
+ $this->logger->error('could not get user for uid='.$this->uid.'', ['app' => 'user_ldap']);
+ return;
}
// prepare AccountManager and Account
$accountManager = Server::get(IAccountManager::class);
$account = $accountManager->getAccount($user); // get Account
- if (is_null($account)) {
- return; // FIXME: I guess getAccount would never return null here
- }
- $defaultScopes = array_merge(AccountManager::DEFAULT_SCOPES, $this->config->getSystemValue('account_manager.default_property_scope', []));
+ $defaultScopes = array_merge(AccountManager::DEFAULT_SCOPES,
+ $this->config->getSystemValue('account_manager.default_property_scope', []));
// loop through the properties and handle them
foreach($profileValues as $property => $valueFromLDAP) {
// check and update profile properties
@@ -604,17 +615,21 @@ class User {
try {
$accountProperty = $account->getProperty($property);
$currentValue = $accountProperty->getValue();
- $scope = ($accountProperty->getScope() ? $accountProperty->getScope() : $defaultScopes[$property]);
+ $scope = ($accountProperty->getScope() ? $accountProperty->getScope()
+ : $defaultScopes[$property]);
}
catch (PropertyDoesNotExistException $e) { // thrown at getProperty
- $this->logger->error('property does not exist: '.$property.' for uid='.$this->uid.'', ['app' => 'user_ldap', 'exception' => $e]);
+ $this->logger->error('property does not exist: '.$property
+ .' for uid='.$this->uid.''
+ , ['app' => 'user_ldap', 'exception' => $e]);
$currentValue = '';
$scope = $defaultScopes[$property];
}
$verified = IAccountManager::VERIFIED; // trust the LDAP admin knew what he put there
if ($currentValue !== $value) {
$account->setProperty($property,$value,$scope,$verified);
- $this->logger->debug('update property: '.$property.'='.$value.' for uid='.$this->uid.'', ['app' => 'user_ldap']);
+ $this->logger->debug('update user profile: '.$property.'='.$value
+ .' for uid='.$this->uid.'', ['app' => 'user_ldap']);
}
}
$accountManager->updateAccount($account);
From 72d0a3f26e41b5edb0521cf61bc87d6c08389ced Mon Sep 17 00:00:00 2001
From: Marc Hefter
Date: Sun, 26 Mar 2023 20:13:20 +0200
Subject: [PATCH 20/23] added simple data conversion for LDAP attributes
Signed-off-by: Marc Hefter
---
apps/user_ldap/lib/User/User.php | 26 +++++++++++++++++++-------
1 file changed, 19 insertions(+), 7 deletions(-)
diff --git a/apps/user_ldap/lib/User/User.php b/apps/user_ldap/lib/User/User.php
index f44ea8f9084..6c38cba7039 100644
--- a/apps/user_ldap/lib/User/User.php
+++ b/apps/user_ldap/lib/User/User.php
@@ -250,14 +250,20 @@ class User {
//User Profile Field - website
$attr = strtolower($this->connection->ldapAttributeWebsite);
if (isset($ldapEntry[$attr])) {
- $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_WEBSITE]
- = $ldapEntry[$attr][0];
+ if (str_contains($ldapEntry[$attr][0],' ')) {
+ // drop appended label
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_WEBSITE]
+ = substr($ldapEntry[$attr][0],0,strpos($ldapEntry[$attr][0]," "));
+ } else {
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_WEBSITE]
+ = $ldapEntry[$attr][0];
+ }
}
//User Profile Field - Address
$attr = strtolower($this->connection->ldapAttributeAddress);
if (isset($ldapEntry[$attr])) {
- // basic format conversion from postalAddress syntax to comma delimited
if (str_contains($ldapEntry[$attr][0],'$')) {
+ // basic format conversion from postalAddress syntax to commata delimited
$profileValues[\OCP\Accounts\IAccountManager::PROPERTY_ADDRESS]
= str_replace('$', ", ", $ldapEntry[$attr][0]);
} else {
@@ -298,8 +304,14 @@ class User {
//User Profile Field - biography
$attr = strtolower($this->connection->ldapAttributeBiography);
if (isset($ldapEntry[$attr])) {
- $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_BIOGRAPHY]
- = $ldapEntry[$attr][0];
+ if (str_contains($ldapEntry[$attr][0],'\r')) {
+ // convert line endings
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_BIOGRAPHY]
+ = str_replace(array("\r\n","\r"), "\n", $ldapEntry[$attr][0]);
+ } else {
+ $profileValues[\OCP\Accounts\IAccountManager::PROPERTY_BIOGRAPHY]
+ = $ldapEntry[$attr][0];
+ }
}
// Update user profile
$this->updateProfile($profileValues);
@@ -481,7 +493,7 @@ class User {
* @brief checks whether an update method specified by feature was run
* already. If not, it will marked like this, because it is expected that
* the method will be run, when false is returned.
- * @param string $feature email | quota | avatar (can be extended)
+ * @param string $feature email | quota | avatar | profile (can be extended)
* @return bool
*/
private function wasRefreshed($feature) {
@@ -632,7 +644,7 @@ class User {
.' for uid='.$this->uid.'', ['app' => 'user_ldap']);
}
}
- $accountManager->updateAccount($account);
+ $accountManager->updateAccount($account); // may throw InvalidArgumentException
}
/**
From ebb0c53f9e271cc0036c5f5c8d6316722a78b33c Mon Sep 17 00:00:00 2001
From: Marc Hefter
Date: Fri, 31 Mar 2023 11:42:11 +0200
Subject: [PATCH 21/23] trying to make github-code-scanning bot happy
Signed-off-by: Marc Hefter
---
apps/user_ldap/lib/User/User.php | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/apps/user_ldap/lib/User/User.php b/apps/user_ldap/lib/User/User.php
index 6c38cba7039..f6a2d037ea7 100644
--- a/apps/user_ldap/lib/User/User.php
+++ b/apps/user_ldap/lib/User/User.php
@@ -250,10 +250,11 @@ class User {
//User Profile Field - website
$attr = strtolower($this->connection->ldapAttributeWebsite);
if (isset($ldapEntry[$attr])) {
- if (str_contains($ldapEntry[$attr][0],' ')) {
+ $cutPosition = strpos($ldapEntry[$attr][0]," ");
+ if ($cutPosition) {
// drop appended label
$profileValues[\OCP\Accounts\IAccountManager::PROPERTY_WEBSITE]
- = substr($ldapEntry[$attr][0],0,strpos($ldapEntry[$attr][0]," "));
+ = substr($ldapEntry[$attr][0],0,$cutPosition);
} else {
$profileValues[\OCP\Accounts\IAccountManager::PROPERTY_WEBSITE]
= $ldapEntry[$attr][0];
From eec5e702da5ce7e6a65adb56ad611aee4c97f718 Mon Sep 17 00:00:00 2001
From: Marc Hefter
Date: Tue, 11 Apr 2023 16:40:00 +0200
Subject: [PATCH 22/23] error handling in update profile from LDAP
added error message on InvalidArgumentException
Signed-off-by: Marc Hefter
---
apps/user_ldap/lib/User/User.php | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/apps/user_ldap/lib/User/User.php b/apps/user_ldap/lib/User/User.php
index f6a2d037ea7..8685ba0c60a 100644
--- a/apps/user_ldap/lib/User/User.php
+++ b/apps/user_ldap/lib/User/User.php
@@ -645,7 +645,13 @@ class User {
.' for uid='.$this->uid.'', ['app' => 'user_ldap']);
}
}
- $accountManager->updateAccount($account); // may throw InvalidArgumentException
+ try {
+ $accountManager->updateAccount($account); // may throw InvalidArgumentException
+ } catch (\InvalidArgumentException $e) {
+ $this->logger->error('invalid data from LDAP: for uid='.$this->uid.''
+ , ['app' => 'user_ldap', 'func' => 'updateProfile'
+ , 'exception' => $e]);
+ }
}
/**
From 64914593a0b3157a67621188a062e722b34976bd Mon Sep 17 00:00:00 2001
From: Marc Hefter
Date: Fri, 14 Apr 2023 11:08:46 +0200
Subject: [PATCH 23/23] optimized handling of user profile data change
Check profile data checksum before updating user profile, to ensure
data has changed. Write checksum to user settings and cache.
Signed-off-by: Marc Hefter
---
apps/user_ldap/lib/User/User.php | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/apps/user_ldap/lib/User/User.php b/apps/user_ldap/lib/User/User.php
index 8685ba0c60a..f6a3bf70792 100644
--- a/apps/user_ldap/lib/User/User.php
+++ b/apps/user_ldap/lib/User/User.php
@@ -237,9 +237,15 @@ class User {
}
unset($attr);
+ // check for cached profile data
+ $username = $this->getUsername(); // buffer variable, to save resource
+ $cacheKey = 'getUserProfile-'.$username;
+ $profileCached = $this->connection->getFromCache($cacheKey);
// honoring profile disabled in config.php and check if user profile was refreshed
if ($this->config->getSystemValueBool('profile.enabled', true) &&
+ ($profileCached === null) && // no cache or TTL not expired
!$this->wasRefreshed('profile')) {
+ // check current data
$profileValues = array();
//User Profile Field - Phone number
$attr = strtolower($this->connection->ldapAttributePhone);
@@ -314,9 +320,25 @@ class User {
= $ldapEntry[$attr][0];
}
}
+ // check for changed data and cache just for TTL checking
+ $checksum = hash('sha256', json_encode($profileValues));
+ $this->connection->writeToCache($cacheKey
+ , $checksum // write array to cache. is waste of cache space
+ , null); // use ldapCacheTTL from configuration
// Update user profile
- $this->updateProfile($profileValues);
+ if ($this->config->getUserValue($username, 'user_ldap', 'lastProfileChecksum', null) !== $checksum) {
+ $this->config->setUserValue($username, 'user_ldap', 'lastProfileChecksum', $checksum);
+ $this->updateProfile($profileValues);
+ $this->logger->info("updated profile uid=$username"
+ , ['app' => 'user_ldap']);
+ } else {
+ $this->logger->debug("profile data from LDAP unchanged"
+ , ['app' => 'user_ldap', 'uid' => $username]);
+ }
unset($attr);
+ } elseif ($profileCached !== null) { // message delayed, to declutter log
+ $this->logger->debug("skipping profile check, while cached data exist"
+ , ['app' => 'user_ldap', 'uid' => $username]);
}
//Avatar