diff --git a/appinfo/info.xml b/appinfo/info.xml
index e9d62deb4b5b81294fb0f8b75f61970037ae3846..2803cce99977bfc705dac0e84e01551395f02448 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -10,7 +10,7 @@
- 1.2.0
+ 2.0.0
agpl
Akhil Potukuchi
EcloudAccounts
diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php
index 799c6b78458b6dc80670397773466cee3d54d662..cc21683232c52632782abfcb5c60ba2f66c3dba4 100644
--- a/lib/AppInfo/Application.php
+++ b/lib/AppInfo/Application.php
@@ -32,10 +32,14 @@ use OCP\AppFramework\Bootstrap\IBootstrap;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
use OCP\AppFramework\Bootstrap\IBootContext;
use OCP\User\Events\UserDeletedEvent;
-use OCP\User\Events\UserChangedEvent;
use OCA\EcloudAccounts\Listeners\UserDeletedListener;
+use OCA\EcloudAccounts\Listeners\BeforeUserDeletedListener;
+use OCA\EcloudAccounts\Service\LDAPConnectionService;
+use OCP\User\Events\BeforeUserDeletedEvent;
+use OCP\User\Events\UserChangedEvent;
use OCA\EcloudAccounts\Listeners\UserChangedListener;
+
class Application extends App implements IBootstrap
{
@@ -49,10 +53,15 @@ class Application extends App implements IBootstrap
public function register(IRegistrationContext $context): void
{
$context->registerEventListener(UserDeletedEvent::class, UserDeletedListener::class);
+ $context->registerEventListener(BeforeUserDeletedEvent::class, BeforeUserDeletedListener::class);
$context->registerEventListener(UserChangedEvent::class, UserChangedListener::class);
}
public function boot(IBootContext $context): void
{
+ $serverContainer = $context->getServerContainer();
+ $serverContainer->registerService('LDAPConnectionService', function($c) {
+ return new LDAPConnectionService();
+ });
}
}
diff --git a/lib/Listeners/BeforeUserDeletedListener.php b/lib/Listeners/BeforeUserDeletedListener.php
new file mode 100644
index 0000000000000000000000000000000000000000..0ca586cb320a7b5097cd7e11bb2eee0bb37d51d2
--- /dev/null
+++ b/lib/Listeners/BeforeUserDeletedListener.php
@@ -0,0 +1,76 @@
+logger = $logger;
+ $this->LDAPConnectionService = $LDAPConnectionService;
+ }
+
+
+ public function handle(Event $event): void
+ {
+ if (!($event instanceof BeforeUserDeletedEvent)) {
+ return;
+ }
+
+ $user = $event->getUser();
+ $email = $user->getEMailAddress();
+ $uid = $user->getUID();
+
+ try {
+ if ($this->LDAPConnectionService->isLDAPEnabled() && $this->LDAPConnectionService->isUserOnLDAPBackend($user)) {
+ $conn = $this->LDAPConnectionService->getLDAPConnection($uid);
+ $this->deleteAliasEntries($conn, $email);
+ $this->LDAPConnectionService->closeLDAPConnection($conn);
+ }
+ } catch (Exception $e) {
+ $this->logger->error('Error deleting aliases for user '. $uid . ' :' . $e->getMessage());
+ }
+ }
+
+ private function deleteAliasEntries($conn, string $email)
+ {
+ $aliasBaseDn = getenv('LDAP_ALIASES_BASE_DN');
+ $aliasDns = $this->getAliasEntries($conn, $aliasBaseDn, $email);
+ foreach ($aliasDns as $aliasDn) {
+ $deleted = ldap_delete($conn, $aliasDn);
+ if (!$deleted) {
+ $this->logger->error('Deleting alias ' . $aliasDn . ' for email ' . $email . ' failed');
+ }
+ }
+ }
+
+ private function getAliasEntries($conn, string $aliasBaseDn, string $email) : array
+ {
+ $filter = "(mailAddress=$email)";
+ $aliasEntries = ldap_search($conn, $aliasBaseDn, $filter);
+ if (!$aliasEntries) {
+ return [];
+ }
+
+ $aliasEntries = ldap_get_entries($conn, $aliasEntries);
+ $aliasEntries = array_filter($aliasEntries, fn ($entry) => is_array($entry));
+ $aliasEntries = array_map(
+ fn ($entry) => $entry['dn'],
+ $aliasEntries
+ );
+
+ return $aliasEntries;
+ }
+}
diff --git a/lib/Listeners/UserChangedListener.php b/lib/Listeners/UserChangedListener.php
index c62e254159a20e9f7d9cdf5e9303ca42b81977e8..40c782c251c74ca7f787e562f41a624b4fe9b5ff 100644
--- a/lib/Listeners/UserChangedListener.php
+++ b/lib/Listeners/UserChangedListener.php
@@ -4,25 +4,33 @@ declare(strict_types=1);
namespace OCA\EcloudAccounts\Listeners;
+use Exception;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\Util;
+use OCP\ILogger;
use OCP\User\Events\UserChangedEvent;
use OCA\EcloudAccounts\Db\MailboxMapper;
+use OCA\EcloudAccounts\Service\LDAPConnectionService;
class UserChangedListener implements IEventListener
{
-
private const QUOTA_FEATURE = 'quota';
private $util;
+ private $logger;
+
+ private $ldapConnectionService;
+
private $mailboxMapper;
- public function __construct(Util $util, MailboxMapper $mailboxMapper)
+ public function __construct(Util $util, LDAPConnectionService $LDAPConnectionService, ILogger $logger, MailboxMapper $mailboxMapper)
{
$this->util = $util;
+ $this->ldapConnectionService = $LDAPConnectionService;
$this->mailboxMapper = $mailboxMapper;
+ $this->logger = $logger;
}
public function handle(Event $event): void
@@ -36,12 +44,38 @@ class UserChangedListener implements IEventListener
if ($feature !== self::QUOTA_FEATURE) {
return;
}
-
$user = $event->getUser();
$username = $user->getUID();
$updatedQuota = $event->getValue();
-
$quotaInBytes = (int) $this->util->computerFileSize($updatedQuota);
- $this->mailboxMapper->updateMailboxQuota($username, $quotaInBytes);
+ $backend = $user->getBackend()->getBackendName();
+
+ try {
+ if ($backend === 'SQL raw') {
+ $this->mailboxMapper->updateMailboxQuota($username, $quotaInBytes);
+ }
+ if ($backend === 'LDAP') {
+ $this->updateQuotaInLDAP($username, $quotaInBytes);
+ }
+ } catch (Exception $e) {
+ $this->logger->error("Error setting quota for user $username " . $e->getMessage());
+ }
+ }
+
+ private function updateQuotaInLDAP(string $username, int $quota)
+ {
+ if ($this->ldapConnectionService->isLDAPEnabled()) {
+ $conn = $this->ldapConnectionService->getLDAPConnection();
+ $userDn = $this->ldapConnectionService->username2dn($username);
+
+ $entry = [
+ 'quota' => $quota
+ ];
+
+ if (!ldap_modify($conn, $userDn, $entry)) {
+ throw new Exception('Could not modify user entry at LDAP server!');
+ }
+ $this->ldapConnectionService->closeLDAPConnection($conn);
+ }
}
}
diff --git a/lib/Listeners/UserDeletedListener.php b/lib/Listeners/UserDeletedListener.php
index 25e98359fec52d0c6c2326f914aa438fa0e872c6..6e63f56838fe24a6429e48589ec446014b05d5ea 100644
--- a/lib/Listeners/UserDeletedListener.php
+++ b/lib/Listeners/UserDeletedListener.php
@@ -5,39 +5,47 @@ declare(strict_types=1);
namespace OCA\EcloudAccounts\Listeners;
use Curl;
+use Exception;
use OCA\EcloudAccounts\AppInfo\Application;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\IConfig;
use OCP\ILogger;
use OCP\User\Events\UserDeletedEvent;
+use OCA\EcloudAccounts\Service\LDAPConnectionService;
require_once 'curl.class.php';
class UserDeletedListener implements IEventListener
{
-
private $logger;
private $config;
+ private $ldapConnectionService;
- public function __construct(ILogger $logger, IConfig $config)
+ public function __construct(ILogger $logger, IConfig $config, LDAPConnectionService $LDAPConnectionService)
{
$this->logger = $logger;
$this->config = $config;
+ $this->ldapConnectionService = $LDAPConnectionService;
}
+
public function handle(Event $event): void
{
if (!($event instanceof UserDeletedEvent)) {
return;
}
- $uid = $event->getUser()->getUID();
+ $user = $event->getUser();
+ $uid = $user->getUID();
+ $isUserOnLDAP = $this->ldapConnectionService->isUserOnLDAPBackend($user);
+
$this->logger->info("PostDelete user {user}", array('user' => $uid));
$this->ecloudDelete(
$uid,
$this->config->getSystemValue('e_welcome_domain'),
- $this->config->getSystemValue('e_welcome_secret')
+ $this->config->getSystemValue('e_welcome_secret'),
+ $isUserOnLDAP
);
}
@@ -51,10 +59,13 @@ class UserDeletedListener implements IEventListener
* @param $welcomeSecret string generated at ecloud selfhosting install and added as a custom var in NC's config
* @return mixed response of the external endpoint
*/
- public function ecloudDelete(string $userID, string $welcomeDomain, string $welcomeSecret)
+ public function ecloudDelete(string $userID, string $welcomeDomain, string $welcomeSecret, bool $isUserOnLDAP = false)
{
-
- $postDeleteUrl = "https://" . $welcomeDomain . "/postDelete.php";
+ $endpoint = 'postDelete.php';
+ if($isUserOnLDAP) {
+ $endpoint = 'postDeleteLDAP.php';
+ }
+ $postDeleteUrl = "https://" . $welcomeDomain . $endpoint;
$curl = new Curl();
/**
@@ -62,7 +73,6 @@ class UserDeletedListener implements IEventListener
* Handling the non NC part of deletion process
*/
try {
-
$headers = array(
'Content-Type: application/json'
);
diff --git a/lib/Service/LDAPConnectionService.php b/lib/Service/LDAPConnectionService.php
new file mode 100644
index 0000000000000000000000000000000000000000..dc0ee7b284c13ccc310a2011aec178e91510c679
--- /dev/null
+++ b/lib/Service/LDAPConnectionService.php
@@ -0,0 +1,96 @@
+userManager = $userManager;
+ $this->getConfigurationFromBackend();
+ }
+
+
+ private function getConfigurationFromBackend()
+ {
+ // We don't actually need user id to get access from backend
+ $uid = '';
+ $backends = $this->userManager->getBackends();
+ foreach ($backends as $backend) {
+ if ($backend->getBackendName() === 'LDAP') {
+ $this->access = $backend->getLDAPAccess($uid);
+ $connection = $this->access->getConnection();
+ $configuration = $connection->getConfiguration();
+
+ if ($configuration['ldap_configuration_active']) {
+ $this->ldapEnabled = true;
+ $this->configuration = $configuration;
+ break;
+ }
+ }
+ }
+ }
+
+ public function isUserOnLDAPBackend($user) {
+ $backend = $user->getBackend();
+ return $backend->getBackendName() === 'LDAP';
+ }
+
+ public function isLDAPEnabled() : bool {
+ return $this->ldapEnabled;
+ }
+
+ public function username2dn(string $username) {
+ return $this->access->username2dn($username);
+ }
+
+
+ public function getUserBaseDn() : string
+ {
+ if (isset($this->configuration['ldap_base_users'])) {
+ return $this->configuration['ldap_base_users'];
+ }
+ throw new Exception('User Base Dn not set!');
+ }
+
+ public function getLDAPConnection()
+ {
+ if(!$this->ldapEnabled) {
+ throw new Exception('LDAP backend is not enabled');
+ }
+
+ $adminDn = $this->configuration['ldap_dn'];
+ $adminPassword = $this->configuration['ldap_agent_password'];
+ $host = $this->configuration['ldap_host'];
+ $port = intval($this->configuration['ldap_port']);
+
+ $conn = ldap_connect($host, $port);
+ ldap_set_option($conn, LDAP_OPT_PROTOCOL_VERSION, 3);
+ ldap_bind($conn, $adminDn, $adminPassword);
+
+ if (!$conn) {
+ throw new Exception('Could not connect to LDAP server!');
+ }
+ return $conn;
+ }
+
+ public function closeLDAPConnection($conn) : void
+ {
+ ldap_close($conn);
+ }
+}
diff --git a/lib/Service/UserService.php b/lib/Service/UserService.php
index 0b8610a110b02cd5d5edbe868061fb5f2a826376..f32a1256a76475fb73350751e707d549f4bf3a20 100644
--- a/lib/Service/UserService.php
+++ b/lib/Service/UserService.php
@@ -40,7 +40,22 @@ class UserService
public function userExists(string $uid): bool
{
- return $this->userManager->userExists($uid);
+ $exists = $this->userManager->userExists($uid);
+ if ($exists) {
+ return $exists;
+ }
+
+ $backends = $this->userManager->getBackends();
+ foreach ($backends as $backend) {
+ if ($backend->getBackendName() === 'LDAP') {
+ $access = $backend->getLDAPAccess($uid);
+ $users = $access->fetchUsersByLoginName($uid) ;
+ if (count($users) > 0) {
+ $exists = true;
+ }
+ }
+ }
+ return $exists;
}
public function getUser(string $uid): ?IUser
@@ -75,8 +90,8 @@ class UserService
try {
$this->config->setUserValue($uid, 'hide-my-email', 'email-aliases', $aliases);
return true;
- } catch(UnexpectedValueException $e) {
+ } catch (UnexpectedValueException $e) {
return false;
- }
+ }
}
}