leilukin-tumbleblog/includes/model/User.php

264 lines
7.8 KiB
PHP

<?php
/**
* Class: User
* The User model.
*
* See Also:
* <Model>
*/
class User extends Model {
public $belongs_to = "group";
public $has_many = array("posts", "pages");
/**
* Function: __construct
*
* See Also:
* <Model::grab>
*/
public function __construct($user_id, $options = array()) {
parent::grab($this, $user_id, $options);
if ($this->no_results)
return;
Trigger::current()->filter($this, "user");
}
/**
* Function: find
*
* See Also:
* <Model::search>
*/
public static function find(
$options = array(),
$options_for_object = array()
): array {
fallback($options["order"], "id ASC");
return parent::search(
self::class,
$options,
$options_for_object
);
}
/**
* Function: authenticate
* Checks to see if a given login and password match a user in the database.
*
* Parameters:
* $login - The Login to check.
* $password - The matching Password to check.
*
* Returns:
* @true@ or @false@
*/
static function authenticate($login, $password): bool {
$check = new self(array("login" => $login));
if ($check->no_results)
return false;
if (self::check_password($password, $check->password))
return true;
return false;
}
/**
* Function: add
* Adds a user to the database.
*
* Parameters:
* $login - The Login for the new user.
* $password - The hashed password for the new user.
* $email - The email for the new user.
* $full_name - The full name of the user (optional).
* $website - The user's website (optional).
* $group_id - The user's <Group> ID (defaults to the default group).
* $joined_at - Join date (defaults to now).
*
* Returns:
* The newly created <User>.
*
* See Also:
* <update>
*/
public static function add(
$login,
$password,
$email,
$full_name = "",
$website = "",
$group_id = null,
$approved = true,
$joined_at = null
): self {
$config = Config::current();
$sql = SQL::current();
$trigger = Trigger::current();
$new_values = array(
"login" => strip_tags($login),
"password" => $password,
"email" => strip_tags($email),
"full_name" => strip_tags($full_name),
"website" => strip_tags($website),
"group_id" => oneof($group_id, $config->default_group),
"approved" => oneof($approved, true),
"joined_at" => oneof($joined_at, datetime())
);
$trigger->filter($new_values, "before_add_user");
$sql->insert(table:"users", data:$new_values);
$user = new self($sql->latest("users"));
$trigger->call("add_user", $user);
return $user;
}
/**
* Function: update
* Updates a user with the given parameters.
*
* Parameters:
* $login - The new Login to set.
* $password - The new hashed password to set.
* $full_name - The new Full Name to set.
* $email - The new email to set.
* $website - The new Website to set.
* $group_id - The new <Group> ID to set.
*
* Returns:
* The updated <User>.
*
* See Also:
* <add>
*/
public function update(
$login = null,
$password = null,
$email = null,
$full_name = null,
$website = null,
$group_id = null,
$approved = null,
$joined_at = null
): self|false {
if ($this->no_results)
return false;
$sql = SQL::current();
$trigger = Trigger::current();
$new_values = array(
"login" => (
isset($login) ?
strip_tags($login) :
$this->login
),
"password" => (
isset($password) ?
$password :
$this->password
),
"email" => (
isset($email) ?
strip_tags($email) :
$this->email
),
"full_name" => (
isset($full_name) ?
strip_tags($full_name) :
$this->full_name
),
"website" => (
isset($website) ?
strip_tags($website) :
$this->website
),
"group_id" => oneof(
$group_id,
$this->group_id
),
"approved" => oneof(
$approved,
$this->approved
),
"joined_at" => oneof(
$joined_at,
$this->joined_at
)
);
$trigger->filter($new_values, "before_update_user");
$sql->update(
table:"users",
conds:array("id" => $this->id),
data:$new_values
);
$user = new self(
null,
array(
"read_from" => array_merge(
$new_values,
array("id" => $this->id)
)
)
);
$trigger->call("update_user", $user, $this);
return $user;
}
/**
* Function: delete
* Deletes a given user.
*
* See Also:
* <Model::destroy>
*/
public static function delete($user_id): void {
parent::destroy(self::class, $user_id);
}
/**
* Function: hash_password
* Creates a hash of a user's password for the database.
*
* Parameters:
* $password - The unhashed password.
*
* Returns:
* The password hashed using the SHA-512 algorithm.
*
* Notes:
* <random> tries to be cryptographically secure.
*/
public static function hash_password($password): string {
$salt = random(16);
$prefix = '$6$rounds=50000$';
return crypt($password, $prefix.$salt);
}
/**
* Function: check_password
* Checks a given password against the user's stored hash.
*
* Parameters:
* $password - The unhashed password given during a login attempt.
* $stored - The the user's stored hash value from the database.
*
* Returns:
* @true@ or @false@
*
* Notes:
* Uses <hash_equals> to mitigate timing attacks.
*/
public static function check_password($password, $stored): bool {
return password_verify($password, $stored);
}
}