owncloud/core

View on GitHub
apps/files_sharing/lib/Controller/NotificationController.php

Summary

Maintainability
B
6 hrs
Test Coverage
<?php
/**
 * @author Semih Serhat Karakaya <karakayasemi@itu.edu.tr>
 *
 * @copyright Copyright (c) 2019, ownCloud GmbH
 * @license AGPL-3.0
 *
 * This code is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License, version 3,
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License, version 3,
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 *
 */

namespace OCA\Files_Sharing\Controller;

use OC\OCS\Result;
use OC\Security\TrustedDomainHelper;
use OC\Share\MailNotifications;
use OCP\AppFramework\OCSController;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\IGroupManager;
use OCP\IL10N;
use OCP\IRequest;
use OCP\IUser;
use OCP\IUserManager;
use OCP\IUserSession;
use OCP\Share;
use OCP\Share\Exceptions\GenericShareException;

class NotificationController extends OCSController {
    /** @var MailNotifications */
    private $mailNotifications;
    /** @var IUserSession */
    private $userSession;
    /** @var IUserManager */
    private $userManager;
    /** @var IGroupManager */
    private $groupManager;
    /** @var IRootFolder */
    private $rootFolder;
    /** @var IL10N */
    private $l;
    private TrustedDomainHelper $trustedDomainHelper;

    public function __construct(
        string $appName,
        IRequest $request,
        MailNotifications $mailNotifications,
        IUserSession $userSession,
        IUserManager $userManager,
        IGroupManager $groupManager,
        IRootFolder $rootFolder,
        IL10N $l,
        TrustedDomainHelper $trustedDomainHelper
    ) {
        parent::__construct($appName, $request);
        $this->mailNotifications = $mailNotifications;
        $this->userSession = $userSession;
        $this->userManager = $userManager;
        $this->groupManager = $groupManager;
        $this->rootFolder = $rootFolder;
        $this->l = $l;
        $this->trustedDomainHelper = $trustedDomainHelper;
    }

    /**
     * @NoCSRFRequired
     * @NoAdminRequired
     *
     * @param string $link URL of the shared link
     * @param string[] $recipients
     * @param string $personalNote Sender's personal note about share
     * @return Result
     */
    public function notifyPublicLinkRecipientsByEmail($link, $recipients, $personalNote) {
        # verify that the link is for a trusted domain
        if (!$this->trustedDomainHelper->isUrlTrusted($link)) {
            return new Result(null, 400, "Invalid shared link");
        }

        $message = null;
        $code = 100;
        $sender = $this->userSession->getUser();
        $result = $recipients;
        if ($sender) {
            try {
                $result = $this->mailNotifications->sendLinkShareMail(
                    $sender,
                    $recipients,
                    $link,
                    $personalNote
                );
            } catch (GenericShareException | NotFoundException $e) {
                $code = $e->getCode() === 0 ? 403 : $e->getCode();
                return new Result(null, $code, $e->getHint());
            }
        }
        if (!empty($result)) {
            $message = $this->l->t(
                "Couldn't send mail to following recipient(s): %s ",
                \implode(', ', $result)
            );
            $code = 400;
        }
        return new Result(null, $code, $message);
    }

    /**
     * Send a notification to share recipient(s)
     *
     * @NoCSRFRequired
     * @NoAdminRequired
     *
     * @param int $itemSource
     * @param string $itemType
     * @param int $shareType
     * @param string $recipient
     *
     * @return Result
     */
    public function notifyRecipients($itemSource, $itemType, $shareType, $recipient) {
        $recipientList = [];
        $sender = $this->userSession->getUser();
        if ($shareType === Share::SHARE_TYPE_USER) {
            $recipientList[] = $this->userManager->get($recipient);
        } elseif ($shareType === Share::SHARE_TYPE_GROUP) {
            $group = $this->groupManager->get($recipient);
            $recipientList = $group->searchUsers('');
        }
        // don't send a mail to the user who shared the file
        $recipientList = \array_filter($recipientList, function ($user) {
            /** @var IUser $user */
            return $user->getUID() !== $this->userSession->getUser()->getUID();
        });

        $userFolder = $this->rootFolder->getUserFolder($sender->getUID());
        $nodes = $userFolder->getById($itemSource, true);
        $node = $nodes[0] ?? null;
        try {
            $result = $this->mailNotifications->sendInternalShareMail($sender, $node, $shareType, $recipientList);
        } catch (GenericShareException $e) {
            $code = $e->getCode() === 0 ? 403 : $e->getCode();
            return new Result(null, $code, $e->getHint());
        }

        // if we were able to send to at least one recipient, mark as sent
        // allowing the user to resend would spam users who already got a notification
        if (\count($result) < \count($recipientList)) {
            // FIXME: migrate to a new share API
            Share::setSendMailStatus($itemType, $itemSource, $shareType, $recipient, true);
        }

        if (empty($result)) {
            $message = null;
            $data = ['status' => 'success'];
        } else {
            $message = $this->l->t(
                "Couldn't send mail to following recipient(s): %s ",
                \implode(', ', $result)
            );
            $data = ['status' => 'error'];
        }
        return new Result($data, 200, $message);
    }

    /**
     * Just mark a notification to share recipient(s) as sent
     *
     * @NoCSRFRequired
     * @NoAdminRequired
     *
     * @param int $itemSource
     * @param string $itemType
     * @param int $shareType
     * @param string $recipient
     *
     * @return Result
     */
    public function notifyRecipientsDisabled($itemSource, $itemType, $shareType, $recipient) {
        // FIXME: migrate to a new share API
        Share::setSendMailStatus($itemType, $itemSource, $shareType, $recipient, true);
        return new Result(['status' => 'success']);
    }
}