KXStudio Website https://kx.studio/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

276 lines
9.4KB

  1. <?php
  2. /**
  3. * Class: User
  4. * The User model.
  5. *
  6. * See Also:
  7. * <Model>
  8. */
  9. class User extends Model {
  10. public $belongs_to = "group";
  11. public $has_many = array("posts", "pages");
  12. /**
  13. * Function: __construct
  14. * See Also:
  15. * <Model::grab>
  16. */
  17. public function __construct($user_id, $options = array()) {
  18. parent::grab($this, $user_id, $options);
  19. if ($this->no_results)
  20. return false;
  21. Trigger::current()->filter($this, "user");
  22. }
  23. /**
  24. * Function: find
  25. * See Also:
  26. * <Model::search>
  27. */
  28. static function find($options = array(), $options_for_object = array()) {
  29. fallback($options["order"], "id ASC");
  30. return parent::search(get_class(), $options, $options_for_object);
  31. }
  32. /**
  33. * Function: authenticate
  34. * Checks to see if a given Login and Password match a user in the database.
  35. *
  36. * Parameters:
  37. * $login - The Login to check.
  38. * $password - The matching Password to check.
  39. *
  40. * Returns:
  41. * @true@ or @false@
  42. */
  43. static function authenticate($login, $password) {
  44. $check = new self(array("login" => $login));
  45. if ($check->no_results)
  46. return false;
  47. else {
  48. if (self::checkPassword($password, $check->password))
  49. return true;
  50. elseif (md5($password) == $check->password) {
  51. # Backwards-compatibility:
  52. # if their old password is stored as MD5, update
  53. # it on authentication to the new hashing scheme.
  54. $check->update(null, self::hashPassword($password));
  55. return true;
  56. } elseif(SQL::current()->adapter == "mysql") {
  57. # Some imports might use MySQL password hashing (such as MovableType 3).
  58. # Try those too, and update the user if they match.
  59. $sql = SQL::current();
  60. $old = $sql->query("SELECT OLD_PASSWORD(:pass)", array(":pass" => $password))->fetch();
  61. if ($old[0] == $check->password) {
  62. $check->update(null, self::hashPassword($password));
  63. return true;
  64. }
  65. $new = $sql->query("SELECT PASSWORD(:pass)", array(":pass" => $password))->fetch();
  66. if ($new[0] == $check->password) {
  67. $check->update(null, self::hashPassword($password));
  68. return true;
  69. }
  70. }
  71. }
  72. return false;
  73. }
  74. /**
  75. * Function: add
  76. * Adds a user to the database with the passed username, password, and e-mail.
  77. *
  78. * Calls the @add_user@ trigger with the inserted user.
  79. *
  80. * Parameters:
  81. * $login - The Login for the new user.
  82. * $password - The Password for the new user. Don't hash this, it's done in the function.
  83. * $email - The E-Mail for the new user.
  84. * $full_name - The full name of the user.
  85. * $website - The user's website.
  86. * $group - The user's group (defaults to the configured default group).
  87. * $joined_at - Join date (defaults to now).
  88. * $hash_password - Hash the password automatically? (defaults to true)
  89. *
  90. * Returns:
  91. * The newly created <User>.
  92. *
  93. * See Also:
  94. * <update>
  95. */
  96. static function add($login,
  97. $password,
  98. $email,
  99. $full_name = "",
  100. $website = "",
  101. $group_ = null,
  102. $joined_at = null,
  103. $hash_password = true) {
  104. $config = Config::current();
  105. $sql = SQL::current();
  106. $trigger = Trigger::current();
  107. if (empty($group))
  108. $group_id = $config->default_group;
  109. else
  110. $group_id = ($group instanceof Group) ? $group->id : $group;
  111. $new_values = array("login" => strip_tags($login),
  112. "password" => ($hash_password ? self::hashPassword($password) : $password),
  113. "email" => strip_tags($email),
  114. "full_name" => strip_tags($full_name),
  115. "website" => strip_tags($website),
  116. "group_id" => $group_id,
  117. "joined_at" => oneof($joined_at, datetime()));
  118. $trigger->filter($new_values, "before_add_user");
  119. $sql->insert("users", $new_values);
  120. $user = new self($sql->latest("users"));
  121. $trigger->call("add_user", $user);
  122. return $user;
  123. }
  124. /**
  125. * Function: update
  126. * Updates the user with the given login, password, full name, e-mail, website, and <Group> ID.
  127. *
  128. * Passes all of the arguments to the update_user trigger.
  129. *
  130. * Parameters:
  131. * $login - The new Login to set.
  132. * $password - The new Password to set, already encoded.
  133. * $full_name - The new Full Name to set.
  134. * $email - The new E-Mail to set.
  135. * $website - The new Website to set.
  136. * $group_id - The new <Group> to set.
  137. *
  138. * See Also:
  139. * <add>
  140. */
  141. public function update($login = null,
  142. $password = null,
  143. $email = null,
  144. $full_name = null,
  145. $website = null,
  146. $group_id = null,
  147. $joined_at = null) {
  148. if ($this->no_results)
  149. return false;
  150. $sql = SQL::current();
  151. $trigger = Trigger::current();
  152. $old = clone $this;
  153. foreach (array("login", "password", "email", "full_name", "website", "group_id", "joined_at") as $attr)
  154. $this->$attr = $$attr = ($$attr !== null ? $$attr : $this->$attr);
  155. $new_values = array("login" => strip_tags($login),
  156. "password" => $password,
  157. "email" => strip_tags($email),
  158. "full_name" => strip_tags($full_name),
  159. "website" => strip_tags($website),
  160. "group_id" => $group_id,
  161. "joined_at" => $joined_at);
  162. $trigger->filter($new_values, "before_update_user");
  163. $sql->update("users",
  164. array("id" => $this->id),
  165. $new_values);
  166. $trigger->call("update_user", $this, $old);
  167. }
  168. /**
  169. * Function: delete
  170. * Deletes a given user. Calls the @delete_user@ trigger and passes the <User> as an argument.
  171. *
  172. * Parameters:
  173. * $id - The user to delete.
  174. */
  175. static function delete($id) {
  176. parent::destroy(get_class(), $id);
  177. }
  178. /**
  179. * Function: hashPassword
  180. * Creates a secure hash of a user's password.
  181. *
  182. * Parameters:
  183. * $password - The unhashed password.
  184. *
  185. * Returns:
  186. * The securely hashed password to be stored in the database.
  187. */
  188. static function hashPassword($password) {
  189. $hasher = new PasswordHash(8, false);
  190. $hashedPassword = $hasher->HashPassword($password);
  191. return $hashedPassword;
  192. }
  193. /**
  194. * Function: checkPassword
  195. * Checks a given password against the stored hash.
  196. *
  197. * Parameters:
  198. * $password - The unhashed password given during a login attempt.
  199. * $storedHash - The stored hash for the user.
  200. *
  201. * Returns:
  202. * @true@ or @false@
  203. */
  204. static function checkPassword($password, $storedHash) {
  205. $hasher = new PasswordHash(8, false);
  206. return $hasher->CheckPassword($password, $storedHash);
  207. }
  208. /**
  209. * Function: group
  210. * Returns a user's group. Example: $user->group->can("do_something")
  211. *
  212. * !! DEPRECATED AFTER 2.0 !!
  213. */
  214. public function group() {
  215. if ($this->no_results)
  216. return false;
  217. return new Group($this->group_id);
  218. }
  219. /**
  220. * Function: posts
  221. * Returns all the posts of the user.
  222. *
  223. * !! DEPRECATED AFTER 2.0 !!
  224. */
  225. public function posts() {
  226. if ($this->no_results)
  227. return false;
  228. return Post::find(array("where" => array("user_id" => $this->id)));
  229. }
  230. /**
  231. * Function: pages
  232. * Returns all the pages of the user.
  233. *
  234. * !! DEPRECATED AFTER 2.0 !!
  235. */
  236. public function pages() {
  237. if ($this->no_results)
  238. return false;
  239. return Page::find(array("where" => array("user_id" => $this->id)));
  240. }
  241. }