Commit 9762c6ef authored by Sonia Zorba's avatar Sonia Zorba
Browse files

Added user persistence to database and REST endpoint for retrieving user by id

parent 3f825974
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
vendor
composer.lock
nbproject
logs
+34 −43
Original line number Diff line number Diff line
@@ -24,61 +24,52 @@

namespace RAP;

use PDO;
abstract class DAO {

class DAO {
    public abstract function getDBHandler();

    private static function getDBHandler() {
        global $PDO;
        return new PDO($PDO['connection_string'], $PDO['user'], $PDO['password']);
    }

    public static function insertLogin($user) {

        global $log;
    public abstract function insertTokenData($token, $data);

        $token = bin2hex(openssl_random_pseudo_bytes(16)); // http://stackoverflow.com/a/18890309/771431
    public abstract function findTokenData($token);

        $dbh = DAO::getDBHandler();
    public abstract function deleteToken($token);

        $stmt = $dbh->prepare("INSERT INTO token (token, data) VALUES(:token, :data)");

        $params = array(
            ':token' => $token,
            ':data' => json_encode($user)
        );
    /**
     * Return the new identity ID.
     */
    public abstract function insertIdentity(Identity $identity, $userId);

        if ($stmt->execute($params)) {
            return $token;
        } else {
            $log->error($stmt->errorInfo()[2]);
            throw new \Exception("SQL error while storing user token");
        }
    }
    /**
     * Return the new user ID.
     */
    public abstract function createUser();

    public static function getTokenData($token) {
    public abstract function findUserById($userId);
    
        $dbh = DAO::getDBHandler();
    /**
     * Return a User object, null if nothing was found.
     * @param type $type Identity type (EDU_GAIN, X509, GOOGLE, ...)
     * @param type $identifier value used to search the identity in the database
     * @param type $dbIdentifier identifier of the database (used only for local identities)
     */
    public abstract function findUserByIdentity($type, $identifier, $dbIdentifier);

        $stmt = $dbh->prepare("SELECT data FROM token WHERE token = :token AND CURRENT_TIMESTAMP < TIMESTAMPADD(MINUTE,1,creation_time)");
        $stmt->bindParam(':token', $token);
    public abstract function addEmailToUser($email, $userId);

        $stmt->execute();
    public $config;

        foreach ($stmt->fetchAll() as $row) {
            return $row['data'];
    public function __construct($config) {
        $this->config = $config;
    }

        return null;
    public static function get() {
        $config = parse_ini_file(ROOT . '/config.ini', true);
        switch ($config['dbtype']) {
            case 'MySQL':
                return new MySQLDAO($config);
            default:
                throw new \Exception($config['dbtype'] . ' not supported yet');
        }

    public static function deleteToken($token) {

        $dbh = DAO::getDBHandler();

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

}

classes/Identity.php

0 → 100644
+108 −0
Original line number 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;

class Identity {

    const EDU_GAIN = "eduGAIN";
    const X509 = "X.509";
    const GOOGLE = "Google";
    const FACEBOOK = "Facebook";
    const LINKEDIN = "LinkedIn";
    const LOCAL = "Local";

    private static $ALLOWED_TYPES = [Identity::EDU_GAIN, Identity::X509, Identity::GOOGLE, Identity::FACEBOOK, Identity::LINKEDIN, Identity::LOCAL];

    /**
     * Identity id in the database. Mandatory field.
     */
    public $id;

    /**
     * One of the types specified above. Mandatory field.
     */
    private $type;

    /**
     * Data related to specific account type (shibboleth persistent id, facebook id, etc, ...). Mandatory field.
     */
    public $typedId;

    /**
     * Primary email related to this identity. Mandatory field.
     * User can have additional email addresses. These are stored into User class.
     */
    public $email;

    /**
     * Unique identifier for local user database (specified in configuration file).
     */
    public $localDBId;

    /**
     * First name
     */
    public $name;

    /**
     * Last name / Family name
     */
    public $surname;

    /**
     * Institution / Organization. Not mandatory.
     */
    public $institution;

    /**
     * For local identities.
     */
    public $username;

    /**
     * For eduGAIN identities.
     */
    public $eppn;

    public function __construct($userType) {
        $isAllowedType = false;
        foreach (Identity::$ALLOWED_TYPES as $type) {
            if ($userType === $type) {
                $isAllowedType = true;
                break;
            }
        }
        if (!$isAllowedType) {
            throw new \Exception($userType . " is not a supported user type");
        }

        $this->type = $userType;
    }

    public function getType() {
        return $this->type;
    }

}

classes/MySQLDAO.php

0 → 100644
+186 −0
Original line number 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 PDO;

class MySQLDAO extends DAO {

    public function getDBHandler() {
        $connectionString = "mysql:host=" . $this->config['hostname'] . ";dbname=" . $this->config['dbname'];
        return new PDO($connectionString, $this->config['username'], $this->config['password']);
    }

    public function insertTokenData($token, $data) {

        global $log;

        $dbh = $this->getDBHandler();
        $stmt = $dbh->prepare("INSERT INTO token (token, data) VALUES(:token, :data)");

        $params = array(
            ':token' => $token,
            ':data' => $data
        );

        if ($stmt->execute($params)) {
            return $token;
        } else {
            $log->error($stmt->errorInfo()[2]);
            throw new \Exception("SQL error while storing user token");
        }
    }

    public function findTokenData($token) {

        $dbh = $this->getDBHandler();

        $stmt = $dbh->prepare("SELECT data FROM token WHERE token = :token AND CURRENT_TIMESTAMP < TIMESTAMPADD(MINUTE,1,creation_time)");
        $stmt->bindParam(':token', $token);

        $stmt->execute();

        foreach ($stmt->fetchAll() as $row) {
            return $row['data'];
        }

        return null;
    }

    public function deleteToken($token) {

        $dbh = $this->getDBHandler();

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

    public function insertIdentity(Identity $identity, $userId) {

        $dbh = $this->getDBHandler();

        $stmt = $dbh->prepare("INSERT INTO identity(`user_id`, `type`, `email`, `name`, `surname`, `institution`, `username`, `local_db_id`, `typed_id`, `eppn`)"
                . " VALUES(:user_id, :type, :email, :name, :surname, :institution, :username, :local_db_id, :typed_id, :eppn)");

        $stmt->bindParam(':user_id', $userId);
        $stmt->bindParam(':type', $identity->getType());
        $stmt->bindParam(':email', $identity->email);
        $stmt->bindParam(':name', $identity->name);
        $stmt->bindParam(':surname', $identity->surname);
        $stmt->bindParam(':institution', $identity->institution);
        $stmt->bindParam(':username', $identity->username);
        $stmt->bindParam(':local_db_id', $identity->localDBId);
        $stmt->bindParam(':typed_id', $identity->typedId);
        $stmt->bindParam(':eppn', $identity->eppn);

        $stmt->execute();

        return $dbh->lastInsertId();
    }

    public function createUser() {

        $dbh = $this->getDBHandler();

        $stmt = $dbh->prepare("INSERT INTO user() VALUES()");
        $stmt->execute();

        return $dbh->lastInsertId();
    }

    public function findUserById($userId) {

        $dbh = $this->getDBHandler();

        $stmt = $dbh->prepare("SELECT `id`, `type`, `typed_id`, `email`, `local_db_id`, `name`, `surname`, `institution`, `username`, `eppn`"
                . " FROM identity WHERE user_id = :user_id");

        $stmt->bindParam(':user_id', $userId);
        $stmt->execute();

        $user = new User();
        $user->id = $userId;

        foreach ($stmt->fetchAll() as $row) {
            $identity = new Identity($row['type']);
            $identity->id = $row['id'];
            $identity->typedId = $row['typed_id'];
            $identity->email = $row['email'];
            $identity->localDBId = $row['local_db_id'];
            $identity->name = $row['name'];
            $identity->surname = $row['surname'];
            $identity->institution = $row['institution'];
            $identity->username = $row['username'];
            $identity->eppn = $row['eppn'];
            $user->addIdentity($identity);
        }

        $stmtMail = $dbh->prepare("SELECT `email` FROM `additional_email` WHERE `user_id` = :user_id");
        $stmtMail->bindParam(':user_id', $userId);
        $stmtMail->execute();
        foreach ($stmtMail->fetchAll() as $row) {
            $user->addAdditionalEmail($row['email']);
        }

        return $user;
    }

    public function findUserByIdentity($type, $identifier, $dbIdentifier) {

        $dbh = $this->getDBHandler();

        $stmt = $dbh->prepare("SELECT user_id FROM identity WHERE type = :type AND typed_id = :typed_id AND local_db_id = :local_db_id");
        $stmt->bindParam(':type', $type);
        $stmt->bindParam(':typed_id', $identifier);
        $stmt->bindParam(':local_db_id', $dbIdentifier);

        $stmt->execute();

        $result = $stmt->fetchAll();

        if (count($result) === 0) {
            return null;
        }
        if (count($result) > 1) {
            throw new Exception("Found multiple users associated to the same identity!");
        }

        $userId = $result[0]['user_id'];
        return $this->findUserById($userId);
    }

    public function addEmailToUser($email, $userId) {

        $dbh = $this->getDBHandler();

        $stmt = $dbh->prepare("INSERT INTO `additional_email`(`user_id`, `email`) VALUES(:user_id, :email)");
        $stmt->bindParam(':user_id', $userId);
        $stmt->bindParam(':email', $email);

        $stmt->execute();
    }

}
+44 −0
Original line number 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;

class SessionData {

    public $callback;
    public $user;

    public function save() {
        $_SESSION['SessionData'] = $this;
    }

    public static function get() {

        if (!isset($_SESSION['SessionData'])) {
            $session = new SessionData();
            $session->save();
        }
        return $_SESSION['SessionData'];
    }
}
Loading