<?php

class UserController extends Controller
{

  public $layout = '//layouts/column2';

  public function filters()
  {
    return array (
        'accessControl',
        array (
            'application.filters.SyslogFilter' 
        ) 
    );
  }

  public function accessRules()
  {
    return array (
        // può cancellare
        array (
            'allow',
            'actions' => array (
                'delete' 
            ),
            'roles' => array (
                'user_delete' 
            ) 
        ),
        // può modificare tutti
        array (
            'allow',
            'actions' => array (
                'update',
                'switchActive',
                'switchSuperuser' 
            ),
            'roles' => array (
                'user_update' 
            ) 
        ),
        // può creare utenti
        array (
            'allow',
            'actions' => array (
                'create' 
            ),
            'roles' => array (
                'user_create' 
            ) 
        ),
        // può vedere i dettagli di un utente
        array (
            'allow',
            'actions' => array (
                'view' 
            ),
            'roles' => array (
                'user_view' 
            ) 
        ), // può resettare la password di utente
        array (
            'allow',
            'actions' => array (
                'ResetPassword' 
            ),
            'roles' => array (
                'user_reset_password' 
            ) 
        ), // può resettare la password di molti utenti
        array (
            'allow',
            'actions' => array (
                'ResetPasswords' 
            ),
            'roles' => array (
                'user_reset_password' 
            ) 
        ),
        // può vedere la lista utenti
        array (
            'allow',
            'actions' => array (
                'index' 
            ),
            'roles' => array (
                'manage_users' 
            ) 
        ),
        // può vedere sé stesso
        array (
            'allow',
            'actions' => array (
                'view' 
            ),
            'expression' => 'isset($_GET[id]) && $user->id === $_GET[id]' 
        ),
        // può modificare sé stesso
        array (
            'allow',
            'actions' => array (
                'update' 
            ),
            'expression' => 'isset($_GET[id]) && $user->id === $_GET[id]' 
        ),
        // TEMP: può PDF
        array (
            'allow',
            'actions' => array (
                'pdf' 
            ) 
        ),
        array (
            'allow',
            'actions' => array (
                'settings' 
            ) 
        ),
        // nessun altro può entrare
        array (
            'deny' 
        ) 
    );
  }

  public function actionView($id)
  {
    $model = $this->loadModel ( $id );
    $this->render ( 'view', array (
        'model' => $model 
    ) );
  }

  public function actionResetPassword($id)
  {
    $usr = $this->loadModel ( $id );
    
    $newPassword = rand_str ( '1qazZAQ2wsxXSW3edcCDE4rfvVFR5tgbBGT6yhnNHY7ujmMJU8ikKI9olLO0pP,.-;:_!/*-+@#', 8 );
    
    $result = $usr->resetPassword ( $newPassword );
    
    $this->render ( 'reset_password', get_defined_vars () );
  }

  public function actionResetPasswords()
  {
    $action = array_get ( $_REQUEST, 'action', 'nono' );
    
    $pwd_length = array_get ( $_REQUEST, 'pwd_length', 8 );
    $pwd_upper = array_get ( $_REQUEST, 'pwd_upper', 0 );
    $pwd_lower = array_get ( $_REQUEST, 'pwd_lower', 1 );
    $pwd_digit = array_get ( $_REQUEST, 'pwd_digit', 0 );
    $pwd_symbols = array_get ( $_REQUEST, 'pwd_symbols', 0 );
    $userid = array_get ( $_REQUEST, 'userid', array () );
    
    if ($action == 'doit')
    {
      $charset = "";
      
      if ($pwd_upper)
        $charset .= "0123456789";
      if ($pwd_lower)
        $charset .= "0123456789";
      if ($pwd_digit)
        $charset .= "0123456789";
      if ($pwd_symbols)
        $charset .= "\\/,.;:_@#[]{}()=?!%&$*-+";
      
      $data = array ();
      foreach ( $userid as $uid => $UNUSED )
      {
        $u = User::findById ( $uid );
        if ($u == null)
          continue;
        
        $newPassword = rand_str ( $charset, $pwd_length );
        
        if ($u->resetPassword ( $newPassword ))
        {
          $info = array ();
          $info ['id'] = $u->id;
          $info ['username'] = $u->username;
          $info ['first_name'] = $u->first_name;
          $info ['last_name'] = $u->last_name;
          $info ['email'] = $u->email;
          $info ['password'] = $newPassword;
          $data [] = $info;
        }
      }
      
      if (count ( $data ) > 0)
        outputXlsx ( 'users_' . DateTimeEx::now ()->toFilesafeDateTimeString () . '.xlsx', $data, null, "" );
      else
        user ()->setFlash ( 'error', t ( 'Select at least one user' ) );
    }
    $this->render ( 'reset_passwords', get_defined_vars () );
  }

  public function actionCreate()
  {
    $passwordIsOk = false;
    $model = new User ();
    $originalPassword = null;
    $originalPasswordRepeat = null;
    
    // Uncomment the following line if AJAX validation is needed
    // $this->performAjaxValidation($model);
    
    if (isset ( $_POST ['User'] ))
    {
      $userInfo = $_POST ['User'];
      
      if ($userInfo ['password_repeat'] == $userInfo ['password'] && $userInfo ['password'] != '')
      {
        $originalPassword = $userInfo ['password'];
        $originalPasswordRepeat = $userInfo ['password_repeat'];
        $passwordIsOk = $model->validatePasswordStrength ( $userInfo ['password'] );
        
        $userInfo ['password'] = $model->hashPassword ( $userInfo ['password'] );
        $userInfo ['password_repeat'] = $userInfo ['password'];
        $userInfo ['password_last_update'] = date ( "Y-m-d H:i:s" );
      }
      
      $model->attributes = $userInfo;
      
      $model->create_time = DateHelper::ensureObjectEx ( null );
      $model->update_time = DateHelper::ensureObjectEx ( null );
      
      if ($passwordIsOk && $model->save ())
      {
        if (isset ( $userInfo ['role'] ) && $userInfo ['role'] != '')
        {
          Yii::app ()->authManager->assign ( $userInfo ['role'], $model->id );
        }
        $this->redirect ( array (
            'view',
            'id' => $model->id 
        ) );
      }
      else
      {
        $model->password = $originalPassword;
        $model->password_repeat = $originalPasswordRepeat;
      }
    }
    else
      $model->apikey = rand_str ( '0123456789QAZWSXEDCRFVTGBYHNUJMIKOLP', 32 );
    
    $assignable_roles = array ();
    
    $permessi = Yii::app ()->user->model->getAllAuths ();
    
    $assignable_roles [''] = Yii::t ( 'app', 'None' );
    foreach ( AuthItem::model ()->findAll ( 'type=2' ) as $a )
    {
      if (array_key_exists ( 'assign_' . $a->name, $permessi ))
        $assignable_roles [$a->name] = $a->description;
    }
    
    $this->render ( 'create', array (
        'model' => $model,
        'assignable_roles' => $assignable_roles 
    ) );
  }

  public function actionUpdate($id)
  {
    $passwordIsOk = false;
    $passwordHasChanged = false;
    $model = $this->loadModel ( $id );
    
    // Uncomment the following line if AJAX validation is needed
    // $this->performAjaxValidation($model);
    
    if (isset ( $_POST ['User'] ))
    {
      $userInfo = $_POST ['User'];
      
      if ($model->username != $userInfo ['username'] && in_array ( $model->username, Yii::app ()->authManager->admins ))
        throw new CHttpException ( 403, 'Invalid request. User \'' . $model->username . '\' can\'t change username.' );
      
      if (Yii::app ()->user->model->canChangePassword ( $id ))
      {
        if ($model->password != $userInfo ['password'])
        {
          if ($userInfo ['password_repeat'] == $userInfo ['password'] && $userInfo ['password'] != '')
          {
            $passwordIsOk = $model->validatePasswordStrength ( $userInfo ['password'] );
            $passwordHasChanged = true;
            
            $userInfo ['password_repeat'] = $userInfo ['password'] = $model->hashPassword ( $userInfo ['password'] );
            $userInfo ['password_last_update'] = date ( "Y-m-d H:i:s" );
            $model->password_last_update = $userInfo ['password_last_update'];
          }
        }
        else
        {
          $userInfo ['password_repeat'] = $userInfo ['password'];
        }
      }
      else
      {
        $userInfo ['password'] = $model->password;
        $userInfo ['password_repeat'] = $model->password;
      }
      
      $model->attributes = $userInfo;
      
      if (($passwordIsOk || ! $passwordHasChanged) && $model->save ())
        $this->redirect ( array (
            'view',
            'id' => $model->id 
        ) );
    }
    
    $this->render ( 'update', array (
        'model' => $model 
    ) );
  }

  public function actionDelete($id)
  {
    if (Yii::app ()->request->isPostRequest)
    {
      $model = $this->loadModel ( $id );
      
      if (in_array ( $model->username, Yii::app ()->authManager->admins ))
        throw new CHttpException ( 403, 'Invalid request. User \'' . $model->username . '\' can\'t be deleted.' );
      
      $model->delete ();
      
      // if AJAX request (triggered by deletion via admin grid view), we should not redirect the browser
      if (! isset ( $_GET ['ajax'] ))
        $this->redirect ( isset ( $_POST ['returnUrl'] ) ? $_POST ['returnUrl'] : array (
            'index' 
        ) );
    }
    else
      throw new CHttpException ( 400, 'Invalid request. Please do not repeat this request again.' );
  }

  public function actionIndex()
  {
    $model = new User ( 'search' );
    $model->unsetAttributes (); // clear any default values
    if (isset ( $_GET ['User'] ))
      $model->attributes = $_GET ['User'];
    
    $debug_string = null;
    
    $this->render ( 'index', array (
        'model' => $model,
        'debug_string' => $debug_string 
    ) );
  }

  /**
   *
   * @param
   *          string id the user id (pk)
   * @return User the user model
   *        
   */
  public function loadModel($id)
  {
    $model = User::model ()->findByPk ( $id );
    if ($model === null)
      throw new CHttpException ( 404, 'The requested page does not exist.' );
    return $model;
  }

  public function actionSwitchActive($id, $returnUrl = null)
  {
    $model = $this->loadModel ( $id );
    $model->status = ($model->status == User::STATUS_ACTIVE ? User::STATUS_INACTIVE : User::STATUS_ACTIVE);
    if ($model->save ( false ))
      user ()->setFlash ( 'success', t ( "Saved" ) );
    else
      user ()->setFlash ( 'error', $model->getErrorsHtml () );
    $this->redirect ( empty ( $returnUrl ) ? url ( "user/index" ) : $returnUrl );
  }

  public function actionSwitchSuperuser($id, $returnUrl = null)
  {
    access_denied_check ( 'manage_superuser' );
    $model = $this->loadModel ( $id );
    $model->superuser = ($model->superuser == 1 ? 0 : 1);
    if ($model->save ( false ))
      user ()->setFlash ( 'success', t ( "Saved" ) );
    else
      user ()->setFlash ( 'error', $model->getErrorsHtml () );
    $this->redirect ( empty ( $returnUrl ) ? url ( "user/index" ) : $returnUrl );
  }

  protected function performAjaxValidation($model)
  {
    if (isset ( $_POST ['ajax'] ) && $_POST ['ajax'] === 'user-form')
    {
      echo CActiveForm::validate ( $model );
      Yii::app ()->end ();
    }
  }

  public function actionViewSettings($id)
  {
    $user = $this->loadModel ( $id );
    $settings = $user->getSettings ();
    
    $text = "<h1>User " . $user->getFullName () . " settings:</h1>";
    foreach ( $settings->getKeys () as $item )
    {
      $k = $item->key;
      $value = $settings->$k;
      switch ($item->type)
      {
        case 'boolean' :
          $text .= "$item->description: <input name=\"$item->key\" type=\"checkbox\"><br>";
          break;
        default :
          $text .= "$item->description: <input name=\"$item->key\" type=\"text\"><br>";
          break;
      }
    }
    
    $this->renderText ( $text );
  }

  public function actionSettings($id = null)
  {
    access_denied_check ( 'user_settings' );
    
    $me = user ()->model;
    if ($id == null || $id == $me->id)
    {
      $user = $me;
    }
    else
    {
      access_denied_check ( 'user_settings_full' );
      $user = $this->loadModel ( $id );
    }
    $this->render ( 'settings', array (
        'user' => $user 
    ) );
  }
}
