Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6f5c7bd0 authored by Akhil's avatar Akhil 🙂 Committed by Arnau Vàzquez
Browse files

Check if user exists using LDAP backend method

parent f1c81430
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -10,7 +10,7 @@
    <description><![CDATA[in /e/ cloud self-hosting setup, nextcloud accounts are linked to mail accounts and some other things. This app sets the mail, quota and storage of the user upon creation. 
    It also completes the account deletion by cleaning other parts of the /e/ cloud setup to ensure no more data is retained when a user requests an account deletion.
    This app uses the UserDeletedEvent to invoke scripts in the docker-welcome container of /e/ cloud setup]]></description>
    <version>1.2.0</version>
    <version>2.0.0</version>
    <licence>agpl</licence>
    <author mail="dev@e.email" homepage="https://gitlab.e.foundation/">Akhil Potukuchi</author>
    <namespace>EcloudAccounts</namespace>
+10 −1
Original line number Diff line number Diff line
@@ -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();
        });
    }
}
+76 −0
Original line number Diff line number Diff line
<?php

declare(strict_types=1);

namespace OCA\EcloudAccounts\Listeners;

use Exception;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\ILogger;
use OCP\User\Events\BeforeUserDeletedEvent;
use OCA\EcloudAccounts\Service\LDAPConnectionService;

class BeforeUserDeletedListener implements IEventListener
{
    private $logger;
    private $LDAPConnectionService;

    public function __construct(ILogger $logger, LDAPConnectionService $LDAPConnectionService)
    {
        $this->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;
    }
}
+39 −5
Original line number Diff line number Diff line
@@ -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);
        $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);
        }
    }
}
+18 −8
Original line number Diff line number Diff line
@@ -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'
            );
Loading