PageRenderTime 80ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/protected/models/Users.php

https://github.com/charlesportwoodii/CiiMS
PHP | 262 lines | 136 code | 29 blank | 97 comment | 12 complexity | 1e60defb49a7885c20780a574e32ddb8 MD5 | raw file
Possible License(s): MIT
  1. <?php
  2. /**
  3. * This is the model class for table "users".
  4. *
  5. * The followings are the available columns in table 'users':
  6. * @property integer $id
  7. * @property string $email
  8. * @property string $password
  9. * @property string $firstName
  10. * @property string $lastName
  11. * @property string $displayName
  12. * @property string $about
  13. * @property integer $user_role
  14. * @property integer $status
  15. * @property string $created
  16. * @property string $updated
  17. *
  18. * The followings are the available model relations:
  19. * @property Comments[] $comments
  20. * @property Content[] $contents
  21. * @property Tags[] $tags
  22. * @property UserMetadata[] $userMetadatas
  23. * @property UserRoles $userRole
  24. */
  25. class Users extends CiiModel
  26. {
  27. const INACTIVE = 0;
  28. const ACTIVE = 1;
  29. const BANNED = 2;
  30. const PENDING_INVITATION = 3;
  31. public $pageSize = 15;
  32. /**
  33. * Returns the static model of the specified AR class.
  34. * @param string $className active record class name.
  35. * @return Users the static model class
  36. */
  37. public static function model($className=__CLASS__)
  38. {
  39. return parent::model($className);
  40. }
  41. /**
  42. * @return string the associated database table name
  43. */
  44. public function tableName()
  45. {
  46. return 'users';
  47. }
  48. /**
  49. * @return array primary key of the table
  50. **/
  51. public function primaryKey()
  52. {
  53. return array('id');
  54. }
  55. /**
  56. * @return array validation rules for model attributes.
  57. */
  58. public function rules()
  59. {
  60. // NOTE: you should only define rules for those attributes that
  61. // will receive user inputs.
  62. return array(
  63. array('email, password, displayName, user_role, status', 'required'),
  64. array('email', 'email'),
  65. array('user_role, status', 'numerical', 'integerOnly'=>true),
  66. array('email, firstName, lastName, displayName', 'length', 'max'=>255),
  67. array('password', 'length', 'max'=>64),
  68. // The following rule is used by search().
  69. array('id, email, password, firstName, lastName, displayName, about, user_role, status, created, updated', 'safe', 'on'=>'search'),
  70. );
  71. }
  72. /**
  73. * @return array relational rules.
  74. */
  75. public function relations()
  76. {
  77. // NOTE: you may need to adjust the relation name and the related
  78. // class name for the relations automatically generated below.
  79. return array(
  80. 'comments' => array(self::HAS_MANY, 'Comments', 'user_id'),
  81. 'content' => array(self::HAS_MANY, 'Content', 'author_id'),
  82. 'tags' => array(self::HAS_MANY, 'Tags', 'user_id'),
  83. // Don't pull in dashboard junk...
  84. 'metadata' => array(self::HAS_MANY, 'UserMetadata', 'user_id', 'condition' => '`metadata`.`entity_type` = 0'),
  85. 'role' => array(self::BELONGS_TO, 'UserRoles', 'user_role'),
  86. );
  87. }
  88. /**
  89. * @return array customized attribute labels (name=>label)
  90. */
  91. public function attributeLabels()
  92. {
  93. return array(
  94. 'id' => Yii::t('ciims.models.Users', 'ID'),
  95. 'email' => Yii::t('ciims.models.Users', 'Email'),
  96. 'password' => Yii::t('ciims.models.Users', 'Password'),
  97. 'firstName' => Yii::t('ciims.models.Users', 'First Name'),
  98. 'lastName' => Yii::t('ciims.models.Users', 'Last Name'),
  99. 'displayName' => Yii::t('ciims.models.Users', 'Display Name'),
  100. 'about' => Yii::t('ciims.models.Users', 'About'),
  101. 'user_role' => Yii::t('ciims.models.Users', 'User Role'),
  102. 'status' => Yii::t('ciims.models.Users', 'Active'),
  103. 'created' => Yii::t('ciims.models.Users', 'Created'),
  104. 'updated' => Yii::t('ciims.models.Users', 'Updated'),
  105. );
  106. }
  107. /**
  108. * Gets the first and last name instead of the displayname
  109. */
  110. public function getName()
  111. {
  112. return $this->firstName . ' ' . $this->lastName;
  113. }
  114. /**
  115. * Retrieves a list of models based on the current search/filter conditions.
  116. * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
  117. */
  118. public function search()
  119. {
  120. $criteria=new CDbCriteria;
  121. $criteria->compare('id',$this->id);
  122. $criteria->compare('email',$this->email,true);
  123. $criteria->compare('password',$this->password,true);
  124. $criteria->compare('firstName',$this->firstName,true);
  125. $criteria->compare('lastName',$this->lastName,true);
  126. $criteria->compare('displayName',$this->displayName,true);
  127. $criteria->compare('about',$this->about,true);
  128. $criteria->compare('user_role',$this->user_role);
  129. $criteria->compare('status',$this->status);
  130. $criteria->compare('created',$this->created,true);
  131. $criteria->compare('updated',$this->updated,true);
  132. $criteria->addCondition('status != ' . self::PENDING_INVITATION);
  133. $criteria->order = "user_role DESC, created DESC";
  134. return new CActiveDataProvider($this, array(
  135. 'criteria' => $criteria,
  136. 'pagination' => array(
  137. 'pageSize' => $this->pageSize
  138. )
  139. ));
  140. }
  141. /**
  142. * Sets some default values for the user record.
  143. * TODO: This should have been moved to CiiModel
  144. * @see CActiveRecord::beforeValidate()
  145. **/
  146. public function beforeValidate()
  147. {
  148. if ($this->about == NULL || $this->about == '')
  149. $this->about = ' ';
  150. return parent::beforeValidate();
  151. }
  152. /**
  153. * Bind behaviors for changing the user's email, and allow them to make the appropriate changes on their end.
  154. * The intention behind this, is that the user has to first, verify that they requested the change, and second
  155. * verify that they own both email addresses.
  156. *
  157. * The intention behind this is to protect the user from changes to their account, either by an administrator or a malicious user.
  158. * This doesn't protect from database attacks, it only protects from malicious attacks from within CiiMS.
  159. *
  160. * @return parent::afterSave();
  161. */
  162. public function beforeSave()
  163. {
  164. // If the user's email address is about to change
  165. if (isset($this->_oldAttributes['email']) && $this->_oldAttributes['email'] != $this->email)
  166. {
  167. // Store the new email address
  168. $newEmail = $this->email;
  169. // Reset the email addres and block the change internally
  170. $this->email = $this->_oldAttributes['email'];
  171. // Save the NEW email address in the database as a metadata record
  172. $meta = UserMetadata::model()->findByAttributes(array('user_id' => $this->id, 'key' => 'newEmailAddress'));
  173. if ($meta === NULL)
  174. $meta = new UserMetadata;
  175. $meta->user_id = $this->id;
  176. $meta->key = 'newEmailAddress';
  177. $meta->value = $newEmail;
  178. $meta->save();
  179. $meta = UserMetadata::model()->findByAttributes(array('user_id' => $this->id, 'key' => 'newEmailAddressChangeKey'));
  180. if ($meta === NULL)
  181. $meta = new UserMetadata;
  182. $meta->user_id = $this->id;
  183. $meta->key = 'newEmailAddressChangeKey';
  184. $key = $meta->value = md5(md5($newEmail . time()) . Yii::app()->params['encryptionKey']);
  185. $meta->save();
  186. // Delete all API tokens associated to this account
  187. $response = Yii::app()->db->createCommand('DELETE FROM user_metadata WHERE `key` LIKE "api_key%" AND user_id = :id')->bindParam(':id', $this->id)->execute();
  188. // Fire off an email to the OLD email address asking them VERIFY the change
  189. $response = Yii::app()->controller->sendEmail($this, Yii::t('Dashboard.email', 'CiiMS Email Change Notification'), 'application.modules.dashboard.views.email.email-change', array('key' => $key));
  190. }
  191. return parent::beforeSave();
  192. }
  193. /**
  194. * Lets us know if the user likes a given content post or not
  195. * @param int $id The id of the content we want to know about
  196. * @return bool Whether or not the user likes the post
  197. */
  198. public function likesPost($id = NULL)
  199. {
  200. if ($id === NULL)
  201. return false;
  202. $likes = UserMetadata::model()->findByAttributes(array('user_id' => $this->id, 'key' => 'likes'));
  203. if ($likes === NULL)
  204. return false;
  205. $likesArray = json_decode($likes->value, true);
  206. if (in_array($id, array_values($likesArray)))
  207. return true;
  208. return false;
  209. }
  210. /**
  211. * Creates an encrypted hash to be used as a password
  212. * @param string $email The user email
  213. * @param string $password The password to be encrypted
  214. * @param string $_dbsalt The salt value to be used (Yii::app()->params['encryptionKey'])
  215. * @return 64 character encrypted string
  216. */
  217. public function encryptHash($email, $password, $_dbsalt)
  218. {
  219. return mb_strimwidth(hash("sha512", hash("sha512", hash("whirlpool", md5($password . md5($email)))) . hash("sha512", md5($password . md5($_dbsalt))) . $_dbsalt), 0, 64);
  220. }
  221. /**
  222. * Returns the gravatar image url for a particular user
  223. * The beauty of this is that you can call User::model()->findByPk()->gravatarImage() and not have to do anything else
  224. * Implemention details borrowed from Hypatia Cii User Extensions with permission
  225. * @param string $size The size of the image we want to display
  226. * @param string $default The default image to be displayed if none is found
  227. * @return string gravatar api image
  228. */
  229. public function gravatarImage($size=20, $default=NULL)
  230. {
  231. return "https://www.gravatar.com/avatar/" . md5(strtolower(trim($this->email))).'?s='.$size;
  232. }
  233. }