254 lines
9.0 KiB
PHP
254 lines
9.0 KiB
PHP
<?php
|
||
|
||
class Account extends BaseEntity {
|
||
|
||
protected $db_name = 'accounts';
|
||
protected $db_name_session = 'accounts_session';
|
||
|
||
// Переменные свойств объекта
|
||
|
||
public $id_department;
|
||
public $name;
|
||
public $username;
|
||
public $password;
|
||
public $avatar_url;
|
||
public $telegram;
|
||
|
||
// Валидация данных при создании аккаунта
|
||
protected function validate() {
|
||
static::$error_message = [];
|
||
|
||
// === ИМЯ ===
|
||
if (!$this->name) {
|
||
$this->addError('name', 'Имя не может быть пустым');
|
||
} elseif (mb_strlen($this->name) < 2) {
|
||
$this->addError('name', 'Имя слишком короткое');
|
||
} elseif (mb_strlen($this->name) > 50) {
|
||
$this->addError('name', 'Имя слишком длинное');
|
||
} elseif (!preg_match('/^[\p{L}\s\-]+$/u', $this->name)) {
|
||
// Только буквы (любого языка), пробелы и дефис
|
||
$this->addError('name', 'Имя может содержать только буквы');
|
||
}
|
||
|
||
// === ЛОГИН ===
|
||
if (!$this->username) {
|
||
$this->addError('username', 'Логин не может быть пустым');
|
||
} elseif (strlen($this->username) < 3) {
|
||
$this->addError('username', 'Логин минимум 3 символа');
|
||
} elseif (strlen($this->username) > 32) {
|
||
$this->addError('username', 'Логин максимум 32 символа');
|
||
} elseif (!preg_match('/^[a-zA-Z][a-zA-Z0-9_]*$/', $this->username)) {
|
||
// Начинается с буквы, далее a-z, 0-9, _
|
||
$this->addError('username', 'Логин: латиница, цифры и _ (начинается с буквы)');
|
||
} elseif (Database::get($this->db_name, ['id'], ['username' => $this->username])) {
|
||
$this->addError('username', 'Этот логин уже занят');
|
||
}
|
||
|
||
// === ПАРОЛЬ ===
|
||
if (!$this->password) {
|
||
$this->addError('password', 'Пароль не может быть пустым');
|
||
} elseif (strlen($this->password) < 6) {
|
||
$this->addError('password', 'Пароль минимум 6 символов');
|
||
} elseif (strlen($this->password) > 100) {
|
||
$this->addError('password', 'Пароль слишком длинный');
|
||
}
|
||
|
||
return $this->getErrors();
|
||
}
|
||
|
||
// Очистка данных перед сохранением
|
||
protected function sanitize() {
|
||
// Имя: убираем лишние пробелы
|
||
$this->name = trim(preg_replace('/\s+/', ' ', $this->name));
|
||
|
||
// Логин: только допустимые символы (регистр сохраняется)
|
||
$this->username = preg_replace('/[^a-zA-Z0-9_]/', '', $this->username);
|
||
|
||
// Telegram: убираем @, только допустимые символы
|
||
if ($this->telegram) {
|
||
$this->telegram = str_replace('@', '', $this->telegram);
|
||
$this->telegram = preg_replace('/[^a-zA-Z0-9_]/', '', $this->telegram);
|
||
$this->telegram = strtolower($this->telegram);
|
||
$this->telegram = $this->telegram ?: null;
|
||
}
|
||
}
|
||
|
||
// Создание нового аккаунта
|
||
public function create() {
|
||
|
||
// Очищаем данные
|
||
$this->sanitize();
|
||
|
||
// Валидация данных
|
||
if ($errors = $this->validate()) {
|
||
return $errors;
|
||
}
|
||
|
||
// Вставляем в БД
|
||
Database::insert($this->db_name, [
|
||
'id_department' => $this->id_department,
|
||
'name' => $this->name,
|
||
'username' => $this->username,
|
||
'password' => $this->password,
|
||
'avatar_url' => $this->avatar_url,
|
||
'telegram' => $this->telegram
|
||
]);
|
||
|
||
return ['success' => true];
|
||
}
|
||
|
||
// Получение всех пользователей
|
||
public function getAll() {
|
||
return Database::select($this->db_name, [
|
||
'id',
|
||
'id_department',
|
||
'name',
|
||
'username',
|
||
'avatar_url',
|
||
'telegram'
|
||
]);
|
||
}
|
||
|
||
// Создание сессии для пользователя
|
||
public function create_session($name_account, $password) {
|
||
|
||
// Получаем полные данные аккаунта по переданному имени аккаунта
|
||
$account = Database::get($this->db_name, '*', ['username' => $name_account]);
|
||
|
||
|
||
if (!$account) {
|
||
$this->addError('username', 'Пользователь не найден');
|
||
return $this->getErrors();
|
||
}
|
||
|
||
if ($account['password'] !== $password) {
|
||
$this->addError('password', 'Неверный пароль');
|
||
return $this->getErrors();
|
||
}
|
||
|
||
$keycookies = $name_account . "_" . bin2hex(random_bytes(32));
|
||
$week_seconds = 604800; // 1 неделя в секундах
|
||
$data_closed = date('Y-m-d H:i:s', time() + $week_seconds);
|
||
|
||
Database::insert($this->db_name_session, [
|
||
'id_accounts' => $account['id'],
|
||
'keycookies' => $keycookies,
|
||
'data_create' => date('Y-m-d H:i:s'),
|
||
'data_closed' => $data_closed,
|
||
'ip_address' => $_SERVER['REMOTE_ADDR'],
|
||
'user_agent' => $_SERVER['HTTP_USER_AGENT']
|
||
]);
|
||
|
||
// Устанавливаем cookie
|
||
setcookie('session', $keycookies, [
|
||
'expires' => time() + $week_seconds,
|
||
'path' => '/',
|
||
'httponly' => true,
|
||
'samesite' => 'Lax'
|
||
]);
|
||
|
||
return [
|
||
'success' => true,
|
||
'keycookies' => $keycookies
|
||
];
|
||
}
|
||
|
||
// Проверка сессии и получение данных пользователя
|
||
public function check_session($keycookies) {
|
||
// Проверяем, что сессия не пустая
|
||
if (!$keycookies) {
|
||
$this->addError('session', 'Сессия не указана');
|
||
return $this->getErrors();
|
||
}
|
||
|
||
// Ищем сессию
|
||
$session = Database::get($this->db_name_session, '*', [
|
||
'keycookies' => $keycookies,
|
||
'data_closed[>]' => date('Y-m-d H:i:s')
|
||
]);
|
||
|
||
// Проверяем, что сессия не пустая
|
||
if (!$session) {
|
||
$this->addError('session', 'Сессия не найдена или истекла');
|
||
return $this->getErrors();
|
||
}
|
||
|
||
// Получаем данные пользователя
|
||
$user = Database::get($this->db_name, [
|
||
'id',
|
||
'id_department',
|
||
'name',
|
||
'username',
|
||
'avatar_url',
|
||
'telegram'
|
||
], [
|
||
'id' => $session['id_accounts']
|
||
]);
|
||
|
||
if (!$user) {
|
||
$this->addError('user', 'Пользователь не найден');
|
||
return $this->getErrors();
|
||
}
|
||
|
||
return [
|
||
'success' => true,
|
||
'user' => $user
|
||
];
|
||
}
|
||
|
||
// Удаление только текущей сессии (logout)
|
||
public function logout($keycookies) {
|
||
// Проверяем, что сессия не пустая
|
||
if (!$keycookies) {
|
||
$this->addError('session', 'Сессия не указана');
|
||
return $this->getErrors();
|
||
}
|
||
|
||
// Удаляем только текущую сессию
|
||
Database::delete($this->db_name_session, [
|
||
'keycookies' => $keycookies
|
||
]);
|
||
|
||
// Удаляем cookie
|
||
setcookie('session', '', [
|
||
'expires' => time() - 3600,
|
||
'path' => '/'
|
||
]);
|
||
|
||
return ['success' => true];
|
||
}
|
||
|
||
// Удаление всех сессий пользователя (logout со всех устройств)
|
||
public function logout_all($keycookies) {
|
||
// Проверяем, что сессия не пустая
|
||
if (!$keycookies) {
|
||
$this->addError('session', 'Сессия не указана');
|
||
return $this->getErrors();
|
||
}
|
||
|
||
// Получаем сессию чтобы узнать id пользователя
|
||
$session = Database::get($this->db_name_session, ['id_accounts'], [
|
||
'keycookies' => $keycookies
|
||
]);
|
||
|
||
if (!$session) {
|
||
$this->addError('session', 'Сессия не найдена');
|
||
return $this->getErrors();
|
||
}
|
||
|
||
// Удаляем все сессии этого пользователя
|
||
Database::delete($this->db_name_session, [
|
||
'id_accounts' => $session['id_accounts']
|
||
]);
|
||
|
||
// Удаляем cookie
|
||
setcookie('session', '', [
|
||
'expires' => time() - 3600,
|
||
'path' => '/'
|
||
]);
|
||
|
||
return ['success' => true];
|
||
}
|
||
}
|
||
|
||
?>
|