first commit
This commit is contained in:
@@ -0,0 +1,270 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Models\UserModel;
|
||||
use App\Models\OrganizationModel;
|
||||
use App\Models\OrganizationUserModel;
|
||||
use App\Libraries\EmailLibrary;
|
||||
|
||||
class Auth extends BaseController
|
||||
{
|
||||
protected $emailLibrary;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->emailLibrary = new EmailLibrary();
|
||||
}
|
||||
|
||||
public function register()
|
||||
{
|
||||
if ($this->request->getMethod() === 'POST') {
|
||||
|
||||
log_message('debug', 'POST запрос получен: ' . print_r($this->request->getPost(), true));
|
||||
// Валидация (упрощенная для примера)
|
||||
$rules = [
|
||||
'name' => 'required|min_length[3]',
|
||||
'email' => 'required|valid_email|is_unique[users.email]',
|
||||
'password' => 'required|min_length[6]',
|
||||
];
|
||||
|
||||
|
||||
if (!$this->validate($rules)) {
|
||||
return redirect()->back()->with('error', 'Ошибка регистрации');
|
||||
}
|
||||
|
||||
|
||||
$userModel = new UserModel();
|
||||
$orgModel = new OrganizationModel();
|
||||
$orgUserModel = new OrganizationUserModel();
|
||||
|
||||
// Генерируем токен для подтверждения email
|
||||
$verificationToken = bin2hex(random_bytes(32));
|
||||
|
||||
// 1. Создаем пользователя с токеном верификации
|
||||
$userData = [
|
||||
'name' => $this->request->getPost('name'),
|
||||
'email' => $this->request->getPost('email'),
|
||||
'password' => $this->request->getPost('password'), // Хешируется в модели
|
||||
'verification_token' => $verificationToken,
|
||||
'email_verified' => 0,
|
||||
];
|
||||
|
||||
log_message('debug', 'Registration userData: ' . print_r($userData, true));
|
||||
|
||||
$userId = $userModel->insert($userData);
|
||||
|
||||
log_message('debug', 'Insert result, userId: ' . $userId);
|
||||
|
||||
|
||||
// 2. Создаем "Личную организацию" (п. 5.2.1 ТЗ)
|
||||
$orgData = [
|
||||
'owner_id' => $userId,
|
||||
'name' => 'Личное пространство',
|
||||
'type' => 'personal',
|
||||
];
|
||||
$orgId = $orgModel->insert($orgData);
|
||||
|
||||
// 3. Привязываем пользователя к этой организации (роль owner)
|
||||
$orgUserModel->insert([
|
||||
'organization_id' => $orgId,
|
||||
'user_id' => $userId,
|
||||
'role' => 'owner',
|
||||
'status' => 'active',
|
||||
'joined_at' => date('Y-m-d H:i:s'),
|
||||
]);
|
||||
|
||||
// 4. Отправляем письмо для подтверждения email
|
||||
$this->emailLibrary->sendVerificationEmail(
|
||||
$userData['email'],
|
||||
$userData['name'],
|
||||
$verificationToken
|
||||
);
|
||||
|
||||
// 5. Показываем сообщение о необходимости подтверждения
|
||||
session()->setFlashdata('success', 'Регистрация успешна! Пожалуйста, проверьте вашу почту и подтвердите email.');
|
||||
return redirect()->to('/register/success');
|
||||
}
|
||||
|
||||
return $this->renderTwig('auth/register');
|
||||
}
|
||||
|
||||
/**
|
||||
* Страница после успешной регистрации
|
||||
*/
|
||||
public function registerSuccess()
|
||||
{
|
||||
return $this->renderTwig('auth/register_success');
|
||||
}
|
||||
|
||||
/**
|
||||
* Подтверждение email по токену
|
||||
*/
|
||||
public function verify($token)
|
||||
{
|
||||
log_message('debug', 'Verify called with token: ' . $token);
|
||||
|
||||
if (empty($token)) {
|
||||
return $this->renderTwig('auth/verify_error', [
|
||||
'message' => 'Отсутствует токен подтверждения.'
|
||||
]);
|
||||
}
|
||||
|
||||
$userModel = new UserModel();
|
||||
|
||||
// Ищем пользователя по токену
|
||||
$user = $userModel->where('verification_token', $token)->first();
|
||||
|
||||
log_message('debug', 'User found: ' . ($user ? 'yes' : 'no'));
|
||||
if ($user) {
|
||||
log_message('debug', 'User email_verified: ' . $user['email_verified']);
|
||||
}
|
||||
|
||||
if (!$user) {
|
||||
return $this->renderTwig('auth/verify_error', [
|
||||
'message' => 'Недействительная ссылка для подтверждения. Возможно, ссылка уже была использована или истек срок её действия.'
|
||||
]);
|
||||
}
|
||||
|
||||
if ($user['email_verified']) {
|
||||
return $this->renderTwig('auth/verify_error', [
|
||||
'message' => 'Email уже подтверждён. Вы можете войти в систему.'
|
||||
]);
|
||||
}
|
||||
|
||||
// Подтверждаем email
|
||||
$updateData = [
|
||||
'email_verified' => 1,
|
||||
'verified_at' => date('Y-m-d H:i:s'),
|
||||
'verification_token' => null, // Удаляем токен после использования
|
||||
];
|
||||
|
||||
$result = $userModel->update($user['id'], $updateData);
|
||||
|
||||
log_message('debug', 'Update result: ' . ($result ? 'success' : 'failed'));
|
||||
log_message('debug', 'Update data: ' . print_r($updateData, true));
|
||||
|
||||
if (!$result) {
|
||||
log_message('error', 'Update errors: ' . print_r($userModel->errors(), true));
|
||||
}
|
||||
|
||||
// Отправляем приветственное письмо
|
||||
$this->emailLibrary->sendWelcomeEmail($user['email'], $user['name']);
|
||||
|
||||
return $this->renderTwig('auth/verify_success', [
|
||||
'name' => $user['name']
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Повторная отправка письма для подтверждения
|
||||
*/
|
||||
public function resendVerification()
|
||||
{
|
||||
if ($this->request->getMethod() === 'POST') {
|
||||
$email = $this->request->getPost('email');
|
||||
|
||||
if (empty($email)) {
|
||||
return redirect()->back()->with('error', 'Введите email');
|
||||
}
|
||||
|
||||
$userModel = new UserModel();
|
||||
$user = $userModel->where('email', $email)->first();
|
||||
|
||||
if (!$user) {
|
||||
return redirect()->back()->with('error', 'Пользователь с таким email не найден');
|
||||
}
|
||||
|
||||
if ($user['email_verified']) {
|
||||
return redirect()->to('/login')->with('info', 'Email уже подтверждён. Вы можете войти.');
|
||||
}
|
||||
|
||||
// Генерируем новый токен
|
||||
$newToken = bin2hex(random_bytes(32));
|
||||
$userModel->update($user['id'], [
|
||||
'verification_token' => $newToken
|
||||
]);
|
||||
|
||||
// Отправляем письмо повторно
|
||||
$this->emailLibrary->sendVerificationEmail(
|
||||
$user['email'],
|
||||
$user['name'],
|
||||
$newToken
|
||||
);
|
||||
|
||||
return redirect()->back()->with('success', 'Письмо для подтверждения отправлено повторно. Проверьте почту.');
|
||||
}
|
||||
|
||||
return $this->renderTwig('auth/resend_verification');
|
||||
}
|
||||
|
||||
public function login()
|
||||
{
|
||||
if ($this->request->getMethod() === 'POST') {
|
||||
$userModel = new \App\Models\UserModel();
|
||||
$orgUserModel = new \App\Models\OrganizationUserModel();
|
||||
|
||||
$email = $this->request->getPost('email');
|
||||
$password = $this->request->getPost('password');
|
||||
|
||||
$user = $userModel->where('email', $email)->first();
|
||||
|
||||
if ($user && password_verify($password, $user['password'])) {
|
||||
|
||||
// Проверяем, подтвержден ли email
|
||||
if (!$user['email_verified']) {
|
||||
session()->setFlashdata('warning', 'Email не подтверждён. Проверьте почту или <a href="/auth/resend-verification">запросите письмо повторно</a>.');
|
||||
return redirect()->to('/login');
|
||||
}
|
||||
|
||||
// Получаем организации пользователя
|
||||
$userOrgs = $orgUserModel->where('user_id', $user['id'])->findAll();
|
||||
|
||||
if (empty($userOrgs)) {
|
||||
// Экстремальный случай: если по какой-то причине у пользователя нет организаций
|
||||
session()->setFlashdata('error', 'Ваш аккаунт не привязан ни к одной организации. Обратитесь к поддержке.');
|
||||
return redirect()->to('/login');
|
||||
}
|
||||
// Базовые данные сессии (пользователь авторизован)
|
||||
$sessionData = [
|
||||
'user_id' => $user['id'],
|
||||
'email' => $user['email'],
|
||||
'name' => $user['name'],
|
||||
'isLoggedIn' => true
|
||||
];
|
||||
|
||||
// АВТОМАТИЧЕСКИЙ ВЫБОР ОРГАНИЗАЦИИ
|
||||
if (count($userOrgs) === 1) {
|
||||
// Если одна организация — заходим автоматически для удобства
|
||||
$sessionData['active_org_id'] = $userOrgs[0]['organization_id'];
|
||||
session()->set($sessionData);
|
||||
return redirect()->to('/');
|
||||
}
|
||||
|
||||
// ОЧИЩАЕМ active_org_id если несколько организаций
|
||||
session()->remove('active_org_id');
|
||||
|
||||
// Если несколько организаций — отправляем на страницу выбора
|
||||
session()->set($sessionData);
|
||||
|
||||
// (Опционально) Записываем информацию, что пользователь залогинен, но орга не выбрана,
|
||||
// чтобы страница /organizations не редиректнула его обратно (см. Organizations::index)
|
||||
session()->setFlashdata('info', 'Выберите пространство для работы');
|
||||
|
||||
return redirect()->to('/organizations');
|
||||
//}
|
||||
} else {
|
||||
return redirect()->back()->with('error', 'Неверный логин или пароль');
|
||||
}
|
||||
}
|
||||
|
||||
return $this->renderTwig('auth/login');
|
||||
}
|
||||
|
||||
public function logout()
|
||||
{
|
||||
session()->destroy();
|
||||
session()->remove('active_org_id');
|
||||
return redirect()->to('/');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user