|    1:  | <?php | 
|    2:  |  | 
|    3:  |  | 
|    4:  |  | 
|    5:  |  | 
|    6:  |  | 
|    7:  |  | 
|    8:  | namespace Aurora\Modules\Core; | 
|    9:  |  | 
|   10:  | use Aurora\Api; | 
|   11:  | use Aurora\Modules\Contacts\Enums\StorageType; | 
|   12:  | use Aurora\Modules\Contacts\Module as ContactsModule; | 
|   13:  | use Aurora\Modules\Core\Enums\ErrorCodes; | 
|   14:  | use Aurora\Modules\Core\Models\Group; | 
|   15:  | use Aurora\Modules\Core\Models\User; | 
|   16:  | use Aurora\Modules\Core\Models\UserBlock; | 
|   17:  | use Aurora\System\Enums\UserRole; | 
|   18:  | use Aurora\System\Exceptions\ApiException; | 
|   19:  | use Aurora\System\Notifications; | 
|   20:  | use Illuminate\Database\Eloquent\Builder; | 
|   21:  | use Symfony\Component\Console\Input\ArrayInput; | 
|   22:  | use Symfony\Component\Console\Output\NullOutput; | 
|   23:  | use Symfony\Component\Console\Output\BufferedOutput; | 
|   24:  | use Aurora\System\Logger; | 
|   25:  | use Aurora\System\Managers\Integrator; | 
|   26:  |  | 
|   27:  |  | 
|   28:  |  | 
|   29:  |  | 
|   30:  |  | 
|   31:  |  | 
|   32:  |  | 
|   33:  |  | 
|   34:  |  | 
|   35:  |  | 
|   36:  |  | 
|   37:  |  | 
|   38:  | class Module extends \Aurora\System\Module\AbstractModule | 
|   39:  | { | 
|   40:  |     protected $oTenantsManager = null; | 
|   41:  |  | 
|   42:  |     protected $oChannelsManager = null; | 
|   43:  |  | 
|   44:  |     protected $oUsersManager = null; | 
|   45:  |  | 
|   46:  |     protected $oIntegratorManager = null; | 
|   47:  |  | 
|   48:  |      | 
|   49:  |  | 
|   50:  |  | 
|   51:  |     public static function getInstance() | 
|   52:  |     { | 
|   53:  |         return parent::getInstance(); | 
|   54:  |     } | 
|   55:  |  | 
|   56:  |      | 
|   57:  |  | 
|   58:  |  | 
|   59:  |     public static function Decorator() | 
|   60:  |     { | 
|   61:  |         return parent::Decorator(); | 
|   62:  |     } | 
|   63:  |  | 
|   64:  |      | 
|   65:  |  | 
|   66:  |  | 
|   67:  |     public function getModuleSettings() | 
|   68:  |     { | 
|   69:  |         return $this->oModuleSettings; | 
|   70:  |     } | 
|   71:  |  | 
|   72:  |      | 
|   73:  |  | 
|   74:  |  | 
|   75:  |     public function getTenantsManager() | 
|   76:  |     { | 
|   77:  |         if ($this->oTenantsManager === null) { | 
|   78:  |             $this->oTenantsManager = new Managers\Tenants($this); | 
|   79:  |         } | 
|   80:  |  | 
|   81:  |         return $this->oTenantsManager; | 
|   82:  |     } | 
|   83:  |  | 
|   84:  |      | 
|   85:  |  | 
|   86:  |  | 
|   87:  |     public function getChannelsManager() | 
|   88:  |     { | 
|   89:  |         if ($this->oChannelsManager === null) { | 
|   90:  |             $this->oChannelsManager = new Managers\Channels($this); | 
|   91:  |         } | 
|   92:  |  | 
|   93:  |         return $this->oChannelsManager; | 
|   94:  |     } | 
|   95:  |  | 
|   96:  |      | 
|   97:  |  | 
|   98:  |  | 
|   99:  |     public function getUsersManager() | 
|  100:  |     { | 
|  101:  |         if ($this->oUsersManager === null) { | 
|  102:  |             $this->oUsersManager = new Managers\Users($this); | 
|  103:  |         } | 
|  104:  |  | 
|  105:  |         return $this->oUsersManager; | 
|  106:  |     } | 
|  107:  |  | 
|  108:  |      | 
|  109:  |  | 
|  110:  |  | 
|  111:  |     public function getIntegratorManager() | 
|  112:  |     { | 
|  113:  |         if ($this->oIntegratorManager === null) { | 
|  114:  |             $this->oIntegratorManager = new \Aurora\System\Managers\Integrator(); | 
|  115:  |         } | 
|  116:  |  | 
|  117:  |         return $this->oIntegratorManager; | 
|  118:  |     } | 
|  119:  |  | 
|  120:  |      | 
|  121:  |      | 
|  122:  |  | 
|  123:  |  | 
|  124:  |  | 
|  125:  |  | 
|  126:  |     public function init() | 
|  127:  |     { | 
|  128:  |         $this->aErrors = [ | 
|  129:  |             Enums\ErrorCodes::ChannelDoesNotExist => $this->i18N('ERROR_CHANNEL_NOT_EXISTS'), | 
|  130:  |             Enums\ErrorCodes::TenantAlreadyExists => $this->i18N('ERROR_TENANT_ALREADY_EXISTS'), | 
|  131:  |             Enums\ErrorCodes::GroupAlreadyExists => $this->i18N('ERROR_GROUP_ALREADY_EXISTS'), | 
|  132:  |             Enums\ErrorCodes::MySqlConfigError => 'Please make sure your PHP/MySQL environment meets the minimal system requirements.', | 
|  133:  |         ]; | 
|  134:  |  | 
|  135:  |         \Aurora\System\Router::getInstance()->registerArray( | 
|  136:  |             self::GetName(), | 
|  137:  |             [ | 
|  138:  |                 'api' => [$this, 'EntryApi'], | 
|  139:  |                 'ping' => [$this, 'EntryPing'], | 
|  140:  |                 'pull' => [$this, 'EntryPull'], | 
|  141:  |                 'mobile' => [$this, 'EntryMobile'], | 
|  142:  |                 'sso' => [$this, 'EntrySso'], | 
|  143:  |                 'postlogin' => [$this, 'EntryPostlogin'], | 
|  144:  |                 'file-cache' => [$this, 'EntryFileCache'] | 
|  145:  |             ] | 
|  146:  |         ); | 
|  147:  |  | 
|  148:  |         \Aurora\System\EventEmitter::getInstance()->onAny( | 
|  149:  |             [ | 
|  150:  |                 ['CreateAccount', [$this, 'onCreateAccount'], 100], | 
|  151:  |                 ['Core::GetCompatibilities::after', [$this, 'onAfterGetCompatibilities']], | 
|  152:  |                 ['System::RunEntry::before', [$this, 'onBeforeRunEntry'], 100] | 
|  153:  |             ] | 
|  154:  |         ); | 
|  155:  |  | 
|  156:  |         $this->denyMethodsCallByWebApi([ | 
|  157:  |             'Authenticate', | 
|  158:  |             'UpdateUserObject', | 
|  159:  |             'GetUserByUUID', | 
|  160:  |             'GetUserByPublicId', | 
|  161:  |             'GetAdminUser', | 
|  162:  |             'GetTenantWithoutRoleCheck', | 
|  163:  |             'GetTenantName', | 
|  164:  |             'GetTenantIdByName', | 
|  165:  |             'GetDefaultGlobalTenant', | 
|  166:  |             'UpdateTenantObject', | 
|  167:  |             'GetUserWithoutRoleCheck', | 
|  168:  |             'UpdateTokensValidFromTimestamp', | 
|  169:  |             'GetAccountUsedToAuthorize', | 
|  170:  |             'GetDigestHash', | 
|  171:  |             'VerifyPassword', | 
|  172:  |             'SetAuthDataAndGetAuthToken', | 
|  173:  |             'IsModuleDisabledForObject', | 
|  174:  |             'GetBlockedUser', | 
|  175:  |             'BlockUser', | 
|  176:  |             'IsBlockedUser', | 
|  177:  |             'GetAllGroup', | 
|  178:  |             'CheckIpReputation' | 
|  179:  |         ]); | 
|  180:  |     } | 
|  181:  |  | 
|  182:  |      | 
|  183:  |  | 
|  184:  |  | 
|  185:  |  | 
|  186:  |     private function getUploadData() | 
|  187:  |     { | 
|  188:  |         $mResult = false; | 
|  189:  |         $oFile = null; | 
|  190:  |         if (count($_FILES) > 0) { | 
|  191:  |             $oFile = current($_FILES); | 
|  192:  |         } | 
|  193:  |         if (isset($oFile, $oFile['name'], $oFile['tmp_name'], $oFile['size'], $oFile['type'])) { | 
|  194:  |             $iError = (isset($oFile['error'])) ? (int) $oFile['error'] : UPLOAD_ERR_OK; | 
|  195:  |             $mResult = (UPLOAD_ERR_OK === $iError) ? $oFile : false; | 
|  196:  |         } | 
|  197:  |  | 
|  198:  |         return $mResult; | 
|  199:  |     } | 
|  200:  |  | 
|  201:  |      | 
|  202:  |  | 
|  203:  |  | 
|  204:  |  | 
|  205:  |  | 
|  206:  |  | 
|  207:  |  | 
|  208:  |  | 
|  209:  |  | 
|  210:  |  | 
|  211:  |  | 
|  212:  |     public function onCreateAccount(&$Args, &$Result) | 
|  213:  |     { | 
|  214:  |         $oUser = null; | 
|  215:  |  | 
|  216:  |         if (isset($Args['UserId']) && (int)$Args['UserId'] > 0) { | 
|  217:  |             $oUser = $this->getUsersManager()->getUser($Args['UserId']); | 
|  218:  |         } else { | 
|  219:  |             $Email = (isset($Args['Email'])) ? $Args['Email'] : ''; | 
|  220:  |             $PublicId = (isset($Args['PublicId'])) ? $Args['PublicId'] : ''; | 
|  221:  |             $sPublicId = null; | 
|  222:  |             if (!empty($PublicId)) { | 
|  223:  |                 $sPublicId = $PublicId; | 
|  224:  |             } elseif (!empty($Email)) { | 
|  225:  |                 $sPublicId = $Email; | 
|  226:  |             } | 
|  227:  |             if (!empty($sPublicId)) { | 
|  228:  |                 $oUser = $this->getUsersManager()->getUserByPublicId($sPublicId); | 
|  229:  |             } | 
|  230:  |             if (!isset($oUser)) { | 
|  231:  |                 $bPrevState = Api::skipCheckUserRole(true); | 
|  232:  |                 $iUserId = self::Decorator()->CreateUser(isset($Args['TenantId']) ? (int) $Args['TenantId'] : 0, $sPublicId); | 
|  233:  |                 Api::skipCheckUserRole($bPrevState); | 
|  234:  |                 $oUser = $this->getUsersManager()->getUser($iUserId); | 
|  235:  |             } | 
|  236:  |  | 
|  237:  |             if (isset($oUser) && isset($oUser->Id)) { | 
|  238:  |                 $Args['UserId'] = $oUser->Id; | 
|  239:  |             } | 
|  240:  |         } | 
|  241:  |  | 
|  242:  |         $Result = $oUser; | 
|  243:  |     } | 
|  244:  |  | 
|  245:  |      | 
|  246:  |  | 
|  247:  |  | 
|  248:  |  | 
|  249:  |  | 
|  250:  |     public function onAfterGetCompatibilities($aArgs, &$mResult) | 
|  251:  |     { | 
|  252:  |         $aCompatibility['php.version'] = phpversion(); | 
|  253:  |         $aCompatibility['php.version.valid'] = (int) (version_compare($aCompatibility['php.version'], '7.2.5') > -1); | 
|  254:  |  | 
|  255:  |         $aCompatibility['safe-mode'] = @ini_get('safe_mode'); | 
|  256:  |         $aCompatibility['safe-mode.valid'] = is_numeric($aCompatibility['safe-mode']) | 
|  257:  |             ? !((bool) $aCompatibility['safe-mode']) | 
|  258:  |             : ('off' === strtolower($aCompatibility['safe-mode']) || empty($aCompatibility['safe-mode'])); | 
|  259:  |  | 
|  260:  |         $aCompatibility['mysql.valid'] = (int) extension_loaded('mysql'); | 
|  261:  |         $aCompatibility['pdo.valid'] = (int) | 
|  262:  |             ((bool) extension_loaded('pdo') && (bool) extension_loaded('pdo_mysql')); | 
|  263:  |  | 
|  264:  |         $aCompatibility['mysqlnd.valid'] = (int) ( | 
|  265:  |             function_exists('mysqli_fetch_all') && | 
|  266:  |             strpos(mysqli_get_client_info(), "mysqlnd") !== false | 
|  267:  |         ); | 
|  268:  |  | 
|  269:  |         $aCompatibility['socket.valid'] = (int) function_exists('fsockopen'); | 
|  270:  |         $aCompatibility['iconv.valid'] = (int) function_exists('iconv'); | 
|  271:  |         $aCompatibility['curl.valid'] = (int) function_exists('curl_init'); | 
|  272:  |         $aCompatibility['mbstring.valid'] = (int) function_exists('mb_detect_encoding'); | 
|  273:  |         $aCompatibility['openssl.valid'] = (int) extension_loaded('openssl'); | 
|  274:  |         $aCompatibility['xml.valid'] = (int) (class_exists('DOMDocument') && function_exists('xml_parser_create')); | 
|  275:  |         $aCompatibility['json.valid'] = (int) function_exists('json_decode'); | 
|  276:  |         $aCompatibility['gd.valid'] = (int) extension_loaded('gd'); | 
|  277:  |  | 
|  278:  |         $aCompatibility['ini-get.valid'] = (int) function_exists('ini_get'); | 
|  279:  |         $aCompatibility['ini-set.valid'] = (int) function_exists('ini_set'); | 
|  280:  |         $aCompatibility['set-time-limit.valid'] = (int) function_exists('set_time_limit'); | 
|  281:  |  | 
|  282:  |         $aCompatibility['session.valid'] = (int) (function_exists('session_start') && isset($_SESSION['checksessionindex'])); | 
|  283:  |  | 
|  284:  |         $dataPath = Api::DataPath(); | 
|  285:  |  | 
|  286:  |         $aCompatibility['data.dir'] = $dataPath; | 
|  287:  |         $aCompatibility['data.dir.valid'] = (int) (@is_dir($aCompatibility['data.dir']) && @is_writable($aCompatibility['data.dir'])); | 
|  288:  |  | 
|  289:  |         $sTempPathName = '_must_be_deleted_' . md5(time()); | 
|  290:  |  | 
|  291:  |         $aCompatibility['data.dir.create'] = | 
|  292:  |             (int) @mkdir($aCompatibility['data.dir'] . '/' . $sTempPathName); | 
|  293:  |         $aCompatibility['data.file.create'] = | 
|  294:  |             (int) (bool) @fopen($aCompatibility['data.dir'] . '/' . $sTempPathName . '/' . $sTempPathName . '.test', 'w+'); | 
|  295:  |         $aCompatibility['data.file.delete'] = | 
|  296:  |             (int) (bool) @unlink($aCompatibility['data.dir'] . '/' . $sTempPathName . '/' . $sTempPathName . '.test'); | 
|  297:  |         $aCompatibility['data.dir.delete'] = | 
|  298:  |             (int) @rmdir($aCompatibility['data.dir'] . '/' . $sTempPathName); | 
|  299:  |  | 
|  300:  |  | 
|  301:  |         $oSettings = &Api::GetSettings(); | 
|  302:  |  | 
|  303:  |         $aCompatibility['settings.file'] = $oSettings ? $oSettings->GetPath() : ''; | 
|  304:  |  | 
|  305:  |         $aCompatibility['settings.file.exist'] = (int) @file_exists($aCompatibility['settings.file']); | 
|  306:  |         $aCompatibility['settings.file.read'] = (int) @is_readable($aCompatibility['settings.file']); | 
|  307:  |         $aCompatibility['settings.file.write'] = (int) @is_writable($aCompatibility['settings.file']); | 
|  308:  |  | 
|  309:  |         $aCompatibilities = [ | 
|  310:  |             [ | 
|  311:  |                 'Name' => 'PHP version', | 
|  312:  |                 'Result' => $aCompatibility['php.version.valid'], | 
|  313:  |                 'Value' => $aCompatibility['php.version.valid'] | 
|  314:  |                 ? 'OK' | 
|  315:  |                 : [$aCompatibility['php.version'] . ' detected, 7.2.5 or above required.', | 
|  316:  | 'You need to upgrade PHP engine installed on your server. | 
|  317:  | If it\'s a dedicated or your local server, you can download the latest version of PHP from its | 
|  318:  | <a href="http://php.net/downloads.php" target="_blank">official site</a> and install it yourself. | 
|  319:  | In case of a shared hosting, you need to ask your hosting provider to perform the upgrade.'] | 
|  320:  |             ], | 
|  321:  |             [ | 
|  322:  |                 'Name' => 'Safe Mode is off', | 
|  323:  |                 'Result' => $aCompatibility['safe-mode.valid'], | 
|  324:  |                 'Value' => ($aCompatibility['safe-mode.valid']) | 
|  325:  |                 ? 'OK' | 
|  326:  |                 : ['Error, safe_mode is enabled.', | 
|  327:  | 'You need to <a href="http://php.net/manual/en/ini.sect.safe-mode.php" target="_blank">disable it in your php.ini</a> | 
|  328:  | or contact your hosting provider and ask to do this.'] | 
|  329:  |             ], | 
|  330:  |             [ | 
|  331:  |                 'Name' => 'PDO MySQL Extension', | 
|  332:  |                 'Result' => $aCompatibility['pdo.valid'], | 
|  333:  |                 'Value' => ($aCompatibility['pdo.valid']) | 
|  334:  |                 ? 'OK' | 
|  335:  |                 : ['Error, PHP PDO MySQL extension not detected.', | 
|  336:  | 'You need to install this PHP extension or enable it in php.ini file.'] | 
|  337:  |             ], | 
|  338:  |             [ | 
|  339:  |                 'Name' => 'MySQL Native Driver (mysqlnd)', | 
|  340:  |                 'Result' => $aCompatibility['mysqlnd.valid'], | 
|  341:  |                 'Value' => ($aCompatibility['mysqlnd.valid']) | 
|  342:  |                 ? 'OK' | 
|  343:  |                 : ['Error, MySQL Native Driver not found.', | 
|  344:  | 'You need to install this PHP extension or enable it in php.ini file.'] | 
|  345:  |             ], | 
|  346:  |             [ | 
|  347:  |                 'Name' => 'Iconv Extension', | 
|  348:  |                 'Result' => $aCompatibility['iconv.valid'], | 
|  349:  |                 'Value' => ($aCompatibility['iconv.valid']) | 
|  350:  |                 ? 'OK' | 
|  351:  |                 : ['Error, iconv extension not detected.', | 
|  352:  | 'You need to install this PHP extension or enable it in php.ini file.'] | 
|  353:  |             ], | 
|  354:  |             [ | 
|  355:  |                 'Name' => 'Multibyte String Extension', | 
|  356:  |                 'Result' => $aCompatibility['mbstring.valid'], | 
|  357:  |                 'Value' => ($aCompatibility['mbstring.valid']) | 
|  358:  |                 ? 'OK' | 
|  359:  |                 : ['Error, mb_string extension not detected.', | 
|  360:  | 'You need to install this PHP extension or enable it in php.ini file.'] | 
|  361:  |             ], | 
|  362:  |             [ | 
|  363:  |                 'Name' => 'CURL Extension', | 
|  364:  |                 'Result' => $aCompatibility['curl.valid'], | 
|  365:  |                 'Value' => ($aCompatibility['curl.valid']) | 
|  366:  |                 ? 'OK' | 
|  367:  |                 : ['Error, curl extension not detected.', | 
|  368:  | 'You need to install this PHP extension or enable it in php.ini file.'] | 
|  369:  |             ], | 
|  370:  |             [ | 
|  371:  |                 'Name' => 'JSON Extension', | 
|  372:  |                 'Result' => $aCompatibility['json.valid'], | 
|  373:  |                 'Value' => ($aCompatibility['json.valid']) | 
|  374:  |                 ? 'OK' | 
|  375:  |                 : ['Error, JSON extension not detected.', | 
|  376:  | 'You need to install this PHP extension or enable it in php.ini file.'] | 
|  377:  |             ], | 
|  378:  |             [ | 
|  379:  |                 'Name' => 'XML/DOM Extension', | 
|  380:  |                 'Result' => $aCompatibility['xml.valid'], | 
|  381:  |                 'Value' => ($aCompatibility['xml.valid']) | 
|  382:  |                 ? 'OK' | 
|  383:  |                 : ['Error, xml (DOM) extension not detected.', | 
|  384:  | 'You need to install this PHP extension or enable it in php.ini file.'] | 
|  385:  |             ], | 
|  386:  |             [ | 
|  387:  |                 'Name' => 'GD Extension', | 
|  388:  |                 'Result' => $aCompatibility['gd.valid'], | 
|  389:  |                 'Value' => ($aCompatibility['gd.valid']) | 
|  390:  |                 ? 'OK' | 
|  391:  |                 : ['Error, GD extension not detected.', | 
|  392:  | 'You need to install this PHP extension or enable it in php.ini file.'] | 
|  393:  |             ], | 
|  394:  |             [ | 
|  395:  |                 'Name' => 'Sockets', | 
|  396:  |                 'Result' => $aCompatibility['socket.valid'], | 
|  397:  |                 'Value' => ($aCompatibility['socket.valid']) | 
|  398:  |                 ? 'OK' | 
|  399:  |                 : ['Error, creating network sockets must be enabled.', ' | 
|  400:  | To enable sockets, you should remove fsockopen function from the list of prohibited functions in disable_functions directive of your php.ini file. | 
|  401:  | In case of a shared hosting, you need to ask your hosting provider to do this.'] | 
|  402:  |             ], | 
|  403:  |             [ | 
|  404:  |                 'Name' => 'SSL (OpenSSL extension)', | 
|  405:  |                 'Result' => $aCompatibility['openssl.valid'], | 
|  406:  |                 'Value' => ($aCompatibility['openssl.valid']) | 
|  407:  |                 ? 'OK' | 
|  408:  |                 : ['SSL connections (like Gmail) will not be available. ', ' | 
|  409:  | You need to enable OpenSSL support in your PHP configuration and make sure OpenSSL library is installed on your server. | 
|  410:  | For instructions, please refer to the official PHP documentation. In case of a shared hosting, | 
|  411:  | you need to ask your hosting provider to enable OpenSSL support. | 
|  412:  | You may ignore this if you\'re not going to connect to SSL-only mail servers (like Gmail).'] | 
|  413:  |             ], | 
|  414:  |             [ | 
|  415:  |                 'Name' => 'Setting memory limits', | 
|  416:  |                 'Result' => $aCompatibility['ini-get.valid'], | 
|  417:  |                 'Value' => ($aCompatibility['ini-get.valid'] && $aCompatibility['ini-set.valid']) | 
|  418:  |                 ? 'OK' | 
|  419:  |                 : ['Opening large e-mails may fail.', ' | 
|  420:  | You need to enable setting memory limits in your PHP configuration, i.e. remove ini_get and ini_set functions | 
|  421:  | from the list of prohibited functions in disable_functions directive of your php.ini file. | 
|  422:  | In case of a shared hosting, you need to ask your hosting provider to do this.'] | 
|  423:  |             ], | 
|  424:  |             [ | 
|  425:  |                 'Name' => 'Setting script timeout', | 
|  426:  |                 'Result' => $aCompatibility['set-time-limit.valid'], | 
|  427:  |                 'Value' => ($aCompatibility['set-time-limit.valid']) | 
|  428:  |                 ? 'OK' | 
|  429:  |                 : ['Downloading large mailboxes may fail.', ' | 
|  430:  | To enable setting script timeout, you should remove set_time_limit function from the list | 
|  431:  | of prohibited functions in disable_functions directive of your php.ini file. | 
|  432:  | In case of a shared hosting, you need to ask your hosting provider to do this.'] | 
|  433:  |             ], | 
|  434:  |             [ | 
|  435:  |                 'Name' => 'WebMail data directory', | 
|  436:  |                 'Result' => $aCompatibility['data.dir.valid'], | 
|  437:  |                 'Value' => ($aCompatibility['data.dir.valid']) | 
|  438:  |                 ? 'Found' | 
|  439:  |                 : ['Error, data directory path discovery failure.'] | 
|  440:  |             ], | 
|  441:  |             [ | 
|  442:  |                 'Name' => 'Creating/deleting directories', | 
|  443:  |                 'Result' => $aCompatibility['data.dir.create'] && $aCompatibility['data.dir.delete'], | 
|  444:  |                 'Value' => ($aCompatibility['data.dir.create'] && $aCompatibility['data.dir.delete']) | 
|  445:  |                 ? 'OK' | 
|  446:  |                 : ['Error, can\'t create/delete sub-directories in the data directory.', ' | 
|  447:  | You need to grant read/write permission over data directory and all its contents to your web server user. | 
|  448:  | For instructions, please refer to this section of documentation and our | 
|  449:  | <a href="https://afterlogic.com/docs/webmail-pro-8/troubleshooting/troubleshooting-issues-with-data-directory" target="_blank">FAQ</a>.'] | 
|  450:  |             ], | 
|  451:  |             [ | 
|  452:  |                 'Name' => 'Creating/deleting files', | 
|  453:  |                 'Result' => $aCompatibility['data.file.create'] && $aCompatibility['data.file.delete'], | 
|  454:  |                 'Value' => ($aCompatibility['data.file.create'] && $aCompatibility['data.file.delete']) | 
|  455:  |                 ? 'OK' | 
|  456:  |                 : ['Error, can\'t create/delete files in the data directory.', ' | 
|  457:  | You need to grant read/write permission over data directory and all its contents to your web server user. | 
|  458:  | For instructions, please refer to this section of documentation and our | 
|  459:  | <a href="https://afterlogic.com/docs/webmail-pro-8/troubleshooting/troubleshooting-issues-with-data-directory" target="_blank">FAQ</a>.'] | 
|  460:  |             ], | 
|  461:  |             [ | 
|  462:  |                 'Name' => 'WebMail Settings File', | 
|  463:  |                 'Result' => $aCompatibility['settings.file.exist'], | 
|  464:  |                 'Value' => ($aCompatibility['settings.file.exist']) | 
|  465:  |                 ? 'Found' | 
|  466:  |                 : ['Not Found, can\'t find "' . $aCompatibility['settings.file'] . '" file.', ' | 
|  467:  | Make sure you completely copied the data directory with all its contents from installation package. | 
|  468:  | By default, the data directory is webmail subdirectory, and if it\'s not the case make sure its location matches one specified in inc_settings_path.php file.'] | 
|  469:  |             ], | 
|  470:  |             [ | 
|  471:  |                 'Name' => 'Read/write settings file', | 
|  472:  |                 'Result' => $aCompatibility['settings.file.read'] && $aCompatibility['settings.file.write'], | 
|  473:  |                 'Value' => ($aCompatibility['settings.file.read'] && $aCompatibility['settings.file.write']) | 
|  474:  |                 ? 'OK / OK' | 
|  475:  |                 : ['Not Found, can\'t find "' . $aCompatibility['settings.file'] . '" file.', ' | 
|  476:  | You should grant read/write permission over settings file to your web server user. | 
|  477:  | For instructions, please refer to this section of documentation and our | 
|  478:  | <a href="https://afterlogic.com/docs/webmail-pro-8/troubleshooting/troubleshooting-issues-with-data-directory" target="_blank">FAQ</a>.'] | 
|  479:  |             ], | 
|  480:  |         ]; | 
|  481:  |  | 
|  482:  |         $mResult[self::GetName()] = $aCompatibilities; | 
|  483:  |     } | 
|  484:  |  | 
|  485:  |     public function onBeforeRunEntry($aArgs, &$mResult) | 
|  486:  |     { | 
|  487:  |         \Aurora\Api::removeOldLogs(); | 
|  488:  |  | 
|  489:  |         return $this->redirectToHttps($aArgs['EntryName'], $mResult); | 
|  490:  |     } | 
|  491:  |  | 
|  492:  |      | 
|  493:  |  | 
|  494:  |  | 
|  495:  |  | 
|  496:  |  | 
|  497:  |  | 
|  498:  |  | 
|  499:  |     protected function removeDirByTime($sTempPath, $iTime2Kill, $iNow) | 
|  500:  |     { | 
|  501:  |         $iFileCount = 0; | 
|  502:  |         if (@is_dir($sTempPath)) { | 
|  503:  |             $rDirH = @opendir($sTempPath); | 
|  504:  |             if ($rDirH) { | 
|  505:  |                 while (($sFile = @readdir($rDirH)) !== false) { | 
|  506:  |                     if ('.' !== $sFile && '..' !== $sFile) { | 
|  507:  |                         if (@is_dir($sTempPath . '/' . $sFile)) { | 
|  508:  |                             $this->removeDirByTime($sTempPath . '/' . $sFile, $iTime2Kill, $iNow); | 
|  509:  |                         } else { | 
|  510:  |                             $iFileCount++; | 
|  511:  |                         } | 
|  512:  |                     } | 
|  513:  |                 } | 
|  514:  |                 @closedir($rDirH); | 
|  515:  |             } | 
|  516:  |  | 
|  517:  |             if ($iFileCount > 0) { | 
|  518:  |                 if ($this->removeFilesByTime($sTempPath, $iTime2Kill, $iNow)) { | 
|  519:  |                     @rmdir($sTempPath); | 
|  520:  |                 } | 
|  521:  |             } else { | 
|  522:  |                 @rmdir($sTempPath); | 
|  523:  |             } | 
|  524:  |         } | 
|  525:  |     } | 
|  526:  |  | 
|  527:  |      | 
|  528:  |  | 
|  529:  |  | 
|  530:  |  | 
|  531:  |  | 
|  532:  |  | 
|  533:  |  | 
|  534:  |  | 
|  535:  |  | 
|  536:  |     protected function removeFilesByTime($sTempPath, $iTime2Kill, $iNow) | 
|  537:  |     { | 
|  538:  |         $bResult = true; | 
|  539:  |         if (@is_dir($sTempPath)) { | 
|  540:  |             $rDirH = @opendir($sTempPath); | 
|  541:  |             if ($rDirH) { | 
|  542:  |                 while (($sFile = @readdir($rDirH)) !== false) { | 
|  543:  |                     if ($sFile !== '.' && $sFile !== '..') { | 
|  544:  |                         if ($iNow - filemtime($sTempPath . '/' . $sFile) > $iTime2Kill) { | 
|  545:  |                             @unlink($sTempPath . '/' . $sFile); | 
|  546:  |                         } else { | 
|  547:  |                             $bResult = false; | 
|  548:  |                         } | 
|  549:  |                     } | 
|  550:  |                 } | 
|  551:  |                 @closedir($rDirH); | 
|  552:  |             } | 
|  553:  |         } | 
|  554:  |         return $bResult; | 
|  555:  |     } | 
|  556:  |  | 
|  557:  |     protected function redirectToHttps($sEntryName, $mResult) | 
|  558:  |     { | 
|  559:  |         $oSettings = &\Aurora\Api::GetSettings(); | 
|  560:  |         if ($oSettings) { | 
|  561:  |             $bRedirectToHttps = $oSettings->RedirectToHttps; | 
|  562:  |  | 
|  563:  |             $bHttps = \Aurora\Api::isHttps(); | 
|  564:  |             if ($bRedirectToHttps && !$bHttps) { | 
|  565:  |                 if (\strtolower($sEntryName) !== 'api') { | 
|  566:  |                     \header("Location: https://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']); | 
|  567:  |                 } else { | 
|  568:  |                     $mResult = [ | 
|  569:  |                         'ErrorCode' => 110 | 
|  570:  |                     ]; | 
|  571:  |                     return true; | 
|  572:  |                 } | 
|  573:  |             } | 
|  574:  |         } | 
|  575:  |     } | 
|  576:  |      | 
|  577:  |  | 
|  578:  |      | 
|  579:  |      | 
|  580:  |  | 
|  581:  |  | 
|  582:  |  | 
|  583:  |     private function deleteTree($dir) | 
|  584:  |     { | 
|  585:  |         $files = array_diff(scandir($dir), array('.','..')); | 
|  586:  |  | 
|  587:  |         foreach ($files as $file) { | 
|  588:  |             (is_dir("$dir/$file")) ? $this->deleteTree("$dir/$file") : unlink("$dir/$file"); | 
|  589:  |         } | 
|  590:  |  | 
|  591:  |         return rmdir($dir); | 
|  592:  |     } | 
|  593:  |      | 
|  594:  |  | 
|  595:  |      | 
|  596:  |      | 
|  597:  |  | 
|  598:  |  | 
|  599:  |  | 
|  600:  |  | 
|  601:  |     public function EntryApi() | 
|  602:  |     { | 
|  603:  |         @ob_start(); | 
|  604:  |  | 
|  605:  |         if (!is_writable(Api::DataPath())) { | 
|  606:  |             throw new ApiException(Notifications::SystemNotConfigured, null, 'Check the write permission of the data folder'); | 
|  607:  |         } | 
|  608:  |  | 
|  609:  |         $aResponseItem = null; | 
|  610:  |         $sModule = $this->oHttp->GetPost('Module', null); | 
|  611:  |         $sMethod = $this->oHttp->GetPost('Method', null); | 
|  612:  |         $sParameters = $this->oHttp->GetPost('Parameters', null); | 
|  613:  |         $sFormat = $this->oHttp->GetPost('Format', null); | 
|  614:  |         $sTenantName = $this->oHttp->GetPost('TenantName', null); | 
|  615:  |  | 
|  616:  |         if (isset($sModule, $sMethod)) { | 
|  617:  |             $oModule = Api::GetModule($sModule); | 
|  618:  |             if ($oModule instanceof \Aurora\System\Module\AbstractModule) { | 
|  619:  |                 try { | 
|  620:  |                     Api::Log(" "); | 
|  621:  |                     Api::Log(" ===== API: " . $sModule . '::' . $sMethod); | 
|  622:  |  | 
|  623:  |                     Api::validateAuthToken(); | 
|  624:  |  | 
|  625:  |                     if (!empty($sMethod)) { | 
|  626:  |                         Api::setTenantName($sTenantName); | 
|  627:  |  | 
|  628:  |                         $aParameters = []; | 
|  629:  |                         if (isset($sParameters) && \is_string($sParameters) && !empty($sParameters)) { | 
|  630:  |                             $aParameters = @\json_decode($sParameters, true); | 
|  631:  |  | 
|  632:  |                             if (json_last_error() !== JSON_ERROR_NONE) { | 
|  633:  |                                 throw new ApiException( | 
|  634:  |                                     Notifications::InvalidInputParameter, | 
|  635:  |                                     null, | 
|  636:  |                                     'InvalidInputParameter' | 
|  637:  |                                 ); | 
|  638:  |                             } | 
|  639:  |  | 
|  640:  |                             if (!\is_array($aParameters)) { | 
|  641:  |                                 $aParameters = array($aParameters); | 
|  642:  |                             } | 
|  643:  |                         } | 
|  644:  |  | 
|  645:  |                         $mUploadData = $this->getUploadData(); | 
|  646:  |                         if (\is_array($mUploadData)) { | 
|  647:  |                             $aParameters['UploadData'] = $mUploadData; | 
|  648:  |                         } | 
|  649:  |  | 
|  650:  |                         $oModule->CallMethod( | 
|  651:  |                             $sMethod, | 
|  652:  |                             $aParameters, | 
|  653:  |                             true | 
|  654:  |                         ); | 
|  655:  |  | 
|  656:  |                         $oLastException = Api::GetModuleManager()->GetLastException(); | 
|  657:  |                         if (isset($oLastException)) { | 
|  658:  |                             throw $oLastException; | 
|  659:  |                         } | 
|  660:  |  | 
|  661:  |                         $aResponseItem = $oModule->DefaultResponse( | 
|  662:  |                             $sMethod, | 
|  663:  |                             Api::GetModuleManager()->GetResults() | 
|  664:  |                         ); | 
|  665:  |                     } | 
|  666:  |  | 
|  667:  |                     if (!\is_array($aResponseItem)) { | 
|  668:  |                         throw new ApiException( | 
|  669:  |                             Notifications::UnknownError, | 
|  670:  |                             null, | 
|  671:  |                             'UnknownError' | 
|  672:  |                         ); | 
|  673:  |                     } | 
|  674:  |                 } catch (\Exception $oException) { | 
|  675:  |                     Api::LogException($oException); | 
|  676:  |  | 
|  677:  |                     $aAdditionalParams = null; | 
|  678:  |                     if ($oException instanceof ApiException) { | 
|  679:  |                         if (!$oException->GetModule()) { | 
|  680:  |                             $oException = new ApiException( | 
|  681:  |                                 $oException->getCode(), | 
|  682:  |                                 $oException->getPrevious(), | 
|  683:  |                                 $oException->getMessage(), | 
|  684:  |                                 $oException->GetObjectParams(), | 
|  685:  |                                 $oModule | 
|  686:  |                             ); | 
|  687:  |                         } | 
|  688:  |                         $aAdditionalParams = $oException->GetObjectParams(); | 
|  689:  |                     } | 
|  690:  |  | 
|  691:  |                     $aResponseItem = $oModule->ExceptionResponse( | 
|  692:  |                         $sMethod, | 
|  693:  |                         $oException, | 
|  694:  |                         $aAdditionalParams | 
|  695:  |                     ); | 
|  696:  |                 } | 
|  697:  |             } else { | 
|  698:  |                 $oException = new ApiException( | 
|  699:  |                     Notifications::ModuleNotFound, | 
|  700:  |                     null, | 
|  701:  |                     'Module not found' | 
|  702:  |                 ); | 
|  703:  |                 $aResponseItem = $this->ExceptionResponse( | 
|  704:  |                     $sMethod, | 
|  705:  |                     $oException | 
|  706:  |                 ); | 
|  707:  |             } | 
|  708:  |         } else { | 
|  709:  |             $oException = new ApiException( | 
|  710:  |                 Notifications::InvalidInputParameter, | 
|  711:  |                 null, | 
|  712:  |                 'Invalid input parameter' | 
|  713:  |             ); | 
|  714:  |             $aResponseItem = $this->ExceptionResponse( | 
|  715:  |                 $sMethod, | 
|  716:  |                 $oException | 
|  717:  |             ); | 
|  718:  |         } | 
|  719:  |  | 
|  720:  |         if (isset($aResponseItem['Parameters'])) { | 
|  721:  |             unset($aResponseItem['Parameters']); | 
|  722:  |         } | 
|  723:  |  | 
|  724:  |         return \Aurora\System\Managers\Response::GetJsonFromObject($sFormat, $aResponseItem); | 
|  725:  |     } | 
|  726:  |  | 
|  727:  |      | 
|  728:  |  | 
|  729:  |  | 
|  730:  |     public function EntryMobile() | 
|  731:  |     { | 
|  732:  |         $oApiIntegrator = $this->getIntegratorManager(); | 
|  733:  |         $oApiIntegrator->setMobile(true); | 
|  734:  |  | 
|  735:  |         Api::Location('./'); | 
|  736:  |     } | 
|  737:  |  | 
|  738:  |      | 
|  739:  |  | 
|  740:  |  | 
|  741:  |     public function EntrySso() | 
|  742:  |     { | 
|  743:  |         try { | 
|  744:  |             $sHash = $this->oHttp->GetRequest('hash'); | 
|  745:  |             if (!empty($sHash)) { | 
|  746:  |                 $sData = Api::Cacher()->get('SSO:' . $sHash, true); | 
|  747:  |                 $aData = Api::DecodeKeyValues($sData); | 
|  748:  |  | 
|  749:  |                 if (isset($aData['Password'], $aData['Email'])) { | 
|  750:  |                     $sLanguage = $this->oHttp->GetRequest('lang'); | 
|  751:  |                     $aResult = self::Decorator()->Login($aData['Email'], $aData['Password'], $sLanguage); | 
|  752:  |  | 
|  753:  |                      | 
|  754:  |                      | 
|  755:  |                      | 
|  756:  |                      | 
|  757:  |                      | 
|  758:  |                 } | 
|  759:  |             } else { | 
|  760:  |                 self::Decorator()->Logout(); | 
|  761:  |             } | 
|  762:  |         } catch (\Exception $oExc) { | 
|  763:  |             Api::LogException($oExc); | 
|  764:  |         } | 
|  765:  |  | 
|  766:  |         Api::Location('./'); | 
|  767:  |     } | 
|  768:  |  | 
|  769:  |      | 
|  770:  |  | 
|  771:  |  | 
|  772:  |     public function EntryPostlogin() | 
|  773:  |     { | 
|  774:  |         if ($this->oModuleSettings->AllowPostLogin) { | 
|  775:  |             $sEmail = trim((string) $this->oHttp->GetRequest('Email', '')); | 
|  776:  |             $sLogin = (string) $this->oHttp->GetRequest('Login', ''); | 
|  777:  |             $sPassword = (string) $this->oHttp->GetRequest('Password', ''); | 
|  778:  |  | 
|  779:  |             if ($sLogin === '') { | 
|  780:  |                 $sLogin = $sEmail; | 
|  781:  |             } | 
|  782:  |  | 
|  783:  |             $aResult = self::Decorator()->Login($sLogin, $sPassword); | 
|  784:  |              | 
|  785:  |              | 
|  786:  |              | 
|  787:  |  | 
|  788:  |             Api::Location('./'); | 
|  789:  |         } | 
|  790:  |     } | 
|  791:  |  | 
|  792:  |     public function EntryFileCache() | 
|  793:  |     { | 
|  794:  |         Api::checkUserRoleIsAtLeast(UserRole::NormalUser); | 
|  795:  |  | 
|  796:  |         $sRawKey = \Aurora\System\Router::getItemByIndex(1, ''); | 
|  797:  |         $sAction = \Aurora\System\Router::getItemByIndex(2, ''); | 
|  798:  |         $aValues = Api::DecodeKeyValues($sRawKey); | 
|  799:  |  | 
|  800:  |         $bDownload = true; | 
|  801:  |         $bThumbnail = false; | 
|  802:  |  | 
|  803:  |         switch ($sAction) { | 
|  804:  |             case 'view': | 
|  805:  |                 $bDownload = false; | 
|  806:  |                 $bThumbnail = false; | 
|  807:  |                 break; | 
|  808:  |             case 'thumb': | 
|  809:  |                 $bDownload = false; | 
|  810:  |                 $bThumbnail = true; | 
|  811:  |                 break; | 
|  812:  |             default: | 
|  813:  |                 $bDownload = true; | 
|  814:  |                 $bThumbnail = false; | 
|  815:  |                 break; | 
|  816:  |         } | 
|  817:  |  | 
|  818:  |         $iUserId = (isset($aValues['UserId'])) ? $aValues['UserId'] : 0; | 
|  819:  |  | 
|  820:  |         if (isset($aValues['TempFile'], $aValues['TempName'], $aValues['Name'])) { | 
|  821:  |             $sModule = isset($aValues['Module']) && !empty($aValues['Module']) ? $aValues['Module'] : 'System'; | 
|  822:  |             $sUUID = Api::getUserUUIDById($iUserId); | 
|  823:  |             $oApiFileCache = new \Aurora\System\Managers\Filecache(); | 
|  824:  |             $mResult = $oApiFileCache->getFile($sUUID, $aValues['TempName'], '', $sModule); | 
|  825:  |  | 
|  826:  |             if (is_resource($mResult)) { | 
|  827:  |                 $sFileName = $aValues['Name']; | 
|  828:  |                 $sContentType = (empty($sFileName)) ? 'text/plain' : \MailSo\Base\Utils::MimeContentType($sFileName); | 
|  829:  |                 $sFileName = \Aurora\System\Utils::clearFileName($sFileName, $sContentType); | 
|  830:  |  | 
|  831:  |                 \Aurora\System\Utils::OutputFileResource($sUUID, $sContentType, $sFileName, $mResult, $bThumbnail, $bDownload); | 
|  832:  |             } | 
|  833:  |         } | 
|  834:  |     } | 
|  835:  |  | 
|  836:  |     public function IsModuleExists($Module) | 
|  837:  |     { | 
|  838:  |         return Api::GetModuleManager()->ModuleExists($Module); | 
|  839:  |     } | 
|  840:  |  | 
|  841:  |      | 
|  842:  |  | 
|  843:  |  | 
|  844:  |  | 
|  845:  |     public function GetVersion() | 
|  846:  |     { | 
|  847:  |         return Api::Version(); | 
|  848:  |     } | 
|  849:  |  | 
|  850:  |      | 
|  851:  |  | 
|  852:  |  | 
|  853:  |  | 
|  854:  |  | 
|  855:  |  | 
|  856:  |  | 
|  857:  |  | 
|  858:  |     protected function ClearTempFiles() | 
|  859:  |     { | 
|  860:  |         $sTempPath = Api::DataPath() . '/temp'; | 
|  861:  |         if (@is_dir($sTempPath)) { | 
|  862:  |             $iNow = time(); | 
|  863:  |  | 
|  864:  |             $iTime2Run = $this->oModuleSettings->CronTimeToRunSeconds; | 
|  865:  |             $iTime2Kill = $this->oModuleSettings->CronTimeToKillSeconds; | 
|  866:  |             $sDataFile = $this->oModuleSettings->CronTimeFile; | 
|  867:  |  | 
|  868:  |             $iFiletTime = -1; | 
|  869:  |             if (@file_exists(Api::DataPath() . '/' . $sDataFile)) { | 
|  870:  |                 $iFiletTime = (int) @file_get_contents(Api::DataPath() . '/' . $sDataFile); | 
|  871:  |             } | 
|  872:  |  | 
|  873:  |             if ($iFiletTime === -1 || $iNow - $iFiletTime > $iTime2Run) { | 
|  874:  |                 $this->removeDirByTime($sTempPath, $iTime2Kill, $iNow); | 
|  875:  |                 @file_put_contents(Api::DataPath() . '/' . $sDataFile, $iNow); | 
|  876:  |             } | 
|  877:  |         } | 
|  878:  |  | 
|  879:  |         return true; | 
|  880:  |     } | 
|  881:  |  | 
|  882:  |      | 
|  883:  |  | 
|  884:  |  | 
|  885:  |  | 
|  886:  |  | 
|  887:  |  | 
|  888:  |  | 
|  889:  |  | 
|  890:  |  | 
|  891:  |     public function UpdateUserObject($oUser) | 
|  892:  |     { | 
|  893:  |          | 
|  894:  |  | 
|  895:  |         return $this->getUsersManager()->updateUser($oUser); | 
|  896:  |     } | 
|  897:  |  | 
|  898:  |      | 
|  899:  |  | 
|  900:  |  | 
|  901:  |  | 
|  902:  |  | 
|  903:  |  | 
|  904:  |  | 
|  905:  |  | 
|  906:  |  | 
|  907:  |     public function GetUserWithoutRoleCheck($UserId = '') | 
|  908:  |     { | 
|  909:  |          | 
|  910:  |  | 
|  911:  |         $oUser = $this->getUsersManager()->getUser($UserId); | 
|  912:  |  | 
|  913:  |         return $oUser ? $oUser : null; | 
|  914:  |     } | 
|  915:  |  | 
|  916:  |      | 
|  917:  |  | 
|  918:  |  | 
|  919:  |  | 
|  920:  |  | 
|  921:  |  | 
|  922:  |  | 
|  923:  |  | 
|  924:  |  | 
|  925:  |     public function GetUserByUUID($UUID) | 
|  926:  |     { | 
|  927:  |          | 
|  928:  |  | 
|  929:  |         $oUser = $this->getUsersManager()->getUser($UUID); | 
|  930:  |  | 
|  931:  |         return $oUser ? $oUser : null; | 
|  932:  |     } | 
|  933:  |  | 
|  934:  |      | 
|  935:  |  | 
|  936:  |  | 
|  937:  |  | 
|  938:  |  | 
|  939:  |  | 
|  940:  |  | 
|  941:  |  | 
|  942:  |  | 
|  943:  |     public function GetUserByPublicId($PublicId) | 
|  944:  |     { | 
|  945:  |          | 
|  946:  |  | 
|  947:  |         $oUser = $this->getUsersManager()->getUserByPublicId($PublicId); | 
|  948:  |  | 
|  949:  |         return $oUser ? $oUser : null; | 
|  950:  |     } | 
|  951:  |  | 
|  952:  |      | 
|  953:  |  | 
|  954:  |  | 
|  955:  |  | 
|  956:  |  | 
|  957:  |  | 
|  958:  |  | 
|  959:  |  | 
|  960:  |  | 
|  961:  |  | 
|  962:  |     public function GetAdminUser() | 
|  963:  |     { | 
|  964:  |          | 
|  965:  |  | 
|  966:  |         return Integrator::GetAdminUser(); | 
|  967:  |     } | 
|  968:  |  | 
|  969:  |      | 
|  970:  |  | 
|  971:  |  | 
|  972:  |  | 
|  973:  |  | 
|  974:  |  | 
|  975:  |  | 
|  976:  |  | 
|  977:  |  | 
|  978:  |     public function GetTenantWithoutRoleCheck($Id) | 
|  979:  |     { | 
|  980:  |          | 
|  981:  |  | 
|  982:  |         $oTenant = $this->getTenantsManager()->getTenantById($Id); | 
|  983:  |  | 
|  984:  |         return $oTenant ? $oTenant : null; | 
|  985:  |     } | 
|  986:  |  | 
|  987:  |      | 
|  988:  |  | 
|  989:  |  | 
|  990:  |  | 
|  991:  |  | 
|  992:  |  | 
|  993:  |  | 
|  994:  |  | 
|  995:  |  | 
|  996:  |     public function GetTenantIdByName($TenantName = '') | 
|  997:  |     { | 
|  998:  |          | 
|  999:  |  | 
| 1000:  |         $iTenantId = $this->getTenantsManager()->getTenantIdByName((string) $TenantName); | 
| 1001:  |  | 
| 1002:  |         return $iTenantId ? $iTenantId : null; | 
| 1003:  |     } | 
| 1004:  |  | 
| 1005:  |      | 
| 1006:  |  | 
| 1007:  |  | 
| 1008:  |  | 
| 1009:  |  | 
| 1010:  |  | 
| 1011:  |  | 
| 1012:  |  | 
| 1013:  |     public function GetTenantName() | 
| 1014:  |     { | 
| 1015:  |          | 
| 1016:  |  | 
| 1017:  |         $sTenant = ''; | 
| 1018:  |  | 
| 1019:  |         $oUser = Api::getAuthenticatedUser(); | 
| 1020:  |         if ($oUser) { | 
| 1021:  |             $oTenant = self::Decorator()->GetTenantWithoutRoleCheck($oUser->IdTenant); | 
| 1022:  |             if ($oTenant) { | 
| 1023:  |                 $sTenant = $oTenant->Name; | 
| 1024:  |  | 
| 1025:  |                 $sPostTenant = $this->oHttp->GetPost('TenantName', ''); | 
| 1026:  |                 if (!empty($sPostTenant) && !empty($sTenant) && $sPostTenant !== $sTenant) { | 
| 1027:  |                     $sTenant = ''; | 
| 1028:  |                 } | 
| 1029:  |             } | 
| 1030:  |         } else { | 
| 1031:  |             $sTenant = $this->oHttp->GetRequest('tenant', ''); | 
| 1032:  |         } | 
| 1033:  |         Api::setTenantName($sTenant); | 
| 1034:  |         return $sTenant; | 
| 1035:  |     } | 
| 1036:  |  | 
| 1037:  |      | 
| 1038:  |  | 
| 1039:  |  | 
| 1040:  |  | 
| 1041:  |  | 
| 1042:  |  | 
| 1043:  |  | 
| 1044:  |  | 
| 1045:  |     public function GetDefaultGlobalTenant() | 
| 1046:  |     { | 
| 1047:  |          | 
| 1048:  |  | 
| 1049:  |         $oTenant = $this->getTenantsManager()->getDefaultGlobalTenant(); | 
| 1050:  |  | 
| 1051:  |         return $oTenant ? $oTenant : null; | 
| 1052:  |     } | 
| 1053:  |  | 
| 1054:  |      | 
| 1055:  |  | 
| 1056:  |  | 
| 1057:  |  | 
| 1058:  |  | 
| 1059:  |  | 
| 1060:  |  | 
| 1061:  |  | 
| 1062:  |  | 
| 1063:  |     public function UpdateTenantObject($oTenant) | 
| 1064:  |     { | 
| 1065:  |          | 
| 1066:  |  | 
| 1067:  |         return $this->getTenantsManager()->updateTenant($oTenant); | 
| 1068:  |     } | 
| 1069:  |  | 
| 1070:  |      | 
| 1071:  |  | 
| 1072:  |  | 
| 1073:  |  | 
| 1074:  |  | 
| 1075:  |  | 
| 1076:  |  | 
| 1077:  |     public function UpdateTokensValidFromTimestamp($oUser) | 
| 1078:  |     { | 
| 1079:  |          | 
| 1080:  |  | 
| 1081:  |         $oUser->TokensValidFromTimestamp = time(); | 
| 1082:  |         $this->getUsersManager()->updateUser($oUser); | 
| 1083:  |         return $oUser->TokensValidFromTimestamp; | 
| 1084:  |     } | 
| 1085:  |      | 
| 1086:  |  | 
| 1087:  |      | 
| 1088:  |      | 
| 1089:  |  | 
| 1090:  |  | 
| 1091:  |  | 
| 1092:  |  | 
| 1093:  |      | 
| 1094:  |  | 
| 1095:  |  | 
| 1096:  |  | 
| 1097:  |  | 
| 1098:  |  | 
| 1099:  |  | 
| 1100:  |  | 
| 1101:  |  | 
| 1102:  |  | 
| 1103:  |  | 
| 1104:  |  | 
| 1105:  |  | 
| 1106:  |  | 
| 1107:  |  | 
| 1108:  |  | 
| 1109:  |  | 
| 1110:  |  | 
| 1111:  |  | 
| 1112:  |  | 
| 1113:  |  | 
| 1114:  |  | 
| 1115:  |  | 
| 1116:  |  | 
| 1117:  |  | 
| 1118:  |  | 
| 1119:  |  | 
| 1120:  |  | 
| 1121:  |  | 
| 1122:  |  | 
| 1123:  |  | 
| 1124:  |  | 
| 1125:  |  | 
| 1126:  |  | 
| 1127:  |  | 
| 1128:  |  | 
| 1129:  |  | 
| 1130:  |  | 
| 1131:  |  | 
| 1132:  |  | 
| 1133:  |  | 
| 1134:  |  | 
| 1135:  |      | 
| 1136:  |  | 
| 1137:  |  | 
| 1138:  |  | 
| 1139:  |  | 
| 1140:  |     public function DoServerInitializations($Timezone = '') | 
| 1141:  |     { | 
| 1142:  |         Api::checkUserRoleIsAtLeast(UserRole::Customer); | 
| 1143:  |         $result = true; | 
| 1144:  |  | 
| 1145:  |         $oCacher = Api::Cacher(); | 
| 1146:  |  | 
| 1147:  |         $bDoGC = false; | 
| 1148:  |         if ($oCacher && $oCacher->IsInited()) { | 
| 1149:  |             $iTime = $oCacher->GetTimer('Cache/ClearFileCache'); | 
| 1150:  |             if (0 === $iTime || $iTime + 60 * 60 * 24 < time()) { | 
| 1151:  |                 if ($oCacher->SetTimer('Cache/ClearFileCache')) { | 
| 1152:  |                     $bDoGC = true; | 
| 1153:  |                 } | 
| 1154:  |             } | 
| 1155:  |         } | 
| 1156:  |  | 
| 1157:  |         if ($bDoGC) { | 
| 1158:  |             Api::Log('GC: FileCache / Start'); | 
| 1159:  |             $oApiFileCache = new \Aurora\System\Managers\Filecache(); | 
| 1160:  |             $oApiFileCache->gc(); | 
| 1161:  |             $oCacher->gc(); | 
| 1162:  |             Api::Log('GC: FileCache / End'); | 
| 1163:  |         } | 
| 1164:  |  | 
| 1165:  |         return $result; | 
| 1166:  |     } | 
| 1167:  |  | 
| 1168:  |      | 
| 1169:  |  | 
| 1170:  |  | 
| 1171:  |  | 
| 1172:  |  | 
| 1173:  |  | 
| 1174:  |  | 
| 1175:  |  | 
| 1176:  |  | 
| 1177:  |  | 
| 1178:  |  | 
| 1179:  |  | 
| 1180:  |  | 
| 1181:  |  | 
| 1182:  |  | 
| 1183:  |  | 
| 1184:  |  | 
| 1185:  |  | 
| 1186:  |  | 
| 1187:  |  | 
| 1188:  |  | 
| 1189:  |  | 
| 1190:  |  | 
| 1191:  |  | 
| 1192:  |  | 
| 1193:  |  | 
| 1194:  |  | 
| 1195:  |  | 
| 1196:  |      | 
| 1197:  |  | 
| 1198:  |  | 
| 1199:  |  | 
| 1200:  |  | 
| 1201:  |     public function Ping() | 
| 1202:  |     { | 
| 1203:  |         Api::checkUserRoleIsAtLeast(UserRole::Anonymous); | 
| 1204:  |  | 
| 1205:  |         return 'Pong'; | 
| 1206:  |     } | 
| 1207:  |  | 
| 1208:  |      | 
| 1209:  |  | 
| 1210:  |  | 
| 1211:  |  | 
| 1212:  |  | 
| 1213:  |  | 
| 1214:  |  | 
| 1215:  |  | 
| 1216:  |  | 
| 1217:  |  | 
| 1218:  |  | 
| 1219:  |  | 
| 1220:  |  | 
| 1221:  |  | 
| 1222:  |  | 
| 1223:  |  | 
| 1224:  |  | 
| 1225:  |  | 
| 1226:  |  | 
| 1227:  |  | 
| 1228:  |  | 
| 1229:  |  | 
| 1230:  |  | 
| 1231:  |  | 
| 1232:  |  | 
| 1233:  |  | 
| 1234:  |  | 
| 1235:  |  | 
| 1236:  |  | 
| 1237:  |  | 
| 1238:  |  | 
| 1239:  |  | 
| 1240:  |  | 
| 1241:  |  | 
| 1242:  |  | 
| 1243:  |      | 
| 1244:  |  | 
| 1245:  |  | 
| 1246:  |  | 
| 1247:  |  | 
| 1248:  |     public function GetAppData() | 
| 1249:  |     { | 
| 1250:  |         $oApiIntegrator = $this->getIntegratorManager(); | 
| 1251:  |         return $oApiIntegrator->appData(); | 
| 1252:  |     } | 
| 1253:  |  | 
| 1254:  |      | 
| 1255:  |  | 
| 1256:  |  | 
| 1257:  |  | 
| 1258:  |  | 
| 1259:  |  | 
| 1260:  |  | 
| 1261:  |  | 
| 1262:  |  | 
| 1263:  |  | 
| 1264:  |  | 
| 1265:  |  | 
| 1266:  |  | 
| 1267:  |  | 
| 1268:  |  | 
| 1269:  |  | 
| 1270:  |  | 
| 1271:  |  | 
| 1272:  |  | 
| 1273:  |  | 
| 1274:  |  | 
| 1275:  |  | 
| 1276:  |  | 
| 1277:  |  | 
| 1278:  |  | 
| 1279:  |  | 
| 1280:  |  | 
| 1281:  |  | 
| 1282:  |  | 
| 1283:  |  | 
| 1284:  |  | 
| 1285:  |  | 
| 1286:  |  | 
| 1287:  |  | 
| 1288:  |  | 
| 1289:  |  | 
| 1290:  |  | 
| 1291:  |  | 
| 1292:  |  | 
| 1293:  |  | 
| 1294:  |  | 
| 1295:  |  | 
| 1296:  |  | 
| 1297:  |  | 
| 1298:  |  | 
| 1299:  |  | 
| 1300:  |  | 
| 1301:  |  | 
| 1302:  |  | 
| 1303:  |  | 
| 1304:  |  | 
| 1305:  |  | 
| 1306:  |  | 
| 1307:  |  | 
| 1308:  |  | 
| 1309:  |  | 
| 1310:  |  | 
| 1311:  |  | 
| 1312:  |  | 
| 1313:  |  | 
| 1314:  |      | 
| 1315:  |  | 
| 1316:  |  | 
| 1317:  |  | 
| 1318:  |  | 
| 1319:  |     public function GetSettings() | 
| 1320:  |     { | 
| 1321:  |         Api::checkUserRoleIsAtLeast(UserRole::Anonymous); | 
| 1322:  |  | 
| 1323:  |         $oUser = Api::getAuthenticatedUser(); | 
| 1324:  |  | 
| 1325:  |         $oApiIntegrator = $this->getIntegratorManager(); | 
| 1326:  |         $iLastErrorCode = $oApiIntegrator->getLastErrorCode(); | 
| 1327:  |         if (0 < $iLastErrorCode) { | 
| 1328:  |             $oApiIntegrator->clearLastErrorCode(); | 
| 1329:  |         } | 
| 1330:  |  | 
| 1331:  |         $oSettings = &Api::GetSettings(); | 
| 1332:  |  | 
| 1333:  |         $aSettings = array( | 
| 1334:  |             'AutodetectLanguage' => $this->oModuleSettings->AutodetectLanguage, | 
| 1335:  |             'UserSelectsDateFormat' => $this->oModuleSettings->UserSelectsDateFormat, | 
| 1336:  |             'DateFormat' => $this->oModuleSettings->DateFormat, | 
| 1337:  |             'DateFormatList' => $this->oModuleSettings->DateFormatList, | 
| 1338:  |             'EUserRole' => (new UserRole())->getMap(), | 
| 1339:  |             'Language' => Api::GetLanguage(), | 
| 1340:  |             'ShortLanguage' => \Aurora\System\Utils::ConvertLanguageNameToShort(Api::GetLanguage()), | 
| 1341:  |             'LanguageList' => $oApiIntegrator->getLanguageList(), | 
| 1342:  |             'LastErrorCode' => $iLastErrorCode, | 
| 1343:  |             'SiteName' => $this->oModuleSettings->SiteName, | 
| 1344:  |             'SocialName' => '', | 
| 1345:  |             'TenantName' => Api::getTenantName(), | 
| 1346:  |             'EnableMultiTenant' => $oSettings->EnableMultiTenant, | 
| 1347:  |             'TimeFormat' => $this->oModuleSettings->TimeFormat, | 
| 1348:  |             'UserId' => Api::getAuthenticatedUserId(), | 
| 1349:  |             'IsSystemConfigured' => is_writable(Api::DataPath()) && | 
| 1350:  |                 (file_exists(Api::GetEncryptionKeyPath()) && strlen(@file_get_contents(Api::GetEncryptionKeyPath()))), | 
| 1351:  |             'Version' => Api::VersionFull(), | 
| 1352:  |             'ProductName' => $this->oModuleSettings->ProductName, | 
| 1353:  |             'PasswordMinLength' => $oSettings->PasswordMinLength, | 
| 1354:  |             'PasswordMustBeComplex' => $oSettings->PasswordMustBeComplex, | 
| 1355:  |             'CookiePath' => Api::getCookiePath(), | 
| 1356:  |             'CookieSecure' => Api::getCookieSecure(), | 
| 1357:  |             'AuthTokenCookieExpireTime' => $this->oModuleSettings->AuthTokenCookieExpireTime, | 
| 1358:  |             'StoreAuthTokenInDB' => $oSettings->StoreAuthTokenInDB, | 
| 1359:  |             'AvailableClientModules' => $oApiIntegrator->GetClientModuleNames(), | 
| 1360:  |             'AvailableBackendModules' => $oApiIntegrator->GetBackendModules(), | 
| 1361:  |             'AllowGroups' => $this->oModuleSettings->AllowGroups, | 
| 1362:  |         ); | 
| 1363:  |  | 
| 1364:  |         if ($oSettings && ($oUser instanceof User) && $oUser->Role === UserRole::SuperAdmin) { | 
| 1365:  |             $sAdminPassword = $oSettings->AdminPassword; | 
| 1366:  |  | 
| 1367:  |             $aSettings = array_merge($aSettings, array( | 
| 1368:  |                 'DBHost' => $oSettings->DBHost, | 
| 1369:  |                 'DBName' => $oSettings->DBName, | 
| 1370:  |                 'DBLogin' => $oSettings->DBLogin, | 
| 1371:  |                 'AdminLogin' => $oSettings->AdminLogin, | 
| 1372:  |                 'AdminHasPassword' => !empty($sAdminPassword), | 
| 1373:  |                 'AdminLanguage' => $oSettings->AdminLanguage, | 
| 1374:  |                 'CommonLanguage' => $this->oModuleSettings->Language, | 
| 1375:  |                 'EncryptionKeyNotEmpty' => file_exists(Api::GetEncryptionKeyPath()) && strlen(@file_get_contents(Api::GetEncryptionKeyPath())), | 
| 1376:  |                 'EnableLogging' => $oSettings->EnableLogging, | 
| 1377:  |                 'EnableEventLogging' => $oSettings->EnableEventLogging, | 
| 1378:  |                 'LoggingLevel' => $oSettings->LoggingLevel, | 
| 1379:  |                 'LogFilesData' => $this->GetLogFilesData(), | 
| 1380:  |                 'ELogLevel' => (new \Aurora\System\Enums\LogLevel())->getMap() | 
| 1381:  |             )); | 
| 1382:  |         } | 
| 1383:  |  | 
| 1384:  |         if (($oUser instanceof User) && $oUser->isNormalOrTenant()) { | 
| 1385:  |             if ($oUser->DateFormat !== '') { | 
| 1386:  |                 $aSettings['DateFormat'] = $oUser->DateFormat; | 
| 1387:  |             } | 
| 1388:  |             $aSettings['TimeFormat'] = $oUser->TimeFormat; | 
| 1389:  |             $aSettings['Timezone'] = $oUser->DefaultTimeZone; | 
| 1390:  |         } | 
| 1391:  |  | 
| 1392:  |         return $aSettings; | 
| 1393:  |     } | 
| 1394:  |  | 
| 1395:  |      | 
| 1396:  |  | 
| 1397:  |  | 
| 1398:  |  | 
| 1399:  |  | 
| 1400:  |  | 
| 1401:  |  | 
| 1402:  |  | 
| 1403:  |  | 
| 1404:  |  | 
| 1405:  |  | 
| 1406:  |  | 
| 1407:  |  | 
| 1408:  |  | 
| 1409:  |  | 
| 1410:  |  | 
| 1411:  |  | 
| 1412:  |  | 
| 1413:  |  | 
| 1414:  |  | 
| 1415:  |  | 
| 1416:  |  | 
| 1417:  |  | 
| 1418:  |  | 
| 1419:  |  | 
| 1420:  |  | 
| 1421:  |  | 
| 1422:  |  | 
| 1423:  |  | 
| 1424:  |  | 
| 1425:  |  | 
| 1426:  |  | 
| 1427:  |  | 
| 1428:  |  | 
| 1429:  |  | 
| 1430:  |  | 
| 1431:  |  | 
| 1432:  |  | 
| 1433:  |  | 
| 1434:  |  | 
| 1435:  |  | 
| 1436:  |  | 
| 1437:  |  | 
| 1438:  |  | 
| 1439:  |  | 
| 1440:  |  | 
| 1441:  |  | 
| 1442:  |  | 
| 1443:  |  | 
| 1444:  |  | 
| 1445:  |  | 
| 1446:  |  | 
| 1447:  |  | 
| 1448:  |  | 
| 1449:  |  | 
| 1450:  |  | 
| 1451:  |  | 
| 1452:  |  | 
| 1453:  |  | 
| 1454:  |  | 
| 1455:  |  | 
| 1456:  |  | 
| 1457:  |      | 
| 1458:  |  | 
| 1459:  |  | 
| 1460:  |  | 
| 1461:  |  | 
| 1462:  |  | 
| 1463:  |  | 
| 1464:  |  | 
| 1465:  |  | 
| 1466:  |  | 
| 1467:  |  | 
| 1468:  |  | 
| 1469:  |  | 
| 1470:  |  | 
| 1471:  |  | 
| 1472:  |  | 
| 1473:  |  | 
| 1474:  |  | 
| 1475:  |  | 
| 1476:  |  | 
| 1477:  |  | 
| 1478:  |     public function UpdateSettings( | 
| 1479:  |         $DbLogin = null, | 
| 1480:  |         $DbPassword = null, | 
| 1481:  |         $DbName = null, | 
| 1482:  |         $DbHost = null, | 
| 1483:  |         $AdminLogin = null, | 
| 1484:  |         $Password = null, | 
| 1485:  |         $NewPassword = null, | 
| 1486:  |         $AdminLanguage = null, | 
| 1487:  |         $SiteName = null, | 
| 1488:  |         $Language = null, | 
| 1489:  |         $AutodetectLanguage = null, | 
| 1490:  |         $TimeFormat = null, | 
| 1491:  |         $DateFormat = null, | 
| 1492:  |         $EnableLogging = null, | 
| 1493:  |         $EnableEventLogging = null, | 
| 1494:  |         $LoggingLevel = null | 
| 1495:  |     ) { | 
| 1496:  |         Api::checkUserRoleIsAtLeast(UserRole::NormalUser); | 
| 1497:  |  | 
| 1498:  |         $oUser = Api::getAuthenticatedUser(); | 
| 1499:  |  | 
| 1500:  |         if ($oUser->Role === UserRole::SuperAdmin) { | 
| 1501:  |             if ($SiteName !== null || $Language !== null || $TimeFormat !== null || $AutodetectLanguage !== null) { | 
| 1502:  |                 if ($SiteName !== null) { | 
| 1503:  |                     $this->setConfig('SiteName', $SiteName); | 
| 1504:  |                 } | 
| 1505:  |                 if ($AutodetectLanguage !== null) { | 
| 1506:  |                     $this->setConfig('AutodetectLanguage', $AutodetectLanguage); | 
| 1507:  |                 } | 
| 1508:  |                 if ($Language !== null) { | 
| 1509:  |                     $this->setConfig('Language', $Language); | 
| 1510:  |                 } | 
| 1511:  |                 if ($TimeFormat !== null) { | 
| 1512:  |                     $this->setConfig('TimeFormat', (int) $TimeFormat); | 
| 1513:  |                 } | 
| 1514:  |                 $this->saveModuleConfig(); | 
| 1515:  |             } | 
| 1516:  |             $oSettings = &Api::GetSettings(); | 
| 1517:  |             if ($DbLogin !== null) { | 
| 1518:  |                 $oSettings->DBLogin = $DbLogin; | 
| 1519:  |             } | 
| 1520:  |             if ($DbPassword !== null) { | 
| 1521:  |                 $oSettings->DBPassword = $DbPassword; | 
| 1522:  |             } | 
| 1523:  |             if ($DbName !== null) { | 
| 1524:  |                 $oSettings->DBName = $DbName; | 
| 1525:  |             } | 
| 1526:  |             if ($DbHost !== null) { | 
| 1527:  |                 $oSettings->DBHost = $DbHost; | 
| 1528:  |             } | 
| 1529:  |             if ($AdminLogin !== null && $AdminLogin !== $oSettings->AdminLogin) { | 
| 1530:  |                 $aArgs = array( | 
| 1531:  |                     'Login' => $AdminLogin | 
| 1532:  |                 ); | 
| 1533:  |                 $this->broadcastEvent( | 
| 1534:  |                     'CheckAccountExists', | 
| 1535:  |                     $aArgs | 
| 1536:  |                 ); | 
| 1537:  |  | 
| 1538:  |                 $oSettings->AdminLogin = $AdminLogin; | 
| 1539:  |             } | 
| 1540:  |  | 
| 1541:  |             $sAdminPassword = $oSettings->AdminPassword; | 
| 1542:  |             if ((empty($sAdminPassword) && empty($Password) || !empty($Password)) && !empty($NewPassword)) { | 
| 1543:  |                 if (empty($sAdminPassword) || password_verify($Password, $sAdminPassword)) { | 
| 1544:  |                     $oSettings->AdminPassword = password_hash(trim($NewPassword), PASSWORD_BCRYPT); | 
| 1545:  |                 } else { | 
| 1546:  |                     throw new ApiException(Notifications::AccountOldPasswordNotCorrect); | 
| 1547:  |                 } | 
| 1548:  |             } | 
| 1549:  |  | 
| 1550:  |             if ($AdminLanguage !== null) { | 
| 1551:  |                 $oSettings->AdminLanguage = $AdminLanguage; | 
| 1552:  |             } | 
| 1553:  |             if ($EnableLogging !== null) { | 
| 1554:  |                 $oSettings->EnableLogging = $EnableLogging; | 
| 1555:  |             } | 
| 1556:  |             if ($EnableEventLogging !== null) { | 
| 1557:  |                 $oSettings->EnableEventLogging = $EnableEventLogging; | 
| 1558:  |             } | 
| 1559:  |             if ($LoggingLevel !== null) { | 
| 1560:  |                 $oSettings->LoggingLevel = $LoggingLevel; | 
| 1561:  |             } | 
| 1562:  |             return $oSettings->Save(); | 
| 1563:  |         } | 
| 1564:  |  | 
| 1565:  |         if ($oUser->isNormalOrTenant()) { | 
| 1566:  |             if ($Language !== null) { | 
| 1567:  |                 $oUser->Language = $Language; | 
| 1568:  |             } | 
| 1569:  |             if ($TimeFormat !== null) { | 
| 1570:  |                 $oUser->TimeFormat = $TimeFormat; | 
| 1571:  |             } | 
| 1572:  |             if ($DateFormat !== null) { | 
| 1573:  |                 $oUser->DateFormat = $DateFormat; | 
| 1574:  |             } | 
| 1575:  |             return $this->UpdateUserObject($oUser); | 
| 1576:  |         } | 
| 1577:  |  | 
| 1578:  |         return false; | 
| 1579:  |     } | 
| 1580:  |  | 
| 1581:  |     public function UpdateLoggingSettings($EnableLogging = null, $EnableEventLogging = null, $LoggingLevel = null) | 
| 1582:  |     { | 
| 1583:  |         Api::checkUserRoleIsAtLeast(UserRole::SuperAdmin); | 
| 1584:  |  | 
| 1585:  |         $oSettings = &Api::GetSettings(); | 
| 1586:  |  | 
| 1587:  |         if ($EnableLogging !== null) { | 
| 1588:  |             $oSettings->EnableLogging = $EnableLogging; | 
| 1589:  |         } | 
| 1590:  |         if ($EnableEventLogging !== null) { | 
| 1591:  |             $oSettings->EnableEventLogging = $EnableEventLogging; | 
| 1592:  |         } | 
| 1593:  |         if ($LoggingLevel !== null) { | 
| 1594:  |             $oSettings->LoggingLevel = $LoggingLevel; | 
| 1595:  |         } | 
| 1596:  |  | 
| 1597:  |         return $oSettings->Save(); | 
| 1598:  |     } | 
| 1599:  |  | 
| 1600:  |      | 
| 1601:  |  | 
| 1602:  |  | 
| 1603:  |  | 
| 1604:  |  | 
| 1605:  |  | 
| 1606:  |     public function SetMobile($Mobile) | 
| 1607:  |     { | 
| 1608:  |         Api::checkUserRoleIsAtLeast(UserRole::Anonymous); | 
| 1609:  |         $oIntegrator = $this->getIntegratorManager(); | 
| 1610:  |         return $oIntegrator ? $oIntegrator->setMobile($Mobile) : false; | 
| 1611:  |     } | 
| 1612:  |  | 
| 1613:  |      | 
| 1614:  |  | 
| 1615:  |  | 
| 1616:  |  | 
| 1617:  |  | 
| 1618:  |  | 
| 1619:  |  | 
| 1620:  |  | 
| 1621:  |  | 
| 1622:  |  | 
| 1623:  |  | 
| 1624:  |  | 
| 1625:  |  | 
| 1626:  |  | 
| 1627:  |  | 
| 1628:  |  | 
| 1629:  |  | 
| 1630:  |  | 
| 1631:  |  | 
| 1632:  |  | 
| 1633:  |  | 
| 1634:  |  | 
| 1635:  |  | 
| 1636:  |  | 
| 1637:  |  | 
| 1638:  |  | 
| 1639:  |  | 
| 1640:  |  | 
| 1641:  |  | 
| 1642:  |  | 
| 1643:  |  | 
| 1644:  |  | 
| 1645:  |  | 
| 1646:  |  | 
| 1647:  |  | 
| 1648:  |  | 
| 1649:  |  | 
| 1650:  |  | 
| 1651:  |  | 
| 1652:  |  | 
| 1653:  |  | 
| 1654:  |  | 
| 1655:  |      | 
| 1656:  |  | 
| 1657:  |  | 
| 1658:  |  | 
| 1659:  |  | 
| 1660:  |     public function CreateTables() | 
| 1661:  |     { | 
| 1662:  |         Api::checkUserRoleIsAtLeast(UserRole::SuperAdmin); | 
| 1663:  |  | 
| 1664:  |         if (!function_exists('mysqli_fetch_all')) { | 
| 1665:  |             throw new ApiException(0, null, 'Please make sure your PHP/MySQL environment meets the minimal system requirements.'); | 
| 1666:  |         } | 
| 1667:  |  | 
| 1668:  |         $bResult = false; | 
| 1669:  |  | 
| 1670:  |         try { | 
| 1671:  |             $container = \Aurora\Api::GetContainer(); | 
| 1672:  |  | 
| 1673:  |             $oPdo = $container['connection']->getPdo(); | 
| 1674:  |             if ($oPdo && strpos($oPdo->getAttribute(\PDO::ATTR_CLIENT_VERSION), 'mysqlnd') === false) { | 
| 1675:  |                 throw new ApiException(Enums\ErrorCodes::MySqlConfigError, null, 'MySqlConfigError'); | 
| 1676:  |             } | 
| 1677:  |  | 
| 1678:  |             $container['console']->setAutoExit(false); | 
| 1679:  |  | 
| 1680:  |             $container['console']->find('migrate') | 
| 1681:  |                 ->run(new ArrayInput([ | 
| 1682:  |                     '--force' => true, | 
| 1683:  |                     '--seed' => true | 
| 1684:  |                 ]), new NullOutput()); | 
| 1685:  |  | 
| 1686:  |             $bResult = true; | 
| 1687:  |         } catch (\Exception $oEx) { | 
| 1688:  |             Api::LogException($oEx); | 
| 1689:  |             if ($oEx instanceof ApiException) { | 
| 1690:  |                 throw $oEx; | 
| 1691:  |             } | 
| 1692:  |         } | 
| 1693:  |  | 
| 1694:  |         return $bResult; | 
| 1695:  |     } | 
| 1696:  |  | 
| 1697:  |     public function GetOrphans() | 
| 1698:  |     { | 
| 1699:  |         Api::checkUserRoleIsAtLeast(UserRole::SuperAdmin); | 
| 1700:  |  | 
| 1701:  |         $bResult = false; | 
| 1702:  |  | 
| 1703:  |         try { | 
| 1704:  |             $container = \Aurora\Api::GetContainer(); | 
| 1705:  |             $container['console']->setAutoExit(false); | 
| 1706:  |  | 
| 1707:  |             $output = new BufferedOutput(); | 
| 1708:  |             $container['console']->find('get-orphans') | 
| 1709:  |             ->run(new ArrayInput([]), $output); | 
| 1710:  |  | 
| 1711:  |             $content = array_filter(explode(PHP_EOL, $output->fetch())); | 
| 1712:  |             $bResult = $content; | 
| 1713:  |         } catch (\Exception $oEx) { | 
| 1714:  |             Api::LogException($oEx); | 
| 1715:  |         } | 
| 1716:  |  | 
| 1717:  |         return $bResult; | 
| 1718:  |     } | 
| 1719:  |  | 
| 1720:  |      | 
| 1721:  |  | 
| 1722:  |  | 
| 1723:  |  | 
| 1724:  |     public function UpdateConfig() | 
| 1725:  |     { | 
| 1726:  |         Api::checkUserRoleIsAtLeast(UserRole::SuperAdmin); | 
| 1727:  |  | 
| 1728:  |         return Api::UpdateSettings(); | 
| 1729:  |     } | 
| 1730:  |  | 
| 1731:  |      | 
| 1732:  |  | 
| 1733:  |  | 
| 1734:  |  | 
| 1735:  |  | 
| 1736:  |  | 
| 1737:  |  | 
| 1738:  |  | 
| 1739:  |  | 
| 1740:  |  | 
| 1741:  |  | 
| 1742:  |  | 
| 1743:  |  | 
| 1744:  |  | 
| 1745:  |  | 
| 1746:  |  | 
| 1747:  |  | 
| 1748:  |  | 
| 1749:  |  | 
| 1750:  |  | 
| 1751:  |  | 
| 1752:  |  | 
| 1753:  |  | 
| 1754:  |  | 
| 1755:  |  | 
| 1756:  |  | 
| 1757:  |  | 
| 1758:  |  | 
| 1759:  |  | 
| 1760:  |  | 
| 1761:  |  | 
| 1762:  |  | 
| 1763:  |  | 
| 1764:  |  | 
| 1765:  |  | 
| 1766:  |  | 
| 1767:  |  | 
| 1768:  |  | 
| 1769:  |  | 
| 1770:  |  | 
| 1771:  |  | 
| 1772:  |  | 
| 1773:  |  | 
| 1774:  |  | 
| 1775:  |  | 
| 1776:  |  | 
| 1777:  |  | 
| 1778:  |  | 
| 1779:  |  | 
| 1780:  |  | 
| 1781:  |  | 
| 1782:  |      | 
| 1783:  |  | 
| 1784:  |  | 
| 1785:  |  | 
| 1786:  |  | 
| 1787:  |  | 
| 1788:  |  | 
| 1789:  |  | 
| 1790:  |  | 
| 1791:  |     public function TestDbConnection($DbLogin, $DbName, $DbHost, $DbPassword = null) | 
| 1792:  |     { | 
| 1793:  |         Api::checkUserRoleIsAtLeast(UserRole::SuperAdmin); | 
| 1794:  |         if (!function_exists('mysqli_fetch_all')) { | 
| 1795:  |             throw new ApiException(0, null, 'Please make sure your PHP/MySQL environment meets the minimal system requirements.'); | 
| 1796:  |         } | 
| 1797:  |  | 
| 1798:  |         if (empty($DbName) || empty($DbHost) || empty($DbLogin)) { | 
| 1799:  |             throw new ApiException(Notifications::InvalidInputParameter, null, 'InvalidInputParameter'); | 
| 1800:  |         } | 
| 1801:  |  | 
| 1802:  |         $oPdo = null; | 
| 1803:  |         $oSettings = &Api::GetSettings(); | 
| 1804:  |         if ($oSettings) { | 
| 1805:  |             if ($DbPassword === null) { | 
| 1806:  |                 $DbPassword = $oSettings->DBPassword; | 
| 1807:  |             } | 
| 1808:  |             $capsule = new \Illuminate\Database\Capsule\Manager(); | 
| 1809:  |             $capsule->addConnection(Api::GetDbConfig( | 
| 1810:  |                 $oSettings->DBType, | 
| 1811:  |                 $DbHost, | 
| 1812:  |                 $DbName, | 
| 1813:  |                 $oSettings->DBPrefix, | 
| 1814:  |                 $DbLogin, | 
| 1815:  |                 $DbPassword | 
| 1816:  |             )); | 
| 1817:  |             $oPdo = $capsule->getConnection()->getPdo(); | 
| 1818:  |  | 
| 1819:  |             if ($oPdo && strpos($oPdo->getAttribute(\PDO::ATTR_CLIENT_VERSION), 'mysqlnd') === false) { | 
| 1820:  |                 throw new ApiException(Enums\ErrorCodes::MySqlConfigError, null, 'MySqlConfigError'); | 
| 1821:  |             } | 
| 1822:  |         } | 
| 1823:  |  | 
| 1824:  |         return $oPdo instanceof \PDO; | 
| 1825:  |     } | 
| 1826:  |  | 
| 1827:  |      | 
| 1828:  |  | 
| 1829:  |  | 
| 1830:  |  | 
| 1831:  |  | 
| 1832:  |     public function GetAuthenticatedAccount($AuthToken) | 
| 1833:  |     { | 
| 1834:  |         Api::checkUserRoleIsAtLeast(UserRole::Anonymous); | 
| 1835:  |  | 
| 1836:  |         $aUserInfo = Api::getAuthenticatedUserInfo($AuthToken); | 
| 1837:  |         $oAccount = call_user_func_array([$aUserInfo['accountType'], 'find'], [(int)$aUserInfo['account']]); | 
| 1838:  |  | 
| 1839:  |         return $oAccount; | 
| 1840:  |     } | 
| 1841:  |  | 
| 1842:  |      | 
| 1843:  |  | 
| 1844:  |  | 
| 1845:  |  | 
| 1846:  |  | 
| 1847:  |  | 
| 1848:  |  | 
| 1849:  |     public function GetAccounts($AuthToken, $Type = '') | 
| 1850:  |     { | 
| 1851:  |         Api::checkUserRoleIsAtLeast(UserRole::Anonymous); | 
| 1852:  |  | 
| 1853:  |         $aUserInfo = Api::getAuthenticatedUserInfo($AuthToken); | 
| 1854:  |  | 
| 1855:  |         $aResult = []; | 
| 1856:  |         if (isset($aUserInfo['userId'])) { | 
| 1857:  |             $aArgs = array( | 
| 1858:  |                 'UserId' => $aUserInfo['userId'] | 
| 1859:  |             ); | 
| 1860:  |  | 
| 1861:  |             $this->broadcastEvent( | 
| 1862:  |                 'GetAccounts', | 
| 1863:  |                 $aArgs, | 
| 1864:  |                 $aResult | 
| 1865:  |             ); | 
| 1866:  |         } | 
| 1867:  |  | 
| 1868:  |         if (!empty($Type)) { | 
| 1869:  |             $aTempResult = []; | 
| 1870:  |             foreach ($aResult as $aItem) { | 
| 1871:  |                 if ($aItem['Type'] === $Type) { | 
| 1872:  |                     $aTempResult[] = $aItem; | 
| 1873:  |                 } | 
| 1874:  |             } | 
| 1875:  |             $aResult = $aTempResult; | 
| 1876:  |         } | 
| 1877:  |  | 
| 1878:  |         return $aResult; | 
| 1879:  |     } | 
| 1880:  |  | 
| 1881:  |      | 
| 1882:  |  | 
| 1883:  |  | 
| 1884:  |  | 
| 1885:  |  | 
| 1886:  |  | 
| 1887:  |  | 
| 1888:  |     public function GetUserAccounts($UserId, $Type = '') | 
| 1889:  |     { | 
| 1890:  |         Api::checkUserRoleIsAtLeast(UserRole::NormalUser); | 
| 1891:  |         $aResult = []; | 
| 1892:  |  | 
| 1893:  |         $oAuthenticatedUser = Api::getAuthenticatedUser(); | 
| 1894:  |  | 
| 1895:  |          | 
| 1896:  |          | 
| 1897:  |         if ($oAuthenticatedUser) { | 
| 1898:  |             $UserId = $oAuthenticatedUser->Id; | 
| 1899:  |         } | 
| 1900:  |  | 
| 1901:  |         if ($UserId) { | 
| 1902:  |             $aArgs = array( | 
| 1903:  |                 'UserId' => $UserId | 
| 1904:  |             ); | 
| 1905:  |  | 
| 1906:  |             $this->broadcastEvent( | 
| 1907:  |                 'GetAccounts', | 
| 1908:  |                 $aArgs, | 
| 1909:  |                 $aResult | 
| 1910:  |             ); | 
| 1911:  |             if (!empty($Type)) { | 
| 1912:  |                 $aTempResult = []; | 
| 1913:  |                 foreach ($aResult as $aItem) { | 
| 1914:  |                     if ($aItem['Type'] === $Type) { | 
| 1915:  |                         $aTempResult[] = $aItem; | 
| 1916:  |                     } | 
| 1917:  |                 } | 
| 1918:  |                 $aResult = $aTempResult; | 
| 1919:  |             } | 
| 1920:  |         } | 
| 1921:  |  | 
| 1922:  |         return $aResult; | 
| 1923:  |     } | 
| 1924:  |  | 
| 1925:  |      | 
| 1926:  |  | 
| 1927:  |  | 
| 1928:  |  | 
| 1929:  |  | 
| 1930:  |  | 
| 1931:  |     public function IsBlockedUser($sEmail, $sIp) | 
| 1932:  |     { | 
| 1933:  |          | 
| 1934:  |  | 
| 1935:  |         $bEnableFailedLoginBlock = $this->oModuleSettings->EnableFailedLoginBlock; | 
| 1936:  |         $iLoginBlockAvailableTriesCount = $this->oModuleSettings->LoginBlockAvailableTriesCount; | 
| 1937:  |         $iLoginBlockDurationMinutes = $this->oModuleSettings->LoginBlockDurationMinutes; | 
| 1938:  |  | 
| 1939:  |         if ($bEnableFailedLoginBlock) { | 
| 1940:  |             try { | 
| 1941:  |                 $oBlockedUser = $this->GetBlockedUser($sEmail, $sIp); | 
| 1942:  |                 if ($oBlockedUser) { | 
| 1943:  |                     if ($oBlockedUser->ErrorLoginsCount >= $iLoginBlockAvailableTriesCount) { | 
| 1944:  |                         $iBlockTime = (time() - $oBlockedUser->Time) / 60; | 
| 1945:  |                         if ($iBlockTime > $iLoginBlockDurationMinutes) { | 
| 1946:  |                             $oBlockedUser->delete(); | 
| 1947:  |                         } else { | 
| 1948:  |                             $this->BlockUser($sEmail, $sIp); | 
| 1949:  |                             throw new ApiException( | 
| 1950:  |                                 1000, | 
| 1951:  |                                 null, | 
| 1952:  |                                 $this->i18N("BLOCKED_USER_MESSAGE_ERROR", [ | 
| 1953:  |                                     "N" => $iLoginBlockAvailableTriesCount, | 
| 1954:  |                                     "M" => ceil($iLoginBlockDurationMinutes - $iBlockTime) | 
| 1955:  |                                 ]) | 
| 1956:  |                             ); | 
| 1957:  |                         } | 
| 1958:  |                     } | 
| 1959:  |                 } elseif ($this->CheckIpReputation($sIp)) { | 
| 1960:  |                     $this->BlockUser($sEmail, $sIp, true); | 
| 1961:  |  | 
| 1962:  |                     throw new ApiException( | 
| 1963:  |                         1000, | 
| 1964:  |                         null, | 
| 1965:  |                         $this->i18N("BLOCKED_USER_IP_REPUTATION_MESSAGE_ERROR") | 
| 1966:  |                     ); | 
| 1967:  |                 } | 
| 1968:  |             } catch (\Aurora\System\Exceptions\DbException $oEx) { | 
| 1969:  |                 Api::LogException($oEx); | 
| 1970:  |             } | 
| 1971:  |         } | 
| 1972:  |     } | 
| 1973:  |  | 
| 1974:  |      | 
| 1975:  |  | 
| 1976:  |  | 
| 1977:  |  | 
| 1978:  |  | 
| 1979:  |  | 
| 1980:  |     public function GetBlockedUser($sEmail, $sIp) | 
| 1981:  |     { | 
| 1982:  |          | 
| 1983:  |  | 
| 1984:  |         $mResult = false; | 
| 1985:  |  | 
| 1986:  |         if ($this->oModuleSettings->EnableFailedLoginBlock) { | 
| 1987:  |             try { | 
| 1988:  |                 $mResult = Models\UserBlock::where('Email', $sEmail)->where('IpAddress', $sIp)->first(); | 
| 1989:  |             } catch (\Exception $oEx) { | 
| 1990:  |                 $mResult = false; | 
| 1991:  |             } | 
| 1992:  |         } | 
| 1993:  |  | 
| 1994:  |         return $mResult; | 
| 1995:  |     } | 
| 1996:  |  | 
| 1997:  |      | 
| 1998:  |  | 
| 1999:  |  | 
| 2000:  |  | 
| 2001:  |  | 
| 2002:  |     public function CheckIpReputation($sIp) | 
| 2003:  |     { | 
| 2004:  |          | 
| 2005:  |  | 
| 2006:  |         $mResult = false; | 
| 2007:  |  | 
| 2008:  |         if ($this->oModuleSettings->EnableFailedLoginBlock && is_numeric($this->oModuleSettings->LoginBlockIpReputationThreshold) && $this->oModuleSettings->LoginBlockIpReputationThreshold > 0) { | 
| 2009:  |             $iLoginBlockAvailableTriesCount = $this->oModuleSettings->LoginBlockAvailableTriesCount; | 
| 2010:  |  | 
| 2011:  |             $count = Models\UserBlock::where('IpAddress', $sIp)->where('ErrorLoginsCount', '>=', $iLoginBlockAvailableTriesCount)->count(); | 
| 2012:  |  | 
| 2013:  |             $mResult = $count >= $this->oModuleSettings->LoginBlockIpReputationThreshold; | 
| 2014:  |         } | 
| 2015:  |  | 
| 2016:  |         return $mResult; | 
| 2017:  |     } | 
| 2018:  |  | 
| 2019:  |      | 
| 2020:  |  | 
| 2021:  |  | 
| 2022:  |  | 
| 2023:  |  | 
| 2024:  |     public function BlockUser($sEmail, $sIp, $bMaxErrorLoginsCount = false) | 
| 2025:  |     { | 
| 2026:  |          | 
| 2027:  |  | 
| 2028:  |         if ($this->oModuleSettings->EnableFailedLoginBlock) { | 
| 2029:  |  | 
| 2030:  |             try { | 
| 2031:  |                 $oBlockedUser = $this->GetBlockedUser($sEmail, $sIp); | 
| 2032:  |                 if (!$oBlockedUser) { | 
| 2033:  |                     $oBlockedUser = new Models\UserBlock(); | 
| 2034:  |                     $oBlockedUser->Email = $sEmail; | 
| 2035:  |                     $oBlockedUser->IpAddress = $sIp; | 
| 2036:  |                 } | 
| 2037:  |                 $iUserId = Api::getUserIdByPublicId($sEmail); | 
| 2038:  |                 if ($iUserId) { | 
| 2039:  |                     $oBlockedUser->UserId = $iUserId; | 
| 2040:  |                     if ($bMaxErrorLoginsCount) { | 
| 2041:  |                         $oBlockedUser->ErrorLoginsCount = $this->oModuleSettings->LoginBlockAvailableTriesCount; | 
| 2042:  |                     } else { | 
| 2043:  |                         $oBlockedUser->ErrorLoginsCount++; | 
| 2044:  |                     } | 
| 2045:  |                     $oBlockedUser->Time = time(); | 
| 2046:  |  | 
| 2047:  |                     $oBlockedUser->save(); | 
| 2048:  |                 } | 
| 2049:  |             } catch (\Exception $oEx) { | 
| 2050:  |                 Api::LogException($oEx); | 
| 2051:  |             } | 
| 2052:  |         } | 
| 2053:  |     } | 
| 2054:  |  | 
| 2055:  |      | 
| 2056:  |  | 
| 2057:  |  | 
| 2058:  |  | 
| 2059:  |  | 
| 2060:  |  | 
| 2061:  |  | 
| 2062:  |     public function Authenticate($Login, $Password, $SignMe = false) | 
| 2063:  |     { | 
| 2064:  |          | 
| 2065:  |  | 
| 2066:  |         $sIp = \Aurora\System\Utils::getClientIp(); | 
| 2067:  |         $this->Decorator()->IsBlockedUser($Login, $sIp); | 
| 2068:  |  | 
| 2069:  |         $mResult = false; | 
| 2070:  |         $aArgs = array( | 
| 2071:  |             'Login' => $Login, | 
| 2072:  |             'Password' => $Password, | 
| 2073:  |             'SignMe' => $SignMe | 
| 2074:  |         ); | 
| 2075:  |  | 
| 2076:  |         try { | 
| 2077:  |             $this->broadcastEvent( | 
| 2078:  |                 'Login', | 
| 2079:  |                 $aArgs, | 
| 2080:  |                 $mResult | 
| 2081:  |             ); | 
| 2082:  |         } catch (\Exception $oException) { | 
| 2083:  |             Api::GetModuleManager()->SetLastException($oException); | 
| 2084:  |         } | 
| 2085:  |  | 
| 2086:  |         if (!$mResult) { | 
| 2087:  |             $this->Decorator()->BlockUser($Login, $sIp); | 
| 2088:  |             $this->Decorator()->IsBlockedUser($Login, $sIp); | 
| 2089:  |         } else { | 
| 2090:  |             $oBlockedUser = $this->Decorator()->GetBlockedUser($Login, $sIp); | 
| 2091:  |             if ($oBlockedUser) { | 
| 2092:  |                 $oBlockedUser->delete(); | 
| 2093:  |             } | 
| 2094:  |         } | 
| 2095:  |  | 
| 2096:  |         return $mResult; | 
| 2097:  |     } | 
| 2098:  |  | 
| 2099:  |      | 
| 2100:  |  | 
| 2101:  |  | 
| 2102:  |     public function SetAuthDataAndGetAuthToken($aAuthData, $Language = '', $SignMe = false) | 
| 2103:  |     { | 
| 2104:  |          | 
| 2105:  |  | 
| 2106:  |         $mResult = false; | 
| 2107:  |         if ($aAuthData && is_array($aAuthData)) { | 
| 2108:  |             $mResult = $aAuthData; | 
| 2109:  |             if (isset($aAuthData['token'])) { | 
| 2110:  |                 $iTime = $SignMe ? 0 : time(); | 
| 2111:  |                 $iAuthTokenExpirationLifetimeDays = \Aurora\Api::GetSettings()->AuthTokenExpirationLifetimeDays; | 
| 2112:  |                 $iExpire = 0; | 
| 2113:  |                 if ($iAuthTokenExpirationLifetimeDays > 0) { | 
| 2114:  |                     $iExpire = time() + ($iAuthTokenExpirationLifetimeDays * 24 * 60 * 60); | 
| 2115:  |                 } | 
| 2116:  |  | 
| 2117:  |                 $sAuthToken = Api::UserSession()->Set($aAuthData, $iTime, $iExpire); | 
| 2118:  |  | 
| 2119:  |                  | 
| 2120:  |                 $oUser = Api::getAuthenticatedUser($sAuthToken, true); | 
| 2121:  |                 if ($oUser) { | 
| 2122:  |                     if ($oUser->Role !== UserRole::SuperAdmin) { | 
| 2123:  |                          | 
| 2124:  |                          | 
| 2125:  |                         $oTenant = Api::getTenantByWebDomain(); | 
| 2126:  |                         if ($oTenant && $oUser->IdTenant !== $oTenant->Id) { | 
| 2127:  |                             throw new ApiException(Notifications::AuthError, null, 'AuthError'); | 
| 2128:  |                         } | 
| 2129:  |                     } | 
| 2130:  |  | 
| 2131:  |                     if ($Language !== '' && $oUser->Language !== $Language) { | 
| 2132:  |                         $oUser->Language = $Language; | 
| 2133:  |                     } | 
| 2134:  |  | 
| 2135:  |                     $oUser->LastLogin = date('Y-m-d H:i:s'); | 
| 2136:  |                     $oUser->LoginsCount =  $oUser->LoginsCount + 1; | 
| 2137:  |  | 
| 2138:  |                     $this->getUsersManager()->updateUser($oUser); | 
| 2139:  |                     Api::LogEvent('login-success: ' . $oUser->PublicId, self::GetName()); | 
| 2140:  |                     $mResult = [ | 
| 2141:  |                         \Aurora\System\Application::AUTH_TOKEN_KEY => $sAuthToken | 
| 2142:  |                     ]; | 
| 2143:  |                 } else { | 
| 2144:  |                     throw new ApiException(Notifications::AuthError, null, 'AuthError'); | 
| 2145:  |                 } | 
| 2146:  |             } | 
| 2147:  |         } else { | 
| 2148:  |             Api::LogEvent('login-failed', self::GetName()); | 
| 2149:  |             Api::GetModuleManager()->SetLastException( | 
| 2150:  |                 new ApiException(Notifications::AuthError, null, 'AuthError') | 
| 2151:  |             ); | 
| 2152:  |         } | 
| 2153:  |  | 
| 2154:  |         return $mResult; | 
| 2155:  |     } | 
| 2156:  |  | 
| 2157:  |      | 
| 2158:  |  | 
| 2159:  |  | 
| 2160:  |  | 
| 2161:  |  | 
| 2162:  |  | 
| 2163:  |  | 
| 2164:  |  | 
| 2165:  |  | 
| 2166:  |  | 
| 2167:  |  | 
| 2168:  |  | 
| 2169:  |  | 
| 2170:  |  | 
| 2171:  |  | 
| 2172:  |  | 
| 2173:  |  | 
| 2174:  |  | 
| 2175:  |  | 
| 2176:  |  | 
| 2177:  |  | 
| 2178:  |  | 
| 2179:  |  | 
| 2180:  |  | 
| 2181:  |  | 
| 2182:  |  | 
| 2183:  |  | 
| 2184:  |  | 
| 2185:  |  | 
| 2186:  |  | 
| 2187:  |  | 
| 2188:  |  | 
| 2189:  |  | 
| 2190:  |  | 
| 2191:  |  | 
| 2192:  |  | 
| 2193:  |  | 
| 2194:  |  | 
| 2195:  |  | 
| 2196:  |  | 
| 2197:  |  | 
| 2198:  |  | 
| 2199:  |  | 
| 2200:  |  | 
| 2201:  |  | 
| 2202:  |      | 
| 2203:  |  | 
| 2204:  |  | 
| 2205:  |  | 
| 2206:  |  | 
| 2207:  |  | 
| 2208:  |  | 
| 2209:  |  | 
| 2210:  |  | 
| 2211:  |  | 
| 2212:  |     public function Login($Login, $Password, $Language = '', $SignMe = false) | 
| 2213:  |     { | 
| 2214:  |         Api::checkUserRoleIsAtLeast(UserRole::Anonymous); | 
| 2215:  |  | 
| 2216:  |         $Login = str_replace(" ", "", $Login); | 
| 2217:  |         $aAuthData = $this->Decorator()->Authenticate($Login, $Password, $SignMe); | 
| 2218:  |  | 
| 2219:  |         return $this->Decorator()->SetAuthDataAndGetAuthToken($aAuthData, $Language, $SignMe); | 
| 2220:  |     } | 
| 2221:  |  | 
| 2222:  |      | 
| 2223:  |  | 
| 2224:  |  | 
| 2225:  |  | 
| 2226:  |  | 
| 2227:  |  | 
| 2228:  |  | 
| 2229:  |     public function GetDigestHash($Login, $Realm, $Type) | 
| 2230:  |     { | 
| 2231:  |          | 
| 2232:  |  | 
| 2233:  |         $mResult = null; | 
| 2234:  |  | 
| 2235:  |         $aArgs = array( | 
| 2236:  |             'Login' => $Login, | 
| 2237:  |             'Realm' => $Realm, | 
| 2238:  |             'Type' => $Type | 
| 2239:  |         ); | 
| 2240:  |  | 
| 2241:  |         $this->broadcastEvent( | 
| 2242:  |             'GetDigestHash', | 
| 2243:  |             $aArgs, | 
| 2244:  |             $mResult | 
| 2245:  |         ); | 
| 2246:  |  | 
| 2247:  |         return $mResult; | 
| 2248:  |     } | 
| 2249:  |  | 
| 2250:  |     public function GetAccountUsedToAuthorize($Login) | 
| 2251:  |     { | 
| 2252:  |          | 
| 2253:  |  | 
| 2254:  |         $mResult = null; | 
| 2255:  |  | 
| 2256:  |         $aArgs = array( | 
| 2257:  |             'Login' => $Login | 
| 2258:  |         ); | 
| 2259:  |  | 
| 2260:  |         $this->broadcastEvent( | 
| 2261:  |             'GetAccountUsedToAuthorize', | 
| 2262:  |             $aArgs, | 
| 2263:  |             $mResult | 
| 2264:  |         ); | 
| 2265:  |  | 
| 2266:  |         return $mResult; | 
| 2267:  |     } | 
| 2268:  |  | 
| 2269:  |      | 
| 2270:  |  | 
| 2271:  |  | 
| 2272:  |  | 
| 2273:  |  | 
| 2274:  |     public function VerifyPassword($Password) | 
| 2275:  |     { | 
| 2276:  |          | 
| 2277:  |  | 
| 2278:  |         Api::checkUserRoleIsAtLeast(UserRole::Anonymous); | 
| 2279:  |         $mResult = false; | 
| 2280:  |         $bResult = false; | 
| 2281:  |  | 
| 2282:  |         $oApiIntegrator = $this->getIntegratorManager(); | 
| 2283:  |         $aUserInfo = $oApiIntegrator->getAuthenticatedUserInfo(Api::getAuthToken()); | 
| 2284:  |         if (isset($aUserInfo['account']) && isset($aUserInfo['accountType'])) { | 
| 2285:  |             $r = new \ReflectionClass($aUserInfo['accountType']); | 
| 2286:  |             $oQuery = $r->getMethod('query')->invoke(null); | 
| 2287:  |  | 
| 2288:  |             $oAccount = $oQuery->find($aUserInfo['account']); | 
| 2289:  |             if ($oAccount) { | 
| 2290:  |                 $aArgs = array( | 
| 2291:  |                     'Login' => $oAccount->getLogin(), | 
| 2292:  |                     'Password' => $Password, | 
| 2293:  |                     'SignMe' => false | 
| 2294:  |                 ); | 
| 2295:  |                 $this->broadcastEvent( | 
| 2296:  |                     'Login', | 
| 2297:  |                     $aArgs, | 
| 2298:  |                     $mResult | 
| 2299:  |                 ); | 
| 2300:  |  | 
| 2301:  |                 if (is_array($mResult) | 
| 2302:  |                     && isset($mResult['token']) | 
| 2303:  |                     && $mResult['token'] === 'auth' | 
| 2304:  |                     && isset($mResult['id']) | 
| 2305:  |                 ) { | 
| 2306:  |                     $UserId = Api::getAuthenticatedUserId(); | 
| 2307:  |                     if ($mResult['id'] === $UserId) { | 
| 2308:  |                         $bResult = true; | 
| 2309:  |                     } | 
| 2310:  |                 } | 
| 2311:  |             } | 
| 2312:  |         } | 
| 2313:  |  | 
| 2314:  |         return $bResult; | 
| 2315:  |     } | 
| 2316:  |  | 
| 2317:  |      | 
| 2318:  |  | 
| 2319:  |  | 
| 2320:  |  | 
| 2321:  |  | 
| 2322:  |     public function ResetPassword($email, $resetOption) | 
| 2323:  |     { | 
| 2324:  |         $mResult = false; | 
| 2325:  |  | 
| 2326:  |         $aArgs = array( | 
| 2327:  |             'email' => $email, | 
| 2328:  |             'resetOption' => $resetOption | 
| 2329:  |         ); | 
| 2330:  |         $this->broadcastEvent( | 
| 2331:  |             'ResetPassword', | 
| 2332:  |             $aArgs, | 
| 2333:  |             $mResult | 
| 2334:  |         ); | 
| 2335:  |  | 
| 2336:  |  | 
| 2337:  |         if (!empty($mResult)) { | 
| 2338:  |             Api::LogEvent('resetPassword-success: ' . $email, self::GetName()); | 
| 2339:  |         } else { | 
| 2340:  |             Api::LogEvent('resetPassword-failed: ' . $email, self::GetName()); | 
| 2341:  |         } | 
| 2342:  |  | 
| 2343:  |         return $mResult; | 
| 2344:  |     } | 
| 2345:  |  | 
| 2346:  |  | 
| 2347:  |      | 
| 2348:  |  | 
| 2349:  |  | 
| 2350:  |     public function ResetPasswordBySecurityQuestion($securityAnswer, $securityToken) | 
| 2351:  |     { | 
| 2352:  |         $mResult = false; | 
| 2353:  |  | 
| 2354:  |         $aArgs = array( | 
| 2355:  |             'securityAnswer' => $securityAnswer, | 
| 2356:  |             'securityToken' => $securityToken | 
| 2357:  |         ); | 
| 2358:  |         $this->broadcastEvent( | 
| 2359:  |             'ResetPasswordBySecurityQuestion', | 
| 2360:  |             $aArgs, | 
| 2361:  |             $mResult | 
| 2362:  |         ); | 
| 2363:  |  | 
| 2364:  |  | 
| 2365:  |         if (!empty($mResult)) { | 
| 2366:  |             Api::LogEvent('ResetPasswordBySecurityQuestion-success: ' . $securityAnswer, self::GetName()); | 
| 2367:  |             return $mResult; | 
| 2368:  |         } | 
| 2369:  |  | 
| 2370:  |         Api::LogEvent('ResetPasswordBySecurityQuestion-failed: ' . $securityAnswer, self::GetName()); | 
| 2371:  |     } | 
| 2372:  |  | 
| 2373:  |      | 
| 2374:  |  | 
| 2375:  |  | 
| 2376:  |     public function UpdatePassword($Password, $ConfirmPassword, $Hash) | 
| 2377:  |     { | 
| 2378:  |         $mResult = false; | 
| 2379:  |  | 
| 2380:  |         $aArgs = array( | 
| 2381:  |             'Password' => $Password, | 
| 2382:  |             'ConfirmPassword' => $ConfirmPassword, | 
| 2383:  |             'Hash' => $Hash | 
| 2384:  |         ); | 
| 2385:  |         $this->broadcastEvent( | 
| 2386:  |             'UpdatePassword', | 
| 2387:  |             $aArgs, | 
| 2388:  |             $mResult | 
| 2389:  |         ); | 
| 2390:  |  | 
| 2391:  |         if (!empty($mResult)) { | 
| 2392:  |             Api::LogEvent('updatePassword-success: ' . $Hash, self::GetName()); | 
| 2393:  |             return $mResult; | 
| 2394:  |         } | 
| 2395:  |  | 
| 2396:  |         Api::LogEvent('updatePassword-failed: ' . $Hash, self::GetName()); | 
| 2397:  |     } | 
| 2398:  |  | 
| 2399:  |      | 
| 2400:  |  | 
| 2401:  |  | 
| 2402:  |  | 
| 2403:  |  | 
| 2404:  |  | 
| 2405:  |  | 
| 2406:  |  | 
| 2407:  |  | 
| 2408:  |  | 
| 2409:  |  | 
| 2410:  |  | 
| 2411:  |  | 
| 2412:  |  | 
| 2413:  |  | 
| 2414:  |  | 
| 2415:  |  | 
| 2416:  |  | 
| 2417:  |  | 
| 2418:  |  | 
| 2419:  |  | 
| 2420:  |  | 
| 2421:  |  | 
| 2422:  |  | 
| 2423:  |  | 
| 2424:  |  | 
| 2425:  |  | 
| 2426:  |  | 
| 2427:  |  | 
| 2428:  |  | 
| 2429:  |  | 
| 2430:  |  | 
| 2431:  |  | 
| 2432:  |  | 
| 2433:  |  | 
| 2434:  |  | 
| 2435:  |  | 
| 2436:  |  | 
| 2437:  |  | 
| 2438:  |  | 
| 2439:  |  | 
| 2440:  |  | 
| 2441:  |      | 
| 2442:  |  | 
| 2443:  |  | 
| 2444:  |  | 
| 2445:  |  | 
| 2446:  |  | 
| 2447:  |     public function Logout() | 
| 2448:  |     { | 
| 2449:  |         Api::checkUserRoleIsAtLeast(UserRole::Anonymous); | 
| 2450:  |  | 
| 2451:  |         Api::LogEvent('logout', self::GetName()); | 
| 2452:  |  | 
| 2453:  |         Api::UserSession()->Delete( | 
| 2454:  |             Api::getAuthToken() | 
| 2455:  |         ); | 
| 2456:  |  | 
| 2457:  |         return true; | 
| 2458:  |     } | 
| 2459:  |  | 
| 2460:  |      | 
| 2461:  |  | 
| 2462:  |  | 
| 2463:  |  | 
| 2464:  |  | 
| 2465:  |  | 
| 2466:  |  | 
| 2467:  |  | 
| 2468:  |     public function CreateChannel($Login, $Description = '') | 
| 2469:  |     { | 
| 2470:  |         $mResult = -1; | 
| 2471:  |         Api::checkUserRoleIsAtLeast(UserRole::SuperAdmin); | 
| 2472:  |  | 
| 2473:  |         $mResult = false; | 
| 2474:  |  | 
| 2475:  |         $Login = \trim($Login); | 
| 2476:  |         if ($Login !== '') { | 
| 2477:  |             $oChannel = new Models\Channel(); | 
| 2478:  |  | 
| 2479:  |             $oChannel->Login = $Login; | 
| 2480:  |  | 
| 2481:  |             if ($Description !== '') { | 
| 2482:  |                 $oChannel->Description = $Description; | 
| 2483:  |             } | 
| 2484:  |  | 
| 2485:  |             if ($this->getChannelsManager()->createChannel($oChannel)) { | 
| 2486:  |                 $mResult = $oChannel->Id; | 
| 2487:  |             } | 
| 2488:  |         } else { | 
| 2489:  |             throw new ApiException(Notifications::InvalidInputParameter, null, 'InvalidInputParameter'); | 
| 2490:  |         } | 
| 2491:  |  | 
| 2492:  |         return $mResult; | 
| 2493:  |     } | 
| 2494:  |  | 
| 2495:  |      | 
| 2496:  |  | 
| 2497:  |  | 
| 2498:  |  | 
| 2499:  |  | 
| 2500:  |  | 
| 2501:  |  | 
| 2502:  |  | 
| 2503:  |  | 
| 2504:  |     public function UpdateChannel($ChannelId, $Login = '', $Description = '') | 
| 2505:  |     { | 
| 2506:  |         Api::checkUserRoleIsAtLeast(UserRole::SuperAdmin); | 
| 2507:  |  | 
| 2508:  |         if ($ChannelId > 0) { | 
| 2509:  |             $oChannel = $this->getChannelsManager()->getChannelById($ChannelId); | 
| 2510:  |  | 
| 2511:  |             if ($oChannel) { | 
| 2512:  |                 $Login = \trim($Login); | 
| 2513:  |                 if (!empty($Login)) { | 
| 2514:  |                     $oChannel->Login = $Login; | 
| 2515:  |                 } | 
| 2516:  |                 if (!empty($Description)) { | 
| 2517:  |                     $oChannel->Description = $Description; | 
| 2518:  |                 } | 
| 2519:  |  | 
| 2520:  |                 return $this->getChannelsManager()->updateChannel($oChannel); | 
| 2521:  |             } | 
| 2522:  |         } else { | 
| 2523:  |             throw new ApiException(Notifications::InvalidInputParameter, null, 'InvalidInputParameter'); | 
| 2524:  |         } | 
| 2525:  |  | 
| 2526:  |         return false; | 
| 2527:  |     } | 
| 2528:  |  | 
| 2529:  |      | 
| 2530:  |  | 
| 2531:  |  | 
| 2532:  |  | 
| 2533:  |  | 
| 2534:  |  | 
| 2535:  |  | 
| 2536:  |     public function DeleteChannel($ChannelId) | 
| 2537:  |     { | 
| 2538:  |         Api::checkUserRoleIsAtLeast(UserRole::SuperAdmin); | 
| 2539:  |  | 
| 2540:  |         if ($ChannelId > 0) { | 
| 2541:  |             $oChannel = $this->getChannelsManager()->getChannelById($ChannelId); | 
| 2542:  |  | 
| 2543:  |             if ($oChannel) { | 
| 2544:  |                 return $this->getChannelsManager()->deleteChannel($oChannel); | 
| 2545:  |             } | 
| 2546:  |         } else { | 
| 2547:  |             throw new ApiException(Notifications::InvalidInputParameter, null, 'InvalidInputParameter'); | 
| 2548:  |         } | 
| 2549:  |  | 
| 2550:  |         return false; | 
| 2551:  |     } | 
| 2552:  |  | 
| 2553:  |      | 
| 2554:  |  | 
| 2555:  |  | 
| 2556:  |  | 
| 2557:  |  | 
| 2558:  |  | 
| 2559:  |  | 
| 2560:  |  | 
| 2561:  |  | 
| 2562:  |  | 
| 2563:  |  | 
| 2564:  |  | 
| 2565:  |  | 
| 2566:  |  | 
| 2567:  |  | 
| 2568:  |  | 
| 2569:  |  | 
| 2570:  |  | 
| 2571:  |  | 
| 2572:  |  | 
| 2573:  |  | 
| 2574:  |  | 
| 2575:  |  | 
| 2576:  |  | 
| 2577:  |  | 
| 2578:  |  | 
| 2579:  |  | 
| 2580:  |  | 
| 2581:  |  | 
| 2582:  |  | 
| 2583:  |  | 
| 2584:  |  | 
| 2585:  |  | 
| 2586:  |  | 
| 2587:  |  | 
| 2588:  |  | 
| 2589:  |  | 
| 2590:  |  | 
| 2591:  |  | 
| 2592:  |  | 
| 2593:  |  | 
| 2594:  |  | 
| 2595:  |  | 
| 2596:  |  | 
| 2597:  |  | 
| 2598:  |  | 
| 2599:  |  | 
| 2600:  |  | 
| 2601:  |  | 
| 2602:  |  | 
| 2603:  |  | 
| 2604:  |  | 
| 2605:  |  | 
| 2606:  |      | 
| 2607:  |  | 
| 2608:  |  | 
| 2609:  |  | 
| 2610:  |  | 
| 2611:  |  | 
| 2612:  |  | 
| 2613:  |  | 
| 2614:  |  | 
| 2615:  |  | 
| 2616:  |  | 
| 2617:  |     public function GetTenants($Offset = 0, $Limit = 0, $Search = '') | 
| 2618:  |     { | 
| 2619:  |         Api::checkUserRoleIsAtLeast(UserRole::TenantAdmin); | 
| 2620:  |  | 
| 2621:  |         $oAuthenticatedUser = Api::getAuthenticatedUser(); | 
| 2622:  |         $bSuperadmin = $oAuthenticatedUser->Role === UserRole::SuperAdmin; | 
| 2623:  |  | 
| 2624:  |         $aTenantsFromDb = $this->getTenantsManager()->getTenantList($Offset, $Limit, $Search); | 
| 2625:  |         $oSettings = $this->oModuleSettings; | 
| 2626:  |         $aTenants = []; | 
| 2627:  |  | 
| 2628:  |         foreach ($aTenantsFromDb as $oTenant) { | 
| 2629:  |             if ($bSuperadmin || $oTenant->Id === $oAuthenticatedUser->IdTenant) { | 
| 2630:  |                 $aTenants[] = [ | 
| 2631:  |                     'Id' => $oTenant->Id, | 
| 2632:  |                     'Name' => $oTenant->Name, | 
| 2633:  |                     'SiteName' => $oSettings->GetTenantValue($oTenant->Name, 'SiteName', '') | 
| 2634:  |                 ]; | 
| 2635:  |             } | 
| 2636:  |         } | 
| 2637:  |  | 
| 2638:  |         $iTenantsCount = $Limit > 0 ? $this->getTenantsManager()->getTenantsCount($Search) : count($aTenants); | 
| 2639:  |         return array( | 
| 2640:  |             'Items' => $aTenants, | 
| 2641:  |             'Count' => $iTenantsCount, | 
| 2642:  |         ); | 
| 2643:  |     } | 
| 2644:  |  | 
| 2645:  |      | 
| 2646:  |  | 
| 2647:  |  | 
| 2648:  |  | 
| 2649:  |  | 
| 2650:  |  | 
| 2651:  |  | 
| 2652:  |  | 
| 2653:  |  | 
| 2654:  |  | 
| 2655:  |  | 
| 2656:  |  | 
| 2657:  |  | 
| 2658:  |  | 
| 2659:  |  | 
| 2660:  |  | 
| 2661:  |  | 
| 2662:  |  | 
| 2663:  |  | 
| 2664:  |  | 
| 2665:  |  | 
| 2666:  |  | 
| 2667:  |  | 
| 2668:  |  | 
| 2669:  |  | 
| 2670:  |  | 
| 2671:  |  | 
| 2672:  |  | 
| 2673:  |  | 
| 2674:  |  | 
| 2675:  |  | 
| 2676:  |  | 
| 2677:  |  | 
| 2678:  |  | 
| 2679:  |  | 
| 2680:  |  | 
| 2681:  |  | 
| 2682:  |  | 
| 2683:  |  | 
| 2684:  |  | 
| 2685:  |  | 
| 2686:  |  | 
| 2687:  |  | 
| 2688:  |  | 
| 2689:  |  | 
| 2690:  |  | 
| 2691:  |  | 
| 2692:  |      | 
| 2693:  |  | 
| 2694:  |  | 
| 2695:  |  | 
| 2696:  |  | 
| 2697:  |  | 
| 2698:  |     public function GetTenant($Id) | 
| 2699:  |     { | 
| 2700:  |         $oAuthenticatedUser = Api::getAuthenticatedUser(); | 
| 2701:  |         if (($oAuthenticatedUser instanceof User) && $oAuthenticatedUser->IdTenant === $Id) { | 
| 2702:  |             Api::checkUserRoleIsAtLeast(UserRole::TenantAdmin); | 
| 2703:  |         } else { | 
| 2704:  |             Api::checkUserRoleIsAtLeast(UserRole::SuperAdmin); | 
| 2705:  |         } | 
| 2706:  |  | 
| 2707:  |         return $this->GetTenantWithoutRoleCheck($Id); | 
| 2708:  |     } | 
| 2709:  |  | 
| 2710:  |      | 
| 2711:  |  | 
| 2712:  |  | 
| 2713:  |  | 
| 2714:  |  | 
| 2715:  |  | 
| 2716:  |  | 
| 2717:  |  | 
| 2718:  |  | 
| 2719:  |  | 
| 2720:  |  | 
| 2721:  |  | 
| 2722:  |  | 
| 2723:  |  | 
| 2724:  |  | 
| 2725:  |  | 
| 2726:  |  | 
| 2727:  |  | 
| 2728:  |  | 
| 2729:  |  | 
| 2730:  |  | 
| 2731:  |  | 
| 2732:  |  | 
| 2733:  |  | 
| 2734:  |  | 
| 2735:  |  | 
| 2736:  |  | 
| 2737:  |  | 
| 2738:  |  | 
| 2739:  |  | 
| 2740:  |  | 
| 2741:  |  | 
| 2742:  |  | 
| 2743:  |  | 
| 2744:  |  | 
| 2745:  |  | 
| 2746:  |  | 
| 2747:  |  | 
| 2748:  |  | 
| 2749:  |  | 
| 2750:  |  | 
| 2751:  |  | 
| 2752:  |  | 
| 2753:  |  | 
| 2754:  |  | 
| 2755:  |  | 
| 2756:  |  | 
| 2757:  |  | 
| 2758:  |  | 
| 2759:  |  | 
| 2760:  |  | 
| 2761:  |      | 
| 2762:  |  | 
| 2763:  |  | 
| 2764:  |  | 
| 2765:  |  | 
| 2766:  |  | 
| 2767:  |  | 
| 2768:  |  | 
| 2769:  |  | 
| 2770:  |  | 
| 2771:  |  | 
| 2772:  |     public function CreateTenant($ChannelId = 0, $Name = '', $Description = '', $WebDomain = '', $SiteName = null) | 
| 2773:  |     { | 
| 2774:  |         Api::checkUserRoleIsAtLeast(UserRole::SuperAdmin); | 
| 2775:  |  | 
| 2776:  |         $oSettings = &Api::GetSettings(); | 
| 2777:  |         if ($ChannelId === 0) {  | 
| 2778:  |             $aChannels = $this->getChannelsManager()->getChannelList(0, 1); | 
| 2779:  |             $ChannelId = count($aChannels) === 1 ? $aChannels[0]->Id : 0; | 
| 2780:  |         } | 
| 2781:  |         $Name = \trim(\Aurora\System\Utils::getSanitizedFilename($Name)); | 
| 2782:  |  | 
| 2783:  |         if ($Name !== '' && $ChannelId > 0) { | 
| 2784:  |             $iTenantsCount = $this->getTenantsManager()->getTenantsByChannelIdCount($ChannelId); | 
| 2785:  |             if ($oSettings->EnableMultiTenant || $iTenantsCount === 0) { | 
| 2786:  |                 $oTenant = new Models\Tenant(); | 
| 2787:  |  | 
| 2788:  |                 $oTenant->Name = $Name; | 
| 2789:  |                 $oTenant->Description = $Description; | 
| 2790:  |                 $oTenant->WebDomain = $WebDomain; | 
| 2791:  |                 $oTenant->IdChannel = $ChannelId; | 
| 2792:  |  | 
| 2793:  |                 if ($this->getTenantsManager()->createTenant($oTenant)) { | 
| 2794:  |                     if ($SiteName !== null) { | 
| 2795:  |                         $oSettings = $this->oModuleSettings; | 
| 2796:  |                         $oSettings->SaveTenantSettings($oTenant->Name, [ | 
| 2797:  |                             'SiteName' => $SiteName | 
| 2798:  |                         ]); | 
| 2799:  |                     } | 
| 2800:  |                     return $oTenant->Id; | 
| 2801:  |                 } | 
| 2802:  |             } | 
| 2803:  |         } else { | 
| 2804:  |             throw new ApiException(Notifications::InvalidInputParameter, null, 'InvalidInputParameter'); | 
| 2805:  |         } | 
| 2806:  |  | 
| 2807:  |         return false; | 
| 2808:  |     } | 
| 2809:  |  | 
| 2810:  |      | 
| 2811:  |  | 
| 2812:  |  | 
| 2813:  |  | 
| 2814:  |  | 
| 2815:  |  | 
| 2816:  |  | 
| 2817:  |  | 
| 2818:  |  | 
| 2819:  |  | 
| 2820:  |  | 
| 2821:  |  | 
| 2822:  |  | 
| 2823:  |  | 
| 2824:  |  | 
| 2825:  |  | 
| 2826:  |  | 
| 2827:  |  | 
| 2828:  |  | 
| 2829:  |  | 
| 2830:  |  | 
| 2831:  |  | 
| 2832:  |  | 
| 2833:  |  | 
| 2834:  |  | 
| 2835:  |  | 
| 2836:  |  | 
| 2837:  |  | 
| 2838:  |  | 
| 2839:  |  | 
| 2840:  |  | 
| 2841:  |  | 
| 2842:  |  | 
| 2843:  |  | 
| 2844:  |  | 
| 2845:  |  | 
| 2846:  |  | 
| 2847:  |  | 
| 2848:  |  | 
| 2849:  |  | 
| 2850:  |  | 
| 2851:  |  | 
| 2852:  |  | 
| 2853:  |  | 
| 2854:  |  | 
| 2855:  |  | 
| 2856:  |  | 
| 2857:  |  | 
| 2858:  |  | 
| 2859:  |  | 
| 2860:  |  | 
| 2861:  |      | 
| 2862:  |  | 
| 2863:  |  | 
| 2864:  |  | 
| 2865:  |  | 
| 2866:  |  | 
| 2867:  |  | 
| 2868:  |  | 
| 2869:  |  | 
| 2870:  |  | 
| 2871:  |  | 
| 2872:  |     public function UpdateTenant($TenantId, $Description = null, $WebDomain = null, $SiteName = null, $ChannelId = 0) | 
| 2873:  |     { | 
| 2874:  |         Api::checkUserRoleIsAtLeast(UserRole::TenantAdmin); | 
| 2875:  |         $oAuthenticatedUser = Api::getAuthenticatedUser(); | 
| 2876:  |         if ($oAuthenticatedUser->Role === UserRole::TenantAdmin && $oAuthenticatedUser->IdTenant !== $TenantId) { | 
| 2877:  |             throw new ApiException(Notifications::AccessDenied, null, 'AccessDenied'); | 
| 2878:  |         } else { | 
| 2879:  |             Api::checkUserRoleIsAtLeast(UserRole::SuperAdmin); | 
| 2880:  |         } | 
| 2881:  |  | 
| 2882:  |         if (!empty($TenantId)) { | 
| 2883:  |             $oTenant = $this->getTenantsManager()->getTenantById($TenantId); | 
| 2884:  |             if ($oTenant) { | 
| 2885:  |                 if ($SiteName !== null) { | 
| 2886:  |                     $oSettings = $this->oModuleSettings; | 
| 2887:  |                     $oSettings->SaveTenantSettings($oTenant->Name, [ | 
| 2888:  |                         'SiteName' => $SiteName | 
| 2889:  |                     ]); | 
| 2890:  |                 } | 
| 2891:  |                 if ($Description !== null) { | 
| 2892:  |                     $oTenant->Description = $Description; | 
| 2893:  |                 } | 
| 2894:  |                 if ($WebDomain !== null && $oAuthenticatedUser->Role === UserRole::SuperAdmin) { | 
| 2895:  |                     $oTenant->WebDomain = $WebDomain; | 
| 2896:  |                 } | 
| 2897:  |                 if (!empty($ChannelId) && $oAuthenticatedUser->Role === UserRole::SuperAdmin) { | 
| 2898:  |                     $oTenant->IdChannel = $ChannelId; | 
| 2899:  |                 } | 
| 2900:  |  | 
| 2901:  |                 return $this->getTenantsManager()->updateTenant($oTenant); | 
| 2902:  |             } | 
| 2903:  |         } else { | 
| 2904:  |             throw new ApiException(Notifications::InvalidInputParameter, null, 'InvalidInputParameter'); | 
| 2905:  |         } | 
| 2906:  |  | 
| 2907:  |         return false; | 
| 2908:  |     } | 
| 2909:  |  | 
| 2910:  |      | 
| 2911:  |  | 
| 2912:  |  | 
| 2913:  |  | 
| 2914:  |  | 
| 2915:  |  | 
| 2916:  |  | 
| 2917:  |  | 
| 2918:  |  | 
| 2919:  |  | 
| 2920:  |  | 
| 2921:  |  | 
| 2922:  |  | 
| 2923:  |  | 
| 2924:  |  | 
| 2925:  |  | 
| 2926:  |  | 
| 2927:  |  | 
| 2928:  |  | 
| 2929:  |  | 
| 2930:  |  | 
| 2931:  |  | 
| 2932:  |  | 
| 2933:  |  | 
| 2934:  |  | 
| 2935:  |  | 
| 2936:  |  | 
| 2937:  |  | 
| 2938:  |  | 
| 2939:  |  | 
| 2940:  |  | 
| 2941:  |  | 
| 2942:  |  | 
| 2943:  |  | 
| 2944:  |  | 
| 2945:  |  | 
| 2946:  |  | 
| 2947:  |  | 
| 2948:  |  | 
| 2949:  |  | 
| 2950:  |  | 
| 2951:  |  | 
| 2952:  |  | 
| 2953:  |  | 
| 2954:  |  | 
| 2955:  |  | 
| 2956:  |  | 
| 2957:  |      | 
| 2958:  |  | 
| 2959:  |  | 
| 2960:  |  | 
| 2961:  |  | 
| 2962:  |     public function DeleteTenants($IdList) | 
| 2963:  |     { | 
| 2964:  |         Api::checkUserRoleIsAtLeast(UserRole::SuperAdmin); | 
| 2965:  |  | 
| 2966:  |         $bResult = true; | 
| 2967:  |  | 
| 2968:  |         foreach ($IdList as $sId) { | 
| 2969:  |             $bResult = $bResult && self::Decorator()->DeleteTenant($sId); | 
| 2970:  |         } | 
| 2971:  |  | 
| 2972:  |         return $bResult; | 
| 2973:  |     } | 
| 2974:  |  | 
| 2975:  |      | 
| 2976:  |  | 
| 2977:  |  | 
| 2978:  |  | 
| 2979:  |  | 
| 2980:  |  | 
| 2981:  |  | 
| 2982:  |  | 
| 2983:  |  | 
| 2984:  |  | 
| 2985:  |  | 
| 2986:  |  | 
| 2987:  |  | 
| 2988:  |  | 
| 2989:  |  | 
| 2990:  |  | 
| 2991:  |  | 
| 2992:  |  | 
| 2993:  |  | 
| 2994:  |  | 
| 2995:  |  | 
| 2996:  |  | 
| 2997:  |  | 
| 2998:  |  | 
| 2999:  |  | 
| 3000:  |  | 
| 3001:  |  | 
| 3002:  |  | 
| 3003:  |  | 
| 3004:  |  | 
| 3005:  |  | 
| 3006:  |  | 
| 3007:  |  | 
| 3008:  |  | 
| 3009:  |  | 
| 3010:  |  | 
| 3011:  |  | 
| 3012:  |  | 
| 3013:  |  | 
| 3014:  |  | 
| 3015:  |  | 
| 3016:  |  | 
| 3017:  |  | 
| 3018:  |  | 
| 3019:  |  | 
| 3020:  |  | 
| 3021:  |  | 
| 3022:  |      | 
| 3023:  |  | 
| 3024:  |  | 
| 3025:  |  | 
| 3026:  |  | 
| 3027:  |  | 
| 3028:  |  | 
| 3029:  |     public function DeleteTenant($TenantId) | 
| 3030:  |     { | 
| 3031:  |         Api::checkUserRoleIsAtLeast(UserRole::SuperAdmin); | 
| 3032:  |  | 
| 3033:  |         if (!empty($TenantId)) { | 
| 3034:  |             $oTenant = $this->getTenantsManager()->getTenantById($TenantId); | 
| 3035:  |  | 
| 3036:  |             if ($oTenant) { | 
| 3037:  |                  | 
| 3038:  |                 $sTenantSpacePath = Api::GetModuleManager()->GetModulesSettingsPath() . 'tenants/' . $oTenant->Name; | 
| 3039:  |                 if (@is_dir($sTenantSpacePath)) { | 
| 3040:  |                     $this->deleteTree($sTenantSpacePath); | 
| 3041:  |                 } | 
| 3042:  |  | 
| 3043:  |                  | 
| 3044:  |                 Group::where('TenantId', $oTenant->Id)->delete(); | 
| 3045:  |  | 
| 3046:  |                  | 
| 3047:  |                 $userIds = User::where('IdTenant', $oTenant->Id)->select('Id')->pluck('Id')->toArray(); | 
| 3048:  |                 self::Decorator()->DeleteUsers($userIds); | 
| 3049:  |  | 
| 3050:  |                  | 
| 3051:  |                 return $this->getTenantsManager()->deleteTenant($oTenant); | 
| 3052:  |             } | 
| 3053:  |         } else { | 
| 3054:  |             throw new ApiException(Notifications::InvalidInputParameter, null, 'InvalidInputParameter'); | 
| 3055:  |         } | 
| 3056:  |  | 
| 3057:  |         return false; | 
| 3058:  |     } | 
| 3059:  |  | 
| 3060:  |      | 
| 3061:  |  | 
| 3062:  |  | 
| 3063:  |  | 
| 3064:  |  | 
| 3065:  |  | 
| 3066:  |  | 
| 3067:  |  | 
| 3068:  |  | 
| 3069:  |  | 
| 3070:  |  | 
| 3071:  |  | 
| 3072:  |  | 
| 3073:  |  | 
| 3074:  |  | 
| 3075:  |  | 
| 3076:  |  | 
| 3077:  |  | 
| 3078:  |  | 
| 3079:  |  | 
| 3080:  |  | 
| 3081:  |  | 
| 3082:  |  | 
| 3083:  |  | 
| 3084:  |  | 
| 3085:  |  | 
| 3086:  |  | 
| 3087:  |  | 
| 3088:  |  | 
| 3089:  |  | 
| 3090:  |  | 
| 3091:  |  | 
| 3092:  |  | 
| 3093:  |  | 
| 3094:  |  | 
| 3095:  |  | 
| 3096:  |  | 
| 3097:  |  | 
| 3098:  |  | 
| 3099:  |  | 
| 3100:  |  | 
| 3101:  |  | 
| 3102:  |  | 
| 3103:  |  | 
| 3104:  |  | 
| 3105:  |  | 
| 3106:  |  | 
| 3107:  |  | 
| 3108:  |  | 
| 3109:  |  | 
| 3110:  |  | 
| 3111:  |  | 
| 3112:  |  | 
| 3113:  |  | 
| 3114:  |  | 
| 3115:  |  | 
| 3116:  |  | 
| 3117:  |      | 
| 3118:  |  | 
| 3119:  |  | 
| 3120:  |  | 
| 3121:  |  | 
| 3122:  |  | 
| 3123:  |  | 
| 3124:  |  | 
| 3125:  |  | 
| 3126:  |  | 
| 3127:  |  | 
| 3128:  |  | 
| 3129:  |  | 
| 3130:  |  | 
| 3131:  |  | 
| 3132:  |     public function GetUsers($TenantId = 0, $Offset = 0, $Limit = 0, $OrderBy = 'PublicId', $OrderType = \Aurora\System\Enums\SortOrder::ASC, $Search = '', $Filters = null, $GroupId = -1) | 
| 3133:  |     { | 
| 3134:  |         Api::checkUserRoleIsAtLeast(UserRole::TenantAdmin); | 
| 3135:  |  | 
| 3136:  |         $oAuthenticatedUser = Api::getAuthenticatedUser(); | 
| 3137:  |         if ($oAuthenticatedUser->Role === UserRole::TenantAdmin) { | 
| 3138:  |             if ($oAuthenticatedUser->IdTenant !== $TenantId) { | 
| 3139:  |                 throw new ApiException(Notifications::AccessDenied, null, 'AccessDenied'); | 
| 3140:  |             } | 
| 3141:  |         } else { | 
| 3142:  |             Api::checkUserRoleIsAtLeast(UserRole::SuperAdmin); | 
| 3143:  |         } | 
| 3144:  |  | 
| 3145:  |         $aResult = [ | 
| 3146:  |             'Items' => [], | 
| 3147:  |             'Count' => 0, | 
| 3148:  |         ]; | 
| 3149:  |  | 
| 3150:  |         $Filters = ($Filters instanceof Builder) ? $Filters : Models\User::query(); | 
| 3151:  |         if ($TenantId !== 0) { | 
| 3152:  |             $Filters = $Filters->where('IdTenant', $TenantId); | 
| 3153:  |         } | 
| 3154:  |  | 
| 3155:  |         $aResult['Count'] = $this->getUsersManager()->getUsersCount($Search, $Filters, $GroupId); | 
| 3156:  |         $aUsers = $this->getUsersManager()->getUserList($Offset, $Limit, $OrderBy, $OrderType, $Search, $Filters, $GroupId); | 
| 3157:  |         foreach ($aUsers as $oUser) { | 
| 3158:  |             $aGroups = []; | 
| 3159:  |             if ($this->oModuleSettings->AllowGroups) { | 
| 3160:  |                 foreach ($oUser->Groups as $oGroup) { | 
| 3161:  |                     if (!$oGroup->IsAll) { | 
| 3162:  |                         $aGroups[] = [ | 
| 3163:  |                             'Id' => $oGroup->Id, | 
| 3164:  |                             'TenantId' => $oGroup->TenantId, | 
| 3165:  |                             'Name' => $oGroup->Name | 
| 3166:  |                         ]; | 
| 3167:  |                     } | 
| 3168:  |                 } | 
| 3169:  |             } | 
| 3170:  |             $aResult['Items'][] = [ | 
| 3171:  |                 'Id' => $oUser->Id, | 
| 3172:  |                 'UUID' => $oUser->UUID, | 
| 3173:  |                 'Name' => $oUser->Name, | 
| 3174:  |                 'PublicId' => $oUser->PublicId, | 
| 3175:  |                 'Role' => $oUser->Role, | 
| 3176:  |                 'IsDisabled' => $oUser->IsDisabled, | 
| 3177:  |                 'Groups' => $aGroups, | 
| 3178:  |             ]; | 
| 3179:  |         } | 
| 3180:  |  | 
| 3181:  |         return $aResult; | 
| 3182:  |     } | 
| 3183:  |  | 
| 3184:  |      | 
| 3185:  |  | 
| 3186:  |  | 
| 3187:  |     public function GetTotalUsersCount() | 
| 3188:  |     { | 
| 3189:  |         Api::checkUserRoleIsAtLeast(UserRole::TenantAdmin); | 
| 3190:  |  | 
| 3191:  |         return $this->getUsersManager()->getTotalUsersCount(); | 
| 3192:  |     } | 
| 3193:  |  | 
| 3194:  |      | 
| 3195:  |  | 
| 3196:  |  | 
| 3197:  |  | 
| 3198:  |  | 
| 3199:  |  | 
| 3200:  |  | 
| 3201:  |  | 
| 3202:  |  | 
| 3203:  |  | 
| 3204:  |  | 
| 3205:  |  | 
| 3206:  |  | 
| 3207:  |  | 
| 3208:  |  | 
| 3209:  |  | 
| 3210:  |  | 
| 3211:  |  | 
| 3212:  |  | 
| 3213:  |  | 
| 3214:  |  | 
| 3215:  |  | 
| 3216:  |  | 
| 3217:  |  | 
| 3218:  |  | 
| 3219:  |  | 
| 3220:  |  | 
| 3221:  |  | 
| 3222:  |  | 
| 3223:  |  | 
| 3224:  |  | 
| 3225:  |  | 
| 3226:  |  | 
| 3227:  |  | 
| 3228:  |  | 
| 3229:  |  | 
| 3230:  |  | 
| 3231:  |  | 
| 3232:  |  | 
| 3233:  |  | 
| 3234:  |  | 
| 3235:  |  | 
| 3236:  |  | 
| 3237:  |  | 
| 3238:  |  | 
| 3239:  |  | 
| 3240:  |  | 
| 3241:  |  | 
| 3242:  |  | 
| 3243:  |  | 
| 3244:  |  | 
| 3245:  |  | 
| 3246:  |      | 
| 3247:  |  | 
| 3248:  |  | 
| 3249:  |  | 
| 3250:  |  | 
| 3251:  |  | 
| 3252:  |     public function GetUser($Id = '') | 
| 3253:  |     { | 
| 3254:  |         $oUser = $this->getUsersManager()->getUser($Id); | 
| 3255:  |         $oAuthenticatedUser = Api::getAuthenticatedUser(); | 
| 3256:  |  | 
| 3257:  |         if ($oUser) {  | 
| 3258:  |             if (($oAuthenticatedUser instanceof User) && $oAuthenticatedUser->Role === UserRole::NormalUser && $oAuthenticatedUser->Id === $oUser->Id) { | 
| 3259:  |                 Api::checkUserRoleIsAtLeast(UserRole::NormalUser); | 
| 3260:  |             } elseif (($oAuthenticatedUser instanceof User) && $oAuthenticatedUser->Role === UserRole::TenantAdmin && $oAuthenticatedUser->IdTenant === $oUser->IdTenant) { | 
| 3261:  |                 Api::checkUserRoleIsAtLeast(UserRole::TenantAdmin); | 
| 3262:  |             } else { | 
| 3263:  |                 Api::checkUserRoleIsAtLeast(UserRole::SuperAdmin); | 
| 3264:  |             } | 
| 3265:  |  | 
| 3266:  |             return $oUser; | 
| 3267:  |         } | 
| 3268:  |  | 
| 3269:  |         return null; | 
| 3270:  |     } | 
| 3271:  |  | 
| 3272:  |      | 
| 3273:  |  | 
| 3274:  |  | 
| 3275:  |     public function TurnOffSeparateLogs() | 
| 3276:  |     { | 
| 3277:  |         Api::checkUserRoleIsAtLeast(UserRole::TenantAdmin); | 
| 3278:  |  | 
| 3279:  |         $Filters = Models\User::query(); | 
| 3280:  |         $oAuthenticatedUser = Api::getAuthenticatedUser(); | 
| 3281:  |         if ($oAuthenticatedUser->Role === UserRole::TenantAdmin) { | 
| 3282:  |             $Filters = $Filters->where('IdTenant', $oAuthenticatedUser->IdTenant); | 
| 3283:  |         } | 
| 3284:  |  | 
| 3285:  |         $aResults = $this->getUsersManager()->getUserList(0, 0, 'PublicId', \Aurora\System\Enums\SortOrder::ASC, '', $Filters->where('WriteSeparateLog', true)); | 
| 3286:  |         foreach ($aResults as $aUser) { | 
| 3287:  |             $oUser = self::Decorator()->GetUser($aUser['EntityId']); | 
| 3288:  |             if ($oUser) { | 
| 3289:  |                 $oUser->WriteSeparateLog = false; | 
| 3290:  |                 $this->UpdateUserObject($oUser); | 
| 3291:  |             } | 
| 3292:  |         } | 
| 3293:  |  | 
| 3294:  |         return true; | 
| 3295:  |     } | 
| 3296:  |  | 
| 3297:  |      | 
| 3298:  |  | 
| 3299:  |  | 
| 3300:  |     public function ClearSeparateLogs() | 
| 3301:  |     { | 
| 3302:  |         Api::checkUserRoleIsAtLeast(UserRole::TenantAdmin); | 
| 3303:  |  | 
| 3304:  |         Api::RemoveSeparateLogs(); | 
| 3305:  |  | 
| 3306:  |         return true; | 
| 3307:  |     } | 
| 3308:  |  | 
| 3309:  |      | 
| 3310:  |  | 
| 3311:  |  | 
| 3312:  |     public function GetUsersWithSeparateLog() | 
| 3313:  |     { | 
| 3314:  |         Api::checkUserRoleIsAtLeast(UserRole::TenantAdmin); | 
| 3315:  |  | 
| 3316:  |         $Filters = Models\User::query(); | 
| 3317:  |         $oAuthenticatedUser = Api::getAuthenticatedUser(); | 
| 3318:  |         if ($oAuthenticatedUser->Role === UserRole::TenantAdmin) { | 
| 3319:  |             $Filters = $Filters->where('IdTenant', $oAuthenticatedUser->IdTenant); | 
| 3320:  |         } | 
| 3321:  |  | 
| 3322:  |         $aResults = $this->getUsersManager()->getUserList(0, 0, 'PublicId', \Aurora\System\Enums\SortOrder::ASC, '', $Filters->where('WriteSeparateLog', true)); | 
| 3323:  |         $aUsers = []; | 
| 3324:  |         foreach ($aResults as $aUser) { | 
| 3325:  |             $aUsers[] = $aUser['PublicId']; | 
| 3326:  |         } | 
| 3327:  |         return $aUsers; | 
| 3328:  |     } | 
| 3329:  |  | 
| 3330:  |      | 
| 3331:  |  | 
| 3332:  |  | 
| 3333:  |  | 
| 3334:  |  | 
| 3335:  |  | 
| 3336:  |  | 
| 3337:  |  | 
| 3338:  |  | 
| 3339:  |  | 
| 3340:  |  | 
| 3341:  |  | 
| 3342:  |  | 
| 3343:  |  | 
| 3344:  |  | 
| 3345:  |  | 
| 3346:  |  | 
| 3347:  |  | 
| 3348:  |  | 
| 3349:  |  | 
| 3350:  |  | 
| 3351:  |  | 
| 3352:  |  | 
| 3353:  |  | 
| 3354:  |  | 
| 3355:  |  | 
| 3356:  |  | 
| 3357:  |  | 
| 3358:  |  | 
| 3359:  |  | 
| 3360:  |  | 
| 3361:  |  | 
| 3362:  |  | 
| 3363:  |  | 
| 3364:  |  | 
| 3365:  |  | 
| 3366:  |  | 
| 3367:  |  | 
| 3368:  |  | 
| 3369:  |  | 
| 3370:  |  | 
| 3371:  |  | 
| 3372:  |  | 
| 3373:  |  | 
| 3374:  |  | 
| 3375:  |  | 
| 3376:  |  | 
| 3377:  |  | 
| 3378:  |  | 
| 3379:  |      | 
| 3380:  |  | 
| 3381:  |  | 
| 3382:  |  | 
| 3383:  |  | 
| 3384:  |  | 
| 3385:  |  | 
| 3386:  |  | 
| 3387:  |  | 
| 3388:  |  | 
| 3389:  |     public function CreateUser($TenantId = 0, $PublicId = '', $Role = UserRole::NormalUser, $WriteSeparateLog = false, $IsDisabled = false, $Note = null) | 
| 3390:  |     { | 
| 3391:  |         Api::checkUserRoleIsAtLeast(UserRole::TenantAdmin); | 
| 3392:  |  | 
| 3393:  |         if (!UserRole::validateValue($Role)) { | 
| 3394:  |             throw new ApiException(Notifications::InvalidInputParameter, null, 'InvalidInputParameter'); | 
| 3395:  |         } | 
| 3396:  |  | 
| 3397:  |         $oTenant = null; | 
| 3398:  |  | 
| 3399:  |          | 
| 3400:  |         if ($TenantId === 0) { | 
| 3401:  |             Api::checkUserRoleIsAtLeast(UserRole::SuperAdmin); | 
| 3402:  |             $oTenant = $this->getTenantsManager()->getDefaultGlobalTenant(); | 
| 3403:  |             $TenantId = $oTenant ? $oTenant->Id : null; | 
| 3404:  |         } | 
| 3405:  |  | 
| 3406:  |         $oAuthenticatedUser = Api::getAuthenticatedUser(); | 
| 3407:  |         if (!($oAuthenticatedUser instanceof User && $oAuthenticatedUser->Role === UserRole::TenantAdmin && $oAuthenticatedUser->IdTenant === $TenantId)) { | 
| 3408:  |             Api::checkUserRoleIsAtLeast(UserRole::SuperAdmin); | 
| 3409:  |         } | 
| 3410:  |  | 
| 3411:  |         if (!$oTenant) { | 
| 3412:  |             $oTenant = $this->getTenantsManager()->getTenantById($TenantId); | 
| 3413:  |             if (!$oTenant) { | 
| 3414:  |                 throw new ApiException(Notifications::InvalidInputParameter, null, 'InvalidInputParameter'); | 
| 3415:  |             } | 
| 3416:  |         } | 
| 3417:  |  | 
| 3418:  |         $PublicId = \trim($PublicId); | 
| 3419:  |         if (substr_count($PublicId, '@') > 1) { | 
| 3420:  |             throw new ApiException(Notifications::InvalidInputParameter, null, 'InvalidInputParameter'); | 
| 3421:  |         } | 
| 3422:  |  | 
| 3423:  |         if (!empty($TenantId) && !empty($PublicId)) { | 
| 3424:  |             $oUser = $this->getUsersManager()->getUserByPublicId($PublicId); | 
| 3425:  |             if ($oUser instanceof Models\User) { | 
| 3426:  |                 throw new ApiException(Notifications::UserAlreadyExists, null, 'UserAlreadyExists'); | 
| 3427:  |             } else { | 
| 3428:  |                 if (class_exists('\Aurora\Modules\Licensing\Module')) { | 
| 3429:  |                     $oLicense = \Aurora\Modules\Licensing\Module::Decorator(); | 
| 3430:  |                     if (!$oLicense->ValidateUsersCount($this->GetTotalUsersCount()) || !$oLicense->ValidatePeriod()) { | 
| 3431:  |                         Api::Log("Error: License limit"); | 
| 3432:  |                         throw new ApiException(Notifications::LicenseLimit, null, 'LicenseLimit'); | 
| 3433:  |                     } | 
| 3434:  |                 } | 
| 3435:  |             } | 
| 3436:  |  | 
| 3437:  |             $oUser = new Models\User(); | 
| 3438:  |  | 
| 3439:  |             $oUser->PublicId = $PublicId; | 
| 3440:  |             $oUser->IdTenant = $TenantId; | 
| 3441:  |             $oUser->Role = $Role; | 
| 3442:  |             $oUser->WriteSeparateLog = $WriteSeparateLog; | 
| 3443:  |  | 
| 3444:  |             $oUser->Language = Api::GetLanguage(true); | 
| 3445:  |             $oUser->TimeFormat = $this->oModuleSettings->TimeFormat; | 
| 3446:  |             $oUser->DateFormat = $this->oModuleSettings->DateFormat; | 
| 3447:  |             $oUser->DefaultTimeZone = ''; | 
| 3448:  |  | 
| 3449:  |  | 
| 3450:  |             $oUser->IsDisabled = $IsDisabled; | 
| 3451:  |             $oUser->Note = $Note; | 
| 3452:  |  | 
| 3453:  |             if ($this->getUsersManager()->createUser($oUser)) { | 
| 3454:  |                 return $oUser->Id; | 
| 3455:  |             } | 
| 3456:  |         } else { | 
| 3457:  |             throw new ApiException(Notifications::InvalidInputParameter, null, 'InvalidInputParameter'); | 
| 3458:  |         } | 
| 3459:  |  | 
| 3460:  |         return false; | 
| 3461:  |     } | 
| 3462:  |  | 
| 3463:  |      | 
| 3464:  |  | 
| 3465:  |  | 
| 3466:  |  | 
| 3467:  |  | 
| 3468:  |  | 
| 3469:  |  | 
| 3470:  |  | 
| 3471:  |  | 
| 3472:  |  | 
| 3473:  |  | 
| 3474:  |  | 
| 3475:  |  | 
| 3476:  |  | 
| 3477:  |  | 
| 3478:  |  | 
| 3479:  |  | 
| 3480:  |  | 
| 3481:  |  | 
| 3482:  |  | 
| 3483:  |  | 
| 3484:  |  | 
| 3485:  |  | 
| 3486:  |  | 
| 3487:  |  | 
| 3488:  |  | 
| 3489:  |  | 
| 3490:  |  | 
| 3491:  |  | 
| 3492:  |  | 
| 3493:  |  | 
| 3494:  |  | 
| 3495:  |  | 
| 3496:  |  | 
| 3497:  |  | 
| 3498:  |  | 
| 3499:  |  | 
| 3500:  |  | 
| 3501:  |  | 
| 3502:  |  | 
| 3503:  |  | 
| 3504:  |  | 
| 3505:  |  | 
| 3506:  |  | 
| 3507:  |  | 
| 3508:  |  | 
| 3509:  |  | 
| 3510:  |  | 
| 3511:  |  | 
| 3512:  |  | 
| 3513:  |      | 
| 3514:  |  | 
| 3515:  |  | 
| 3516:  |  | 
| 3517:  |  | 
| 3518:  |  | 
| 3519:  |  | 
| 3520:  |  | 
| 3521:  |  | 
| 3522:  |  | 
| 3523:  |  | 
| 3524:  |  | 
| 3525:  |  | 
| 3526:  |  | 
| 3527:  |     public function UpdateUser($UserId, $PublicId = '', $TenantId = 0, $Role = -1, $IsDisabled = null, $WriteSeparateLog = null, $GroupIds = null, $Note = null) | 
| 3528:  |     { | 
| 3529:  |         $PublicId = \trim($PublicId); | 
| 3530:  |  | 
| 3531:  |         $oUser = null; | 
| 3532:  |         if ($UserId > 0) { | 
| 3533:  |             $oUser = self::Decorator()->GetUserWithoutRoleCheck($UserId); | 
| 3534:  |         } | 
| 3535:  |         if ($oUser) { | 
| 3536:  |             if ((!empty($TenantId) && $oUser->IdTenant != $TenantId) || (!empty($PublicId) && $oUser->PublicId != $PublicId)) { | 
| 3537:  |                  | 
| 3538:  |                 Api::checkUserRoleIsAtLeast(UserRole::SuperAdmin); | 
| 3539:  |             } elseif ($Role !== -1 || $IsDisabled !== null || $WriteSeparateLog !== null || $GroupIds !== null || $Note !== null) { | 
| 3540:  |                 Api::checkUserRoleIsAtLeast(UserRole::TenantAdmin); | 
| 3541:  |             } elseif ($UserId === Api::getAuthenticatedUserId()) { | 
| 3542:  |                 Api::checkUserRoleIsAtLeast(UserRole::NormalUser); | 
| 3543:  |             } else { | 
| 3544:  |                 Api::checkUserRoleIsAtLeast(UserRole::SuperAdmin); | 
| 3545:  |             } | 
| 3546:  |  | 
| 3547:  |             Api::checkUserAccess($oUser); | 
| 3548:  |  | 
| 3549:  |             if (!empty($PublicId)) { | 
| 3550:  |                 $oUser->PublicId = $PublicId; | 
| 3551:  |             } | 
| 3552:  |             if (!empty($TenantId)) { | 
| 3553:  |                 $oUser->IdTenant = $TenantId; | 
| 3554:  |             } | 
| 3555:  |             if (UserRole::validateValue($Role)) { | 
| 3556:  |                 $oUser->Role = $Role; | 
| 3557:  |             } | 
| 3558:  |             if ($IsDisabled !== null) { | 
| 3559:  |                 $oUser->IsDisabled = (bool) $IsDisabled; | 
| 3560:  |             } | 
| 3561:  |             if ($WriteSeparateLog !== null) { | 
| 3562:  |                 $oUser->WriteSeparateLog = $WriteSeparateLog; | 
| 3563:  |             } | 
| 3564:  |             if ($Note !== null) { | 
| 3565:  |                 $oUser->Note = (string) $Note; | 
| 3566:  |             } | 
| 3567:  |  | 
| 3568:  |             $mResult = $this->getUsersManager()->updateUser($oUser); | 
| 3569:  |             if ($mResult && $this->oModuleSettings->AllowGroups && $GroupIds !== null) { | 
| 3570:  |                 self::Decorator()->UpdateUserGroups($UserId, $GroupIds); | 
| 3571:  |             } | 
| 3572:  |  | 
| 3573:  |             return $mResult; | 
| 3574:  |         } else { | 
| 3575:  |             throw new ApiException(Notifications::InvalidInputParameter, null, 'InvalidInputParameter'); | 
| 3576:  |         } | 
| 3577:  |     } | 
| 3578:  |  | 
| 3579:  |      | 
| 3580:  |  | 
| 3581:  |  | 
| 3582:  |  | 
| 3583:  |  | 
| 3584:  |  | 
| 3585:  |  | 
| 3586:  |  | 
| 3587:  |  | 
| 3588:  |  | 
| 3589:  |  | 
| 3590:  |  | 
| 3591:  |  | 
| 3592:  |  | 
| 3593:  |  | 
| 3594:  |  | 
| 3595:  |  | 
| 3596:  |  | 
| 3597:  |  | 
| 3598:  |  | 
| 3599:  |  | 
| 3600:  |  | 
| 3601:  |  | 
| 3602:  |  | 
| 3603:  |  | 
| 3604:  |  | 
| 3605:  |  | 
| 3606:  |  | 
| 3607:  |  | 
| 3608:  |  | 
| 3609:  |  | 
| 3610:  |  | 
| 3611:  |  | 
| 3612:  |  | 
| 3613:  |  | 
| 3614:  |  | 
| 3615:  |  | 
| 3616:  |  | 
| 3617:  |  | 
| 3618:  |  | 
| 3619:  |  | 
| 3620:  |  | 
| 3621:  |  | 
| 3622:  |  | 
| 3623:  |  | 
| 3624:  |  | 
| 3625:  |  | 
| 3626:  |      | 
| 3627:  |  | 
| 3628:  |  | 
| 3629:  |  | 
| 3630:  |  | 
| 3631:  |     public function DeleteUsers($IdList) | 
| 3632:  |     { | 
| 3633:  |         $bResult = true; | 
| 3634:  |  | 
| 3635:  |         foreach ($IdList as $sId) { | 
| 3636:  |             $bResult = $bResult && self::Decorator()->DeleteUser($sId); | 
| 3637:  |         } | 
| 3638:  |  | 
| 3639:  |         return $bResult; | 
| 3640:  |     } | 
| 3641:  |  | 
| 3642:  |      | 
| 3643:  |  | 
| 3644:  |  | 
| 3645:  |  | 
| 3646:  |  | 
| 3647:  |  | 
| 3648:  |  | 
| 3649:  |  | 
| 3650:  |  | 
| 3651:  |  | 
| 3652:  |  | 
| 3653:  |  | 
| 3654:  |  | 
| 3655:  |  | 
| 3656:  |  | 
| 3657:  |  | 
| 3658:  |  | 
| 3659:  |  | 
| 3660:  |  | 
| 3661:  |  | 
| 3662:  |  | 
| 3663:  |  | 
| 3664:  |  | 
| 3665:  |  | 
| 3666:  |  | 
| 3667:  |  | 
| 3668:  |  | 
| 3669:  |  | 
| 3670:  |  | 
| 3671:  |  | 
| 3672:  |  | 
| 3673:  |  | 
| 3674:  |  | 
| 3675:  |  | 
| 3676:  |  | 
| 3677:  |  | 
| 3678:  |  | 
| 3679:  |  | 
| 3680:  |  | 
| 3681:  |  | 
| 3682:  |  | 
| 3683:  |  | 
| 3684:  |  | 
| 3685:  |  | 
| 3686:  |  | 
| 3687:  |  | 
| 3688:  |  | 
| 3689:  |      | 
| 3690:  |  | 
| 3691:  |  | 
| 3692:  |  | 
| 3693:  |  | 
| 3694:  |  | 
| 3695:  |  | 
| 3696:  |     public function DeleteUser($UserId = 0) | 
| 3697:  |     { | 
| 3698:  |         $oAuthenticatedUser = Api::getAuthenticatedUser(); | 
| 3699:  |  | 
| 3700:  |         $oUser = self::Decorator()->GetUserWithoutRoleCheck($UserId); | 
| 3701:  |  | 
| 3702:  |         Api::checkUserRoleIsAtLeast(UserRole::TenantAdmin); | 
| 3703:  |  | 
| 3704:  |         if ($oUser instanceof Models\User && $oAuthenticatedUser->Role === UserRole::TenantAdmin && | 
| 3705:  |             $oUser->IdTenant !== $oAuthenticatedUser->IdTenant) { | 
| 3706:  |             throw new ApiException(Notifications::AccessDenied, null, 'AccessDenied'); | 
| 3707:  |         } else { | 
| 3708:  |             if ($oUser->IdTenant === $oAuthenticatedUser->IdTenant) { | 
| 3709:  |                 Api::checkUserRoleIsAtLeast(UserRole::TenantAdmin); | 
| 3710:  |             } else { | 
| 3711:  |                 Api::checkUserRoleIsAtLeast(UserRole::SuperAdmin); | 
| 3712:  |             } | 
| 3713:  |         } | 
| 3714:  |  | 
| 3715:  |         $bResult = false; | 
| 3716:  |  | 
| 3717:  |         if (!empty($UserId) && is_int($UserId)) { | 
| 3718:  |             $bResult = $this->getUsersManager()->deleteUserById($UserId); | 
| 3719:  |             if ($bResult) { | 
| 3720:  |                 UserBlock::where('UserId', $UserId)->delete(); | 
| 3721:  |             } | 
| 3722:  |         } else { | 
| 3723:  |             throw new ApiException(Notifications::InvalidInputParameter, null, 'InvalidInputParameter'); | 
| 3724:  |         } | 
| 3725:  |  | 
| 3726:  |         return $bResult; | 
| 3727:  |     } | 
| 3728:  |  | 
| 3729:  |      | 
| 3730:  |  | 
| 3731:  |  | 
| 3732:  |     public function GetLogFilesData() | 
| 3733:  |     { | 
| 3734:  |         $aData = []; | 
| 3735:  |  | 
| 3736:  |         $sFileName = Api::GetLogFileName(); | 
| 3737:  |         $sFilePath = Api::GetLogFileDir() . $sFileName; | 
| 3738:  |         $aData['LogFileName'] = $sFileName; | 
| 3739:  |         $aData['LogSizeBytes'] = file_exists($sFilePath) ? filesize($sFilePath) : 0; | 
| 3740:  |  | 
| 3741:  |         $sEventFileName = Api::GetLogFileName(Logger::$sEventLogPrefix); | 
| 3742:  |         $sEventFilePath = Api::GetLogFileDir() . $sEventFileName; | 
| 3743:  |         $aData['EventLogFileName'] = $sEventFileName; | 
| 3744:  |         $aData['EventLogSizeBytes'] = file_exists($sEventFilePath) ? filesize($sEventFilePath) : 0; | 
| 3745:  |  | 
| 3746:  |         $sErrorFileName = Api::GetLogFileName(Logger::$sErrorLogPrefix); | 
| 3747:  |         $sErrorFilePath = Api::GetLogFileDir() . $sErrorFileName; | 
| 3748:  |         $aData['ErrorLogFileName'] = $sErrorFileName; | 
| 3749:  |         $aData['ErrorLogSizeBytes'] = file_exists($sErrorFilePath) ? filesize($sErrorFilePath) : 0; | 
| 3750:  |  | 
| 3751:  |         return $aData; | 
| 3752:  |     } | 
| 3753:  |  | 
| 3754:  |     public function GetLogFile($FilePrefix = '', $PublicId = '') | 
| 3755:  |     { | 
| 3756:  |         Api::checkUserRoleIsAtLeast(UserRole::SuperAdmin); | 
| 3757:  |  | 
| 3758:  |         if ($PublicId !== '') { | 
| 3759:  |             $FilePrefix = $PublicId . '-'; | 
| 3760:  |         } | 
| 3761:  |         $sFileName = Api::GetLogFileDir() . Api::GetLogFileName($FilePrefix); | 
| 3762:  |  | 
| 3763:  |         if (file_exists($sFileName)) { | 
| 3764:  |             $mResult = fopen($sFileName, "r"); | 
| 3765:  |  | 
| 3766:  |             if (false !== $mResult && is_resource($mResult)) { | 
| 3767:  |                 $sContentType = \MailSo\Base\Utils::MimeContentType($sFileName); | 
| 3768:  |                 \Aurora\System\Managers\Response::OutputHeaders(true, $sContentType, $sFileName); | 
| 3769:  |  | 
| 3770:  |                 if ($sContentType === 'text/plain') { | 
| 3771:  |                     $sLogData = stream_get_contents($mResult); | 
| 3772:  |                     echo(\MailSo\Base\HtmlUtils::ClearTags($sLogData)); | 
| 3773:  |                 } else { | 
| 3774:  |                     \MailSo\Base\Utils::FpassthruWithTimeLimitReset($mResult, 8192, function ($sData) { | 
| 3775:  |                         return \MailSo\Base\HtmlUtils::ClearTags($sData); | 
| 3776:  |                     }); | 
| 3777:  |                 } | 
| 3778:  |  | 
| 3779:  |                 @fclose($mResult); | 
| 3780:  |             } | 
| 3781:  |         } | 
| 3782:  |     } | 
| 3783:  |  | 
| 3784:  |      | 
| 3785:  |  | 
| 3786:  |  | 
| 3787:  |     public function GetLog($FilePrefix = '', $PartSize = 10240) | 
| 3788:  |     { | 
| 3789:  |         Api::checkUserRoleIsAtLeast(UserRole::SuperAdmin); | 
| 3790:  |  | 
| 3791:  |         $sFileName = Api::GetLogFileDir() . Api::GetLogFileName($FilePrefix); | 
| 3792:  |  | 
| 3793:  |         $logData = ''; | 
| 3794:  |  | 
| 3795:  |         if (file_exists($sFileName)) { | 
| 3796:  |             $iOffset = filesize($sFileName) - $PartSize; | 
| 3797:  |             $iOffset = $iOffset < 0 ? 0 : $iOffset; | 
| 3798:  |             $logData = \MailSo\Base\HtmlUtils::ClearTags(file_get_contents($sFileName, false, null, $iOffset, $PartSize)); | 
| 3799:  |         } | 
| 3800:  |  | 
| 3801:  |         return $logData; | 
| 3802:  |     } | 
| 3803:  |  | 
| 3804:  |      | 
| 3805:  |  | 
| 3806:  |  | 
| 3807:  |  | 
| 3808:  |  | 
| 3809:  |     public function ClearLog($FilePrefix = '') | 
| 3810:  |     { | 
| 3811:  |         Api::checkUserRoleIsAtLeast(UserRole::SuperAdmin); | 
| 3812:  |  | 
| 3813:  |         $sFileName = Api::GetLogFileDir() . Api::GetLogFileName($FilePrefix); | 
| 3814:  |  | 
| 3815:  |         return Api::ClearLog($sFileName); | 
| 3816:  |     } | 
| 3817:  |  | 
| 3818:  |      | 
| 3819:  |  | 
| 3820:  |  | 
| 3821:  |  | 
| 3822:  |  | 
| 3823:  |  | 
| 3824:  |     public function UpdateUserTimezone($Timezone) | 
| 3825:  |     { | 
| 3826:  |         Api::checkUserRoleIsAtLeast(UserRole::NormalUser); | 
| 3827:  |  | 
| 3828:  |         $oUser = Api::getAuthenticatedUser(); | 
| 3829:  |  | 
| 3830:  |         if ($oUser && $Timezone) { | 
| 3831:  |             if ($oUser && $oUser->DefaultTimeZone !== $Timezone) { | 
| 3832:  |                 $oUser->DefaultTimeZone = $Timezone; | 
| 3833:  |                 $this->UpdateUserObject($oUser); | 
| 3834:  |             } | 
| 3835:  |         } else { | 
| 3836:  |             return false; | 
| 3837:  |         } | 
| 3838:  |         return true; | 
| 3839:  |     } | 
| 3840:  |  | 
| 3841:  |      | 
| 3842:  |  | 
| 3843:  |  | 
| 3844:  |     public function GetCompatibilities() | 
| 3845:  |     { | 
| 3846:  |         return []; | 
| 3847:  |     } | 
| 3848:  |  | 
| 3849:  |      | 
| 3850:  |  | 
| 3851:  |  | 
| 3852:  |     public function IsModuleDisabledForObject($oObject, $sModuleName) | 
| 3853:  |     { | 
| 3854:  |         return ($oObject instanceof \Aurora\System\Classes\Model) ? $oObject->isModuleDisabled($sModuleName) : false; | 
| 3855:  |     } | 
| 3856:  |  | 
| 3857:  |      | 
| 3858:  |  | 
| 3859:  |  | 
| 3860:  |     public function GetUserSessions() | 
| 3861:  |     { | 
| 3862:  |         $aResult = []; | 
| 3863:  |         if (\Aurora\Api::GetSettings()->StoreAuthTokenInDB) { | 
| 3864:  |             $oUser = Api::getAuthenticatedUser(); | 
| 3865:  |             if ($oUser) { | 
| 3866:  |                 $aUserSessions = Api::UserSession()->GetUserSessionsFromDB($oUser->Id); | 
| 3867:  |                 foreach ($aUserSessions as $oUserSession) { | 
| 3868:  |                     $aTokenInfo = Api::DecodeKeyValues($oUserSession->Token); | 
| 3869:  |  | 
| 3870:  |                     if ($aTokenInfo !== false && isset($aTokenInfo['id'])) { | 
| 3871:  |                         $aResult[] = [ | 
| 3872:  |                             'LastUsageDateTime' => $oUserSession->LastUsageDateTime, | 
| 3873:  |                             'ExpireDateTime' => (int) isset($aTokenInfo['@expire']) ? $aTokenInfo['@expire'] : 0, | 
| 3874:  |                         ]; | 
| 3875:  |                     } | 
| 3876:  |                 } | 
| 3877:  |             } | 
| 3878:  |         } | 
| 3879:  |         return $aResult; | 
| 3880:  |     } | 
| 3881:  |  | 
| 3882:  |      | 
| 3883:  |  | 
| 3884:  |  | 
| 3885:  |     public function CreateGroup($TenantId, $Name) | 
| 3886:  |     { | 
| 3887:  |         if (!$this->oModuleSettings->AllowGroups) { | 
| 3888:  |             throw new ApiException(Notifications::MethodAccessDenied, null, 'MethodAccessDenied'); | 
| 3889:  |         } | 
| 3890:  |  | 
| 3891:  |         Api::checkUserRoleIsAtLeast(UserRole::TenantAdmin); | 
| 3892:  |  | 
| 3893:  |         $oUser = Api::getAuthenticatedUser(); | 
| 3894:  |         if ($oUser->Role === UserRole::TenantAdmin && $oUser->IdTenant !== $TenantId) { | 
| 3895:  |             throw new ApiException(Notifications::AccessDenied, null, 'AccessDenied'); | 
| 3896:  |         } | 
| 3897:  |  | 
| 3898:  |         $oGroup = Group::firstWhere([ | 
| 3899:  |             'TenantId' => $TenantId, | 
| 3900:  |             'Name' => $Name | 
| 3901:  |         ]); | 
| 3902:  |  | 
| 3903:  |         if ($oGroup) { | 
| 3904:  |             throw new \Aurora\Modules\Core\Exceptions\Exception(Enums\ErrorCodes::GroupAlreadyExists); | 
| 3905:  |         } else { | 
| 3906:  |             $oGroup = new Models\Group(); | 
| 3907:  |             $oGroup->Name = $Name; | 
| 3908:  |             $oGroup->TenantId = $TenantId; | 
| 3909:  |             if ($oGroup->save()) { | 
| 3910:  |                 return $oGroup->Id; | 
| 3911:  |             } else { | 
| 3912:  |                 return false; | 
| 3913:  |             } | 
| 3914:  |         } | 
| 3915:  |     } | 
| 3916:  |  | 
| 3917:  |      | 
| 3918:  |  | 
| 3919:  |  | 
| 3920:  |  | 
| 3921:  |  | 
| 3922:  |  | 
| 3923:  |     public function GetGroup($GroupId) | 
| 3924:  |     { | 
| 3925:  |         if (!$this->oModuleSettings->AllowGroups) { | 
| 3926:  |             return false; | 
| 3927:  |         } | 
| 3928:  |  | 
| 3929:  |         $mResult = false; | 
| 3930:  |  | 
| 3931:  |         Api::checkUserRoleIsAtLeast(UserRole::NormalUser); | 
| 3932:  |  | 
| 3933:  |         $oUser = Api::getAuthenticatedUser(); | 
| 3934:  |         $oGroup = Group::firstWhere([ 'Id' => $GroupId ]); | 
| 3935:  |         if ($oUser && $oGroup && ($oUser->Role === UserRole::TenantAdmin || $oUser->Role === UserRole::NormalUser) && $oUser->IdTenant !== $oGroup->TenantId) { | 
| 3936:  |             throw new ApiException(Notifications::AccessDenied, null, 'AccessDenied'); | 
| 3937:  |         } | 
| 3938:  |  | 
| 3939:  |         $mResult = $oGroup; | 
| 3940:  |  | 
| 3941:  |         return $mResult; | 
| 3942:  |     } | 
| 3943:  |  | 
| 3944:  |      | 
| 3945:  |  | 
| 3946:  |  | 
| 3947:  |     public function GetAllGroup($TenantId) | 
| 3948:  |     { | 
| 3949:  |         if (!$this->oModuleSettings->AllowGroups) { | 
| 3950:  |             return false; | 
| 3951:  |         } | 
| 3952:  |  | 
| 3953:  |         $mResult = false; | 
| 3954:  |  | 
| 3955:  |         Api::checkUserRoleIsAtLeast(UserRole::NormalUser); | 
| 3956:  |  | 
| 3957:  |         $oUser = Api::getAuthenticatedUser(); | 
| 3958:  |         if ($oUser && ($oUser->Role === UserRole::TenantAdmin || $oUser->Role === UserRole::NormalUser)  && $oUser->IdTenant !== $TenantId) { | 
| 3959:  |             throw new ApiException(Notifications::AccessDenied, null, 'AccessDenied'); | 
| 3960:  |         } | 
| 3961:  |  | 
| 3962:  |         $oGroup = Group::firstWhere([ | 
| 3963:  |             'TenantId' => $TenantId, | 
| 3964:  |             'IsAll' => true | 
| 3965:  |         ]); | 
| 3966:  |  | 
| 3967:  |         if (!$oGroup) { | 
| 3968:  |             $oGroup = new Models\Group(); | 
| 3969:  |             $oGroup->Name = 'All'; | 
| 3970:  |             $oGroup->TenantId = $TenantId; | 
| 3971:  |             $oGroup->IsAll = true; | 
| 3972:  |  | 
| 3973:  |             if ($oGroup->save()) { | 
| 3974:  |                 $mResult = $oGroup; | 
| 3975:  |             } else { | 
| 3976:  |                 $mResult = false; | 
| 3977:  |             } | 
| 3978:  |         } else { | 
| 3979:  |             $mResult = $oGroup; | 
| 3980:  |         } | 
| 3981:  |  | 
| 3982:  |         return $mResult; | 
| 3983:  |     } | 
| 3984:  |  | 
| 3985:  |      | 
| 3986:  |  | 
| 3987:  |  | 
| 3988:  |     public function GetGroups($TenantId, $Search = '') | 
| 3989:  |     { | 
| 3990:  |         if (!$this->oModuleSettings->AllowGroups) { | 
| 3991:  |             return [ | 
| 3992:  |                 'Items' => [], | 
| 3993:  |                 'Count' => 0 | 
| 3994:  |             ]; | 
| 3995:  |         } | 
| 3996:  |  | 
| 3997:  |         Api::checkUserRoleIsAtLeast(UserRole::NormalUser); | 
| 3998:  |  | 
| 3999:  |         $oUser = Api::getAuthenticatedUser(); | 
| 4000:  |         if ($oUser && ($oUser->Role === UserRole::TenantAdmin || $oUser->Role === UserRole::NormalUser)  && $oUser->IdTenant !== $TenantId) { | 
| 4001:  |             throw new ApiException(Notifications::AccessDenied, null, 'AccessDenied'); | 
| 4002:  |         } | 
| 4003:  |  | 
| 4004:  |         $query = Group::where('TenantId', $TenantId); | 
| 4005:  |         if (!empty($Search)) { | 
| 4006:  |             $query = $query->where(function ($q) use ($Search) { | 
| 4007:  |                 $q->where('Name', 'LIKE', '%' . $Search . '%'); | 
| 4008:  |                 $q->orWhere('IsAll', true); | 
| 4009:  |             }); | 
| 4010:  |         } | 
| 4011:  |  | 
| 4012:  |         $aGroups = $query->get()->map(function ($oGroup) use ($oUser) { | 
| 4013:  |  | 
| 4014:  |             $aArgs = [ | 
| 4015:  |                 'User' => $oUser, | 
| 4016:  |                 'Group' => $oGroup | 
| 4017:  |             ]; | 
| 4018:  |             $mResult = false; | 
| 4019:  |  | 
| 4020:  |             try { | 
| 4021:  |                 $this->broadcastEvent('GetGroupContactsEmails', $aArgs, $mResult); | 
| 4022:  |             } catch (\Exception $oException) { | 
| 4023:  |             } | 
| 4024:  |  | 
| 4025:  |             $aEmails = []; | 
| 4026:  |             if (is_array($mResult)) { | 
| 4027:  |                 $aEmails = $mResult; | 
| 4028:  |             } | 
| 4029:  |  | 
| 4030:  |             return [ | 
| 4031:  |                 'Id' => $oGroup->Id, | 
| 4032:  |                 'Name' => $oGroup->getName(), | 
| 4033:  |                 'Emails' => implode(', ', $aEmails), | 
| 4034:  |                 'IsAll' => !!$oGroup->IsAll | 
| 4035:  |             ]; | 
| 4036:  |         })->toArray(); | 
| 4037:  |  | 
| 4038:  |         if (!empty($Search)) { | 
| 4039:  |             $aGroups = array_filter($aGroups, function ($aGroup) use ($Search) { | 
| 4040:  |                 return (stripos($aGroup['Name'], $Search) !== false); | 
| 4041:  |             }); | 
| 4042:  |         } | 
| 4043:  |  | 
| 4044:  |         return [ | 
| 4045:  |             'Items' => $aGroups, | 
| 4046:  |             'Count' => count($aGroups) | 
| 4047:  |         ]; | 
| 4048:  |     } | 
| 4049:  |  | 
| 4050:  |      | 
| 4051:  |  | 
| 4052:  |  | 
| 4053:  |     public function UpdateGroup($GroupId, $Name) | 
| 4054:  |     { | 
| 4055:  |         if (!$this->oModuleSettings->AllowGroups) { | 
| 4056:  |             throw new ApiException(Notifications::MethodAccessDenied, null, 'MethodAccessDenied'); | 
| 4057:  |         } | 
| 4058:  |  | 
| 4059:  |         $mResult = false; | 
| 4060:  |  | 
| 4061:  |         Api::checkUserRoleIsAtLeast(UserRole::TenantAdmin); | 
| 4062:  |  | 
| 4063:  |         $oGroup = Group::find($GroupId); | 
| 4064:  |         if ($oGroup && !$oGroup->IsAll) { | 
| 4065:  |             $oUser = Api::getAuthenticatedUser(); | 
| 4066:  |             if ($oUser && $oUser->Role === UserRole::TenantAdmin && $oGroup->TenantId !== $oUser->IdTenant) { | 
| 4067:  |                 throw new ApiException(Notifications::AccessDenied, null, 'AccessDenied'); | 
| 4068:  |             } | 
| 4069:  |  | 
| 4070:  |             if ($oGroup->Name !== $Name && Group::where(['TenantId' => $oGroup->TenantId, 'Name' => $Name])->count() > 0) { | 
| 4071:  |                 throw new ApiException(ErrorCodes::GroupAlreadyExists, null, 'GroupAlreadyExists'); | 
| 4072:  |             } else { | 
| 4073:  |                 $oGroup->Name = $Name; | 
| 4074:  |                 $mResult = !!$oGroup->save(); | 
| 4075:  |             } | 
| 4076:  |         } | 
| 4077:  |  | 
| 4078:  |         return $mResult; | 
| 4079:  |     } | 
| 4080:  |  | 
| 4081:  |      | 
| 4082:  |  | 
| 4083:  |  | 
| 4084:  |  | 
| 4085:  |  | 
| 4086:  |     public function DeleteGroups($IdList) | 
| 4087:  |     { | 
| 4088:  |         if (!$this->oModuleSettings->AllowGroups) { | 
| 4089:  |             throw new ApiException(Notifications::MethodAccessDenied, null, 'MethodAccessDenied'); | 
| 4090:  |         } | 
| 4091:  |  | 
| 4092:  |         Api::checkUserRoleIsAtLeast(UserRole::SuperAdmin); | 
| 4093:  |  | 
| 4094:  |         $bResult = true; | 
| 4095:  |  | 
| 4096:  |         foreach ($IdList as $iId) { | 
| 4097:  |             $bResult = $bResult && self::Decorator()->DeleteGroup($iId); | 
| 4098:  |         } | 
| 4099:  |  | 
| 4100:  |         return $bResult; | 
| 4101:  |     } | 
| 4102:  |  | 
| 4103:  |      | 
| 4104:  |  | 
| 4105:  |  | 
| 4106:  |     public function DeleteGroup($GroupId) | 
| 4107:  |     { | 
| 4108:  |         if (!$this->oModuleSettings->AllowGroups) { | 
| 4109:  |             throw new ApiException(Notifications::MethodAccessDenied, null, 'MethodAccessDenied'); | 
| 4110:  |         } | 
| 4111:  |  | 
| 4112:  |         $mResult = false; | 
| 4113:  |  | 
| 4114:  |         Api::checkUserRoleIsAtLeast(UserRole::TenantAdmin); | 
| 4115:  |  | 
| 4116:  |         $oGroup = Group::find($GroupId); | 
| 4117:  |         if ($oGroup && !$oGroup->IsAll) { | 
| 4118:  |             $oUser = Api::getAuthenticatedUser(); | 
| 4119:  |             if ($oUser && $oUser->Role === UserRole::TenantAdmin && $oGroup->TenantId !== $oUser->IdTenant) { | 
| 4120:  |                 throw new ApiException(Notifications::AccessDenied, null, 'AccessDenied'); | 
| 4121:  |             } | 
| 4122:  |  | 
| 4123:  |             $mResult = $oGroup->delete(); | 
| 4124:  |         } | 
| 4125:  |  | 
| 4126:  |         return $mResult; | 
| 4127:  |     } | 
| 4128:  |  | 
| 4129:  |      | 
| 4130:  |  | 
| 4131:  |  | 
| 4132:  |     public function GetGroupUsers($TenantId, $GroupId) | 
| 4133:  |     { | 
| 4134:  |         if (!$this->oModuleSettings->AllowGroups) { | 
| 4135:  |             throw new ApiException(Notifications::MethodAccessDenied, null, 'MethodAccessDenied'); | 
| 4136:  |         } | 
| 4137:  |  | 
| 4138:  |         $mResult = []; | 
| 4139:  |  | 
| 4140:  |         Api::checkUserRoleIsAtLeast(UserRole::NormalUser); | 
| 4141:  |  | 
| 4142:  |         $oGroup = Group::where('TenantId', $TenantId)->where('Id', $GroupId)->first(); | 
| 4143:  |         if ($oGroup) { | 
| 4144:  |             $oUser = Api::getAuthenticatedUser(); | 
| 4145:  |             if ($oUser && ($oUser->Role === UserRole::NormalUser || $oUser->Role === UserRole::TenantAdmin) && $oGroup->TenantId !== $oUser->IdTenant) { | 
| 4146:  |                 throw new ApiException(Notifications::AccessDenied, null, 'AccessDenied'); | 
| 4147:  |             } | 
| 4148:  |  | 
| 4149:  |             if ($oGroup->IsAll) { | 
| 4150:  |                 $teamContacts = ContactsModule::Decorator()->GetContacts($oUser->Id, StorageType::Team, 0, 0); | 
| 4151:  |                 if (isset($teamContacts['List'])) { | 
| 4152:  |                     $mResult = array_map(function ($item) { | 
| 4153:  |                         return [ | 
| 4154:  |                             'UserId' => $item['UserId'], | 
| 4155:  |                             'Name' => $item['FullName'], | 
| 4156:  |                             'PublicId' => $item['ViewEmail'] | 
| 4157:  |                         ]; | 
| 4158:  |                     }, $teamContacts['List']); | 
| 4159:  |                 } | 
| 4160:  |             } else { | 
| 4161:  |                 $mResult = $oGroup->Users()->get()->map(function ($oUser) { | 
| 4162:  |                     return [ | 
| 4163:  |                         'UserId' => $oUser->Id, | 
| 4164:  |                         'Name' => $oUser->Name, | 
| 4165:  |                         'PublicId' => $oUser->PublicId | 
| 4166:  |                     ]; | 
| 4167:  |                 })->toArray(); | 
| 4168:  |             } | 
| 4169:  |         } | 
| 4170:  |  | 
| 4171:  |         return $mResult; | 
| 4172:  |     } | 
| 4173:  |  | 
| 4174:  |      | 
| 4175:  |  | 
| 4176:  |  | 
| 4177:  |     public function AddUsersToGroup($GroupId, $UserIds) | 
| 4178:  |     { | 
| 4179:  |         if (!$this->oModuleSettings->AllowGroups) { | 
| 4180:  |             throw new ApiException(Notifications::MethodAccessDenied, null, 'MethodAccessDenied'); | 
| 4181:  |         } | 
| 4182:  |  | 
| 4183:  |         $mResult = false; | 
| 4184:  |  | 
| 4185:  |         Api::checkUserRoleIsAtLeast(UserRole::TenantAdmin); | 
| 4186:  |  | 
| 4187:  |         $oGroup = Group::find($GroupId); | 
| 4188:  |         if ($oGroup && !$oGroup->IsAll) { | 
| 4189:  |             $oUser = Api::getAuthenticatedUser(); | 
| 4190:  |             if ($oUser && $oUser->Role === UserRole::TenantAdmin && $oGroup->TenantId !== $oUser->IdTenant) { | 
| 4191:  |                 throw new ApiException(Notifications::AccessDenied, null, 'AccessDenied'); | 
| 4192:  |             } | 
| 4193:  |  | 
| 4194:  |             $oGroup->Users()->syncWithoutDetaching($UserIds); | 
| 4195:  |             $mResult = true; | 
| 4196:  |         } | 
| 4197:  |  | 
| 4198:  |         return $mResult; | 
| 4199:  |     } | 
| 4200:  |  | 
| 4201:  |      | 
| 4202:  |  | 
| 4203:  |  | 
| 4204:  |     public function RemoveUsersFromGroup($GroupId, $UserIds) | 
| 4205:  |     { | 
| 4206:  |         if (!$this->oModuleSettings->AllowGroups) { | 
| 4207:  |             throw new ApiException(Notifications::MethodAccessDenied, null, 'MethodAccessDenied'); | 
| 4208:  |         } | 
| 4209:  |  | 
| 4210:  |         $mResult = false; | 
| 4211:  |  | 
| 4212:  |         Api::checkUserRoleIsAtLeast(UserRole::TenantAdmin); | 
| 4213:  |  | 
| 4214:  |         $oGroup = Group::find($GroupId); | 
| 4215:  |         if ($oGroup) { | 
| 4216:  |             $oUser = Api::getAuthenticatedUser(); | 
| 4217:  |             if ($oUser && $oUser->Role === UserRole::TenantAdmin && $oGroup->TenantId !== $oUser->IdTenant) { | 
| 4218:  |                 throw new ApiException(Notifications::AccessDenied, null, 'AccessDenied'); | 
| 4219:  |             } | 
| 4220:  |  | 
| 4221:  |             $oGroup->Users()->detach($UserIds); | 
| 4222:  |             $mResult = true; | 
| 4223:  |         } | 
| 4224:  |  | 
| 4225:  |         return $mResult; | 
| 4226:  |     } | 
| 4227:  |  | 
| 4228:  |      | 
| 4229:  |  | 
| 4230:  |  | 
| 4231:  |     public function UpdateUserGroups($UserId, $GroupIds) | 
| 4232:  |     { | 
| 4233:  |         if (!$this->oModuleSettings->AllowGroups) { | 
| 4234:  |             throw new ApiException(Notifications::MethodAccessDenied, null, 'MethodAccessDenied'); | 
| 4235:  |         } | 
| 4236:  |  | 
| 4237:  |         $mResult = false; | 
| 4238:  |  | 
| 4239:  |         Api::checkUserRoleIsAtLeast(UserRole::TenantAdmin); | 
| 4240:  |         $oAuthUser = Api::getAuthenticatedUser(); | 
| 4241:  |         $oUser = User::find($UserId); | 
| 4242:  |  | 
| 4243:  |         if ($oAuthUser && $oAuthUser->Role === UserRole::TenantAdmin && $oAuthUser->IdTenant !== $oUser->IdTenant) { | 
| 4244:  |             throw new ApiException(Notifications::AccessDenied, null, 'AccessDenied'); | 
| 4245:  |         } | 
| 4246:  |         if ($oUser) { | 
| 4247:  |             $aGroupIds = Group::where('IsAll', false)->whereIn('Id', $GroupIds)->get(['Id'])->map(function ($oGroup) { | 
| 4248:  |                 return $oGroup->Id; | 
| 4249:  |             }); | 
| 4250:  |             $oUser->Groups()->sync($aGroupIds); | 
| 4251:  |             $mResult = true; | 
| 4252:  |         } | 
| 4253:  |  | 
| 4254:  |         return $mResult; | 
| 4255:  |     } | 
| 4256:  |      | 
| 4257:  | } | 
| 4258:  |  |