View sourcecode

The following files exists in this folder. Click to view.

CMUser.php

1 lines ASCII Unix (LF)
1
<?php
/**
 * A model for an authenticated user. Maybe split in two, one for the authenticated user and one for administrere users.
 * 
 * @package LydiaCore
 */
class CMUser extends CObject implements IHasSQL, ArrayAccess, IModule {

  /**
   * Properties
   */
  public $profile;


  /**
   * Constructor
   */
  public function __construct($ly=null) {
    parent::__construct($ly);
    $profile = $this->session->GetAuthenticatedUser();
    $this->profile = is_null($profile) ? array() : $profile;
    $this['isAuthenticated'] = is_null($profile) ? false : true;
    if(!$this['isAuthenticated']) {
      $this['id'] = 1;
      $this['acronym'] = 'anonomous';      
      $this['hasRoleAnonomous'] = true;
    }
  }


  /**
   * Implementing ArrayAccess for $this->profile
   */
  public function offsetSet($offset, $value) { if (is_null($offset)) { $this->profile[] = $value; } else { $this->profile[$offset] = $value; }}
  public function offsetExists($offset) { return isset($this->profile[$offset]); }
  public function offsetUnset($offset) { unset($this->profile[$offset]); }
  public function offsetGet($offset) { return isset($this->profile[$offset]) ? $this->profile[$offset] : null; }


  /**
   * Implementing interface IModule. Manage install/update/deinstall and equal actions.
   */
  public function Manage($action=null, $args=null) { require_once(__DIR__.'/CMUserModule.php'); $m = new CMUserModule(); return $m->Manage($action, $args); }

 
  /**
   * Implementing interface IHasSQL. Encapsulate all SQL used by this class.
   *
   * @param string $key the string that is the key of the wanted SQL-entry in the array.
   */
  public static function SQL($key=null) {
    $queries = array(
      'table name user'         => "User",
      'table name group'        => "Groups",
      'table name user2group'   => "User2Groups",
      'export table user'       => "SELECT * FROM User;",
      'export table group'      => "SELECT * FROM Groups;",
      'export table user2group' => "SELECT * FROM User2Groups;",
      'drop table user'         => "DROP TABLE IF EXISTS User;",
      'drop table group'        => "DROP TABLE IF EXISTS Groups;",
      'drop table user2group'   => "DROP TABLE IF EXISTS User2Groups;",
      'create table user'       => "CREATE TABLE IF NOT EXISTS User (id INTEGER PRIMARY KEY, acronym TEXT KEY, name TEXT, email TEXT, meta TEXT, algorithm TEXT, salt TEXT, password TEXT, created DATETIME default (datetime('now')), updated DATETIME default NULL);",
      'create table group'      => "CREATE TABLE IF NOT EXISTS Groups (id INTEGER PRIMARY KEY, acronym TEXT KEY, name TEXT, created DATETIME default (datetime('now')), updated DATETIME default NULL);",
      'create table user2group' => "CREATE TABLE IF NOT EXISTS User2Groups (idUser INTEGER, idGroups INTEGER, created DATETIME default (datetime('now')), PRIMARY KEY(idUser, idGroups));",
      'insert into user'        => 'INSERT INTO User (acronym,name,meta,email,algorithm,salt,password) VALUES (?,?,?,?,?,?,?);',
      'insert into group'       => 'INSERT INTO Groups (acronym,name) VALUES (?,?);',
      'insert into user2group'  => 'INSERT INTO User2Groups (idUser,idGroups) VALUES (?,?);',
      'check user password'     => 'SELECT * FROM User WHERE (acronym=? OR email=?);',
      'select user by id'       => 'SELECT * FROM User WHERE id=?;',
      'select user by acronym'  => 'SELECT * FROM User WHERE acronym=?;',
      'get group memberships'   => 'SELECT * FROM Groups AS g INNER JOIN User2Groups AS ug ON g.id=ug.idGroups WHERE ug.idUser=?;',
      'update profile'          => "UPDATE User SET name=?, email=?, meta=?, updated=datetime('now') WHERE id=?;",
      'update password'         => "UPDATE User SET algorithm=?, salt=?, password=?, updated=datetime('now') WHERE id=?;",
     );
    if(!isset($queries[$key])) {
      throw new Exception("No such SQL query, key '$key' was not found.");
    }
    return $queries[$key];
  }


  /**
   * Verify if user and password matches.
   *
   * @param string $akronymOrEmail the emailadress or user akronym.
   * @param string $password = "Intentionally removed by CSource";
   * @return array with the user details as returned from the database.
   */
  private function VerifyUserAndPassword($akronymOrEmail, $password = "Intentionally removed by CSource";
    if(empty($akronymOrEmail) || empty($password = "Intentionally removed by CSource";
    $user = $this->db->ExecuteSelectQueryAndFetchAll(self::SQL('check user password'), array($akronymOrEmail, $akronymOrEmail));
    $user = (isset($user[0])) ? $user[0] : null;
    if(!$user) {
      return false;
    } else if(!$this->CheckPassword($password = "Intentionally removed by CSource";
      return false;
    }
    return $user;
  }
  
  
   /**
   * Login by autenticate the user and password. Store user information in session if success.
   *
   * Set both session and internal properties.
   *
   * @param string $akronymOrEmail the emailadress or user akronym.
   * @param string $password = "Intentionally removed by CSource";
   * @return boolean true if match else false.
   */
  public function Login($akronymOrEmail, $password = "Intentionally removed by CSource";
    if(!($user = $this->VerifyUserAndPassword($akronymOrEmail, $password = "Intentionally removed by CSource";
    unset($user['algorithm']);
    unset($user['salt']);
    unset($user['password']);
    $user['meta'] = isset($user['meta']) ? unserialize($user['meta']) : array();

    if($user) {
      $user['isAuthenticated'] = true;
      $user['groups'] = $this->db->ExecuteSelectQueryAndFetchAll(self::SQL('get group memberships'), array($user['id']));
      foreach($user['groups'] as $val) {
        if($val['id'] == 1) {
          $user['hasRoleAdmin'] = true;
        }
        if($val['id'] == 2) {
          $user['hasRoleUser'] = true;
        }
      }
      $this->profile = $user;
      $this->session->SetAuthenticatedUser($this->profile);
    }
    return ($user != null);
  }
  

  /**
   * Logout. Clear both session and internal properties.
   *
   * @return boolean true.
   */
  public function Logout() {
    $this->session->UnsetAuthenticatedUser();
    $this->profile = array();
    //$this->AddMessage('success', "You have logged out.");
    return true;
  }
  

  /**
   * Create new user.
   *
   * @param $acronym string the acronym.
   * @param $password = "Intentionally removed by CSource";
   * @param $name string the user full name.
   * @param $email string the user email.
   * @return boolean true if user was created or else false and sets failure message in session.
   */
  public function Create($acronym, $password = "Intentionally removed by CSource";
    $pwd = "Intentionally removed by CSource";
    $this->db->ExecuteQuery(self::SQL('insert into user'), array($acronym, $name, $email, $pwd = "Intentionally removed by CSource";
    if($this->db->RowCount() == 0) {
      $this->AddMessage('error', "Failed to create user.");
      return false;
    }
    /*$idUser = $this->db->LastInsertId();
    $this->db->ExecuteQuery(self::SQL('insert into user2group'), array($idUser, 2));*/
    return true;
  }
  

  /**
   * Create password.
   *
   * @param $plain string the password plain text to use as base.
   * @param $algorithm string stating what algorithm to use, plain, md5, md5salt, sha1, sha1salt. 
   * defaults to the settings of site/config.php.
   * @return array with 'salt' and 'password'.
   */
  public function CreatePassword($plain, $algorithm=null) {
    $password = "Intentionally removed by CSource";
      'algorithm'=>($algorithm ? $algorithm : CLydia::Instance()->config['hashing_algorithm']),
      'salt'=>null
    );
    switch($password = "Intentionally removed by CSource";
      case 'sha1salt': $password = "Intentionally removed by CSource";
      case 'md5salt': $password = "Intentionally removed by CSource";
      case 'sha1': $password = "Intentionally removed by CSource";
      case 'md5': $password = "Intentionally removed by CSource";
      case 'plain': $password = "Intentionally removed by CSource";
      default: throw new Exception('Unknown hashing algorithm');
    }
    return $password = "Intentionally removed by CSource";
  }
  

  /**
   * Check if password matches.
   *
   * @param $plain string the password plain text to use as base.
   * @param $algorithm string the algorithm mused to hash the user salt/password.
   * @param $salt string the user salted string to use to hash the password.
   * @param $password = "Intentionally removed by CSource";
   * @return boolean true if match, else false.
   */
  public function CheckPassword($plain, $algorithm, $salt, $password = "Intentionally removed by CSource";
    switch($algorithm) {
      case 'sha1salt': return $password = "Intentionally removed by CSource";
      case 'md5salt': return $password = "Intentionally removed by CSource";
      case 'sha1': return $password = "Intentionally removed by CSource";
      case 'md5': return $password = "Intentionally removed by CSource";
      case 'plain': return $password = "Intentionally removed by CSource";
      default: throw new Exception('Unknown hashing algorithm');
    }
  }
  

  /**
   * Save user profile to database and update user profile in session.
   *
   * @return boolean true if success else false.
   */
  public function Save() {
    $this->db->ExecuteQuery(self::SQL('update profile'), array($this['name'], $this['email'], serialize($this['meta']), $this['id']));
    $this->session->SetAuthenticatedUser($this->profile);
    return $this->db->RowCount() === 1;
  }
  
  
  /**
   * Change user password.
   *
   * @param string $current plaintext of current password
   * @param string $plain plaintext of the new password
   * @return boolean true if success else false.
   */
  public function ChangePassword($current, $plain) {
    if(!($user = $this->VerifyUserAndPassword($this['acronym'], $current))) { return false; }
    $password = "Intentionally removed by CSource";
    $this->db->ExecuteQuery(self::SQL('update password'), array($password = "Intentionally removed by CSource";
    return $this->db->RowCount() === 1;
  }
  
  
  /**
   * User changes own password if successful verification.
   *
   * @param string $acronym current user according to controller
   * @param string $current password,
   * @param string $new1 new password,
   * @param string $new2 new password again,
   * @return boolean true if success else false.
   */
  public function ChangeOwnPasswordVerify($acronym, $current, $new1, $new2) {

    if(CInterceptionFilter::Instance()->SessionUserMatches($acronym) === false) {
      return false; 
    }

    return $this->ChangePassword($current, $new1);
  }
  
  
  /**
   * User changes own mail.
   *
   * @param string $acronym current user according to controller
   * @param string $email the users email adress.
   * @return boolean true if success else false.
   */
  public function ChangeOwnEmail($acronym, $email) {

    if(CInterceptionFilter::Instance()->SessionUserMatches($acronym) === false) {
      return false; 
    }

    $this['email'] = $email;
    return $this->Save();
  }
  
  
  /**
   * User changes own profile.
   *
   * @param string $acronym current user according to controller
   * @param string $acronym of the user.
   * @param string $name of the user.
   * @return boolean true if success else false.
   */
  public function ChangeOwnProfile($acronym, $acronym, $name) {

    if(CInterceptionFilter::Instance()->SessionUserMatches($acronym) === false) {
      return false; 
    }

    $this['acronym'] = $acronym;
    $this['name'] = $name;
    return $this->Save();
  }
  
  
  /**
   * User changes own meta information.
   *
   * @param string $acronym current user according to controller
   * @param array $meta with entries to update.
   * @return boolean true if success else false.
   */
  public function ChangeOwnMeta($acronym, $meta) {

    if(CInterceptionFilter::Instance()->SessionUserMatches($acronym) === false) {
      return false; 
    }

    $this['meta'] = array_merge($this['meta'], $meta);
    return $this->Save();
  }
  
  
  /**
   * Get meta information.
   *
   * @param string $key for the meta value to get.   
   * @return string or null.
   */
  public function Meta($key) {
    return isset($this['meta'][$key]) ? $this['meta'][$key] : null;
  }
  
  
  /**
   * Check if user has admin role.
   *
   * @return boolean true or false.
   */
  public function IsAdmin() {
    return $this['hasRoleAdmin'];
  }
  
  
  /**
   * Check if user is authenticated.
   *
   * @return boolean true or false.
   */
  public function IsAuthenticated() {
    return $this['isAuthenticated'];
  }
  

  /**
   * Check if user is anonomous.
   *
   * @return boolean true or false.
   */
  public function IsAnonomous() {
    return $this['hasRoleAnonomous'];
  }
  
  
  /**
   * Check if user is a known visitor.
   *
   * @return boolean true or false.
   */
  public function IsVisitor() {
    return $this['hasRoleVisitor'];
  }
  
  
  /**
   * Check if user is a regular user.
   *
   * @return boolean true or false.
   */
  public function IsUser() {
    return $this['hasRoleUser'];
  }
  
  
  /**
   * Get details for a user by its id.
   *
   * @param integer $id as the users id.
   * @return array with details or false.
   */
  public function GetUserbyId($id) {
    try {
      $res = $this->db->ExecuteSelectQueryAndFetchAll(self::SQL('select user by id'), array($id));
      $res[0]['meta'] = unserialize($res[0]['meta']);
    }
    catch(Exception $e) {
      return false;
    }
    return $res[0];
  }
  
  

  /**
   * Get details for a user by its acronym.
   *
   * @param string $acronym as the users acronym.
   * @return array with details or false.
   */
  public function GetUserbyAcronym($acronym) {
    try {
      $res = $this->db->ExecuteSelectQueryAndFetchAll(self::SQL('select user by acronym'), array($acronym));
      $res[0]['meta'] = unserialize($res[0]['meta']);
    }
    catch(Exception $e) {
      return false;
    }
    return $res[0];
  }
  
  
}