Files
bp/app/Controllers/InvitationController.php
T
2026-01-12 11:58:12 +03:00

268 lines
9.9 KiB
PHP

<?php
namespace App\Controllers;
use App\Models\OrganizationUserModel;
use App\Models\UserModel;
use App\Models\OrganizationModel;
use App\Services\InvitationService;
use App\Services\AccessService;
class InvitationController extends BaseController
{
protected InvitationService $invitationService;
public function __construct()
{
$this->invitationService = new InvitationService();
}
/**
* Страница принятия/отклонения приглашения
*/
public function accept(string $token)
{
$invitation = $this->invitationService->orgUserModel->findByInviteToken($token);
if (!$invitation) {
return $this->renderTwig('organizations/invitation_expired', [
'title' => 'Приглашение недействительно',
]);
}
// Получаем данные организации
$orgModel = new OrganizationModel();
$organization = $orgModel->find($invitation['organization_id']);
// Получаем данные приглашающего
$invitedByUser = null;
if ($invitation['invited_by']) {
$userModel = new UserModel();
$invitedByUser = $userModel->find($invitation['invited_by']);
}
// Определяем, авторизован ли пользователь
$currentUserId = session()->get('user_id');
$isLoggedIn = !empty($currentUserId);
// Если пользователь авторизован - проверяем, тот ли это email
$emailMatches = true;
if ($isLoggedIn && $invitation['user_id']) {
$currentUser = (new UserModel())->find($currentUserId);
// Проверяем, тот ли пользователь (по ID или email)
$emailMatches = ($currentUserId == $invitation['user_id']);
}
// Метка роли
$roleLabels = [
'owner' => 'Владелец',
'admin' => 'Администратор',
'manager' => 'Менеджер',
'guest' => 'Гость',
];
return $this->renderTwig('organizations/invitation_accept', [
'title' => 'Приглашение в ' . ($organization['name'] ?? 'организацию'),
'token' => $token,
'organization' => $organization,
'role' => $invitation['role'],
'role_label' => $roleLabels[$invitation['role']] ?? $invitation['role'],
'invited_by' => $invitedByUser,
'invited_at' => $invitation['invited_at'],
'is_logged_in' => $isLoggedIn,
'email_matches' => $emailMatches,
'current_user_id'=> $currentUserId,
]);
}
/**
* Обработка принятия приглашения
*/
public function processAccept()
{
$token = $this->request->getPost('token');
$action = $this->request->getPost('action');
if ($action === 'decline') {
return $this->decline($token);
}
$userId = session()->get('user_id');
// Если пользователь не авторизован - редирект на страницу создания пароля
if (!$userId) {
return redirect()->to('/invitation/complete/' . $token);
}
// Принимаем приглашение
$result = $this->invitationService->acceptInvitation($token, $userId);
if (!$result['success']) {
session()->setFlashdata('error', $result['message']);
return redirect()->to('/invitation/accept/' . $token);
}
session()->setFlashdata('success', 'Вы приняли приглашение в организацию "' . $result['organization_name'] . '"');
// Переключаем организацию и редиректим на главную
session()->set('active_org_id', $result['organization_id']);
(new AccessService())->resetCache();
return redirect()->to('/');
}
/**
* Отклонение приглашения
*/
public function decline(string $token)
{
$result = $this->invitationService->declineInvitation($token);
if (!$result['success']) {
session()->setFlashdata('error', $result['message']);
} else {
session()->setFlashdata('info', 'Приглашение отклонено');
}
return redirect()->to('/');
}
/**
* Страница завершения регистрации (для новых пользователей)
*/
public function complete(string $token)
{
$invitation = $this->invitationService->orgUserModel->findByInviteToken($token);
if (!$invitation) {
return $this->renderTwig('organizations/invitation_expired', [
'title' => 'Приглашение недействительно',
]);
}
// Если пользователь уже авторизован и это его приглашение
$userId = session()->get('user_id');
if ($userId && $invitation['user_id'] == $userId) {
return redirect()->to('/invitation/accept/' . $token);
}
// Получаем данные организации
$orgModel = new OrganizationModel();
$organization = $orgModel->find($invitation['organization_id']);
// Метка роли
$roleLabels = [
'owner' => 'Владелец',
'admin' => 'Администратор',
'manager' => 'Менеджер',
'guest' => 'Гость',
];
return $this->renderTwig('organizations/invitation_complete', [
'title' => 'Завершение регистрации',
'token' => $token,
'email' => $invitation['user_id'] ? '' : '', // Email возьмем из теневой записи
'organization' => $organization,
'role' => $invitation['role'],
'role_label' => $roleLabels[$invitation['role']] ?? $invitation['role'],
]);
}
/**
* Обработка завершения регистрации
*/
public function processComplete()
{
$token = $this->request->getPost('token');
$name = $this->request->getPost('name');
$password = $this->request->getPost('password');
$passwordConfirm = $this->request->getPost('password_confirm');
// Валидация
$errors = [];
if (empty($name) || strlen($name) < 2) {
$errors[] = 'Имя должно содержать минимум 2 символа';
}
if (empty($password) || strlen($password) < 8) {
$errors[] = 'Пароль должен содержать минимум 8 символов';
}
if ($password !== $passwordConfirm) {
$errors[] = 'Пароли не совпадают';
}
if (!empty($errors)) {
return redirect()->back()->withInput()->with('errors', $errors);
}
$invitation = $this->invitationService->orgUserModel->findByInviteToken($token);
if (!$invitation) {
return redirect()->to('/');
}
// Находим теневую запись пользователя
$userModel = new UserModel();
// Если user_id указан - обновляем существующего пользователя
if ($invitation['user_id']) {
$user = $userModel->find($invitation['user_id']);
if (!$user) {
session()->setFlashdata('error', 'Пользователь не найден');
return redirect()->to('/invitation/complete/' . $token);
}
// Обновляем профиль
$userModel->update($user['id'], [
'name' => $name,
'password' => $password,
]);
$userId = $user['id'];
} else {
// Создаем нового пользователя (теневой + реальный)
// На самом деле у нас уже есть запись в users - нужно её "активировать"
$shadowUsers = $userModel->where('email', $userModel->getFindByEmail($invitation['organization_id']))->findAll();
// Логика для теневых пользователей требует доработки
session()->setFlashdata('error', 'Ошибка регистрации');
return redirect()->to('/invitation/complete/' . $token);
}
// Авторизуем пользователя
$user = $userModel->find($userId);
$this->loginUser($user);
// Принимаем приглашение
$result = $this->invitationService->acceptInvitation($token, $userId);
if (!$result['success']) {
session()->setFlashdata('error', $result['message']);
return redirect()->to('/');
}
session()->setFlashdata('success', 'Добро пожаловать! Вы успешно зарегистрировались и приняли приглашение.');
// Переключаем организацию
session()->set('active_org_id', $result['organization_id']);
(new AccessService())->resetCache();
return redirect()->to('/');
}
/**
* Авторизация пользователя после регистрации
*/
protected function loginUser(array $user): void
{
session()->set([
'user_id' => $user['id'],
'email' => $user['email'],
'name' => $user['name'],
'logged_in' => true,
]);
}
}