Commit 48517d29 authored by Sonia Zorba's avatar Sonia Zorba
Browse files

Made join working with consecutive logins

parent 0894eff3
Loading
Loading
Loading
Loading

classes/MailBodyBuilder.php

deleted100644 → 0
+0 −160
Original line number Original line Diff line number Diff line
<?php

namespace RAP;

/**
 * This class is used to build an e-mail message body both in HTML and in its
 * equivalent plaintext.
 */
class MailBodyBuilder {

    private $htmlBody;
    private $textBody;
    private $openedHTMLTags;
    private $editable;

    function __construct() {
        $this->htmlBody = "";
        $this->textBody = "";
        $this->openedHTMLTags = [];
        $this->editable = true;
    }

    private function checkEditable() {
        if (!$this->editable) {
            throw new \Exception("You cannot edit the body after it has been generated");
        }
    }

    public function addText($text) {
        $this->checkEditable();
        $this->htmlBody .= $text;
        $this->textBody .= $text;
        return $this;
    }

    public function addLineBreak() {
        $this->checkEditable();
        $this->htmlBody .= "<br>\n";
        $this->textBody .= "\n";
        return $this;
    }

    public function addHr() {
        $this->checkEditable();
        $this->htmlBody .= "<hr/>\n";
        $this->textBody .= "\n---------------------\n";
        return $this;
    }

    public function addLinkWithDescription($url, $text) {
        $this->checkEditable();
        $this->htmlBody .= '<a href="' . $url . '" target="blank_">' . $text . "</a>\n";
        $this->textBody .= $text . " ( " . $url . " ) ";
        return $this;
    }

    public function addLink($url) {
        $this->checkEditable();
        $this->htmlBody .= '<a href="' . $url . '" target="blank_">' . $url . "</a>\n";
        $this->textBody .= $url . " ";
        return $this;
    }

    public function addEmailAddress($email, $description) {
        $this->checkEditable();
        $this->htmlBody .= '<a href="mailto:' . $email . '">' . $description . '</a>';
        $this->textBody .= $description . " (" . $email . ")";
        return $this;
    }

    private function openHTMLTag($tag, $equivalentPlainText) {
        $this->checkEditable();
        if (in_array($tag, $this->openedHTMLTags)) {
            throw new \Exception("You are already inside a " . $tag . " tag!");
        }
        $this->openedHTMLTags[] = $tag;
        $this->htmlBody .= "<" . $tag . ">";
        $this->textBody .= $equivalentPlainText;
        return $this;
    }

    private function closeHTMLTag($tag, $equivalentPlainText) {
        $this->checkEditable();
        if ($this->openedHTMLTags[count($this->openedHTMLTags) - 1] !== $tag) {
            throw new \Exception("You are not inside a " . $tag . " tag!");
        }
        array_pop($this->openedHTMLTags);
        $this->htmlBody .= "</" . $tag . ">";
        $this->textBody .= $equivalentPlainText;
        return $this;
    }

    public function startBold() {
        return $this->openHTMLTag("strong", "*");
    }

    public function endBold() {
        return $this->closeHTMLTag("strong", "*");
    }

    public function startParagraph() {
        return $this->openHTMLTag("p", "");
    }

    public function endParagraph() {
        return $this->closeHTMLTag("p", "\n");
    }

    public function startList() {
        return $this->openHTMLTag("ul", "\n");
    }

    public function startListItem() {
        return $this->openHTMLTag("li", " * ");
    }

    public function endListItem() {
        return $this->closeHTMLTag("li", "\n");
    }

    public function endList() {
        return $this->closeHTMLTag("ul", "\n");
    }

    private function checkEnd() {
        if (count($this->openedHTMLTags) > 0) {
            $unclosedTags = "";
            foreach ($this->openedHTMLTags as $tag) {
                $unclosedTags .= $tag . " ";
            }
            throw new \Exception("You must close all tags before generating email body! Unclosed tags: " . $unclosedTags);
        }
    }

    private function setCompatibleLineBreaks($value) {
        return str_replace("\n", "\n\r", $value);
    }

    private function finalizeBodyIfNecessary() {
        if ($this->editable) {
            $this->checkEnd();

            $this->htmlBody = $this->setCompatibleLineBreaks($this->htmlBody);
            $this->textBody = $this->setCompatibleLineBreaks($this->textBody);

            $this->editable = false;
        }
    }

    public function getTextPlainBody() {
        $this->finalizeBodyIfNecessary();
        return $this->textBody;
    }

    public function getHTMLBody() {
        $this->finalizeBodyIfNecessary();
        return $this->htmlBody;
    }

}

classes/MailSender.php

deleted100644 → 0
+0 −144
Original line number Original line Diff line number Diff line
<?php

/* ----------------------------------------------------------------------------
 *               INAF - National Institute for Astrophysics
 *               IRA  - Radioastronomical Institute - Bologna
 *               OATS - Astronomical Observatory - Trieste
 * ----------------------------------------------------------------------------
 *
 * Copyright (C) 2016 Istituto Nazionale di Astrofisica
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU 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 General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 51
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

namespace RAP;

use \PHPMailer\PHPMailer\PHPMailer;

/**
 * Manage mail sending.
 * Currently used only for join email messages.
 */
class MailSender {

    private $serverName;
    private $basePath;
    private $mbb;

    public function __construct($serverName, $basePath) {
        $this->serverName = $serverName;
        $this->basePath = $basePath;
        $this->mbb = new MailBodyBuilder();
    }

    private function addDescriptionItem($key, $value) {
        $this->mbb->startBold()
                ->addText($key)
                ->endBold()
                ->addText(": " . $value)
                ->addLineBreak();
    }

    /**
     * Send the email for confirming the join request.
     * @param \RAP\User $recipientUser user target of the join requests: he/she
     * will receive the email containing the confirmation link
     * @param \RAP\User $applicantUser user that have requested the join
     * @param string $token the join token
     */
    public function sendJoinEmail(User $recipientUser, User $applicantUser, $token) {

        global $auditLog;

        $confirmJoinURL = $this->basePath . '/confirm-join?token=' . $token;

        $this->mbb->startParagraph()
                ->addText("Dear IA2 user,")
                ->addLineBreak()
                ->addText("the following user requested to join your accounts on the ")
                ->addLinkWithDescription("https://sso.ia2.inaf.it/rap-ia2/", "RAP facility")
                ->addText(":")
                ->endParagraph();

        foreach ($applicantUser->identities as $identity) {

            $this->addDescriptionItem("Type", $identity->type);
            if ($identity->name !== null) {
                $this->addDescriptionItem("Name", $identity->name);
            }
            if ($identity->surname !== null) {
                $this->addDescriptionItem("Surname", $identity->surname);
            }
            $this->addDescriptionItem("E-mail", $identity->email);
            if ($identity->eppn !== null) {
                $this->addDescriptionItem("Eppn", $identity->eppn);
            }
            if ($identity->institution !== null) {
                $this->addDescriptionItem("Institution", $identity->institution);
            }

            $this->mbb->addLineBreak();
        }

        $this->mbb->startParagraph()
                ->addText("If you and this user are ")
                ->startBold()
                ->addText("the same person")
                ->endBold()
                ->addText(" click on the following link for joining your accounts: ")
                ->addLink($confirmJoinURL)
                ->addLineBreak()
                ->addText("Otherwise you can ignore this email.")
                ->endParagraph()
                //
                ->startParagraph()
                ->startBold()
                ->addText("Please don't use this functionality for sharing resources between your coworkers")
                ->endBold()
                ->addText(", use ")
                ->addLinkWithDescription("https://sso.ia2.inaf.it/grouper", "Grouper")
                ->addText(" for that.")
                ->endParagraph()
                //
                ->addLineBreak()
                ->startBold()
                ->addText("*** This is an automatically generated email, please do not reply to this message ***")
                ->endBold()
                ->addLineBreak()
                ->addText("If you need information please contact ")
                ->addEmailAddress("ia2@oats.inaf.it", "IA2 Staff");

        $mail = new PHPMailer(true); // Passing `true` enables exceptions
        try {

            $toAddress = $recipientUser->getPrimaryEmail();

            $mail->isSMTP();
            $mail->Port = 25;
            $mail->setFrom("noreply@" . $this->serverName, 'IA2 SSO');
            $mail->addAddress($toAddress);
            $mail->CharSet = 'utf-8';
            $mail->Subject = "IA2 RAP: Join request";
            $mail->Body = $this->mbb->getHTMLBody();
            $mail->AltBody = $this->mbb->getTextPlainBody();

            $auditLog->info("JOIN email. Sending to " . $toAddress);
            $mail->send();
        } catch (\Exception $ex) {
            error_log($ex->getMessage());
            throw $ex;
        }
    }

}
+22 −13
Original line number Original line Diff line number Diff line
@@ -29,10 +29,12 @@ namespace RAP;
 */
 */
class UserHandler {
class UserHandler {


    private $dao;
    private $locator;
    private $userDAO;


    public function __construct(Locator $locator) {
    public function __construct(Locator $locator) {
        $this->dao = $locator->getUserDAO();
        $this->locator = $locator;
        $this->userDAO = $locator->getUserDAO();
    }
    }


    /**
    /**
@@ -47,25 +49,20 @@ class UserHandler {
        // If new user
        // If new user
        if ($user->id === null) {
        if ($user->id === null) {
            $primarySpecified = false;
            $primarySpecified = false;
            $user->id = $this->dao->createUser();
            $user->id = $this->userDAO->createUser();
        }
        }


        foreach ($user->identities as $identity) {
        foreach ($user->identities as $identity) {
            if ($identity->id === null) {
            if ($identity->id === null) {
                $identity->id = $this->dao->insertIdentity($identity, $user->id);
                $identity->id = $this->userDAO->insertIdentity($identity, $user->id);
                if (!$primarySpecified) {
                if (!$primarySpecified) {
                    $this->dao->setPrimaryIdentity($user->id, $identity->id);
                    $this->userDAO->setPrimaryIdentity($user->id, $identity->id);
                    $identity->primary = true;
                    $identity->primary = true;
                }
                }
            }
            }
        }
        }
    }
    }


    public function findUserByIdentity($type, $identifier) {

        return $this->dao->findUserByIdentity($type, $identifier);
    }

    /**
    /**
     * Build an URL for the web service endpoint that needs to be called in order
     * Build an URL for the web service endpoint that needs to be called in order
     * to move groups from one user to the other during a join operation.
     * to move groups from one user to the other during a join operation.
@@ -82,11 +79,15 @@ class UserHandler {
        return $joinURL;
        return $joinURL;
    }
    }


    public function joinUsers($userId1, $userId2) {
    public function joinUsers(User $user1, User $user2): User {

        $userId1 = $user1->id;
        $userId2 = $user2->id;


        // Call Grouper for moving groups and privileges from one user to the other
        // Call Grouper for moving groups and privileges from one user to the other
        if ($this->grouperConfig !== null) {
        if (isset($this->locator->config->gmsConfig)) {


            // TODO: change with new GMS
            //create cURL connection
            //create cURL connection
            $conn = curl_init($this->getJoinURL());
            $conn = curl_init($this->getJoinURL());


@@ -116,7 +117,15 @@ class UserHandler {
        }
        }


        // Call DAO for performing join operation into the RAP database.
        // Call DAO for performing join operation into the RAP database.
        $this->dao->joinUsers($userId1, $userId2);
        $this->userDAO->joinUsers($userId1, $userId2);

        foreach ($user2->identities as $identity) {
            $identity->primary = false;
            $user1->addIdentity($identity);
        }

        // merged user
        return $user1;
    }
    }


}
}
+0 −26
Original line number Original line Diff line number Diff line
@@ -61,24 +61,6 @@ interface UserDAO {
     */
     */
    function searchUser($searchText);
    function searchUser($searchText);


    /**
     * Store into the database information about a new join request.
     * @param type $token join token
     * @param type $applicantUserId the user asking for the join
     * @param type $targetUserId the user target of the join
     */
    function createJoinRequest($token, $applicantUserId, $targetUserId);

    /**
     * Retrieve join request information.
     * @param type $token join token
     * @return an array of 2 elements having the applicant user id at the first
     * position and the target user id at the second position; null if nothing
     * was found.
     * @throws Exception if multiple requests has been found for the same token.
     */
    function findJoinRequest($token);

    /**
    /**
     * Perform a join request.
     * Perform a join request.
     * @param type $userId1 the user that will receive all identities
     * @param type $userId1 the user that will receive all identities
@@ -86,12 +68,4 @@ interface UserDAO {
     * deleted from the database
     * deleted from the database
     */
     */
    function joinUsers($userId1, $userId2);
    function joinUsers($userId1, $userId2);

    /**
     * When a join action is performed the join request data (join token and user
     * identifiers) needs to be removed from the database.
     * @param type $token join token
     */
    function deleteJoinRequest($token);

}
}
+3 −55
Original line number Original line Diff line number Diff line
@@ -201,44 +201,6 @@ class MySQLUserDAO extends BaseMySQLDAO implements UserDAO {
        return $users;
        return $users;
    }
    }


    public function createJoinRequest($token, $applicantUserId, $targetUserId) {

        if ($applicantUserId === $targetUserId) {
            throw new \Exception("Invalid target user id");
        }

        $dbh = $this->getDBHandler();

        $stmt = $dbh->prepare("INSERT INTO `join_request`(`token`, `applicant_user_id`, `target_user_id`)"
                . " VALUES(:token, :applicant_user_id, :target_user_id)");

        $stmt->bindParam(':token', $token);
        $stmt->bindParam(':applicant_user_id', $applicantUserId);
        $stmt->bindParam(':target_user_id', $targetUserId);

        $stmt->execute();
    }

    public function findJoinRequest($token) {
        $dbh = $this->getDBHandler();

        $stmt = $dbh->prepare("SELECT `applicant_user_id`, `target_user_id` FROM `join_request` WHERE `token` = :token");
        $stmt->bindParam(':token', $token);
        $stmt->execute();

        $result = $stmt->fetchAll();

        switch (count($result)) {
            case 0:
                return null;
            case 1:
                $row = $result[0];
                return [$row['applicant_user_id'], $row['target_user_id']];
            default:
                throw new Exception("Found multiple join request with the same token");
        }
    }

    public function joinUsers($userId1, $userId2) {
    public function joinUsers($userId1, $userId2) {
        $dbh = $this->getDBHandler();
        $dbh = $this->getDBHandler();


@@ -251,16 +213,10 @@ class MySQLUserDAO extends BaseMySQLDAO implements UserDAO {
            $stmt1->bindParam(':id2', $userId2);
            $stmt1->bindParam(':id2', $userId2);
            $stmt1->execute();
            $stmt1->execute();


            // Deleting user2 join requests
            $stmt3 = $dbh->prepare("DELETE FROM `join_request` WHERE `target_user_id` = :tid2 OR `applicant_user_id` = :aid2");
            $stmt3->bindParam(':tid2', $userId2);
            $stmt3->bindParam(':aid2', $userId2);
            $stmt3->execute();

            // Deleting user2
            // Deleting user2
            $stmt4 = $dbh->prepare("DELETE FROM `user` WHERE `id` = :id2");
            $stmt2 = $dbh->prepare("DELETE FROM `user` WHERE `id` = :id2");
            $stmt4->bindParam(':id2', $userId2);
            $stmt2->bindParam(':id2', $userId2);
            $stmt4->execute();
            $stmt2->execute();


            $dbh->commit();
            $dbh->commit();
        } catch (Exception $ex) {
        } catch (Exception $ex) {
@@ -269,12 +225,4 @@ class MySQLUserDAO extends BaseMySQLDAO implements UserDAO {
        }
        }
    }
    }


    public function deleteJoinRequest($token) {
        $dbh = $this->getDBHandler();

        $stmt = $dbh->prepare("DELETE FROM `join_request` WHERE `token` = :token");
        $stmt->bindParam(':token', $token);
        $stmt->execute();
    }

}
}
Loading