Files
crmPRO/autoload/Controllers/UsersController.php
2026-02-28 14:48:24 +01:00

554 lines
16 KiB
PHP

<?php
namespace Controllers;
class UsersController
{
private const ADMIN_USER_ID = 1;
private const IMPERSONATOR_SESSION_KEY = 'impersonator_user';
public static function mainView()
{
global $user, $mdb;
if ( !$user )
return \controls\Users::login_form();
$impersonator_user = self::getImpersonatorUser();
if ( !self::canManageUsers( $user, $impersonator_user ) )
self::forbiddenRedirect();
$users_repository = new \Domain\Users\UserRepository();
$all_users = $users_repository -> all();
$permission_repo = new \Domain\Users\PermissionRepository( $mdb );
$permissions_map = [];
foreach ( $all_users as $u )
{
if ( (int)$u['id'] !== self::ADMIN_USER_ID )
$permissions_map[ (int)$u['id'] ] = $permission_repo -> byUserId( (int)$u['id'] );
}
return \Tpl::view( 'users/main-view', self::buildMainViewModel(
$user,
$impersonator_user,
$all_users,
$permissions_map
) );
}
public static function loginAs()
{
global $user;
if ( !$user )
return \controls\Users::login_form();
$impersonator_user = self::getImpersonatorUser();
if ( !self::canManageUsers( $user, $impersonator_user ) )
self::forbiddenRedirect();
$target_user_id = (int)\S::get( 'user_id' );
$users_repository = new \Domain\Users\UserRepository();
$target_user = $users_repository -> byId( $target_user_id );
if ( !$target_user )
{
\S::alert( 'Nie znaleziono wskazanego uzytkownika.' );
header( 'Location: /users/main_view/' );
exit;
}
$new_session_state = self::impersonationStateAfterLoginAs( $user, $target_user, $impersonator_user );
\S::set_session( 'user', $new_session_state['user'] );
\S::set_session( self::IMPERSONATOR_SESSION_KEY, $new_session_state['impersonator_user'] );
\S::alert( 'Zalogowano jako: ' . $target_user['name'] . ' ' . $target_user['surname'] . '.' );
header( 'Location: /' );
exit;
}
public static function switchBackToAdmin()
{
$impersonator_user = self::getImpersonatorUser();
if ( !$impersonator_user or !isset( $impersonator_user['id'] ) or (int)$impersonator_user['id'] !== self::ADMIN_USER_ID )
{
\S::alert( 'Brak aktywnej sesji podszywania.' );
header( 'Location: /' );
exit;
}
\S::set_session( 'user', $impersonator_user );
\S::del_session( self::IMPERSONATOR_SESSION_KEY );
\S::alert( 'Powrot do konta administratora.' );
header( 'Location: /users/main_view/' );
exit;
}
public static function canManageUsers( $current_user, $impersonator_user = null )
{
if ( !is_array( $current_user ) )
return false;
if ( isset( $current_user['id'] ) and (int)$current_user['id'] === self::ADMIN_USER_ID )
return true;
if ( is_array( $impersonator_user ) and isset( $impersonator_user['id'] ) and (int)$impersonator_user['id'] === self::ADMIN_USER_ID )
return true;
return false;
}
public static function vacations()
{
global $user, $mdb;
if ( !$user )
return \controls\Users::login_form();
$impersonator_user = self::getImpersonatorUser();
if ( !self::canManageUsers( $user, $impersonator_user ) )
self::forbiddenRedirect();
$users_repository = new \Domain\Users\UserRepository();
$vacation_repository = new \Domain\Users\VacationRepository( $mdb );
$all_users = $users_repository -> all();
$year = (int) \S::get( 'year' ) ?: (int) date( 'Y' );
$filter_user_id = (int) \S::get( 'user_id' ) ?: 0;
$vacations = $vacation_repository -> allByYear( $year, $filter_user_id ?: null );
$summary = $vacation_repository -> summaryByYear( $year, $all_users );
$carryover = $vacation_repository -> carryoverByYear( (int) date( 'Y' ), $all_users );
return \Tpl::view( 'users/vacations', [
'active_tab' => 'vacations',
'can_switch_back' => is_array( $impersonator_user ) and isset( $impersonator_user['id'] ) and (int)$impersonator_user['id'] === self::ADMIN_USER_ID,
'users' => $all_users,
'vacations' => $vacations,
'summary' => $summary,
'carryover' => $carryover,
'year' => $year,
'filter_user_id' => $filter_user_id,
'vacation_types' => \Domain\Users\VacationRepository::TYPES
] );
}
public static function vacationAdd()
{
global $user, $mdb;
header( 'Content-Type: application/json; charset=utf-8' );
$response = [ 'status' => 'error', 'msg' => 'Wystąpił błąd podczas dodawania urlopu.' ];
if ( !$user || !self::canManageUsers( $user, self::getImpersonatorUser() ) )
{
$response['msg'] = 'Brak uprawnień.';
echo json_encode( $response );
exit;
}
if ( !\S::csrf_verify() )
{
$response['msg'] = 'Nieprawidłowy token bezpieczeństwa. Odśwież stronę.';
echo json_encode( $response );
exit;
}
$user_id = (int) \S::get( 'user_id' );
$date_from = \S::get( 'date_from' );
$date_to = \S::get( 'date_to' );
$type = \S::get( 'type' );
$comment = \S::get( 'comment' );
if ( !$user_id || !$date_from || !$date_to || !$type )
{
$response['msg'] = 'Wypełnij wszystkie wymagane pola.';
echo json_encode( $response );
exit;
}
if ( !preg_match( '/^\d{4}-\d{2}-\d{2}$/', $date_from ) || !preg_match( '/^\d{4}-\d{2}-\d{2}$/', $date_to ) )
{
$response['msg'] = 'Nieprawidłowy format daty.';
echo json_encode( $response );
exit;
}
$vacation_repository = new \Domain\Users\VacationRepository( $mdb );
$id = $vacation_repository -> add( $user_id, $date_from, $date_to, $type, $comment );
if ( $id )
$response = [ 'status' => 'success', 'msg' => 'Urlop został dodany.' ];
echo json_encode( $response );
exit;
}
public static function vacationEdit()
{
global $user, $mdb;
header( 'Content-Type: application/json; charset=utf-8' );
$response = [ 'status' => 'error', 'msg' => 'Wystąpił błąd podczas edycji urlopu.' ];
if ( !$user || !self::canManageUsers( $user, self::getImpersonatorUser() ) )
{
$response['msg'] = 'Brak uprawnień.';
echo json_encode( $response );
exit;
}
if ( !\S::csrf_verify() )
{
$response['msg'] = 'Nieprawidłowy token bezpieczeństwa. Odśwież stronę.';
echo json_encode( $response );
exit;
}
$id = (int) \S::get( 'id' );
$user_id = (int) \S::get( 'user_id' );
$date_from = \S::get( 'date_from' );
$date_to = \S::get( 'date_to' );
$type = \S::get( 'type' );
$comment = \S::get( 'comment' );
if ( !$id || !$user_id || !$date_from || !$date_to || !$type )
{
$response['msg'] = 'Wypełnij wszystkie wymagane pola.';
echo json_encode( $response );
exit;
}
if ( !preg_match( '/^\d{4}-\d{2}-\d{2}$/', $date_from ) || !preg_match( '/^\d{4}-\d{2}-\d{2}$/', $date_to ) )
{
$response['msg'] = 'Nieprawidłowy format daty.';
echo json_encode( $response );
exit;
}
$vacation_repository = new \Domain\Users\VacationRepository( $mdb );
if ( $vacation_repository -> update( $id, $user_id, $date_from, $date_to, $type, $comment ) )
$response = [ 'status' => 'success', 'msg' => 'Urlop został zaktualizowany.' ];
echo json_encode( $response );
exit;
}
public static function vacationDelete()
{
global $user, $mdb;
header( 'Content-Type: application/json; charset=utf-8' );
$response = [ 'status' => 'error', 'msg' => 'Wystąpił błąd podczas usuwania urlopu.' ];
if ( !$user || !self::canManageUsers( $user, self::getImpersonatorUser() ) )
{
$response['msg'] = 'Brak uprawnień.';
echo json_encode( $response );
exit;
}
if ( !\S::csrf_verify() )
{
$response['msg'] = 'Nieprawidłowy token bezpieczeństwa. Odśwież stronę.';
echo json_encode( $response );
exit;
}
$id = (int) \S::get( 'id' );
if ( !$id )
{
echo json_encode( $response );
exit;
}
$vacation_repository = new \Domain\Users\VacationRepository( $mdb );
if ( $vacation_repository -> delete( $id ) )
$response = [ 'status' => 'success', 'msg' => 'Urlop został usunięty.' ];
echo json_encode( $response );
exit;
}
public static function vacationLimitSave()
{
global $user, $mdb;
header( 'Content-Type: application/json; charset=utf-8' );
$response = [ 'status' => 'error', 'msg' => 'Wystąpił błąd podczas zapisywania limitu.' ];
if ( !$user || !self::canManageUsers( $user, self::getImpersonatorUser() ) )
{
$response['msg'] = 'Brak uprawnień.';
echo json_encode( $response );
exit;
}
if ( !\S::csrf_verify() )
{
$response['msg'] = 'Nieprawidłowy token bezpieczeństwa. Odśwież stronę.';
echo json_encode( $response );
exit;
}
$user_id = (int) \S::get( 'user_id' );
$year = (int) \S::get( 'year' );
$days_limit = (int) \S::get( 'days_limit' );
if ( !$user_id || !$year || $days_limit < 0 )
{
echo json_encode( $response );
exit;
}
$vacation_repository = new \Domain\Users\VacationRepository( $mdb );
if ( $vacation_repository -> setLimit( $user_id, $year, $days_limit ) )
$response = [ 'status' => 'success', 'msg' => 'Limit został zapisany.' ];
echo json_encode( $response );
exit;
}
public static function permissionSave()
{
global $user, $mdb;
header( 'Content-Type: application/json; charset=utf-8' );
$response = [ 'status' => 'error', 'msg' => 'Wystapil blad podczas zapisywania uprawnien.' ];
if ( !$user || !self::canManageUsers( $user, self::getImpersonatorUser() ) )
{
$response['msg'] = 'Brak uprawnien.';
echo json_encode( $response );
exit;
}
if ( !\S::csrf_verify() )
{
$response['msg'] = 'Nieprawidlowy token bezpieczenstwa. Odswiez strone.';
echo json_encode( $response );
exit;
}
$target_user_id = (int) \S::get( 'user_id' );
$module = \S::get( 'perm_module' );
$value = (int) \S::get( 'value' );
if ( !$target_user_id || !$module )
{
echo json_encode( $response );
exit;
}
// Superadmin permissions cannot be changed
if ( $target_user_id === self::ADMIN_USER_ID )
{
$response['msg'] = 'Nie mozna zmieniac uprawnien administratora.';
echo json_encode( $response );
exit;
}
// Whitelist check
if ( !in_array( $module, \Domain\Users\PermissionRepository::MODULES, true ) )
{
$response['msg'] = 'Nieznany modul.';
echo json_encode( $response );
exit;
}
$repo = new \Domain\Users\PermissionRepository( $mdb );
$current = $repo -> byUserId( $target_user_id );
$current[ $module ] = $value ? 1 : 0;
$repo -> save( $target_user_id, $current );
$response = [ 'status' => 'success', 'msg' => 'Uprawnienia zostaly zapisane.' ];
echo json_encode( $response );
exit;
}
public static function permissionPopup()
{
global $user, $mdb;
header( 'Content-Type: application/json; charset=utf-8' );
$response = [ 'status' => 'error', 'msg' => 'Nie mozna otworzyc ustawien uprawnien.' ];
if ( !$user || !self::canManageUsers( $user, self::getImpersonatorUser() ) )
{
$response['msg'] = 'Brak uprawnien.';
echo json_encode( $response );
exit;
}
if ( !\S::csrf_verify() )
{
$response['msg'] = 'Nieprawidlowy token bezpieczenstwa. Odswiez strone.';
echo json_encode( $response );
exit;
}
$target_user_id = (int)\S::get( 'user_id' );
if ( !$target_user_id )
{
echo json_encode( $response );
exit;
}
$users_repository = new \Domain\Users\UserRepository();
$target_user = $users_repository -> byId( $target_user_id );
if ( !$target_user )
{
$response['msg'] = 'Nie znaleziono uzytkownika.';
echo json_encode( $response );
exit;
}
$permission_repo = new \Domain\Users\PermissionRepository( $mdb );
$permissions = (int)$target_user['id'] === self::ADMIN_USER_ID
? \Domain\Users\PermissionRepository::defaults()
: $permission_repo -> byUserId( (int)$target_user['id'] );
$defs = self::permissionDefinitions();
$response = [
'status' => 'success',
'popup_content' => \Tpl::view( 'users/permissions-popup', [
'target_user' => $target_user,
'permissions' => $permissions,
'module_labels' => $defs['module_labels'],
'permission_groups' => $defs['permission_groups']
] )
];
echo json_encode( $response );
exit;
}
public static function permissionSaveBulk()
{
global $user, $mdb;
header( 'Content-Type: application/json; charset=utf-8' );
$response = [ 'status' => 'error', 'msg' => 'Wystapil blad podczas zapisywania uprawnien.' ];
if ( !$user || !self::canManageUsers( $user, self::getImpersonatorUser() ) )
{
$response['msg'] = 'Brak uprawnien.';
echo json_encode( $response );
exit;
}
if ( !\S::csrf_verify() )
{
$response['msg'] = 'Nieprawidlowy token bezpieczenstwa. Odswiez strone.';
echo json_encode( $response );
exit;
}
$target_user_id = (int)\S::get( 'user_id' );
$selected_modules_raw = (string)\S::get( 'selected_modules' );
if ( !$target_user_id )
{
echo json_encode( $response );
exit;
}
if ( $target_user_id === self::ADMIN_USER_ID )
{
$response['msg'] = 'Nie mozna zmieniac uprawnien administratora.';
echo json_encode( $response );
exit;
}
$selected_modules = array_filter( array_map( 'trim', explode( ',', $selected_modules_raw ) ) );
$selected_modules = array_values( array_unique( $selected_modules ) );
$payload = [];
foreach ( \Domain\Users\PermissionRepository::MODULES as $module )
$payload[ $module ] = in_array( $module, $selected_modules, true ) ? 1 : 0;
$repo = new \Domain\Users\PermissionRepository( $mdb );
$repo -> save( $target_user_id, $payload );
echo json_encode( [ 'status' => 'success', 'msg' => 'Uprawnienia zostaly zapisane.' ] );
exit;
}
public static function buildMainViewModel( $current_user, $impersonator_user, array $users, array $permissions_map = [] )
{
$defs = self::permissionDefinitions();
return [
'current_user' => $current_user,
'impersonator_user' => $impersonator_user,
'users' => $users,
'active_tab' => 'users',
'can_switch_back' => is_array( $impersonator_user ) and isset( $impersonator_user['id'] ) and (int)$impersonator_user['id'] === self::ADMIN_USER_ID,
'permissions_map' => $permissions_map,
'modules' => \Domain\Users\PermissionRepository::MODULES,
'module_labels' => $defs['module_labels'],
'permission_groups' => $defs['permission_groups']
];
}
public static function impersonationStateAfterLoginAs( $current_user, $target_user, $existing_impersonator_user = null )
{
$impersonator_user = $existing_impersonator_user;
if ( !is_array( $impersonator_user ) )
$impersonator_user = ( is_array( $current_user ) and isset( $current_user['id'] ) and (int)$current_user['id'] === self::ADMIN_USER_ID ) ? $current_user : null;
return [
'user' => $target_user,
'impersonator_user' => $impersonator_user
];
}
private static function getImpersonatorUser()
{
$session_value = \S::get_session( self::IMPERSONATOR_SESSION_KEY );
if ( is_array( $session_value ) )
return $session_value;
return null;
}
private static function forbiddenRedirect()
{
\S::alert( 'Brak uprawnien do zarzadzania uzytkownikami.' );
header( 'Location: /' );
exit;
}
private static function permissionDefinitions()
{
return [
'module_labels' => [
'tasks' => 'Zadania',
'projects_view' => 'Projekty: przegladanie',
'projects_add' => 'Projekty: dodawanie',
'projects_edit' => 'Projekty: edycja',
'projects_delete' => 'Projekty: usuwanie',
'work_time' => 'Czas pracy',
'finances' => 'Finanse',
'crm' => 'CRM',
'wiki' => 'Wiki'
],
'permission_groups' => [
'Podstawowe' => [ 'tasks', 'work_time', 'wiki' ],
'Projekty' => [ 'projects_view', 'projects_add', 'projects_edit', 'projects_delete' ],
'Pozostale' => [ 'finances', 'crm' ]
]
];
}
}