<?php
if (_ENGINE_MODE=='site') include (_DIR_TO_ROOT."/vendor/autoload.php") ;
use LdapTools\Configuration;
use LdapTools\DomainConfiguration;
use LdapTools\LdapManager;
use LdapTools\Object\LdapObjectType;
use LdapTools\Exception\EmptyResultException;

//if (_ENGINE_MODE=='site') include(_DIR_TO_ROOT.'/vendor/AD.php') ;

$__functions['init'][]='_AD_site_vars' ;
$__functions['boot_site'][]='_AD_site_boot' ;

function AD() {
  if (isset($_SESSION['AD_system'])){
    return($_SESSION['AD_system']);
  } else {
    $_SESSION['AD_system']=new c_AD_system();
    return($_SESSION['AD_system']);
  }
}


function _AD_site_vars()
{
    $_SESSION['init_options']['AD']['debug']=0 ;

    $_SESSION['ARR_AD_to_ESMO_account_name']=array (0=>'firstName lastName',
                                                    1=>'displayName',
                                                    2=>'lastName firstName',
                                                    ) ;
}

function _AD_site_boot($options)
{
  create_system_modul_obj('AD',$options) ;

}


class c_AD_system
{
    public $AD_list ;
    var $domainName;
    var $params=array() ;
    var $config ;
    var $domain ;
    var $manager ;
    var $connected = false;
	var $show_debug_check_AD_user = false ;

    function __construct($create_options=array())
    {
      ENGINE()->reg_ext('AD','ActiveDirectory') ;
    }

    function declare_menu_items_4($page)
    {   $page->menu['/cab/setting/']['items']['/cab/AD/setting/']='Active Directory' ;
    }

    function AD_connect()
    {
        if (!$this->connected) {
            // Эти настройки нужно указать в админке или конфиге
            $this->domainName=$GLOBALS['LS_AD_domainName'];

            $this->params = array(
                'username' => $GLOBALS['LS_AD_username'],
                'password' => $GLOBALS['LS_AD_password'],
                'servers' => [$GLOBALS['LS_AD_servers']],
                'tls' => $GLOBALS['LS_AD_ldap_tls']
            );

            //LOGS()->reg_log('AD',$this->domainName,array('data'=>$this->params)) ;


            $this->config = new Configuration();
            $this->domain = (new DomainConfiguration($this->domainName))
            ->setBaseDn($this->params['base_dn'])
            ->setServers($this->params['servers'])
            ->setUsername($this->params['username'])
                ->setPassword($this->params['password'])
                ->setUseTls($this->params['tls']);
            $this->config->addDomain($this->domain);
            $this->manager = new LdapManager($this->config);
        }
    }

    function get_group_members($GROUP)
    {
        $this->AD_connect() ;
        try {
            $group = $this->manager->buildLdapQuery()->select('members')->fromGroups()->where(['name' => $GROUP])->getLdapQuery()->getSingleResult();
            if ($group->has('members')) {
                return $group->get('members');
            } else {
                return [];
            }
        } catch (EmptyResultException $e) {
            return null;
        }
    }

    function get_group_members2($GROUP)
    {
        $this->AD_connect() ;
        try {
            $group = $this->manager->buildLdapQuery()->select('members')->fromGroups()->where(['name' => ''])->getLdapQuery()->getSingleResult();
            if ($group->has('members')) {
                return $group->get('members');
            } else {
                return [];
            }
        } catch (EmptyResultException $e) {
            return null;
        }
    }

    function get_user_by_dn($dn)
    {
        $this->AD_connect();
        try {
            $user = $this->manager->buildLdapQuery()->select(['name', 'lastName', 'firstName', 'guid', 'username'])->fromUsers()->where(['dn' => $dn])->getLdapQuery()->getSingleResult();
            $result['lastName'] = $user->has('lastName') ? $user->get('lastName') : '';
            $result['firstName'] = $user->has('firstName') ? $user->get('firstName') : '';
            $result['fullName'] = $result['lastName'].' '.$result['firstName'];
            $result['guid']=$user->get('guid') ;
            $result['username']=$user->get('username') ;
        } catch (EmptyResultException $e) {
            $result = null;
        }
        return $result;
    }

    function find_groups($GROUP, $limit=100)
    {
        $this->AD_connect() ;
        try {
            $q = $this->manager->buildLdapQuery();
            $groups = $q->fromGroups()
                ->where($q->filter()->startsWith('name', $GROUP))
                ->setSizeLimit($limit)
                ->getLdapQuery()
                ->getResult();
            // return $group->get('members');
        } catch (EmptyResultException $e) {
            return [];
        }
        return $groups;
    }

   function get_AD_member_info($REMOTE_USER)
   {  $this->AD_connect() ;
      $result=array() ;
      $login = explode('@',$REMOTE_USER, 2)[0];
      if ($login)
      {   try
          { $user = $this->manager->buildLdapQuery()->select(['name', 'lastName', 'firstName', 'dn', 'guid', 'username', 'memberOf','displayName'])->fromUsers()->where(['samaccountname' => $login])->getLdapQuery()->getSingleResult();
            $result['username']=$user->get('username') ;
            $result['name']=$user->has('lastName') ? $user->get('lastName') : $result['username'];
            $result['lastName']=$user->has('lastName') ? $user->get('lastName') : $result['username'];
            $result['firstName']=$user->has('firstName') ? $user->get('firstName') : $result['username'];
            $result['dn']=$user->get('dn') ;
            $result['guid']=$user->get('guid') ;
            $result['username']=$user->get('username') ;
            $result['displayName']=$user->get('displayName') ;
            $result['groups'] = [];

            $groups = $user->has('memberOf') ? $user->get('memberOf') : [];
            if (!is_array($groups)) {
                $groups = [$groups];
            }

            foreach ($groups as $dn) {
               $group = $this->manager->buildLdapQuery()->select(['guid', 'name'])->fromGroups()->where(['dn' => $dn])->getLdapQuery()->getSingleResult();
               $guid = $group->get('guid');
               $name = $group->get('name');
               $result['groups'][$guid] = $name;
            }
            if ($_SESSION['ARR_AD_to_ESMO_account_name'][$GLOBALS['LS_AD_to_ESMO_account_name']]) {
                $AD_field_name_value_array=[];
                $AD_field_name_array=explode(' ',$_SESSION['ARR_AD_to_ESMO_account_name'][$GLOBALS['LS_AD_to_ESMO_account_name']]);
                foreach ($AD_field_name_array as $AD_field_name) {
                    if ($result[$AD_field_name]) $AD_field_name_value_array[]=$result[$AD_field_name];
                }
                if (_sizeof($AD_field_name_value_array)) {
                    $result['account_ESMO_name']=implode(' ',$AD_field_name_value_array);
                } else {
                    $result['account_ESMO_name']=$result['firstName'].' '.$result['lastName'];
                }
            } else {
                $result['account_ESMO_name']=$result['firstName'].' '.$result['lastName'];
            }
          }
          catch (Exception $e)
          {  switch($e->getMessage())
             { //case 'LDAP returned no results': $result= []; break ;
               default: LOGS()->reg_log('AD_error','get_AD_member_info("'.$REMOTE_USER.'"): '.$e->getMessage()) ;

             }
             $result= [];
          }
      } else  $result= [];

      LOG_JSON('AD_autorize')->reg('get_AD_member_info','',array('data'=>$result)) ;

      return($result) ;
   }

   function get_list_groups()
   {  $result=array() ;
      $this->AD_connect() ;
      //# All groups
      $groups = $this->manager->buildLdapQuery()->fromGroups()->getLdapQuery()->getResult();
      //print_r($groups) ;
      //if (_sizeof($groups)) foreach($groups as $LdapObject) $result[$LdapObject->get('guid')] = ['name'=>$LdapObject->get('name'),'dn'=>$LdapObject->get('dn')];
      if (_sizeof($groups)) foreach($groups as $LdapObject) $result[$LdapObject->get('guid')] = $LdapObject->get('name');
      else { $result= []; }
      return($result) ;
   }

   function on_event_check_autorize($data=array())
   {   if (MEMBER()->id) return ;
       ob_start() ;
       //trace() ;
       //$_SERVER['REMOTE_USER']='s2@AD.KVZRM.RU' ;
       $result=array() ;
       //echo 'MEMBER()->id='.MEMBER()->id.'<br>' ;
       //echo 'REMOTE_USER='.$_SERVER['REMOTE_USER'].'<br>' ;
       //echo 'member_AD_is_logout='.$_SESSION['member_AD_is_logout'].'<br>' ;
       //echo 'no_ecp_check_sert_by_auth='.$_SESSION['no_ecp_check_sert_by_auth'].'<br>' ;
       //echo 'LS_ecp_check_sert_by_auth='.$GLOBALS['LS_ecp_check_sert_by_auth'].'<br>' ;
       //echo 'AD_user_sert_valid='.$_SESSION['AD_user_sert_valid'].'<br>' ;
       //echo 'MEMBER()->from_AD='.MEMBER()->from_AD.'<br>' ;

   	   //$cur_page=(is_object($data['cur_page']))? $data['cur_page']:null ;
       //echo 'MEMBER()->id='.MEMBER()->id.'<br>' ;
       //echo 'LS_AD_allow_auth_by_AD_login='.$GLOBALS['LS_AD_allow_auth_by_AD_login'].'<br>' ;
       //echo 'REMOTE_USER='.$_SERVER['REMOTE_USER'].'<br>' ;

	   if (!MEMBER()->id and                                 // если пользователь еще не авторизован
	       $GLOBALS['LS_AD_allow_auth_by_AD_login'] and      // если разрешена авторизация по AD
	       $_SERVER['REMOTE_USER'] and                      // если передано имя пользователя AD
	       !$_SESSION['member_AD_is_logout']             // и пользователь не выходил принудительно с системы
	      )
	   { ob_start() ;
         LOG_JSON('AD_autorize')->reg('on_event_check_autorize','проверяем авторизацию аккаунта по AD логину') ;
		 $result=$this->check_AD_user(array('debug'=>$this->show_debug_check_AD_user)) ;

		 // если результат авторизации - необходимо проверить сертификат  и была попытка авторизоваться  и сертификат пользователя еще не проверен
		 if ($result['code']=='check_sertificate' and !$_SESSION['member_AD_is_logout']  and !$_SESSION['autorize_process']['sert_valid'])  // и сертификат пользователя еще не проверен
		 {  $_SESSION['autorize_process']['account_id']=$result['account_id'] ;
		    echo 'редиректим на страницу /cab/cryptopro/check_sert/<br>' ;
			ENGINE()->redirect_301_to('/cab/cryptopro/check_sert/') ;
		 }

         // если требуется выбор группы сотрудника и группа еще не выбрана
		 if ($result['code']=='select_group' and !$_SESSION['member_AD_is_logout']  and !$_SESSION['autorize_process']['group_id'])  // и группа пользователя еще не выбрана
		 {  $_SESSION['autorize_process']['account_id']=$result['account_id'] ;
            $_SESSION['autorize_process']['account_group_id']=$result['account_group_id'] ;
            echo 'редиректим на страницу /cab/account/select_group/<br>' ;
		   	ENGINE()->redirect_301_to('/cab/account/select_group/') ;
		 }

         // если требуется выбор группы сотрудника и группа еще не выбрана
		 if ($result['code']=='select_rol' and !$_SESSION['member_AD_is_logout']  and !$_SESSION['autorize_process']['rol_id'])  // и роль пользователя еще не выбрана
		 {  $_SESSION['autorize_process']['account_id']=$result['account_id'] ;
            echo 'редиректим на страницу /cab/cryptopro/select_rol/<br>' ;
		   	ENGINE()->redirect_301_to('/cab/AD/select_rol/') ;
		 }
		 echo 'Авторизация завершена' ;
         $text=ob_get_clean() ;
         LOG_JSON('AD_autorize')->reg('on_event_check_autorize',$text) ;
         $log_fname=LOG_JSON('AD_autorize')->flush('AD_autorize_'.ENGINE()->generate_UID()) ;
         LOGS()->reg_log('AD_autorize','<a href="'.$log_fname.'" target="_blank">Лог</a>',array('account_id'=>MEMBER()->id)) ;
	   }

       if (MEMBER()->id and $_SERVER['REMOTE_USER'] and MEMBER()->login!=$_SERVER['REMOTE_USER'])
       { //echo 'Текущая сессия авторизована под пользователем <strong>'.MEMBER()->name.'</strong>, <br>' ;
         //echo 'Производим выход из текущего аккаунта ['.MEMBER()->name.']<br>' ;
         //$member_logout=1 ;
         //$result=array('code'=>'cur_account_logout') ;

         //echo 'Обновляем данные аккаунта ['.$_SERVER['REMOTE_USER'].']<br>' ;
         //$result=ACCOUNTS()->account_save(MEMBER()->id,array('login'=>$_SERVER['REMOTE_USER'],'rol'=>$main_rol,'parent'=>$main_group,'obj_name'=>$data['firstName'].' '.$data['lastName'])) ;
         //if ($rec_account['rol']) $member_autorize=1 ;
        //else $_SESSION['autorize_process']['logs'][]='Не задана роль аккаунта, авторизация отклонена' ;
       }

       $text=ob_get_clean() ;
       if ($text) LOGS()->reg_log('on_event_check_autorize',$text) ;



   }


    // проверка пользователя AD
    // если проверка будет успешной и текущий пользователь еще не авторизован
    // пользователь будет авторизован
    // добавить чтобы при $debug=2 на экран выводилась инфа по работе с AD

    function check_AD_user($options=array())
        {  if (MEMBER()->id) return ; // вход авторизованным пользователям запрещен
           ob_start() ;
           LOG_JSON('AD_autorize')->reg('check_AD_user','URL входа: '._MAIN_PROTOCOL._CUR_DOMAIN._CUR_PAGE_DIR._CUR_PAGE_NAME) ;
           LOG_JSON('AD_autorize')->reg('check_AD_user','Пользователь: '.$_SERVER['REMOTE_USER']) ;
           //echo 'REMOTE_USER='.$_SERVER['REMOTE_USER'].'<br>' ;
           $member_autorize=0 ; // флаг необходимости авторизации пользователя после проверки в AD
           $member_logout=0 ; // флаг необходимости разавторизации  после проверки в AD
           $require_select_group=0 ; // флаг необходимости ручного выбора группы
           $require_select_rol=0 ; // флаг необходимости ручного выбора роли
           $options_autorize=array() ; // опции авторизации
           $text_AD_info='' ;
           $group_by_AD=0 ; $default_group=$GLOBALS['LS_AD_default_group'] ; $root_group=1 ;
           $data=array() ; $rec_account=array() ;

           //$GLOBALS['LS_select_group_to_account']=1 ;
           //$GLOBALS['LS_ecp_check_sert_by_auth']=1 ;

           // если текущее имя пользователя не соответствует имени пользователя в массиве авторизации - удаляем все данные
           if ($_SERVER['REMOTE_USER'] and $_SESSION['autorize_process']['user_name'] and $_SERVER['REMOTE_USER']!=$_SESSION['autorize_process']['user_name']) unset($_SESSION['autorize_process']) ;
           if (!isset($_SESSION['autorize_process'])) $_SESSION['autorize_process']=array('from_AD'=>1,'block_smena'=>0,'user_name'=>$_SERVER['REMOTE_USER']) ;

           // если процесс авторизации начат, не делаем повторный запрос к AD на данные по аккаунту, данные уже сохранены в сессии
//           if (_sizeof($_SESSION['autorize_process']['AD_info'])) $data=$_SESSION['autorize_process']['AD_info'] ;
           /*else*/ if ($_SERVER['REMOTE_USER'])
           {  echo 'Выполняем запрос к AD - ' ;
              $data=$this->get_AD_member_info($_SERVER['REMOTE_USER']) ;
              $_SESSION['autorize_process']['AD_info']=$data ;
              echo (_sizeof($data))? '<span class="green">OK</span>':'<span class="red">ERROR</span>' ;
              echo '<br>' ;
           }

           if ($_SERVER['REMOTE_USER'] and _sizeof($data))
           {     //$data['firstName']='Test2' ;
                 //unset($data['groups']['d1c9435f-8350-4ef7-9aaf-2ba9b4f24b84']);

                 $recs_group=execSQL('select * from obj_site_account where clss in (1,206) and enabled=1') ;
                 // переделать - делать один запрос к БД на все группы сотрудника

                 $arr_rol=array() ; $main_rol=0 ;$arr_group=array() ; $arr_AD_result=array() ;
                 if (_sizeof($data['groups']))  foreach($data['groups'] as $guid=>$group_name)
                   { $id_grp=_IL('IL_ad_groups')->get_id_of_value($group_name) ;
                     if ($id_grp)
                     {   // id роли храниться в поле personal_id
                         $rec_AD=_IL('IL_ad_groups')->recs[$id_grp] ;
                         /*if (!$rec_AD['personal_id'])
                         {
                            ob_start() ;
                            execSQL('select * from view_IL_ad_groups',2) ;
                            damp_array($rec_AD,1,-1) ;
                            $text=ob_get_clean() ;
                            LOGS()->reg_log('AD_error','Не задано ID роли для группы '.$group_name.':<br>'.$text) ;

                         } */
                         if ($rec_AD['personal_id'] and $rec_AD['enabled']) { $arr_rol[]=$rec_AD['personal_id'] ;  $arr_AD_result[$rec_AD['obj_name']]['Роль']=$_SESSION['ARR_roll'][$rec_AD['personal_id']]['obj_name'].' [id='.$rec_AD['personal_id'].']' ;   }
                         if ($rec_AD['group_id'] and $rec_AD['enabled']) { $arr_group[]=$rec_AD['group_id'] ; $arr_AD_result[$rec_AD['obj_name']]['Группа']=$recs_group[$rec_AD['group_id']]['obj_name'].' [id='.$rec_AD['group_id'].']' ;   }
                     }
                   }
                 else echo 'Список групп AD-пользователя пуст<br>' ;

                 // вывод по сопоставлению пойдет в файловый лог
                 ob_start() ;
                 ?><h3>Результат сопоставления групп AD и групп, ролей ЭСМО</h3><?
                 print_2x_arr($arr_AD_result) ;
                 LOG_JSON('AD_autorize')->reg('check_AD_user',ob_get_clean()) ;


                 ob_start() ;
                 ?><h3>Проверка роли аккаунта</h3><?
                 // проверям роли ЭСМО, соответствующие группам AD пользователя, получаем главную роль сотрудника
                 if (_sizeof($arr_rol))
                 {  asort($arr_rol) ;
                    $main_rol=$arr_rol[0] ;
                    echo 'AD=>ESMO: роль аккаунта: "<strong>'.$_SESSION['ARR_roll'][$main_rol]['obj_name'].'</strong>" [id='.$main_rol.']<br>' ;
                    // если у аккаунта AD больше одной роли и включена опция выбора роли - включаем опцию выбора роли
                    // при этом $main_rol не трогаем, так как новый аккаут AD надо создать с ролью по умолчанию
                    // которая затем будет именена на выбранную роль
                    if ($GLOBALS['LS_AD_allow_select_rol'] and _sizeof($arr_rol)>1 and !$_SESSION['autorize_process']['rol_id'] and stripos(session_id(),'vterm')===false) $require_select_rol=1 ;
                    $_SESSION['autorize_process']['arr_rols']=$arr_rol ;
                 }
                 else
                 {   echo '<div class="red">Список доступных ролей для данного аккаунта пуст</div>' ;
                     $result=['error'=>'Список доступных ролей для данного аккаунта пуст'] ;
                     return($result);
                 }
                 LOG_JSON('AD_autorize')->reg('check_AD_user',ob_get_clean()) ;

                 ob_start() ;
                 ?><h3>Проверка группы аккаунта</h3><?
                 // проверям группы ЭСМО, соответствующие группам AD пользователя, получаем главную группу сотрудника
                 if (_sizeof($arr_group))
                 {  asort($arr_group) ;
                    if ($arr_group[0]) $group_by_AD=$arr_group[0] ;
                 }
                 //if (!$main_group and $GLOBALS['LS_AD_default_group']) $main_group=$GLOBALS['LS_AD_default_group'] ;
                 //else  $main_group=1 ; // по умолчанию используем корневую группу
                 echo 'AD=>ESMO: группа аккаунта: ' ;
                 echo ($group_by_AD)? '"<strong>'.$recs_group[$group_by_AD]['obj_name'].'</strong>" [id='.$group_by_AD.']':'<span class="red">не сопоставлена</span>' ;
                 echo '<br>' ;

                 // ищем запись в аккаунтах, соответствубщую данной роли, если пользователь еще не авторизован
                 if ($data['guid'])
                 { $rec_account=execSQL_van('select * from obj_site_account where UID="'.$data['guid'].'"') ;
                   echo 'Поиск аккаунта по guid: ' ;
                   echo ($rec_account['pkey'])? '<span class="green">OK</span> <strong>'.$rec_account['obj_name'].'</strong> ['.$rec_account['pkey'].']':'<span class="red">NOT FOUND</span>' ;
                   echo '<br>' ;
                 }

                 // если не авторизовали по guid - пытаемся найти запись по логину. Это ситуация для авторизации сотрудников AD с уже существующими аккаунтами ЭСМО
                 if (!$rec_account['pkey'])
                 { $rec_account=execSQL_van('select * from obj_site_account where login="'.$data['username'].'" or login="'.$_SERVER['REMOTE_USER'].'"') ;
                   echo 'Поиск аккаунта по username: ' ;
                   echo ($rec_account['pkey'])? '<span class="green">OK</span> <strong>'.$rec_account['obj_name'].'</strong> ['.$rec_account['pkey'].']':'<span class="red">NOT FOUND</span>' ;
                   echo '<br>' ;
                 }

                 if (!$rec_account['pkey'])
                   { echo 'Аккаунт ЭСМО не найден, ' ;
                     echo ($GLOBALS['LS_AD_allow_create_account'])? '<span class="green">автодобавление разрешено</span>':'<span class="red">автодобавление запрещено</span>' ;
                     echo '<br>' ;
                     if ($GLOBALS['LS_AD_allow_create_account'])
                     { if ($main_rol)
                       { echo 'Создаем новый аккаунт на основе данных аккаунта AD<br>' ;
                         if ($group_by_AD)         $use_group=$group_by_AD ;
                         else if ($default_group)  $use_group=$default_group ;
                         else                      $use_group=$root_group ;
                         $account_data = ['group_id'=>$use_group, 'login'=>$_SERVER['REMOTE_USER'], 'rol'=>$main_rol, 'name'=>$data['account_ESMO_name'], 'UID'=>$data['guid'], 'ext_info'=>['AD_group'=>$data['groups']]];
                         // Приоритет: 1) LS_AD_working_name_for_rol для роли 2, 2) working из роли
                         if ($main_rol == 2 && $GLOBALS['LS_AD_working_name_for_rol']) {
                             $account_data['working'] = $GLOBALS['LS_AD_working_name_for_rol'];
                         } elseif (isset($_SESSION['ARR_roll'][$main_rol]['working']) && $_SESSION['ARR_roll'][$main_rol]['working']) {
                             $account_data['working'] = $_SESSION['ARR_roll'][$main_rol]['working'];
                         }
												 $res=ACCOUNTS()->account_create($account_data);
												 damp_array($res,1,-1) ;
                       }
                       else echo 'Не определена роль аккаунта в ЭСМО, <span class="red">автодобавление аккаунта заблокировано</span><br>' ;
                     }
                   }
                 else
                   {   //  два пути
                       // 1. Изменять роль аккаунта в БД
                       // 2. авторизовывать аккаунт под нужной ролью
                       // выбираем первое, так как надежнее
                       if ($_SESSION['autorize_process']['rol_id'])
                       { ACCOUNTS()->account_save($rec_account['pkey'],['rol'=>$_SESSION['autorize_process']['rol_id']]) ;
                         $rec_account['rol']=$_SESSION['autorize_process']['rol_id'] ;
                       }

                       echo 'Проверяем данные аккаунта ['.$rec_account['obj_name'].']<br>' ;
                       $rec=array('UID'=>$data['guid'],'obj_name'=>$data['account_ESMO_name'],'contact_name'=>mb_substr($data['displayName'],0,128)) ;
                       // соответствие роли AD и ЭСМО проверяется только при выключенной опции LS_AD_allow_select_rol
                       if (($rec_account['rol']!=$main_rol and !$GLOBALS['LS_AD_allow_select_rol']) or ($rec_account['rol']!=$main_rol and _sizeof($_SESSION['autorize_process']['arr_rols'])==1))
                       { echo 'Роль аккаунта в ЭСМО отличается от роли аккаунта по группам AD.<br>' ;
                         echo 'ЭСМО: роль "'.$_SESSION['ARR_roll'][$rec_account['rol']]['obj_name'].'"<br>' ;
                         echo 'AD: роль "'.$_SESSION['ARR_roll'][$main_rol]['obj_name'].'"<br>' ;
                         if ($GLOBALS['LS_AD_allow_change_rol']) { $rec['rol']=$main_rol ; echo 'Будет изменена роль аккаунта в ЭСМО<br>' ; }
                         else  echo 'Изменение роли аккаунта ЭСМО запрещено<br>' ;
                       }
                       if ($group_by_AD and $rec_account['parent']!=$group_by_AD)
                       { echo 'Рабочая группа аккаунта в ЭСМО отличается от местоположения аккаунта по группам AD.<br>' ;
                         echo 'ЭСМО: рабочая группа "'.ACCOUNTS()->get_group_name($rec_account['parent']).'"<br>' ;
                         echo 'AD: рабочая группа "'.ACCOUNTS()->get_group_name($group_by_AD).'"<br>' ;
                         if ($GLOBALS['LS_AD_allow_change_group']) { $rec['parent']=$group_by_AD ;   echo 'Разрешено изменение группа аккаунта<br>' ; }
                         else  echo 'Изменение рабочей группы аккаунта ЭСМО запрещено<br>' ;
                       }
                       ACCOUNTS()->account_save($rec_account['pkey'],$rec) ;
                   }
                 LOG_JSON('AD_autorize')->reg('check_AD_user',ob_get_clean()) ;

                 ob_start() ;
                 ?><h3>Авторизация аккаунта</h3><?
                 //  повторное получение данных по аккаунту с учетом возможной правки их после получения из AD
                 $rec_account=execSQL_van('select * from obj_site_account where UID="'.$data['guid'].'"') ;
                 if ($rec_account['pkey'] and $rec_account['rol'] and $rec_account['enabled'])
                   {   echo 'Авторизуем аккаунт ['.$rec_account['obj_name'].']<br>' ;
                       $rec_ARM=ACCOUNTS()->get_group_id_to_ARM_by_ip(IP) ;
                       $has_childrens_group=execSQL_value('select count(pkey) from obj_site_account where parent='.$rec_account['parent'].' and clss=206 and enabled=1') ;
                       echo 'АРМ по IP '.IP.': <strong>'.(($rec_ARM['pkey'])? 'Найден':'Не найден').'</strong><br>' ;

                       // группа по AD имеет наивысшый приоритет - если она задана, пользователь может авторизоваться только в этой группе
                       // если группа AD не задана, проверяем наличие АРМ аккаунта.
                       // если арм аккаунта нет:
                       // проверяем положена ли аккаунту выбор группы
                       // выборп группы положен, если:
                       // -  LS_select_group_to_account=1 и rol=2 и у родительской группы сотрудника есть подгруппы
                       // если группа аккаунта==1, проверяем наличие AРМ. Если АРМ найден, пользователь будет авторизован только в группе АРМ
                       // если АРМ не найден и включена опция  LS_select_group_to_account - аккаунту будет предложено выбрать группу перед авторизацией
                       // если опция LS_select_group_to_account выключена, будет использована переменная LS_AD_default_group
                       // если она не определана, будет использована группа 1 (корневая)
                       if ($group_by_AD)                  { $use_group=$group_by_AD ; $select_group_status='На основе сопоставления групп AD' ; }
                       elseif ($rec_ARM['group_id'])          { $use_group=$rec_ARM['group_id'] ; $select_group_status='На основе родительской группы АРМ' ; }
                         else
                       { $require_select_group=($GLOBALS['LS_select_group_to_account'] and $rec_account['rol']==2 and !$options['group_id_to_auth'] and $has_childrens_group)? 1:0 ;
                         if ($require_select_group)
                         {
                             if (!$_SESSION['autorize_process']['group_id']) { $use_group=0 ; $select_group_status='Требуется ручной выбор группы' ; }
                             else { $use_group=$_SESSION['autorize_process']['group_id'] ;$select_group_status='Выбрана группа' ; }

                         }
                         elseif ($rec_account['parent']>1) { $use_group=$rec_account['parent'] ; $select_group_status='использована родительская группа аккаунта' ;}
                            elseif ($default_group) { $use_group=$default_group ; $select_group_status='использована группа по умолчанию' ;}
                            else  { $use_group=$root_group ; $select_group_status='использована корневая группа'; }
                         }

                       echo 'Выбор группы: <strong>'.$select_group_status.'</strong> '.(($use_group)? ACCOUNTS()->get_group_name($use_group):'').' <br>' ;

                       $require_check_sert=$GLOBALS['LS_ecp_check_sert_by_auth'] // если включена проверка сертификата
                                           && $rec_account['certificate']['IssuerName']!='Эмуляция ЭЦП' // и аккаунт не в эмуляции сертификата
                                           && $_SESSION['ARR_roll'][$rec_account['rol']]['use_auch_as_smena']==1 // и аккаунт работает под сменой
                                           && (bool)!$_SESSION['autorize_process']['sert_valid'] ; // и нет флага что сертификат проверен

                       // подробная информация по проверке сертификата
                       $check_sert_status='' ;
                       if (!$require_check_sert) $check_sert_status='Не требуется' ;
                       else if ($require_check_sert and !$_SESSION['autorize_process']['sert_valid']) $check_sert_status='Требуется' ;
                       else if ($require_check_sert and $_SESSION['autorize_process']['sert_valid']==1) $check_sert_status='Успешно пройдена' ;
                       else if ($require_check_sert and $_SESSION['autorize_process']['sert_valid']==2) $check_sert_status='Пропущена, выбран вход без открытия смены' ;

                       echo 'Проверка сертификата: <strong>'.$check_sert_status.'</strong><br>' ;

                       // проверяем все обязатеьные условия для авторизации пользователя
                       // если что-то нет - возвращаем код действия для перехода на нужную страницу действия
                       // если обязательных условий нет - авториризуем пользователя


                       if ($require_select_rol and !$_SESSION['autorize_process']['rol_id']) $result=array('code'=>'select_rol','account_id'=>$rec_account['pkey']) ;
                       elseif ($require_select_group and !$_SESSION['autorize_process']['group_id']) $result=array('code'=>'select_group','account_id'=>$rec_account['pkey'],'account_group_id'=>$rec_account['parent']) ;
                       elseif ($require_check_sert) $result=array('code'=>'check_sertificate','account_id'=>$rec_account['pkey']) ; // возвращаем ответ, что требуется проверка сертификата
                       else
                       { $options_autorize=array() ;
                         if ($_SESSION['autorize_process']['block_smena']) $options_autorize['block_smena']=$_SESSION['autorize_process']['block_smena'] ;
                         //if ($_SESSION['autorize_process']['group_id'])    $options_autorize['group_id_to_auth']=$_SESSION['autorize_process']['group_id'] ;
                         //else                                              $options_autorize['group_id_to_auth']=$use_group ;
                         $options_autorize['group_id_to_auth']=$use_group ;
                         //if ($_SESSION['autorize_process']['rol_id']) $options_autorize['rol_id_to_auth']=$_SESSION['autorize_process']['rol_id'] ;
                         $member_autorize=1 ;
                       }
                   }
                   elseif ($rec_account['pkey'] and !$rec_account['enabled']) echo 'УЗ заблокирована в ЛК, вход запрещен<br>' ;
                   elseif ($rec_account['pkey'] and !$rec_account['rol']) echo 'Роль не определена, вход не выполнен<br>' ;
                   elseif (!$rec_account['pkey']) echo 'Отсутствует аккаунт ЭСМО, вход не выполнен<br>' ;

                 LOG_JSON('AD_autorize')->reg('check_AD_user',ob_get_clean()) ;

           }

                 /* !!!! отключено в связи с тем, что слишком накладно при каждом обращении к серверу проверять валидность текущих параметров пользователя
                    !!!! это надо сделать либо раз в минуту - в фоне запрашивать данные по AD  пользователя
                    !!!! либо проверять данные только при авторизации
                 else
                 { echo 'Авторизован текущий пользователь <strong>'.MEMBER()->name.'</strong><br>' ;
                   // если изменилась роль текущего аккаунта или группа - необходимо переавтризовать пользователя
                   //damp_array(MEMBER()) ;
                   echo 'Текущая роль аккаунта: '.MEMBER()->rol.'<br>' ;
                   echo 'Текущая группа аккаунта: '.MEMBER()->cur_group_id.'<br>' ;

                   $relogin_account=0 ;
                   if ($main_rol and MEMBER()->rol!=$main_rol) { $relogin_account=1 ; echo 'Аккаунт будет перелогин в связи с изменением роли<br>' ; }
                   if ($main_group and MEMBER()->cur_group_id!=$main_group) { $relogin_account=1 ; echo 'Аккаунт будет перелогин в связи с изменением рабочей группы<br>' ; }
                   if ($relogin_account)
                   { echo 'Выходим из текущего аккаунта ['.MEMBER()->name.']<br>' ;
                     ACCOUNTS()->member_logout()  ;
                   }
                   echo 'Сохраням данные AD авторизованного аккаунта<br>' ;

                   $result=ACCOUNTS()->account_save($rec_account['pkey'],array('login'=>$_SERVER['REMOTE_USER'],'rol'=>$main_rol,'parent'=>$main_group,'obj_name'=>$data['firstName'].' '.$data['lastName'],'ext_info'=>array('AD_group'=>$data['groups']))) ;
                   $rec_account2=execSQL_van('select * from obj_site_account where pkey="'.$rec_account['pkey'].'"') ;
                   //damp_array($rec_account2,1,-1) ;
                   echo 'Текущая роль аккаунта!: '.$rec_account2['rol'].'<br>' ;
                   echo 'Текущая группа аккаунта: '.$rec_account2['group_id'].'<br>' ;

                   //damp_array($rec_account) ;
                   if ($relogin_account)
                   { if ($main_rol) $member_autorize=1 ;
                     else           echo 'Авторизация отклонена вследствии отсуствия роли аккаунта<br>' ;
                   }
                   else if (!$main_rol)
                   { ACCOUNTS()->member_logout()  ;
                     echo 'Выход с аккаунта по факту отсутствия роли для групп аккаунта<br>' ;
                     $reg_log=1 ;
                   }

                 }  */

               //if (_sizeof($_SESSION['autorize_process']['logs'])) echo implode('<br>',$_SESSION['autorize_process']['logs']) ;
          //}
          else if (!$_SERVER['REMOTE_USER'])  $result=array('error'=>'Не задано имя пользователя в переменной окружения REMOTE_USER: "'.$_SERVER['REMOTE_USER'].'"') ;
          else if (!_sizeof($data))  $result=array('error'=>'Ошибка при получении данных от AD по пользователю "'.$_SERVER['REMOTE_USER'].'"') ;


          LOG_JSON('AD_autorize')->reg('check_AD_user',ob_get_clean(),array('data'=>$result)) ;
         // LOGS()->reg_log('AD.check_AD_user',$text,array('data'=>$result,'save_to_file'=>$text_AD_info)) ;

          if ($member_autorize)
          {
              ACCOUNTS()->member_autorize($rec_account,$options_autorize) ;
              MEMBER()->from_AD=1 ;
              //echo 'Авторизуем аккаунт ['.MEMBER()->name.'] в группе '.MEMBER()->cur_group_name.'<br>' ;
              unset($_SESSION['autorize_process']) ; // сбрасываем данные по текущему процессу авторизации
          }
          if ($member_logout)
          {
              ACCOUNTS()->member_logout()  ;
              //echo 'Авторизуем аккаунт ['.MEMBER()->name.'] в группе '.MEMBER()->cur_group_name.'<br>' ;
              unset($_SESSION['autorize_process']) ; // сбрасываем данные по текущему процессу авторизации
          }


          return($result) ;

    }

//Текущая сессия авторизована под пользователем Иван Иванов,
//Производим выход из текущего аккаунта [Иван Иванов]

    function find_users($NAME, $limit=100)
    {
        $this->AD_connect() ;
        try {
            $q = $this->manager->buildLdapQuery();
            $users = $q->fromUsers()
                ->where($q->filter()->contains('username', $NAME))
                ->setSizeLimit($limit)
                ->getLdapQuery()
                ->getResult();
            // return $group->get('members');
        } catch (EmptyResultException $e) {
            return [];
        }
        return $users;
    }

    function get_AD_member_groups($login) {
        $this->AD_connect() ;
        $result=array() ;
        if ($login)
        {   try
        { $user = $this->manager->buildLdapQuery()->select(['memberOf'])->fromUsers()->where(['username' => $login])->getLdapQuery()->getSingleResult();
            $result = [];

            $groups = $user->get('memberOf') ;
            if(!empty($groups)) {
                if(is_array($groups)) {
                    foreach ($groups as $dn) {
                        $group = $this->manager->buildLdapQuery()->select(['guid', 'name'])->fromGroups()->where(['dn' => $dn])->getLdapQuery()->getSingleResult();
                        $result[$group->get('guid')] = $group->get('name');
                    }
                } else {
                    $group = $this->manager->buildLdapQuery()->select(['guid', 'name'])->fromGroups()->where(['dn' => $groups])->getLdapQuery()->getSingleResult();
                    $result[$group->get('guid')] = $group->get('name');
                }
            } else {
                $result = [];
            }
        }
        catch (Exception $e)
        {  switch($e->getMessage())
        { //case 'LDAP returned no results': $result= []; break ;
            default: LOGS()->reg_log('AD_error','get_AD_member_groups("'.$login.'"): '.$e->getMessage()) ;

        }
            $result= [];
        }
        } else  $result= [];
        return($result) ;
    }
}
