776 lines
31 KiB
PHP
776 lines
31 KiB
PHP
<?php
|
||
|
||
namespace App\Controllers;
|
||
|
||
use App\Models\OrganizationModel;
|
||
use App\Models\UserModel;
|
||
use App\Services\AccessService;
|
||
|
||
class Organizations extends BaseController
|
||
{
|
||
public function index()
|
||
{
|
||
$orgModel = new OrganizationModel();
|
||
$userId = $this->getCurrentUserId();
|
||
|
||
// Получаем организации пользователя через связующую таблицу
|
||
$userOrgLinks = $this->getOrgUserModel()->where('user_id', $userId)->findAll();
|
||
|
||
// Нам нужно получить сами данные организаций
|
||
$orgIds = array_column($userOrgLinks, 'organization_id');
|
||
$organizations = [];
|
||
|
||
if (!empty($orgIds)) {
|
||
$organizations = $orgModel->whereIn('id', $orgIds)->findAll();
|
||
}
|
||
|
||
// Если больше 1 или 0, показываем список
|
||
return $this->renderTwig('organizations/index', [
|
||
'organizations' => $organizations,
|
||
'count' => count($organizations)
|
||
]);
|
||
}
|
||
|
||
public function create()
|
||
{
|
||
if ($this->request->getMethod() === 'POST') {
|
||
$orgModel = new OrganizationModel();
|
||
|
||
$rules = [
|
||
'name' => 'required|min_length[2]',
|
||
];
|
||
|
||
if (!$this->validate($rules)) {
|
||
return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
|
||
}
|
||
|
||
// Собираем реквизиты в JSON
|
||
$requisites = [
|
||
'inn' => trim($this->request->getPost('inn') ?? ''),
|
||
'ogrn' => trim($this->request->getPost('ogrn') ?? ''),
|
||
'kpp' => trim($this->request->getPost('kpp') ?? ''),
|
||
'legal_address' => trim($this->request->getPost('legal_address') ?? ''),
|
||
'actual_address' => trim($this->request->getPost('actual_address') ?? ''),
|
||
'phone' => trim($this->request->getPost('phone') ?? ''),
|
||
'email' => trim($this->request->getPost('email') ?? ''),
|
||
'website' => trim($this->request->getPost('website') ?? ''),
|
||
'bank_name' => trim($this->request->getPost('bank_name') ?? ''),
|
||
'bank_bik' => trim($this->request->getPost('bank_bik') ?? ''),
|
||
'checking_account' => trim($this->request->getPost('checking_account') ?? ''),
|
||
'correspondent_account' => trim($this->request->getPost('correspondent_account') ?? ''),
|
||
];
|
||
|
||
// Создаем организацию
|
||
$orgId = $orgModel->insert([
|
||
'owner_id' => $this->getCurrentUserId(),
|
||
'name' => $this->request->getPost('name'),
|
||
'type' => 'business',
|
||
'requisites' => json_encode($requisites),
|
||
'settings' => json_encode([]),
|
||
]);
|
||
|
||
// Привязываем владельца
|
||
$this->getOrgUserModel()->insert([
|
||
'organization_id' => $orgId,
|
||
'user_id' => $this->getCurrentUserId(),
|
||
'role' => 'owner',
|
||
'status' => 'active',
|
||
'joined_at' => date('Y-m-d H:i:s'),
|
||
]);
|
||
|
||
// Сразу переключаемся на неё
|
||
$this->session->set('active_org_id', $orgId);
|
||
$this->session->setFlashdata('success', 'Организация успешно создана!');
|
||
|
||
return redirect()->to('/');
|
||
}
|
||
|
||
// GET запрос - форму создания
|
||
return $this->renderTwig('organizations/create');
|
||
}
|
||
|
||
/**
|
||
* Дашборд управления организацией
|
||
*/
|
||
public function dashboard($orgId)
|
||
{
|
||
$orgId = (int) $orgId;
|
||
$membership = $this->getMembership($orgId);
|
||
|
||
if (!$membership) {
|
||
return $this->redirectWithError('Доступ запрещен', '/organizations');
|
||
}
|
||
|
||
// Получаем данные организации
|
||
$orgModel = new OrganizationModel();
|
||
$organization = $orgModel->find($orgId);
|
||
|
||
if (!$organization) {
|
||
return $this->redirectWithError('Организация не найдена', '/organizations');
|
||
}
|
||
|
||
// Получаем статистику организации
|
||
$stats = [
|
||
'users_total' => $this->getOrgUserModel()->where('organization_id', $orgId)->countAllResults(),
|
||
'users_active' => $this->getOrgUserModel()->where('organization_id', $orgId)->where('status', 'active')->countAllResults(),
|
||
'users_blocked' => $this->getOrgUserModel()->where('organization_id', $orgId)->where('status', 'blocked')->countAllResults(),
|
||
];
|
||
|
||
// Проверяем права для отображения пунктов меню
|
||
$canManageUsers = $this->access->canManageUsers();
|
||
$canEditOrg = true; // Все члены организации могут видеть настройки (редактировать могут только admin+)
|
||
|
||
return $this->renderTwig('organizations/dashboard', [
|
||
'organization' => $organization,
|
||
'organization_id' => $orgId,
|
||
'stats' => $stats,
|
||
'current_role' => $membership['role'],
|
||
'can_manage_users' => $canManageUsers,
|
||
'can_edit_org' => $canEditOrg,
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* Редактирование организации
|
||
*/
|
||
public function edit($orgId)
|
||
{
|
||
// Проверяем доступ через AccessService
|
||
$orgId = (int) $orgId;
|
||
$membership = $this->getMembership($orgId);
|
||
|
||
if (!$membership) {
|
||
return $this->redirectWithError('Доступ запрещен', '/organizations');
|
||
}
|
||
|
||
// Проверяем права на редактирование (все роли могут редактировать)
|
||
$orgModel = new OrganizationModel();
|
||
$organization = $orgModel->find($orgId);
|
||
|
||
if (!$organization) {
|
||
return $this->redirectWithError('Организация не найдена', '/organizations');
|
||
}
|
||
|
||
// Декодируем requisites для формы
|
||
$requisites = json_decode($organization['requisites'] ?? '{}', true);
|
||
|
||
// Если это POST запрос — обновляем данные
|
||
if ($this->request->getMethod() === 'POST') {
|
||
$rules = [
|
||
'name' => 'required|min_length[2]',
|
||
];
|
||
|
||
if (!$this->validate($rules)) {
|
||
return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
|
||
}
|
||
|
||
// Собираем обновлённые реквизиты
|
||
$newRequisites = [
|
||
'inn' => trim($this->request->getPost('inn') ?? ''),
|
||
'ogrn' => trim($this->request->getPost('ogrn') ?? ''),
|
||
'kpp' => trim($this->request->getPost('kpp') ?? ''),
|
||
'legal_address' => trim($this->request->getPost('legal_address') ?? ''),
|
||
'actual_address' => trim($this->request->getPost('actual_address') ?? ''),
|
||
'phone' => trim($this->request->getPost('phone') ?? ''),
|
||
'email' => trim($this->request->getPost('email') ?? ''),
|
||
'website' => trim($this->request->getPost('website') ?? ''),
|
||
'bank_name' => trim($this->request->getPost('bank_name') ?? ''),
|
||
'bank_bik' => trim($this->request->getPost('bank_bik') ?? ''),
|
||
'checking_account' => trim($this->request->getPost('checking_account') ?? ''),
|
||
'correspondent_account' => trim($this->request->getPost('correspondent_account') ?? ''),
|
||
];
|
||
|
||
// Обновляем организацию
|
||
$orgModel->update($orgId, [
|
||
'name' => $this->request->getPost('name'),
|
||
'requisites' => json_encode($newRequisites),
|
||
]);
|
||
|
||
$this->session->setFlashdata('success', 'Организация успешно обновлена!');
|
||
return redirect()->to('/organizations');
|
||
}
|
||
|
||
// GET запрос — форма редактирования
|
||
return $this->renderTwig('organizations/edit', [
|
||
'organization' => $organization,
|
||
'requisites' => $requisites
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* Удаление организации
|
||
*/
|
||
public function delete($orgId)
|
||
{
|
||
$orgId = (int) $orgId;
|
||
$membership = $this->getMembership($orgId);
|
||
|
||
if (!$membership) {
|
||
return $this->redirectWithError('Доступ запрещен', '/organizations');
|
||
}
|
||
|
||
// Проверяем права: только владелец может удалить
|
||
if (!$this->access->canDeleteOrganization()) {
|
||
return $this->redirectWithError('Только владелец может удалить организацию', '/organizations');
|
||
}
|
||
|
||
$orgModel = new OrganizationModel();
|
||
$organization = $orgModel->find($orgId);
|
||
|
||
if (!$organization) {
|
||
return $this->redirectWithError('Организация не найдена', '/organizations');
|
||
}
|
||
|
||
// Если это POST с подтверждением — удаляем
|
||
if ($this->request->getMethod() === 'POST') {
|
||
// Удаляем связи с пользователями через forCurrentOrg()
|
||
$this->getOrgUserModel()->forCurrentOrg()->delete();
|
||
|
||
// Мягкое удаление организации
|
||
$orgModel->delete($orgId);
|
||
|
||
// Если удаляли активную организацию — очищаем
|
||
if ($this->session->get('active_org_id') == $orgId) {
|
||
$this->session->remove('active_org_id');
|
||
}
|
||
|
||
$this->session->setFlashdata('success', 'Организация "' . $organization['name'] . '" удалена');
|
||
return redirect()->to('/organizations');
|
||
}
|
||
|
||
// GET запрос — страница подтверждения удаления
|
||
return $this->renderTwig('organizations/delete', [
|
||
'organization' => $organization
|
||
]);
|
||
}
|
||
|
||
public function switch($orgId)
|
||
{
|
||
$userId = $this->getCurrentUserId();
|
||
$orgId = (int) $orgId;
|
||
|
||
// Проверяем доступ
|
||
$membership = $this->getOrgUserModel()
|
||
->where('organization_id', $orgId)
|
||
->where('user_id', $userId)
|
||
->first();
|
||
|
||
if ($membership) {
|
||
// Сбрасываем кэш AccessService при смене организации
|
||
$this->access->resetCache();
|
||
|
||
$this->session->set('active_org_id', $orgId);
|
||
$this->session->setFlashdata('success', 'Организация изменена');
|
||
$referer = $this->request->getHeader('Referer');
|
||
if ($referer && strpos($referer->getValue(), '/organizations/switch') === false) {
|
||
return redirect()->to($referer->getValue());
|
||
}
|
||
return redirect()->to('/');
|
||
} else {
|
||
$this->session->setFlashdata('error', 'Доступ запрещен');
|
||
return redirect()->to('/organizations');
|
||
}
|
||
}
|
||
|
||
// ========================================
|
||
// Управление пользователями организации
|
||
// ========================================
|
||
|
||
/**
|
||
* Список пользователей организации
|
||
*/
|
||
public function users($orgId)
|
||
{
|
||
$orgId = (int) $orgId;
|
||
$membership = $this->getMembership($orgId);
|
||
|
||
if (!$membership) {
|
||
return $this->redirectWithError('Доступ запрещен', '/organizations');
|
||
}
|
||
|
||
// Получаем организацию
|
||
$orgModel = new OrganizationModel();
|
||
$organization = $orgModel->find($orgId);
|
||
|
||
if (!$organization) {
|
||
return $this->redirectWithError('Организация не найдена', '/organizations');
|
||
}
|
||
|
||
// Проверяем права через единое место в AccessService (включает проверку типа организации)
|
||
if (!$this->access->canManageUsers()) {
|
||
return $this->redirectWithError('У вас нет прав для управления пользователями', '/organizations/' . $orgId . '/dashboard');
|
||
}
|
||
|
||
// Рендерим таблицу через универсальный компонент
|
||
$tableHtml = $this->renderTable($this->getUsersTableConfig($orgId));
|
||
|
||
// Получаем данные пользователей для статистики
|
||
$users = $this->getOrgUserModel()->getOrganizationUsers($orgId);
|
||
|
||
return $this->renderTwig('organizations/users', [
|
||
'organization' => $organization,
|
||
'organization_id' => $orgId,
|
||
'tableHtml' => $tableHtml,
|
||
'users' => $users,
|
||
'current_user_id' => $this->getCurrentUserId(),
|
||
'can_manage_users' => $this->access->canManageUsers(),
|
||
'current_role' => $membership['role'],
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* Конфигурация таблицы пользователей
|
||
*/
|
||
protected function getUsersTableConfig(int $orgId): array
|
||
{
|
||
// Проверяем права для кнопок действий
|
||
$canManage = $this->access->canManageUsers();
|
||
|
||
return [
|
||
'id' => 'users-table',
|
||
'url' => '/organizations/' . $orgId . '/users/table',
|
||
'model' => $this->getOrgUserModel(),
|
||
'columns' => [
|
||
'user_email' => [
|
||
'label' => 'Пользователь',
|
||
'width' => '35%',
|
||
'type' => 'user_display',
|
||
],
|
||
'role' => [
|
||
'label' => 'Роль',
|
||
'width' => '15%',
|
||
'type' => 'role_badge',
|
||
],
|
||
'status' => [
|
||
'label' => 'Статус',
|
||
'width' => '15%',
|
||
'type' => 'status_badge',
|
||
],
|
||
'joined_at' => [
|
||
'label' => 'Дата входа',
|
||
'width' => '20%',
|
||
'type' => 'datetime',
|
||
'default' => '—',
|
||
],
|
||
],
|
||
'searchable' => ['user_email', 'user_name'],
|
||
'sortable' => ['joined_at', 'role', 'status'],
|
||
'defaultSort' => 'joined_at',
|
||
'order' => 'desc',
|
||
'actions' => true, // Включаем колонку действий
|
||
'actionsConfig' => [
|
||
// Изменение роли
|
||
[
|
||
'label' => 'Изменить роль',
|
||
'url' => '/organizations/users/' . $orgId . '/role/{user_id}',
|
||
'icon' => 'fa-solid fa-user-gear',
|
||
'class' => 'btn-outline-primary btn-sm',
|
||
'type' => 'edit',
|
||
],
|
||
// Блокировка
|
||
[
|
||
'label' => 'Заблокировать',
|
||
'url' => '/organizations/users/' . $orgId . '/block/{user_id}',
|
||
'icon' => 'fa-solid fa-ban',
|
||
'class' => 'btn-outline-warning btn-sm',
|
||
'type' => 'block',
|
||
],
|
||
// Разблокировка
|
||
[
|
||
'label' => 'Разблокировать',
|
||
'url' => '/organizations/users/' . $orgId . '/unblock/{user_id}',
|
||
'icon' => 'fa-solid fa-check',
|
||
'class' => 'btn-outline-success btn-sm',
|
||
'type' => 'unblock',
|
||
],
|
||
// Удаление
|
||
[
|
||
'label' => 'Удалить',
|
||
'url' => '/organizations/users/' . $orgId . '/remove/{user_id}',
|
||
'icon' => 'fa-solid fa-user-xmark',
|
||
'class' => 'btn-outline-danger btn-sm',
|
||
'type' => 'delete',
|
||
],
|
||
],
|
||
'can_edit' => $canManage,
|
||
'can_delete' => $canManage,
|
||
'emptyMessage' => 'В организации пока нет участников',
|
||
'emptyIcon' => 'fa-solid fa-users',
|
||
'emptyActionUrl' => '',
|
||
'emptyActionLabel'=> '',
|
||
'emptyActionIcon' => '',
|
||
'scope' => function ($builder) use ($orgId) {
|
||
$builder->select('ou.*, u.email as user_email, u.name as user_name, u.avatar as user_avatar')
|
||
->from('organization_users ou')
|
||
->join('users u', 'u.id = ou.user_id', 'left')
|
||
->where('ou.organization_id', $orgId);
|
||
},
|
||
// Ключи фильтров (совпадают с ключами columns)
|
||
'searchable' => ['user_email', 'user_name'],
|
||
// Маппинг ключей фильтров к реальным колонкам БД
|
||
'fieldMap' => [
|
||
'user_email' => 'u.email',
|
||
'user_name' => 'u.name',
|
||
],
|
||
];
|
||
}
|
||
|
||
/**
|
||
* Таблица пользователей (AJAX)
|
||
*/
|
||
public function usersTable($orgId)
|
||
{
|
||
$orgId = (int) $orgId;
|
||
$membership = $this->getMembership($orgId);
|
||
|
||
if (!$membership) {
|
||
return $this->forbiddenResponse('Доступ запрещён');
|
||
}
|
||
|
||
// Проверяем права через единое место в AccessService (включает проверку типа организации)
|
||
if (!$this->access->canManageUsers()) {
|
||
return $this->forbiddenResponse('Управление пользователями недоступно');
|
||
}
|
||
|
||
return $this->table(
|
||
$this->getUsersTableConfig($orgId),
|
||
'/organizations/' . $orgId . '/users' // URL для редиректа
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Приглашение пользователя (AJAX)
|
||
*/
|
||
public function inviteUser($orgId)
|
||
{
|
||
$orgId = (int) $orgId;
|
||
$membership = $this->getMembership($orgId);
|
||
|
||
if (!$membership) {
|
||
return $this->response->setJSON([
|
||
'success' => false,
|
||
'message' => 'Доступ запрещен',
|
||
]);
|
||
}
|
||
|
||
// Проверяем права на управление пользователями
|
||
if (!$this->access->canManageUsers()) {
|
||
return $this->response->setJSON([
|
||
'success' => false,
|
||
'message' => 'У вас нет прав для приглашения пользователей',
|
||
]);
|
||
}
|
||
|
||
if (!$this->request->isAJAX()) {
|
||
return redirect()->to("/organizations/users/{$orgId}");
|
||
}
|
||
|
||
$email = $this->request->getPost('email');
|
||
$role = $this->request->getPost('role');
|
||
|
||
// Валидация
|
||
if (empty($email) || empty($role)) {
|
||
return $this->response->setJSON([
|
||
'success' => false,
|
||
'message' => 'Email и роль обязательны',
|
||
]);
|
||
}
|
||
|
||
// Проверяем валидность роли
|
||
$availableRoles = $this->access->getAvailableRolesForAssignment($membership['role']);
|
||
if (!in_array($role, $availableRoles)) {
|
||
return $this->response->setJSON([
|
||
'success' => false,
|
||
'message' => 'Недопустимая роль',
|
||
]);
|
||
}
|
||
|
||
// Создаем приглашение через сервис
|
||
$invitationService = new \App\Services\InvitationService();
|
||
$result = $invitationService->createInvitation(
|
||
$orgId,
|
||
$email,
|
||
$role,
|
||
$this->getCurrentUserId()
|
||
);
|
||
|
||
return $this->response->setJSON($result);
|
||
}
|
||
|
||
/**
|
||
* Блокировка пользователя
|
||
*/
|
||
public function blockUser($orgId, $userId)
|
||
{
|
||
$orgId = (int) $orgId;
|
||
$userId = (int) $userId;
|
||
$membership = $this->getMembership($orgId);
|
||
|
||
if (!$membership) {
|
||
return $this->redirectWithError('Доступ запрещен', '/organizations');
|
||
}
|
||
|
||
if (!$this->access->canManageUsers()) {
|
||
return $this->redirectWithError('У вас нет прав для блокировки', "/organizations/users/{$orgId}");
|
||
}
|
||
|
||
// Нельзя заблокировать владельца
|
||
$targetMembership = $this->getOrgUserModel()
|
||
->where('organization_id', $orgId)
|
||
->where('user_id', $userId)
|
||
->first();
|
||
|
||
if (!$targetMembership) {
|
||
return $this->redirectWithError('Пользователь не найден', "/organizations/users/{$orgId}");
|
||
}
|
||
|
||
if ($targetMembership['role'] === 'owner') {
|
||
return $this->redirectWithError('Нельзя заблокировать владельца', "/organizations/users/{$orgId}");
|
||
}
|
||
|
||
$this->getOrgUserModel()->blockUser($targetMembership['id']);
|
||
|
||
$this->session->setFlashdata('success', 'Пользователь заблокирован');
|
||
return redirect()->to("/organizations/users/{$orgId}");
|
||
}
|
||
|
||
/**
|
||
* Разблокировка пользователя
|
||
*/
|
||
public function unblockUser($orgId, $userId)
|
||
{
|
||
$orgId = (int) $orgId;
|
||
$userId = (int) $userId;
|
||
$membership = $this->getMembership($orgId);
|
||
|
||
if (!$membership || !$this->access->canManageUsers()) {
|
||
return $this->redirectWithError('Доступ запрещен', '/organizations');
|
||
}
|
||
|
||
$targetMembership = $this->getOrgUserModel()
|
||
->where('organization_id', $orgId)
|
||
->where('user_id', $userId)
|
||
->first();
|
||
|
||
if (!$targetMembership) {
|
||
return $this->redirectWithError('Пользователь не найден', "/organizations/users/{$orgId}");
|
||
}
|
||
|
||
$this->getOrgUserModel()->unblockUser($targetMembership['id']);
|
||
|
||
$this->session->setFlashdata('success', 'Пользователь разблокирован');
|
||
return redirect()->to("/organizations/users/{$orgId}");
|
||
}
|
||
|
||
/**
|
||
* Выход пользователя из организации
|
||
*/
|
||
public function leaveOrganization($orgId)
|
||
{
|
||
$orgId = (int) $orgId;
|
||
$membership = $this->getMembership($orgId);
|
||
|
||
if (!$membership) {
|
||
if ($this->request->isAJAX()) {
|
||
return $this->response->setJSON([
|
||
'success' => false,
|
||
'message' => 'Вы не состоите в этой организации',
|
||
]);
|
||
}
|
||
return $this->redirectWithError('Вы не состоите в этой организации', '/organizations');
|
||
}
|
||
|
||
// Владелец не может покинуть организацию
|
||
if ($membership['role'] === 'owner') {
|
||
if ($this->request->isAJAX()) {
|
||
return $this->response->setJSON([
|
||
'success' => false,
|
||
'message' => 'Владелец не может покинуть организацию. Передайте права другому администратору.',
|
||
]);
|
||
}
|
||
return $this->redirectWithError('Владелец не может покинуть организацию. Передайте права другому администратору.', "/organizations/users/{$orgId}");
|
||
}
|
||
|
||
// Удаляем из организации
|
||
$this->getOrgUserModel()->delete($membership['id']);
|
||
|
||
// Если это была активная организация - переключаем на другую
|
||
if ($this->session->get('active_org_id') == $orgId) {
|
||
$userId = $this->getCurrentUserId();
|
||
$otherOrgs = $this->getOrgUserModel()->where('user_id', $userId)->where('status', 'active')->findAll();
|
||
|
||
if (!empty($otherOrgs)) {
|
||
$this->session->set('active_org_id', $otherOrgs[0]['organization_id']);
|
||
} else {
|
||
$this->session->remove('active_org_id');
|
||
}
|
||
}
|
||
|
||
// Сбрасываем кэш AccessService
|
||
$this->access->resetCache();
|
||
|
||
if ($this->request->isAJAX()) {
|
||
return $this->response->setJSON([
|
||
'success' => true,
|
||
'message' => 'Вы покинули организацию',
|
||
]);
|
||
}
|
||
|
||
$this->session->setFlashdata('success', 'Вы покинули организацию');
|
||
return redirect()->to('/organizations');
|
||
}
|
||
|
||
/**
|
||
* Повторная отправка приглашения
|
||
*/
|
||
public function resendInvite($orgId, $invitationId)
|
||
{
|
||
$orgId = (int) $orgId;
|
||
$membership = $this->getMembership($orgId);
|
||
|
||
if (!$membership || !$this->access->canManageUsers()) {
|
||
return $this->redirectWithError('Доступ запрещен', '/organizations');
|
||
}
|
||
|
||
$invitationService = new \App\Services\InvitationService();
|
||
$result = $invitationService->resendInvitation($invitationId, $orgId);
|
||
|
||
if ($result['success']) {
|
||
$this->session->setFlashdata('success', 'Приглашение отправлено повторно');
|
||
} else {
|
||
$this->session->setFlashdata('error', $result['message']);
|
||
}
|
||
|
||
return redirect()->to("/organizations/users/{$orgId}");
|
||
}
|
||
|
||
/**
|
||
* Отзыв приглашения
|
||
*/
|
||
public function cancelInvite($orgId, $invitationId)
|
||
{
|
||
$orgId = (int) $orgId;
|
||
$membership = $this->getMembership($orgId);
|
||
|
||
if (!$membership || !$this->access->canManageUsers()) {
|
||
return $this->redirectWithError('Доступ запрещен', '/organizations');
|
||
}
|
||
|
||
$invitationService = new \App\Services\InvitationService();
|
||
$result = $invitationService->cancelInvitation($invitationId, $orgId);
|
||
|
||
if ($result['success']) {
|
||
$this->session->setFlashdata('success', 'Приглашение отозвано');
|
||
} else {
|
||
$this->session->setFlashdata('error', $result['message']);
|
||
}
|
||
|
||
return redirect()->to("/organizations/users/{$orgId}");
|
||
}
|
||
|
||
/**
|
||
* Изменение роли пользователя
|
||
*/
|
||
public function updateUserRole($orgId, $userId)
|
||
{
|
||
$orgId = (int) $orgId;
|
||
$userId = (int) $userId;
|
||
$membership = $this->getMembership($orgId);
|
||
|
||
if (!$membership) {
|
||
return $this->redirectWithError('Доступ запрещен', '/organizations');
|
||
}
|
||
|
||
// Проверяем права
|
||
if (!$this->access->canManageUsers()) {
|
||
return $this->redirectWithError('У вас нет прав для изменения ролей', "/organizations/users/{$orgId}");
|
||
}
|
||
|
||
// Нельзя изменить роль владельца
|
||
$targetMembership = $this->getOrgUserModel()
|
||
->where('organization_id', $orgId)
|
||
->where('user_id', $userId)
|
||
->first();
|
||
|
||
if (!$targetMembership) {
|
||
return $this->redirectWithError('Пользователь не найден в организации', "/organizations/users/{$orgId}");
|
||
}
|
||
|
||
if ($targetMembership['role'] === 'owner') {
|
||
return $this->redirectWithError('Нельзя изменить роль владельца', "/organizations/users/{$orgId}");
|
||
}
|
||
|
||
if ($this->request->getMethod() === 'POST') {
|
||
$newRole = $this->request->getPost('role');
|
||
|
||
// Проверяем валидность роли
|
||
$availableRoles = $this->access->getAvailableRolesForAssignment($membership['role']);
|
||
if (!in_array($newRole, $availableRoles)) {
|
||
return redirect()->back()->withInput()->with('error', 'Недопустимая роль');
|
||
}
|
||
|
||
$this->getOrgUserModel()->update($targetMembership['id'], [
|
||
'role' => $newRole,
|
||
]);
|
||
|
||
$this->session->setFlashdata('success', 'Роль изменена');
|
||
return redirect()->to("/organizations/users/{$orgId}");
|
||
}
|
||
|
||
$userModel = new UserModel();
|
||
$user = $userModel->find($userId);
|
||
|
||
return $this->renderTwig('organizations/edit_user_role', [
|
||
'organization_id' => $orgId,
|
||
'user' => $user,
|
||
'current_role' => $targetMembership['role'],
|
||
'available_roles' => $availableRoles,
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* Удаление пользователя из организации
|
||
*/
|
||
public function removeUser($orgId, $userId)
|
||
{
|
||
$orgId = (int) $orgId;
|
||
$userId = (int) $userId;
|
||
$currentUserId = $this->getCurrentUserId();
|
||
$membership = $this->getMembership($orgId);
|
||
|
||
if (!$membership) {
|
||
return $this->redirectWithError('Доступ запрещен', '/organizations');
|
||
}
|
||
|
||
// Проверяем права
|
||
if (!$this->access->canManageUsers()) {
|
||
return $this->redirectWithError('У вас нет прав для удаления пользователей', "/organizations/users/{$orgId}");
|
||
}
|
||
|
||
// Нельзя удалить владельца
|
||
$targetMembership = $this->getOrgUserModel()
|
||
->where('organization_id', $orgId)
|
||
->where('user_id', $userId)
|
||
->first();
|
||
|
||
if (!$targetMembership) {
|
||
return $this->redirectWithError('Пользователь не найден', "/organizations/users/{$orgId}");
|
||
}
|
||
|
||
if ($targetMembership['role'] === 'owner') {
|
||
return $this->redirectWithError('Нельзя удалить владельца организации', "/organizations/users/{$orgId}");
|
||
}
|
||
|
||
// Нельзя удалить самого себя (если ты admin)
|
||
if ($userId === $currentUserId) {
|
||
return $this->redirectWithError('Нельзя удалить себя из организации', "/organizations/users/{$orgId}");
|
||
}
|
||
|
||
// Удаляем пользователя из организации
|
||
$this->getOrgUserModel()->delete($targetMembership['id']);
|
||
|
||
$this->session->setFlashdata('success', 'Пользователь удалён из организации');
|
||
return redirect()->to("/organizations/users/{$orgId}");
|
||
}
|
||
}
|