Code Coverage  | 
     ||||||||||
Classes and Traits  | 
      Functions and Methods  | 
      Lines  | 
     ||||||||
| Total |         | 
      0.00%  | 
      0 / 1  | 
              | 
      92.59%  | 
      25 / 27  | 
      CRAP |         | 
      98.81%  | 
      250 / 253  | 
     
| User |         | 
      0.00%  | 
      0 / 1  | 
              | 
      92.59%  | 
      25 / 27  | 
      81 |         | 
      98.81%  | 
      250 / 253  | 
     
| __construct(\Scrivo\Context $context=null) |         | 
      100.00%  | 
      1 / 1  | 
      2 |         | 
      100.00%  | 
      12 / 12  | 
     |||
| __get($name) |         | 
      100.00%  | 
      1 / 1  | 
      11 |         | 
      100.00%  | 
      11 / 11  | 
     |||
| __set($name, $value) |         | 
      100.00%  | 
      1 / 1  | 
      9 |         | 
      100.00%  | 
      9 / 9  | 
     |||
| setFields(\Scrivo\Context $context, array $rd) |         | 
      100.00%  | 
      1 / 1  | 
      4 |         | 
      100.00%  | 
      21 / 21  | 
     |||
| patchId($id) |         | 
      100.00%  | 
      1 / 1  | 
      3 |         | 
      100.00%  | 
      5 / 5  | 
     |||
| getRoles() |         | 
      100.00%  | 
      1 / 1  | 
      2 |         | 
      100.00%  | 
      5 / 5  | 
     |||
| setStatus($status) |         | 
      100.00%  | 
      1 / 1  | 
      4 |         | 
      100.00%  | 
      5 / 5  | 
     |||
| setUserCode(\Scrivo\String $userCode) |         | 
      100.00%  | 
      1 / 1  | 
      1 |         | 
      100.00%  | 
      2 / 2  | 
     |||
| setPassword(\Scrivo\String $password) |         | 
      100.00%  | 
      1 / 1  | 
      1 |         | 
      100.00%  | 
      2 / 2  | 
     |||
| setGivenName(\Scrivo\String $givenName) |         | 
      100.00%  | 
      1 / 1  | 
      1 |         | 
      100.00%  | 
      2 / 2  | 
     |||
| setFamilyNamePrefix(\Scrivo\String $familyNamePrefix) |         | 
      100.00%  | 
      1 / 1  | 
      1 |         | 
      100.00%  | 
      2 / 2  | 
     |||
| setFamilyName(\Scrivo\String $familyName) |         | 
      100.00%  | 
      1 / 1  | 
      1 |         | 
      100.00%  | 
      2 / 2  | 
     |||
| setEmailAddress(\Scrivo\String $emailAddress) |         | 
      100.00%  | 
      1 / 1  | 
      1 |         | 
      100.00%  | 
      2 / 2  | 
     |||
| setContext(\Scrivo\Context $context) |         | 
      0.00%  | 
      0 / 1  | 
      2 |         | 
      0.00%  | 
      0 / 2  | 
     |||
| checkUserCode() |         | 
      100.00%  | 
      1 / 1  | 
      3 |         | 
      100.00%  | 
      14 / 14  | 
     |||
| encrypt(\Scrivo\String $password) |         | 
      100.00%  | 
      1 / 1  | 
      1 |         | 
      100.00%  | 
      3 / 3  | 
     |||
| validateInsert() |         | 
      100.00%  | 
      1 / 1  | 
      1 |         | 
      100.00%  | 
      3 / 3  | 
     |||
| insert() |         | 
      100.00%  | 
      1 / 1  | 
      3 |         | 
      100.00%  | 
      23 / 23  | 
     |||
| validateUpdate() |         | 
      100.00%  | 
      1 / 1  | 
      1 |         | 
      100.00%  | 
      3 / 3  | 
     |||
| update() |         | 
      100.00%  | 
      1 / 1  | 
      2 |         | 
      100.00%  | 
      20 / 20  | 
     |||
| updatePassword() |         | 
      100.00%  | 
      1 / 1  | 
      2 |         | 
      100.00%  | 
      11 / 11  | 
     |||
| checkPassword(\Scrivo\String $toTest) |         | 
      100.00%  | 
      1 / 1  | 
      3 |         | 
      100.00%  | 
      12 / 12  | 
     |||
| validateDelete(\Scrivo\Context $context, $id) |         | 
      100.00%  | 
      1 / 1  | 
      3 |         | 
      100.00%  | 
      5 / 5  | 
     |||
| delete(\Scrivo\Context $context, $id) |         | 
      100.00%  | 
      1 / 1  | 
      3 |         | 
      100.00%  | 
      16 / 16  | 
     |||
| assignRoles($roles) |         | 
      100.00%  | 
      1 / 1  | 
      1 |         | 
      100.00%  | 
      3 / 3  | 
     |||
| fetch(\Scrivo\Context $context, $id) |         | 
      0.00%  | 
      0 / 1  | 
      10 |         | 
      97.14%  | 
      34 / 35  | 
     |||
| select(\Scrivo\Context $context, $roleId = null) |         | 
      100.00%  | 
      1 / 1  | 
      6 |         | 
      100.00%  | 
      23 / 23  | 
     |||
| <?php | |
| /* Copyright (c) 2013, Geert Bergman (geert@scrivo.nl) | |
| * All rights reserved. | |
| * | |
| * Redistribution and use in source and binary forms, with or without | |
| * modification, are permitted provided that the following conditions are met: | |
| * | |
| * 1. Redistributions of source code must retain the above copyright notice, | |
| * this list of conditions and the following disclaimer. | |
| * 2. Redistributions in binary form must reproduce the above copyright notice, | |
| * this list of conditions and the following disclaimer in the documentation | |
| * and/or other materials provided with the distribution. | |
| * 3. Neither the name of "Scrivo" nor the names of its contributors may be | |
| * used to endorse or promote products derived from this software without | |
| * specific prior written permission. | |
| * | |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | |
| * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
| * POSSIBILITY OF SUCH DAMAGE. | |
| * | |
| * $Id: User.php 866 2013-08-25 16:22:35Z geert $ | |
| */ | |
| /** | |
| * Implementation of the \Scrivo\User class. | |
| */ | |
| namespace Scrivo; | |
| /** | |
| * The Scrivo User class represents the user entity in Scrivo. Access rights | |
| * to objects like pages and assets are determined using these user principals. | |
| * | |
| * An user is identified by it's object id, but also by it's user code. | |
| * Convention (but not mandatory) is to use email addresses for user codes. | |
| * Both the user id and user code can be used to retrieve a user. | |
| * | |
| * The User class defines some descriptive members for the user's name and | |
| * and email address. For additional user data to store along with a user | |
| * you can use the multipurose 'customData' field. | |
| * | |
| * Peudo users | |
| * | |
| * The situation that you'll need to autenticate to different user database | |
| * arises frequently. Since the existence of Scrivo users is a requirement | |
| * for dertermining access to pages and assest it is suggested to use psuedo | |
| * users. After autenticating to an other database the user should adopt a | |
| * predefined (or progamatically defined) Scrivo user to access Scrivo | |
| * resources. This is already the case for annymous access to Scrivo resources, | |
| * in that case the user will adopt the Scrivo anymous user identity. | |
| * | |
| * TODO currently object ids 1 and 2 are used for reserved user ids, this is | |
| * not in line with the policy for object ids. In the code the are patched to | |
| * the values 3 and 4. | |
| * | |
| * @property-read object $customData A facility for 'free' storage. | |
| * @property-read int $id The user's user id (DB key) | |
| * @property-read array[] $roles An array of role-ids representing the roles | |
| * for the user. | |
| * @property \Scrivo\String $emailAddress The user's email address. | |
| * @property \Scrivo\String $familyName The user's family name. | |
| * @property \Scrivo\String $familyNamePrefix A prefix for the user's family | |
| * name. | |
| * @property \Scrivo\String $givenName The user's given name. | |
| * @property \Scrivo\String $password The user's password (encrypted). | |
| * @property int $status The user's status, one out of the constants | |
| * self::STATUS_* | |
| * @property \Scrivo\String $userCode A more descriptive identification | |
| * for the user than the user id.* | |
| */ | |
| class User { | |
| /** | |
| * Status value indicating an admin user. | |
| */ | |
| const STATUS_ADMIN = 1; | |
| /** | |
| * Status value indicating an editor. | |
| */ | |
| const STATUS_EDITOR = 2; | |
| /** | |
| * Status value indicating a member. | |
| */ | |
| const STATUS_MEMBER = 3; | |
| /** | |
| * Reserved user id for primary admin user. | |
| */ | |
| const PRIMARY_ADMIN_ID = 4; | |
| /** | |
| * Reserved user id for the anonymous user. | |
| */ | |
| const ANONYMOUS_USER_ID = 3; | |
| /** | |
| * The user's user id (DB key) | |
| * @var int | |
| */ | |
| private $id = 0; | |
| /** | |
| * The user status, one out of the constants self::STATUS_* | |
| * @var int | |
| */ | |
| private $status = self::STATUS_MEMBER; | |
| /** | |
| * A more descriptive identification for the user than the user id. | |
| * @var \Scrivo\String | |
| */ | |
| private $userCode = null; | |
| /** | |
| * The user's password (encrypted). | |
| * @var \Scrivo\String | |
| */ | |
| private $password = null; | |
| /** | |
| * The user's given name. | |
| * @var \Scrivo\String | |
| */ | |
| private $givenName = null; | |
| /** | |
| * A prefix for the user's family name. | |
| * @var \Scrivo\String | |
| */ | |
| private $familyNamePrefix = null; | |
| /** | |
| * The user's family name. | |
| * @var \Scrivo\String | |
| */ | |
| private $familyName = null; | |
| /** | |
| * The user's email address. | |
| * @var \Scrivo\String | |
| */ | |
| private $emailAddress = null; | |
| /** | |
| * An array of role-ids representing the roles for the user. | |
| * @var array[] | |
| */ | |
| private $roles = null; | |
| /** | |
| * A facility for 'free' storage. | |
| * @var object | |
| */ | |
| private $customData = null; | |
| /** | |
| * A Scrivo context. | |
| * @var Context | |
| */ | |
| private $context = null; | |
| /** | |
| * Create an empty user object. | |
| * | |
| * @param \Scrivo\Context $context A Scrivo context. | |
| */ | |
| public function __construct(\Scrivo\Context $context=null) { | |
| \Scrivo\ArgumentCheck::assertArgs(func_get_args(), array(null), 0); | |
| if ($context) { | |
| $this->userCode = new \Scrivo\String(); | |
| $this->password = new \Scrivo\String(); | |
| $this->givenName = new \Scrivo\String(); | |
| $this->familyNamePrefix = new \Scrivo\String(); | |
| $this->familyName = new \Scrivo\String(); | |
| $this->emailAddress = new \Scrivo\String(); | |
| $this->customData = new \stdClass; | |
| $this->context = $context; | |
| } | |
| } | |
| /** | |
| * Implementation of the readable properties using the PHP magic | |
| * method __get(). | |
| * | |
| * @param string $name The name of the property to get. | |
| * | |
| * @return mixed The value of the requested property. | |
| */ | |
| public function __get($name) { | |
| switch($name) { | |
| case "id": return $this->id; | |
| case "status": return $this->status; | |
| case "userCode": return $this->userCode; | |
| case "password": return $this->password; | |
| case "givenName": return $this->givenName; | |
| case "familyNamePrefix": return $this->familyNamePrefix; | |
| case "familyName": return $this->familyName; | |
| case "emailAddress": return $this->emailAddress; | |
| case "roles": return $this->getRoles(); | |
| case "customData": return $this->customData; | |
| } | |
| throw new \Scrivo\SystemException("No such get-property '$name'."); | |
| } | |
| /** | |
| * Implementation of the writable properties using the PHP magic | |
| * method __set(). | |
| * | |
| * @param string $name The name of the property to set. | |
| * @param mixed $value The value of the property to set. | |
| */ | |
| public function __set($name, $value) { | |
| switch($name) { | |
| case "status": $this->setStatus($value); return; | |
| case "userCode": $this->setUserCode($value); return; | |
| case "password": $this->setPassword($value); return; | |
| case "givenName": $this->setGivenName($value); return; | |
| case "familyNamePrefix": $this->setFamilyNamePrefix($value); return; | |
| case "familyName": $this->setFamilyName($value); return; | |
| case "emailAddress": $this->setEmailAddress($value); return; | |
| case "context": $this->setContext($value); return; | |
| } | |
| throw new \Scrivo\SystemException("No such set-property '$name'."); | |
| } | |
| /** | |
| * Convenience method to set the fields of a user object from | |
| * an array (result set row). | |
| * | |
| * @param \Scrivo\Context $context A Scrivo context. | |
| * @param array $rd An array containing the field data using the database | |
| * field names as keys. | |
| */ | |
| private function setFields(\Scrivo\Context $context, array $rd) { | |
| $id = intval($rd["user_id"]); | |
| if ($id === 1) { | |
| $id = self::ANONYMOUS_USER_ID; | |
| } | |
| if ($id === 2) { | |
| $id = self::PRIMARY_ADMIN_ID; | |
| } | |
| $this->id = $id; | |
| $this->status = intval($rd["status"]); | |
| $this->userCode = new \Scrivo\String($rd["user_code"]); | |
| $this->password = new \Scrivo\String("- hidden -"); | |
| $this->givenName = new \Scrivo\String($rd["given_name"]); | |
| $this->familyNamePrefix = new \Scrivo\String($rd["family_name_prefix"]); | |
| $this->familyName = new \Scrivo\String($rd["family_name"]); | |
| $this->emailAddress = new \Scrivo\String($rd["email_address"]); | |
| $this->customData = unserialize($rd["custom_data"]); | |
| if (is_array($this->customData)) { | |
| $this->customData = (object)$this->customData; | |
| } | |
| $this->context = $context; | |
| } | |
| /** | |
| * Utility to patch legacy ids 1 and 2. | |
| * @param int $id The id to patch. | |
| * @return int The patched id. | |
| */ | |
| public static function patchId($id) { | |
| if ($id === self::ANONYMOUS_USER_ID) { | |
| return 1; | |
| } | |
| if ($id === self::PRIMARY_ADMIN_ID) { | |
| return 2; | |
| } | |
| return $id; | |
| } | |
| /** | |
| * Get the user-roles for this user. | |
| * | |
| * @return UserRole[roleId] The set of user-roles for this user. | |
| */ | |
| private function getRoles() { | |
| if (!is_array($this->roles)) { | |
| $this->roles = UserRole::select($this->context, $this); | |
| $this->context->cache["U".$this->id] = $this; | |
| } | |
| return $this->roles; | |
| } | |
| /** | |
| * Set the user status, one out of the constants User::STATUS_* | |
| * | |
| * @param int The user status, one out of the constants User::STATUS_* | |
| */ | |
| private function setStatus($status) { | |
| if ($status != self::STATUS_ADMIN && $status != self::STATUS_EDITOR | |
| && $status != self::STATUS_MEMBER) { | |
| throw new \Scrivo\SystemException("Not a valid status"); | |
| } | |
| $this->status = $status; | |
| } | |
| /** | |
| * Set the user code. | |
| * | |
| * @param \Scrivo\String A more descriptive identification for the | |
| * user than the user id. | |
| */ | |
| private function setUserCode(\Scrivo\String $userCode) { | |
| $this->userCode = $userCode; | |
| } | |
| /** | |
| * Set the user's password (not encrypted). | |
| * | |
| * @param \Scrivo\String The user's password (not encrypted). | |
| */ | |
| private function setPassword(\Scrivo\String $password) { | |
| $this->password = new \Scrivo\String($this->encrypt($password)); | |
| } | |
| /** | |
| * Set the user's given name. | |
| * | |
| * @param \Scrivo\String The user's given name. | |
| */ | |
| private function setGivenName(\Scrivo\String $givenName) { | |
| $this->givenName = $givenName; | |
| } | |
| /** | |
| * Set a prefix for the user's family name. | |
| * | |
| * @param \Scrivo\String A prefix for the user's family name. | |
| */ | |
| private function setFamilyNamePrefix(\Scrivo\String $familyNamePrefix) { | |
| $this->familyNamePrefix = $familyNamePrefix; | |
| } | |
| /** | |
| * Set the user's family name. | |
| * | |
| * @param \Scrivo\String The user's family name. | |
| */ | |
| private function setFamilyName(\Scrivo\String $familyName) { | |
| $this->familyName = $familyName; | |
| } | |
| /** | |
| * Set the user's email address | |
| * | |
| * @param \Scrivo\String The user's email address | |
| */ | |
| private function setEmailAddress(\Scrivo\String $emailAddress) { | |
| $this->emailAddress = $emailAddress; | |
| } | |
| /** | |
| * Set the user's context. | |
| * | |
| * @param \Scrivo\Context $context A Scrivo context. | |
| */ | |
| private function setContext(\Scrivo\Context $context) { | |
| $this->context = $context; | |
| } | |
| /** | |
| * Check if the current user code is valid. | |
| * | |
| * The user code must be unique in the current database instance and at | |
| * least three characters in length. | |
| * | |
| * @throws ApplicationException If the user code does not comply. | |
| */ | |
| private function checkUserCode() { | |
| if ($this->userCode->length < 3) { | |
| throw new ApplicationException("User code too short", | |
| StatusCodes::USER_CODE_TOO_SHORT); | |
| } | |
| $sth = $this->context->connection->prepare( | |
| "SELECT COUNT(*) FROM user | |
| WHERE instance_id = :instId AND user_code = :userCode | |
| AND user_id <> :id"); | |
| $this->context->connection->bindInstance($sth); | |
| $sth->bindValue(":id", self::patchId($this->id), \PDO::PARAM_INT); | |
| $sth->bindValue(":userCode", $this->userCode, \PDO::PARAM_STR); | |
| $sth->execute(); | |
| $count = $sth->fetchColumn(); | |
| if ($count != 0) { | |
| throw new \Scrivo\ApplicationException("User code already in use", | |
| StatusCodes::USER_CODE_IN_USE); | |
| } | |
| } | |
| /** | |
| * Encrypt a password. | |
| * | |
| * @param \Scrivo\String $password | |
| * | |
| * @return string | |
| */ | |
| private function encrypt(\Scrivo\String $password) { | |
| $salt = base_convert(md5(mt_rand(0, 1000000)), 16, 36); | |
| $c = crypt($password, "\$2a\$07\$".$salt."\$"); | |
| return $c; | |
| } | |
| /** | |
| * Check if this user object can be inserted into the database. | |
| * | |
| * @throws \Scrivo\ApplicationException If the data is not accessible or | |
| * one or more of the fields contain invalid data. | |
| */ | |
| private function validateInsert() { | |
| $this->context->checkPermission(\Scrivo\AccessController::WRITE_ACCESS); | |
| $this->checkUserCode(); | |
| } | |
| /** | |
| * Insert new user object data into the database. | |
| * | |
| * First it is checked if the data of this user object can be inserted | |
| * into the database, then the data is inserted into the database. If no id | |
| * was set a new object id is generated. | |
| * | |
| * @throws \Scrivo\ApplicationException If the data is not accessible or | |
| * one or more of the fields contain invalid data. | |
| */ | |
| public function insert() { | |
| try { | |
| $this->validateInsert(); | |
| if (!$this->id) { | |
| $this->id = $this->context->connection->generateId(); | |
| } | |
| $sth = $this->context->connection->prepare( | |
| "INSERT INTO user ( | |
| instance_id, user_id, status, user_code, password, | |
| given_name, family_name_prefix, family_name, email_address, | |
| custom_data | |
| ) VALUES ( | |
| :instId, :id, :status, :userCode, :password, | |
| :givenName, :familyNamePrefix, :familyName, :emailAddress, | |
| :customData | |
| )"); | |
| $this->context->connection->bindInstance($sth); | |
| $sth->bindValue(":id", $this->id, \PDO::PARAM_INT); | |
| $sth->bindValue(":status", $this->status, \PDO::PARAM_INT); | |
| $sth->bindValue(":userCode", $this->userCode, \PDO::PARAM_STR); | |
| $sth->bindValue(":password", $this->password, \PDO::PARAM_STR); | |
| $sth->bindValue(":givenName", $this->givenName, \PDO::PARAM_STR); | |
| $sth->bindValue( | |
| ":familyNamePrefix", $this->familyNamePrefix, \PDO::PARAM_STR); | |
| $sth->bindValue(":familyName", $this->familyName, \PDO::PARAM_STR); | |
| $sth->bindValue( | |
| ":emailAddress", $this->emailAddress, \PDO::PARAM_STR); | |
| $sth->bindValue( | |
| ":customData", serialize($this->customData), \PDO::PARAM_STR); | |
| $sth->execute(); | |
| } catch(\PDOException $e) { | |
| throw new \Scrivo\ResourceException($e); | |
| } | |
| } | |
| /** | |
| * Check if this user object can be updated in the database. | |
| * | |
| * @throws \Scrivo\ApplicationException If the data is not accessible or | |
| * one or more of the fields contain invalid data. | |
| */ | |
| private function validateUpdate() { | |
| $this->context->checkPermission(\Scrivo\AccessController::WRITE_ACCESS); | |
| $this->checkUserCode(); | |
| } | |
| /** | |
| * Update existing user object data in the database. | |
| * | |
| * First it is checked if the data of this user object can be updated | |
| * in the database, then the data is updated in the database. | |
| * | |
| * The user's password cannot be updated with this method. Use | |
| * User::updatePassword() in order to do that. | |
| * | |
| * @throws \Scrivo\ApplicationException If the data is not accessible or | |
| * one or more of the fields contain invalid data. | |
| */ | |
| public function update() { | |
| try { | |
| $this->validateUpdate(); | |
| $sth = $this->context->connection->prepare( | |
| "UPDATE user SET | |
| status = :status, user_code = :userCode, | |
| given_name = :givenName, | |
| family_name_prefix = :familyNamePrefix, | |
| family_name = :familyName, email_address = :emailAddress, | |
| custom_data = :customData | |
| WHERE instance_id = :instId AND user_id = :id"); | |
| $this->context->connection->bindInstance($sth); | |
| $sth->bindValue(":id", self::patchId($this->id), \PDO::PARAM_INT); | |
| $sth->bindValue(":status", $this->status, \PDO::PARAM_INT); | |
| $sth->bindValue(":userCode", $this->userCode, \PDO::PARAM_STR); | |
| $sth->bindValue(":givenName", $this->givenName, \PDO::PARAM_STR); | |
| $sth->bindValue( | |
| ":familyNamePrefix", $this->familyNamePrefix, \PDO::PARAM_STR); | |
| $sth->bindValue(":familyName", $this->familyName, \PDO::PARAM_STR); | |
| $sth->bindValue( | |
| ":emailAddress", $this->emailAddress, \PDO::PARAM_STR); | |
| $sth->bindValue( | |
| ":customData", serialize($this->customData), \PDO::PARAM_STR); | |
| $sth->execute(); | |
| unset($this->context->cache["U".$this->id]); | |
| } catch(\PDOException $e) { | |
| throw new \Scrivo\ResourceException($e); | |
| } | |
| } | |
| /** | |
| * Update the password of this user. | |
| * | |
| * The password property should be set to its new value. When saving | |
| * a encrypted value will be stored into the database. When this user | |
| * object is loaded again its password property will contain the encrypted | |
| * value for the new password. | |
| * | |
| * @throws ApplicationException If one or more of the fields contain | |
| * invalid data. | |
| */ | |
| public function updatePassword() { | |
| try { | |
| $this->context->checkPermission(\Scrivo\AccessController::WRITE_ACCESS); | |
| $sth = $this->context->connection->prepare( | |
| "UPDATE user SET password = :password | |
| WHERE instance_id = :instId AND user_id = :id"); | |
| $this->context->connection->bindInstance($sth); | |
| $sth->bindValue(":id", self::patchId($this->id), \PDO::PARAM_INT); | |
| $sth->bindValue( | |
| ":password", $this->password, \PDO::PARAM_STR); | |
| $sth->execute(); | |
| } catch(\PDOException $e) { | |
| throw new \Scrivo\ResourceException($e); | |
| } | |
| } | |
| /** | |
| * Check if a given password matches with the one of this user. | |
| * | |
| * @param \Scrivo\String $toTest Password to test. | |
| * | |
| * @return boolean True if given password matches the user's, false if not. | |
| */ | |
| public function checkPassword(\Scrivo\String $toTest) { | |
| \Scrivo\ArgumentCheck::assertArgs(func_get_args(), array(null)); | |
| try { | |
| $sth = $this->context->connection->prepare( | |
| "SELECT password FROM user | |
| WHERE instance_id = :instId AND user_id = :id"); | |
| $this->context->connection->bindInstance($sth); | |
| $sth->bindValue(":id", self::patchId($this->id), \PDO::PARAM_INT); | |
| $sth->execute(); | |
| if ($sth->rowCount() != 1) { | |
| throw new \Scrivo\SystemException("Failed to load User"); | |
| } | |
| $pw = $sth->fetchColumn(); | |
| return $pw == crypt($toTest, $pw); | |
| } catch(\PDOException $e) { | |
| throw new \Scrivo\ResourceException($e); | |
| } | |
| } | |
| /** | |
| * Check if deletion of user object data does not violate any | |
| * business rules. | |
| * | |
| * @param \Scrivo\Context $context A Scrivo context. | |
| * @param int $id a valid object id. | |
| * | |
| * @throws \Scrivo\ApplicationException If the data is not accessible or | |
| * if it is not possible to delete the user data. | |
| */ | |
| private function validateDelete(\Scrivo\Context $context, $id) { | |
| $context->checkPermission(\Scrivo\AccessController::WRITE_ACCESS); | |
| if ($id == self::PRIMARY_ADMIN_ID || $id == self::ANONYMOUS_USER_ID) { | |
| throw new \Scrivo\ApplicationException("Can't delete system users", | |
| StatusCodes::CANNOT_DELETE_SYSTEM_USERS); | |
| } | |
| } | |
| /** | |
| * Delete existing user data from the database. | |
| * | |
| * First it is is checked if it's possible to delete user data, | |
| * then the user data including its dependecies is deleted from | |
| * the database. | |
| * | |
| * @param \Scrivo\Context $context A Scrivo context. | |
| * @param int $id a valid object id. | |
| * | |
| * @throws \Scrivo\ApplicationException If the data is not accessible or | |
| * if it is not possible to delete the user data. | |
| */ | |
| public static function delete(\Scrivo\Context $context, $id) { | |
| \Scrivo\ArgumentCheck::assertArgs(func_get_args(), array( | |
| null, | |
| array(\Scrivo\ArgumentCheck::TYPE_INTEGER) | |
| )); | |
| try { | |
| self::validateDelete($context, $id); | |
| foreach (array("user", "user_role") as $table) { | |
| $sth = $context->connection->prepare( | |
| "DELETE FROM $table | |
| WHERE instance_id = :instId AND user_id = :id"); | |
| $context->connection->bindInstance($sth); | |
| $sth->bindValue(":id", $id, \PDO::PARAM_INT); | |
| $sth->execute(); | |
| } | |
| unset($context->cache["U".$id]); | |
| } catch(\PDOException $e) { | |
| throw new \Scrivo\ResourceException($e); | |
| } | |
| } | |
| /** | |
| * Assign user roles to this user. | |
| * | |
| * The user roles to set is either an array of UserRole or stdObject | |
| * objects. stdObject need to contain the members roleId and isPublisher. | |
| * | |
| * Note: this sets all the roles for the user at once. So not giving the | |
| * the roles effectivily clears the roles for the given user. | |
| * | |
| * @param UserRole[]|object[] $roles A new set of user-roles for the given | |
| * user. | |
| */ | |
| public function assignRoles($roles) { | |
| \Scrivo\ArgumentCheck::assertArgs(func_get_args(), array(null)); | |
| UserRole::set($this->context, $this, $roles); | |
| } | |
| /** | |
| * Fetch a user object from the database using the object id or | |
| * user code. | |
| * | |
| * @param \Scrivo\Context $context A Scrivo context. | |
| * @param int|\Scrivo\String $id a valid object id or user code. | |
| * | |
| * @return \Scrivo\User The requested user object. | |
| * | |
| * @throws \Scrivo\ApplicationException If the given user code was | |
| * not found (when selecting by user code). | |
| */ | |
| public static function fetch(\Scrivo\Context $context, $id) { | |
| \Scrivo\ArgumentCheck::assertArgs(func_get_args(), array( | |
| null, | |
| array(array(\Scrivo\ArgumentCheck::TYPE_INTEGER, "Scrivo\String")) | |
| )); | |
| try { | |
| if ($id instanceof \Scrivo\String) { | |
| $byUserCode = true; | |
| } else if (is_int($id)) { | |
| $byUserCode = false; | |
| } else { | |
| throw new \Scrivo\SystemException("Invalid argument type"); | |
| } | |
| // Try to retieve the user from the cache ... | |
| if (!$byUserCode && isset($context->cache["U".$id])) { | |
| // ... get it from the cache and set the context. | |
| $user = $context->cache["U".$id]; | |
| $user->context = $context; | |
| } else { | |
| // ... else retrieve it and set it in the cache. | |
| $sth = $context->connection->prepare( | |
| "SELECT user_id, status, user_code, | |
| given_name, family_name_prefix, family_name, email_address, custom_data | |
| FROM user | |
| WHERE instance_id = :instId AND | |
| ".($byUserCode ? "user_code" : "user_id")." = :id"); | |
| $user = new \Scrivo\User($context); | |
| $context->connection->bindInstance($sth); | |
| if ($byUserCode) { | |
| $sth->bindValue(":id", $id, \PDO::PARAM_STR); | |
| } else { | |
| $sth->bindValue( | |
| ":id", $user->patchId($id), \PDO::PARAM_INT); | |
| } | |
| $sth->execute(); | |
| if ($sth->rowCount() != 1) { | |
| if ($byUserCode) { | |
| throw new \Scrivo\ApplicationException( | |
| "Failed to load User $byUserCode"); | |
| } | |
| throw new \Scrivo\SystemException("Failed to load User"); | |
| } | |
| $rd = $sth->fetch(\PDO::FETCH_ASSOC); | |
| $user->setFields($context, $rd); | |
| $context->cache["U".$user->id] = $user; | |
| } | |
| return $user; | |
| } catch(\PDOException $e) { | |
| throw new \Scrivo\ResourceException($e); | |
| } | |
| } | |
| /** | |
| * Select users from the database. | |
| * | |
| * Depending on the given arguments all users or all users for a given | |
| * role can be retrieved. | |
| * | |
| * @param \Scrivo\Context $context A Scrivo context. | |
| * @param int $roleId Optional role id for which to retrieve the users. | |
| * | |
| * @return User[id] An array containing the selected users. | |
| */ | |
| public static function select(\Scrivo\Context $context, $roleId = null) { | |
| \Scrivo\ArgumentCheck::assertArgs(func_get_args(), array( | |
| null, | |
| array(\Scrivo\ArgumentCheck::TYPE_INTEGER) | |
| ), 1); | |
| try { | |
| $sth = $context->connection->prepare( | |
| "SELECT U.user_id, U.status, U.user_code, U.given_name, U.family_name_prefix, | |
| U.family_name, U.email_address, U.custom_data | |
| FROM user U" .($roleId? ", user_role": "")." | |
| WHERE U.instance_id = :instId" .($roleId | |
| ? " AND user_role.instance_id = :instId AND | |
| user_role.user_id = U.user_id AND role_id = :roleId" | |
| : "")); | |
| $context->connection->bindInstance($sth); | |
| if ($roleId) { | |
| $sth->bindValue(":roleId", $roleId, \PDO::PARAM_INT); | |
| } | |
| $sth->execute(); | |
| $res = array(); | |
| while ($rd = $sth->fetch(\PDO::FETCH_ASSOC)) { | |
| $li = new User(); | |
| $li->setFields($context, $rd); | |
| $res[$li->id] = $li; | |
| } | |
| return $res; | |
| } catch(\PDOException $e) { | |
| throw new \Scrivo\ResourceException($e); | |
| } | |
| } | |
| } | |