1: <?php
2: /**
3: * This code is licensed under AGPLv3 license or Afterlogic Software License
4: * if commercial version of the product was purchased.
5: * For full statements of the licenses see LICENSE-AFTERLOGIC and LICENSE-AGPL3 files.
6: */
7:
8: namespace Aurora\System;
9:
10: use Aurora\Modules\Core\Models\User;
11: use Aurora\Modules\Core\Models\Tenant;
12: use Aurora\System\Enums\DbType;
13: use Pimple\Container;
14: use Aurora\System\Console\Commands;
15: use Aurora\System\Exceptions\ApiException;
16:
17: /**
18: * @license https://www.gnu.org/licenses/agpl-3.0.html AGPL-3.0
19: * @license https://afterlogic.com/products/common-licensing Afterlogic Software License
20: * @copyright Copyright (c) 2019, Afterlogic Corp.
21: */
22: if (!defined('AU_APP_ROOT_PATH')) {
23: define('AU_APP_ROOT_PATH', rtrim(realpath(dirname(__DIR__)), '\\/').'/');
24: }
25:
26: define('AU_API_PATH_TO_AURORA', '/../');
27:
28: define('AU_API_CRLF', PHP_EOL);
29: define('AU_API_TAB', "\t");
30:
31: define('AU_API_SESSION_WEBMAIL_NAME', 'PHPWEBMAILSESSID');
32:
33: define('AU_API_HELPDESK_PUBLIC_NAME', '_helpdesk_');
34:
35: // timezone fix
36: $sDefaultTimeZone = function_exists('date_default_timezone_get')
37: ? @date_default_timezone_get() : 'US/Pacific';
38:
39: define('AU_API_SERVER_TIME_ZONE', ($sDefaultTimeZone && 0 < strlen($sDefaultTimeZone))
40: ? $sDefaultTimeZone : 'US/Pacific');
41:
42: if (defined('AU_API_SERVER_TIME_ZONE') && function_exists('date_default_timezone_set')) {
43: @date_default_timezone_set(AU_API_SERVER_TIME_ZONE);
44: }
45:
46: unset($sDefaultTimeZone);
47:
48: /**
49: * @package Api
50: */
51: class Api
52: {
53: /**
54: * @var \Aurora\System\Module\Manager
55: */
56: public static $oModuleManager;
57:
58: /**
59: * @var array
60: */
61: public static $aModuleDecorators;
62:
63: /**
64: * @var array
65: */
66: public static $aSecretWords = [];
67:
68: /**
69: * @var bool
70: */
71: public static $bIsValid;
72:
73: /**
74: * @var string
75: */
76: public static $sSalt;
77:
78: /**
79: * @var array
80: */
81: public static $aI18N = null;
82:
83: /**
84: * @var array
85: */
86: public static $aClientI18N = [];
87:
88: /**
89: * @var bool
90: */
91: public static $bUseDbLog = false;
92:
93: /**
94: * @var bool
95: */
96: public static $bDebug = false;
97:
98:
99: /**
100: * @var array
101: */
102: protected static $aUserSession = [];
103:
104: /**
105: * @var bool
106: */
107: protected static $__SKIP_CHECK_USER_ROLE__ = false;
108:
109: /**
110: * @var string
111: */
112: protected static $sLanguage = null;
113:
114: /**
115: * @var \Aurora\System\Settings
116: */
117: protected static $oSettings;
118:
119: /**
120: * @var \Aurora\System\Db\Storage
121: */
122: protected static $oConnection;
123:
124: /**
125: * @var boolean
126: */
127: protected static $bInitialized = false;
128:
129: /**
130: *
131: */
132: protected static $oAuthenticatedUser = null;
133:
134: /**
135: * @var \Pimple\Container
136: */
137: public static $oContainer = null;
138:
139: /**
140: *
141: * @return string
142: */
143: public static function GetSaltPath()
144: {
145: return self::DataPath().'/salt8.php';
146: }
147:
148: /**
149: *
150: */
151: public static function InitSalt()
152: {
153: $sSalt = '';
154: $sSalt8File = self::GetSaltPath();
155: $sSaltFile = self::DataPath().'/salt.php';
156:
157: if (!@file_exists($sSalt8File)) {
158: if (@file_exists($sSaltFile)) {
159: $sSalt = md5(@file_get_contents($sSaltFile));
160: @unlink($sSaltFile);
161: } else {
162: $sSalt = base64_encode(microtime(true).rand(1000, 9999).microtime(true).rand(1000, 9999));
163: }
164: $sSalt = '<?php \\Aurora\\System\\Api::$sSalt = "'. $sSalt . '";';
165: @file_put_contents($sSalt8File, $sSalt);
166: }
167:
168: if (is_writable($sSalt8File)) {
169: include_once $sSalt8File;
170: }
171:
172: self::$sSalt = '$2y$07$' . self::$sSalt . '$';
173: }
174:
175: /**
176: *
177: */
178: public static function GetUserSession()
179: {
180: return self::$aUserSession;
181: }
182:
183: /**
184: *
185: */
186: public static function SetUserSession($aUserSession)
187: {
188: self::$oAuthenticatedUser = null;
189: return self::$aUserSession = $aUserSession;
190: }
191:
192: /**
193: *
194: */
195: public static function GrantAdminPrivileges()
196: {
197: self::$aUserSession['UserId'] = -1;
198: self::$aUserSession['AuthToken'] = '';
199: }
200:
201: public static function UseDbLogs($bUseDbLogs = false)
202: {
203: self::$bUseDbLog = $bUseDbLogs;
204: }
205:
206: /**
207: *
208: * @param bool $bGrantAdminPrivileges
209: */
210: public static function Init($bGrantAdminPrivileges = false)
211: {
212: if (!defined('AU_API_INIT')) {
213: $apiInitTimeStart = \microtime(true);
214:
215: include_once self::GetVendorPath().'autoload.php';
216: include_once 'bootstrap.php';
217:
218: if ($bGrantAdminPrivileges) {
219: self::GrantAdminPrivileges();
220: }
221:
222: self::InitSalt();
223: self::validateApi();
224: self::GetModuleManager()->loadModules();
225:
226: define('AU_API_INIT', microtime(true) - $apiInitTimeStart);
227: }
228: }
229:
230: /**
231: *
232: * @param bool $bSkip
233: * @return bool Previous state
234: */
235: public static function skipCheckUserRole($bSkip)
236: {
237: $bResult = self::$__SKIP_CHECK_USER_ROLE__;
238: self::$__SKIP_CHECK_USER_ROLE__ = $bSkip;
239: return $bResult;
240: }
241:
242: /**
243: *
244: * @return bool
245: */
246: public static function accessCheckIsSkipped()
247: {
248: return self::$__SKIP_CHECK_USER_ROLE__;
249: }
250:
251: public static function checkUserAccess($oUser)
252: {
253: if ($oUser) {
254: $oAuthUser = Api::getAuthenticatedUser();
255: switch ($oAuthUser->Role) {
256: case \Aurora\System\Enums\UserRole::TenantAdmin:
257: if ($oUser->IdTenant !== $oAuthUser->IdTenant) {
258: throw new ApiException(Notifications::AccessDenied);
259: }
260: break;
261: case \Aurora\System\Enums\UserRole::NormalUser:
262: if ($oUser->Id !== $oAuthUser->Id) {
263: throw new ApiException(Notifications::AccessDenied);
264: }
265: break;
266: }
267: }
268: }
269:
270: /**
271: * @param string $sWord
272: *
273: * @return void
274: */
275: public static function AddSecret($sWord)
276: {
277: if (0 < \strlen(\trim($sWord))) {
278: self::$aSecretWords[] = $sWord;
279: self::$aSecretWords = \array_unique(self::$aSecretWords);
280: }
281: }
282:
283: /**
284: * @return string
285: */
286: public static function EncodeKeyValues(array $aValues)
287: {
288: return Utils::UrlSafeBase64Encode(
289: Utils\Crypt::XxteaEncrypt(
290: @\serialize($aValues),
291: \md5(self::$sSalt)
292: )
293: );
294: }
295:
296: /**
297: * @return array
298: */
299: public static function DecodeKeyValues($sEncodedValues)
300: {
301: $aResult = @\unserialize(
302: Utils\Crypt::XxteaDecrypt(
303: Utils::UrlSafeBase64Decode($sEncodedValues),
304: \md5(self::$sSalt)
305: )
306: );
307:
308: return \is_array($aResult) ? $aResult : array();
309: }
310:
311: /**
312: *
313: * @return \Aurora\System\Module\Manager
314: */
315: public static function GetModuleManager()
316: {
317: if (!isset(self::$oModuleManager)) {
318: self::$oModuleManager = Module\Manager::createInstance();
319: self::$aModuleDecorators = [];
320: }
321:
322: return self::$oModuleManager;
323: }
324:
325: /**
326: *
327: * @param string $sModuleName
328: * @param int $iUser
329: * @return \Aurora\System\Module\Decorator
330: */
331: public static function GetModuleDecorator($sModuleName, $iUser = null)
332: {
333: if (!isset(self::$aModuleDecorators[$sModuleName]) && self::GetModule($sModuleName) !== false) {
334: self::$aModuleDecorators[$sModuleName] = new Module\Decorator($sModuleName, $iUser);
335: }
336:
337: return isset(self::$aModuleDecorators[$sModuleName]) ? self::$aModuleDecorators[$sModuleName] : false;
338: }
339:
340: /**
341: *
342: * @param string $sModuleName
343: * @return \Aurora\System\Module\AbstractModule
344: */
345: public static function GetModule($sModuleName)
346: {
347: return self::GetModuleManager()->GetModule($sModuleName);
348: }
349:
350: /**
351: *
352: * @return array
353: */
354: public static function GetModules()
355: {
356: return self::GetModuleManager()->GetModules();
357: }
358:
359: /**
360: *
361: * @param string $sMethodName
362: * @param array $aParameters
363: * @return mixed
364: */
365: public static function ExecuteMethod($sMethodName, $aParameters = array())
366: {
367: list($sModuleName, $sMethodName) = explode(Module\AbstractModule::$Delimiter, $sMethodName);
368: $oModule = self::GetModule($sModuleName);
369: if ($oModule instanceof Module\AbstractModule) {
370: return $oModule->CallMethod($sModuleName, $sMethodName, $aParameters);
371: }
372: }
373:
374: /**
375: * @return \MailSo\Cache\CacheClient
376: */
377: public static function Cacher()
378: {
379: static $oCacher = null;
380: if (null === $oCacher) {
381: $oCacher = \MailSo\Cache\CacheClient::NewInstance();
382: $oCacher->SetDriver(\MailSo\Cache\Drivers\File::NewInstance(self::DataPath().'/cache'));
383: $oCacher->SetCacheIndex(self::Version());
384: }
385:
386: return $oCacher;
387: }
388:
389: /**
390: * @return UserSession
391: */
392: public static function UserSession()
393: {
394: static $oSession = null;
395: if (null === $oSession) {
396: $oSession = new UserSession();
397: }
398:
399: return $oSession;
400: }
401:
402: /**
403: * @return \Aurora\System\Settings
404: */
405: public static function &GetSettings()
406: {
407: if (null === self::$oSettings) {
408: try {
409: $sSettingsPath = \Aurora\System\Api::DataPath() . '/settings/';
410: if (!\file_exists($sSettingsPath)) {
411: set_error_handler(function () {
412: });
413: mkdir($sSettingsPath, 0777);
414: restore_error_handler();
415: if (!file_exists($sSettingsPath)) {
416: self::$oSettings = false;
417: return self::$oSettings;
418: }
419: }
420:
421: self::$oSettings = new \Aurora\System\Settings($sSettingsPath . 'config.json');
422: } catch (\Aurora\System\Exceptions\BaseException $oException) {
423: self::$oSettings = false;
424: }
425: }
426: return self::$oSettings;
427: }
428:
429: public static function &GetConnection()
430: {
431: if (null === self::$oConnection) {
432: $oSettings =& self::GetSettings();
433:
434: if ($oSettings) {
435: self::$oConnection = new \Aurora\System\Db\Storage($oSettings);
436: } else {
437: self::$oConnection = false;
438: }
439: }
440: return self::$oConnection;
441: }
442:
443: /**
444: * @return \PDO|false
445: */
446: public static function GetPDO()
447: {
448: static $oPdoCache = null;
449: if (null !== $oPdoCache) {
450: return $oPdoCache;
451: }
452:
453: $oPdo = false;
454: $oSettings = &self::GetSettings();
455: if ($oSettings) {
456: $sDbPort = '';
457: $sUnixSocket = '';
458:
459: $iDbType = $oSettings->DBType;
460: $sDbHost = $oSettings->DBHost;
461: $sDbName = $oSettings->DBName;
462: $sDbLogin = $oSettings->DBLogin;
463: $sDbPassword = $oSettings->DBPassword;
464:
465: $iPos = strpos($sDbHost, ':');
466: if (false !== $iPos && 0 < $iPos) {
467: $sAfter = substr($sDbHost, $iPos + 1);
468: $sDbHost = substr($sDbHost, 0, $iPos);
469:
470: if (is_numeric($sAfter)) {
471: $sDbPort = $sAfter;
472: } else {
473: $sUnixSocket = $sAfter;
474: }
475: }
476:
477: if (class_exists('PDO')) {
478: try {
479: $oPdo = @new \PDO((Enums\DbType::PostgreSQL === $iDbType ? 'pgsql' : 'mysql').':dbname='.$sDbName.
480: (empty($sDbHost) ? '' : ';host='.$sDbHost).
481: (empty($sDbPort) ? '' : ';port='.$sDbPort).
482: (empty($sUnixSocket) ? '' : ';unix_socket='.$sUnixSocket) . ';charset=utf8', $sDbLogin, $sDbPassword);
483:
484: if ($oPdo) {
485: $oPdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
486: $oPdo->setAttribute(\PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES utf8");
487: }
488: } catch (\Exception $oException) {
489: self::Log($oException->getMessage(), Enums\LogLevel::Error);
490: self::Log($oException->getTraceAsString(), Enums\LogLevel::Error);
491: $oPdo = false;
492: }
493: } else {
494: self::Log('Class PDO dosn\'t exist', Enums\LogLevel::Error);
495: }
496: }
497:
498: if (false !== $oPdo) {
499: $oPdoCache = $oPdo;
500: }
501:
502: return $oPdo;
503: }
504:
505: /**
506: * @return bool
507: */
508: public static function IsMobileApplication()
509: {
510: /* @var $oIntegrator \Aurora\System\Managers\Integrator */
511: $oIntegrator = \Aurora\System\Managers\Integrator::getInstance();
512:
513: return (bool) $oIntegrator /*&& $oApiCapability->isNotLite()*/ && 1 === $oIntegrator->isMobile(); // todo
514: }
515:
516: /**
517: * @param string $sNewLocation
518: */
519: public static function Location($sNewLocation)
520: {
521: self::Log('Location: '.$sNewLocation);
522: @header('Location: '.$sNewLocation);
523: }
524:
525: /**
526: * @param string $sNewLocation
527: */
528: public static function Location2($sNewLocation)
529: {
530: exit('<META HTTP-EQUIV="refresh" CONTENT="0; url='.$sNewLocation.'">');
531: }
532:
533: /**
534: * @param string $sDesc
535: * @param string $sModuleName
536: */
537: public static function LogEvent($sDesc, $sModuleName = '')
538: {
539: Logger::LogEvent($sDesc, $sModuleName);
540: }
541:
542: /**
543: * @param mixed $mObject
544: * @param int $iLogLevel = \Aurora\System\Enums\LogLevel::Full
545: * @param string $sFilePrefix = ''
546: */
547: public static function LogObject($mObject, $iLogLevel = Enums\LogLevel::Full, $sFilePrefix = '')
548: {
549: Logger::LogObject($mObject, $iLogLevel, $sFilePrefix);
550: }
551:
552: /**
553: * @param Exception $mObject
554: * @param int $iLogLevel = \Aurora\System\Enums\LogLevel::Error
555: * @param string $sFilePrefix = ''
556: */
557: public static function LogException($mObject, $iLogLevel = Enums\LogLevel::Error, $sFilePrefix = 'error-')
558: {
559: Logger::LogException($mObject, $iLogLevel, $sFilePrefix);
560: }
561:
562: /**
563: * @param string $sFilePrefix = ''
564: *
565: * @return string
566: */
567: public static function GetLogFileName($sFilePrefix = '', $iTimestamp = 0)
568: {
569: return Logger::GetLogFileName($sFilePrefix, $iTimestamp);
570: }
571:
572: public static function GetLogFileDir()
573: {
574: return Logger::GetLogFileDir();
575: }
576:
577: /**
578: * @return \MailSo\Log\Logger
579: */
580: public static function SystemLogger()
581: {
582: return Logger::SystemLogger();
583: }
584:
585: /**
586: * @param string $sDesc
587: * @param int $iLogLevel = \Aurora\System\Enums\LogLevel::Full
588: * @param string $sFilePrefix = ''
589: * @param bool $bIdDb = false
590: */
591: public static function Log($sDesc, $iLogLevel = Enums\LogLevel::Full, $sFilePrefix = '')
592: {
593: Logger::Log($sDesc, $iLogLevel, $sFilePrefix);
594: }
595:
596: /**
597: * @param string $sDesc
598: * @param string $sLogFile
599: */
600: public static function LogOnly($sDesc, $sLogFile)
601: {
602: Logger::LogOnly($sDesc, $sLogFile);
603: }
604:
605: public static function ClearLog($sFileFullPath)
606: {
607: return Logger::ClearLog($sFileFullPath);
608: }
609:
610: public static function RemoveSeparateLogs()
611: {
612: Logger::RemoveSeparateLogs();
613: }
614:
615: public static function removeOldLogs()
616: {
617: Logger::removeOldLogs();
618: }
619:
620: public static function GetLoggerGuid()
621: {
622: return Logger::GetLoggerGuid();
623: }
624:
625: /**
626: * @return string
627: */
628: public static function RootPath()
629: {
630: defined('AU_API_ROOTPATH') || define('AU_API_ROOTPATH', rtrim(dirname(__FILE__), '/\\').'/');
631: return AU_API_ROOTPATH;
632: }
633:
634: /**
635: * @return string
636: */
637: public static function WebMailPath()
638: {
639: return self::RootPath().ltrim(AU_API_PATH_TO_AURORA, '/');
640: }
641:
642: /**
643: * @return string
644: */
645: public static function GetVendorPath()
646: {
647: return self::RootPath().'../vendor/';
648: }
649:
650: /**
651: * @return string
652: */
653: public static function VersionFull()
654: {
655: static $sVersion = null;
656: $sAppVersion = @file_get_contents(self::WebMailPath().'VERSION');
657:
658: $sVersion = (empty($sAppVersion)) ? '0.0.0' : $sAppVersion;
659:
660: return $sVersion;
661: }
662:
663: /**
664: * @return string
665: */
666: public static function Version()
667: {
668: static $sVersion = null;
669: if (null === $sVersion) {
670: preg_match('/[\d\.]+/', @file_get_contents(self::WebMailPath().'VERSION'), $matches);
671:
672: if (isset($matches[0])) {
673: $sAppVersion = preg_replace('/[^0-9]/', '', $matches[0]);
674: }
675:
676: $sVersion = (empty($sAppVersion)) ? '0.0.0' : $sAppVersion;
677: }
678: return $sVersion;
679: }
680:
681: /**
682: * @return string
683: */
684: public static function VersionJs()
685: {
686: $oSettings = &self::GetSettings();
687: $sAppVersion = @file_get_contents(self::WebMailPath().'VERSION');
688: $sAppVersion = empty($sAppVersion) ? '0.0.0' : $sAppVersion;
689:
690: return preg_replace('/[^0-9]/', '', $sAppVersion);
691: }
692:
693: /**
694: * @return string
695: */
696: public static function DataPath()
697: {
698: $dataPath = 'data';
699: if (!defined('AU_API_DATA_FOLDER') && @file_exists(self::WebMailPath().'inc_settings_path.php')) {
700: include self::WebMailPath().'inc_settings_path.php';
701: }
702: if (!defined('AU_API_DATA_FOLDER') && isset($dataPath) && null !== $dataPath) {
703: define('AU_API_DATA_FOLDER', Utils::GetFullPath($dataPath, self::WebMailPath()));
704: }
705: $sDataFullPath = defined('AU_API_DATA_FOLDER') ? AU_API_DATA_FOLDER : '';
706:
707: /**
708: if (!\file_exists($sDataFullPath))
709: {
710: \mkdir($sDataFullPath, 0777);
711: }
712: */
713: return $sDataFullPath;
714: }
715:
716: /**
717: * @return bool
718: */
719: protected static function validateApi()
720: {
721: $iResult = 1;
722:
723: $oSettings = &self::GetSettings();
724: $iResult &= $oSettings && ($oSettings instanceof AbstractSettings);
725:
726: self::$bIsValid = (bool) $iResult;
727:
728: return self::$bIsValid;
729: }
730:
731: /**
732: * @return bool
733: */
734: public static function IsValid()
735: {
736: return (bool)self::$bIsValid;
737: }
738:
739: /**
740: * @param string $sEmail
741: * @param string $sPassword
742: * @param string $sLogin = ''
743: * @return string
744: */
745: public static function GenerateSsoToken($sEmail, $sPassword, $sLogin = '')
746: {
747: $sSsoHash = \md5($sEmail.$sPassword.$sLogin.\microtime(true).\rand(10000, 99999));
748: return self::Cacher()->Set('SSO:'.$sSsoHash, self::EncodeKeyValues(array(
749: 'Email' => $sEmail,
750: 'Password' => $sPassword,
751: 'Login' => $sLogin
752: ))) ? $sSsoHash : '';
753: }
754:
755: /**
756: * @param string $sLangFile
757: * @return array
758: */
759: public static function convertIniToLang($sLangFile)
760: {
761: $aResultLang = false;
762:
763: $aLang = @\parse_ini_string(file_get_contents($sLangFile), true);
764: if (is_array($aLang)) {
765: $aResultLang = array();
766: foreach ($aLang as $sKey => $mValue) {
767: if (\is_array($mValue)) {
768: foreach ($mValue as $sSecKey => $mSecValue) {
769: $aResultLang[$sKey.'/'.$sSecKey] = $mSecValue;
770: }
771: } else {
772: $aResultLang[$sKey] = $mValue;
773: }
774: }
775: }
776:
777: return $aResultLang;
778: }
779:
780: /**
781: * @param mixed $mLang
782: * @param string $sData
783: * @param array|null $aParams = null
784: * @return array
785: */
786: public static function processTranslateParams($mLang, $sData, $aParams = null, $iPlural = null)
787: {
788: $sResult = $sData;
789: if ($mLang && isset($mLang[$sData])) {
790: $sResult = $mLang[$sData];
791: }
792:
793: if (isset($iPlural)) {
794: $aPluralParts = explode('|', $sResult);
795:
796: $sResult = ($aPluralParts && $aPluralParts[$iPlural]) ? $aPluralParts[$iPlural] : (
797: $aPluralParts && $aPluralParts[0] ? $aPluralParts[0] : $sResult
798: );
799: }
800:
801: if (null !== $aParams && is_array($aParams)) {
802: foreach ($aParams as $sKey => $sValue) {
803: $sResult = str_replace('%'.$sKey.'%', $sValue, $sResult);
804: }
805: }
806:
807: return $sResult;
808: }
809:
810: /**
811: *
812: * @param string $sLanguage
813: */
814: public static function SetLanguage($sLanguage)
815: {
816: self::$sLanguage = $sLanguage;
817: }
818:
819: /**
820: *
821: * @param bool $bForNewUser
822: * @return string
823: */
824: public static function GetLanguage($bForNewUser = false)
825: {
826: $sResult = null;
827: if (isset(self::$sLanguage)) {
828: $sResult = self::$sLanguage;
829: } else {
830: $iAuthUserId = self::getAuthenticatedUserId();
831: $bSuperAdmin = $iAuthUserId === -1;
832: $oModuleManager = self::GetModuleManager();
833:
834: $sResult = $oModuleManager->getModuleConfigValue('Core', 'Language');
835: if ($oModuleManager->getModuleConfigValue('Core', 'AutodetectLanguage', true)) {
836: $sResult = self::getBrowserLanguage();
837: }
838:
839: if ($bSuperAdmin) {
840: $oSettings = &self::GetSettings();
841: $sResult = $oSettings->AdminLanguage;
842: } elseif (!$bForNewUser) {
843: $oUser = self::getAuthenticatedUser();
844: if ($oUser) {
845: $sResult = $oUser->Language;
846: } elseif (isset($_COOKIE['aurora-lang-on-login'])) {
847: $sResult = $_COOKIE['aurora-lang-on-login'];
848: }
849: }
850: }
851:
852: return $sResult;
853: }
854:
855: protected static function getBrowserLanguage()
856: {
857: $aLanguages = array(
858: 'ar-dz' => 'Arabic', 'ar-bh' => 'Arabic', 'ar-eg' => 'Arabic', 'ar-iq' => 'Arabic', 'ar-jo' => 'Arabic', 'ar-kw' => 'Arabic',
859: 'ar-lb' => 'Arabic', 'ar-ly' => 'Arabic', 'ar-ma' => 'Arabic', 'ar-om' => 'Arabic', 'ar-qa' => 'Arabic', 'ar-sa' => 'Arabic',
860: 'ar-sy' => 'Arabic', 'ar-tn' => 'Arabic', 'ar-ae' => 'Arabic', 'ar-ye' => 'Arabic', 'ar' => 'Arabic',
861: 'bg' => 'Bulgarian',
862: 'zh-cn' => 'Chinese-Simplified', 'zh-hk' => 'Chinese-Simplified', 'zh-mo' => 'Chinese-Simplified', 'zh-sg' => 'Chinese-Simplified',
863: 'zh-tw' => 'Chinese-Simplified', 'zh' => 'Chinese-Simplified',
864: 'cs' => 'Czech',
865: 'da' => 'Danish',
866: 'nl-be' => 'Dutch', 'nl' => 'Dutch',
867: 'en-au' => 'English', 'en-bz' => 'English ', 'en-ca' => 'English', 'en-ie' => 'English', 'en-jm' => 'English',
868: 'en-nz' => 'English', 'en-ph' => 'English', 'en-za' => 'English', 'en-tt' => 'English', 'en-gb' => 'English',
869: 'en-us' => 'English', 'en-zw' => 'English', 'en' => 'English', 'us' => 'English',
870: 'et' => 'Estonian', 'fi' => 'Finnish',
871: 'fr-be' => 'French', 'fr-ca' => 'French', 'fr-lu' => 'French', 'fr-mc' => 'French', 'fr-ch' => 'French', 'fr' => 'French',
872: 'de-at' => 'German', 'de-li' => 'German', 'de-lu' => 'German', 'de-ch' => 'German', 'de' => 'German',
873: 'el' => 'Greek', 'he' => 'Hebrew', 'hu' => 'Hungarian', 'it-ch' => 'Italian', 'it' => 'Italian',
874: 'ja' => 'Japanese', 'ko' => 'Korean', 'lv' => 'Latvian', 'lt' => 'Lithuanian',
875: 'nb-no' => 'Norwegian', 'nn-no' => 'Norwegian', 'no' => 'Norwegian', 'pl' => 'Polish',
876: 'pt-br' => 'Portuguese-Brazil', 'pt' => 'Portuguese-Portuguese', 'pt-pt' => 'Portuguese-Portuguese',
877: 'ro-md' => 'Romanian', 'ro' => 'Romanian',
878: 'ru-md' => 'Russian', 'ru' => 'Russian', 'sr' => 'Serbian',
879: 'es-ar' => 'Spanish', 'es-bo' => 'Spanish', 'es-cl' => 'Spanish', 'es-co' => 'Spanish', 'es-cr' => 'Spanish',
880: 'es-do' => 'Spanish', 'es-ec' => 'Spanish', 'es-sv' => 'Spanish', 'es-gt' => 'Spanish', 'es-hn' => 'Spanish)',
881: 'es-mx' => 'Spanish', 'es-ni' => 'Spanish', 'es-pa' => 'Spanish', 'es-py' => 'Spanish', 'es-pe' => 'Spanish',
882: 'es-pr' => 'Spanish', 'es-us' => 'Spanish ', 'es-uy' => 'Spanish', 'es-ve' => 'Spanish', 'es' => 'Spanish',
883: 'sv-fi' => 'Swedish', 'sv' => 'Swedish', 'th' => 'Thai', 'tr' => 'Turkish', 'uk' => 'Ukrainian', 'vi' => 'Vietnamese', 'sl' => 'Slovenian'
884: );
885:
886: $sLanguage = !empty($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE']) : 'en';
887: $aTempLanguages = preg_split('/[,;]+/', $sLanguage);
888: $sLanguage = !empty($aTempLanguages[0]) ? $aTempLanguages[0] : 'en';
889:
890: $sLanguageShort = substr($sLanguage, 0, 2);
891:
892: return \array_key_exists($sLanguage, $aLanguages) ? $aLanguages[$sLanguage] :
893: (\array_key_exists($sLanguageShort, $aLanguages) ? $aLanguages[$sLanguageShort] : '');
894: }
895:
896: /**
897: * @param string $sData
898: * @param \Aurora\Modules\StandardAuth\Models\StandardAuthAccount $oAccount
899: * @param array $aParams = null
900: *
901: * @return string
902: */
903: public static function ClientI18N($sData, $oAccount = null, $aParams = null, $iPluralCount = null)
904: {
905: $sLanguage = self::GetLanguage();
906:
907: $aLang = null;
908: if (isset(self::$aClientI18N[$sLanguage])) {
909: $aLang = self::$aClientI18N[$sLanguage];
910: } else {
911: self::$aClientI18N[$sLanguage] = false;
912:
913: $sLangFile = self::WebMailPath().'i18n/'.$sLanguage.'.ini';
914: if (!@file_exists($sLangFile)) {
915: $sLangFile = self::WebMailPath().'i18n/English.ini';
916: $sLangFile = @file_exists($sLangFile) ? $sLangFile : '';
917: }
918:
919: if (0 < strlen($sLangFile)) {
920: $aLang = self::convertIniToLang($sLangFile);
921: if (is_array($aLang)) {
922: self::$aClientI18N[$sLanguage] = $aLang;
923: }
924: }
925: }
926:
927: //return self::processTranslateParams($aLang, $sData, $aParams);
928: return isset($iPluralCount) ? self::processTranslateParams($aLang, $sData, $aParams, self::getPlural($sLanguage, $iPluralCount)) : self::processTranslateParams($aLang, $sData, $aParams);
929: }
930:
931: public static function getPlural($sLang = '', $iNumber = 0)
932: {
933: $iResult = 0;
934: $iNumber = (int) $iNumber;
935:
936: switch ($sLang) {
937: case 'Arabic':
938: $iResult = ($iNumber === 0 ? 0 : ($iNumber === 1 ? 1 : ($iNumber === 2 ? 2 : ($iNumber % 100 >= 3 && $iNumber % 100 <= 10 ? 3 : ($iNumber % 100 >= 11 ? 4 : 5)))));
939: break;
940: case 'Bulgarian':
941: $iResult = ($iNumber === 1 ? 0 : 1);
942: break;
943: case 'Chinese-Simplified':
944: $iResult = 0;
945: break;
946: case 'Chinese-Traditional':
947: $iResult = ($iNumber === 1 ? 0 : 1);
948: break;
949: case 'Czech':
950: $iResult = ($iNumber === 1) ? 0 : (($iNumber >= 2 && $iNumber <= 4) ? 1 : 2);
951: break;
952: case 'Danish':
953: $iResult = ($iNumber === 1 ? 0 : 1);
954: break;
955: case 'Dutch':
956: $iResult = ($iNumber === 1 ? 0 : 1);
957: break;
958: case 'English':
959: $iResult = ($iNumber === 1 ? 0 : 1);
960: break;
961: case 'Estonian':
962: $iResult = ($iNumber === 1 ? 0 : 1);
963: break;
964: case 'Finnish':
965: $iResult = ($iNumber === 1 ? 0 : 1);
966: break;
967: case 'French':
968: $iResult = ($iNumber === 1 ? 0 : 1);
969: break;
970: case 'German':
971: $iResult = ($iNumber === 1 ? 0 : 1);
972: break;
973: case 'Greek':
974: $iResult = ($iNumber === 1 ? 0 : 1);
975: break;
976: case 'Hebrew':
977: $iResult = ($iNumber === 1 ? 0 : 1);
978: break;
979: case 'Hungarian':
980: $iResult = ($iNumber === 1 ? 0 : 1);
981: break;
982: case 'Italian':
983: $iResult = ($iNumber === 1 ? 0 : 1);
984: break;
985: case 'Japanese':
986: $iResult = 0;
987: break;
988: case 'Korean':
989: $iResult = 0;
990: break;
991: case 'Latvian':
992: $iResult = ($iNumber % 10 === 1 && $iNumber % 100 !== 11 ? 0 : ($iNumber !== 0 ? 1 : 2));
993: break;
994: case 'Lithuanian':
995: $iResult = ($iNumber % 10 === 1 && $iNumber % 100 !== 11 ? 0 : ($iNumber % 10 >= 2 && ($iNumber % 100 < 10 || $iNumber % 100 >= 20) ? 1 : 2));
996: break;
997: case 'Norwegian':
998: $iResult = ($iNumber === 1 ? 0 : 1);
999: break;
1000: case 'Persian':
1001: $iResult = 0;
1002: break;
1003: case 'Polish':
1004: $iResult = ($iNumber === 1 ? 0 : ($iNumber % 10 >= 2 && $iNumber % 10 <= 4 && ($iNumber % 100 < 10 || $iNumber % 100 >= 20) ? 1 : 2));
1005: break;
1006: case 'Portuguese-Portuguese':
1007: $iResult = ($iNumber === 1 ? 0 : 1);
1008: break;
1009: case 'Portuguese-Brazil':
1010: $iResult = ($iNumber === 1 ? 0 : 1);
1011: break;
1012: case 'Romanian':
1013: $iResult = ($iNumber === 1 ? 0 : (($iNumber === 0 || ($iNumber % 100 > 0 && $iNumber % 100 < 20)) ? 1 : 2));
1014: break;
1015: case 'Russian':
1016: $iResult = ($iNumber % 10 === 1 && $iNumber % 100 !== 11 ? 0 : ($iNumber % 10 >= 2 && $iNumber % 10 <= 4 && ($iNumber % 100 < 10 || $iNumber % 100 >= 20) ? 1 : 2));
1017: break;
1018: case 'Serbian':
1019: $iResult = ($iNumber % 10 === 1 && $iNumber % 100 !== 11 ? 0 : ($iNumber % 10 >= 2 && $iNumber % 10 <= 4 && ($iNumber % 100 < 10 || $iNumber % 100 >= 20) ? 1 : 2));
1020: break;
1021: case 'Slovenian':
1022: $iResult = (($iNumber % 10 === 1 && $iNumber % 100 !== 11) ? 0 : (($iNumber % 10 === 2 && $iNumber % 100 !== 12) ? 1 : 2));
1023: break;
1024: case 'Spanish':
1025: $iResult = ($iNumber === 1 ? 0 : 1);
1026: break;
1027: case 'Swedish':
1028: $iResult = ($iNumber === 1 ? 0 : 1);
1029: break;
1030: case 'Thai':
1031: $iResult = 0;
1032: break;
1033: case 'Turkish':
1034: $iResult = ($iNumber === 1 ? 0 : 1);
1035: break;
1036: case 'Ukrainian':
1037: $iResult = ($iNumber % 10 === 1 && $iNumber % 100 !== 11 ? 0 : ($iNumber % 10 >= 2 && $iNumber % 10 <= 4 && ($iNumber % 100 < 10 || $iNumber % 100 >= 20) ? 1 : 2));
1038: break;
1039: case 'Vietnamese':
1040: $iResult = 0;
1041: break;
1042: default:
1043: $iResult = 0;
1044: break;
1045: }
1046:
1047: return $iResult;
1048: }
1049:
1050: /**
1051: * @param string $sData
1052: * @param array $aParams = null
1053: *
1054: * @return string
1055: */
1056: public static function I18N($sData, $aParams = null, $sForceCustomInitialisationLang = '')
1057: {
1058: if (null === self::$aI18N) {
1059: self::$aI18N = false;
1060:
1061: $sLangFile = '';
1062: if (0 < strlen($sForceCustomInitialisationLang)) {
1063: $sLangFile = self::RootPath().'common/i18n/'.$sForceCustomInitialisationLang.'.ini';
1064: }
1065:
1066: if (0 === strlen($sLangFile) || !@file_exists($sLangFile)) {
1067: $sLangFile = self::RootPath().'common/i18n/English.ini';
1068: }
1069:
1070: if (0 < strlen($sLangFile) && @file_exists($sLangFile)) {
1071: $aResultLang = self::convertIniToLang($sLangFile);
1072: if (is_array($aResultLang)) {
1073: self::$aI18N = $aResultLang;
1074: }
1075: }
1076: }
1077:
1078: return self::processTranslateParams(self::$aI18N, $sData, $aParams);
1079: }
1080:
1081: /**
1082: * Checks if authenticated user has at least specified role.
1083: * @param int $iRole
1084: * @throws \Aurora\System\Exceptions\ApiException
1085: */
1086: public static function checkUserRoleIsAtLeast($iRole)
1087: {
1088: if (!self::$__SKIP_CHECK_USER_ROLE__) {
1089: $oUser = self::getAuthenticatedUser();
1090: $bUserRoleIsAtLeast = empty($oUser) && $iRole === Enums\UserRole::Anonymous ||
1091: !empty($oUser) && $oUser->Role === Enums\UserRole::Customer &&
1092: ($iRole === Enums\UserRole::Customer || $iRole === Enums\UserRole::Anonymous) ||
1093: !empty($oUser) && $oUser->Role === Enums\UserRole::NormalUser &&
1094: ($iRole === Enums\UserRole::NormalUser || $iRole === Enums\UserRole::Customer || $iRole === Enums\UserRole::Anonymous) ||
1095: !empty($oUser) && $oUser->Role === Enums\UserRole::TenantAdmin &&
1096: ($iRole === Enums\UserRole::TenantAdmin || $iRole === Enums\UserRole::NormalUser || $iRole === Enums\UserRole::Customer || $iRole === Enums\UserRole::Anonymous) ||
1097: !empty($oUser) && $oUser->Role === Enums\UserRole::SuperAdmin &&
1098: ($iRole === Enums\UserRole::SuperAdmin || $iRole === Enums\UserRole::TenantAdmin || $iRole === Enums\UserRole::NormalUser || $iRole === Enums\UserRole::Customer || $iRole === Enums\UserRole::Anonymous);
1099: if (!$bUserRoleIsAtLeast) {
1100: throw new Exceptions\ApiException(Notifications::AccessDenied);
1101: }
1102: }
1103: }
1104:
1105: public static function getAuthTokenFromHeaders()
1106: {
1107: $sResult = false;
1108: $sAuthHeader = \MailSo\Base\Http::SingletonInstance()->GetHeader('Authorization');
1109: if (!empty($sAuthHeader)) {
1110: $authHeaderData = explode(' ', $sAuthHeader);
1111:
1112: if (isset($authHeaderData[0]) && strtolower($authHeaderData[0]) === 'bearer' && isset($authHeaderData[1]) && !empty($authHeaderData[1])) {
1113: $sResult = $authHeaderData[1];
1114: }
1115: }
1116:
1117: return $sResult;
1118: }
1119:
1120: public static function requireAdminAuth()
1121: {
1122: $mResult = false;
1123: $response = new \Sabre\HTTP\Response();
1124: $basicAuth = new \Sabre\HTTP\Auth\Basic("Locked down area", \Sabre\HTTP\Sapi::getRequest(), $response);
1125: if (!$userPass = $basicAuth->getCredentials()) {
1126: $basicAuth->requireLogin();
1127: \Sabre\HTTP\Sapi::sendResponse($response);
1128: } elseif (!\Aurora\Modules\AdminAuth\Module::getInstance()->Login($userPass[0], $userPass[1])) {
1129: $basicAuth->requireLogin();
1130: \Sabre\HTTP\Sapi::sendResponse($response);
1131: } else {
1132: $mResult = true;
1133: }
1134:
1135: if (!$mResult) {
1136: $response->setBody('Unauthorized');
1137: \Sabre\HTTP\Sapi::sendResponse($response);
1138: exit;
1139: }
1140: }
1141:
1142: public static function getDeviceIdFromHeaders()
1143: {
1144: $sResult = false;
1145: $sDeviceIdHeader = \MailSo\Base\Http::SingletonInstance()->GetHeader('X-DeviceId');
1146: if (!empty($sDeviceIdHeader)) {
1147: $sResult = $sDeviceIdHeader;
1148: }
1149:
1150: return $sResult;
1151: }
1152:
1153: /**
1154: *
1155: * @return string
1156: */
1157: public static function getAuthToken()
1158: {
1159: $sAuthToken = self::getAuthTokenFromHeaders();
1160: if (!$sAuthToken) {
1161: $sAuthToken = isset($_COOKIE[Application::AUTH_TOKEN_KEY]) ?
1162: $_COOKIE[Application::AUTH_TOKEN_KEY] : '';
1163: }
1164:
1165: return $sAuthToken;
1166: }
1167:
1168: /**
1169: *
1170: * @return bool
1171: */
1172: public static function validateCsrfToken()
1173: {
1174: $bResult = true;
1175: if (isset($_COOKIE[Application::AUTH_TOKEN_KEY])) {
1176: $sAuthToken = self::getAuthTokenFromHeaders();
1177:
1178: $bResult = ($sAuthToken === $_COOKIE[Application::AUTH_TOKEN_KEY]);
1179: }
1180:
1181: return $bResult;
1182: }
1183:
1184: /**
1185: *
1186: * @return \Aurora\Modules\Core\Models\User
1187: */
1188: public static function authorise($sAuthToken = '')
1189: {
1190: $oUser = null;
1191: $mUserId = false;
1192: try {
1193: if (isset(self::$aUserSession['UserId'])) {
1194: $mUserId = self::$aUserSession['UserId'];
1195: } else {
1196: $sAuthToken = empty($sAuthToken) ? self::getAuthToken() : $sAuthToken;
1197: $mUserId = self::getAuthenticatedUserId($sAuthToken);
1198: }
1199: $oUser = Managers\Integrator::getInstance()->getAuthenticatedUserByIdHelper($mUserId);
1200: } catch (\Exception $oException) {
1201: }
1202: return $oUser;
1203: }
1204:
1205: public static function getAuthenticatedUserInfo($sAuthToken = '')
1206: {
1207: $mResult = false;
1208: if (empty($sAuthToken)) {
1209: if (is_array(self::$aUserSession) && isset(self::$aUserSession['AuthToken'])) {
1210: $sAuthToken = self::$aUserSession['AuthToken'];
1211: }
1212: }
1213: /* @var $oIntegrator \Aurora\System\Managers\Integrator */
1214: $oIntegrator = \Aurora\System\Managers\Integrator::getInstance();
1215: if ($oIntegrator) {
1216: $mResult = $oIntegrator->getAuthenticatedUserInfo($sAuthToken);
1217: }
1218:
1219: return $mResult;
1220: }
1221:
1222: public static function validateAuthToken()
1223: {
1224: $bResult = false;
1225: /* @var $oIntegrator \Aurora\System\Managers\Integrator */
1226: $oIntegrator = \Aurora\System\Managers\Integrator::getInstance();
1227: if ($oIntegrator) {
1228: $bResult = $oIntegrator->validateAuthToken(self::getAuthToken());
1229: }
1230:
1231: return $bResult;
1232: }
1233:
1234: public static function getCookiePath()
1235: {
1236: static $sPath = false;
1237:
1238: if (false === $sPath) {
1239: $sScriptName = isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : '';
1240: $aPath = explode('/', $sScriptName);
1241: $sLastPathItem = count($aPath) > 0 ? $aPath[count($aPath) - 1] : '';
1242: if (count($aPath) > 0 && ($sLastPathItem !== '' || strtolower(substr($sLastPathItem, -1)) === '.php')) {
1243: array_pop($aPath);
1244: }
1245: $sPath = implode('/', $aPath) . '/';
1246: }
1247:
1248: return $sPath;
1249: }
1250:
1251: public static function getCookieSecure()
1252: {
1253: return self::isHttps();
1254: }
1255:
1256: public static function isHttps()
1257: {
1258: return (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ||
1259: (isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == '443');
1260: }
1261:
1262: public static function getAuthenticatedUserId($sAuthToken = '')
1263: {
1264: $mResult = false;
1265: if (!empty($sAuthToken)) {
1266: $aInfo = \Aurora\System\Managers\Integrator::getInstance()->getAuthenticatedUserInfo($sAuthToken);
1267: if (!empty(self::$aUserSession['UserId']) && (int) $aInfo['userId'] === (int) self::$aUserSession['UserId']) {
1268: $mResult = (int) self::$aUserSession['UserId'];
1269: } else {
1270: $mResult = $aInfo['userId'];
1271: self::$aUserSession['UserId'] = (int) $mResult;
1272: self::$aUserSession['AuthToken'] = $sAuthToken;
1273: }
1274: } else {
1275: if (is_array(self::$aUserSession) && isset(self::$aUserSession['UserId'])) {
1276: $mResult = self::$aUserSession['UserId'];
1277: } else {
1278: $mResult = 0;
1279: }
1280: }
1281:
1282: return $mResult;
1283: }
1284:
1285: public static function getAuthenticatedUserPublicId($sAuthToken = '')
1286: {
1287: $iUserId = self::getAuthenticatedUserId($sAuthToken);
1288: return self::getUserPublicIdById($iUserId);
1289: }
1290:
1291: /**
1292: * @return \Aurora\Modules\Core\Models\User
1293: */
1294: public static function getAuthenticatedUser($sAuthToken = '')
1295: {
1296: $iUserId = 0;
1297: if (null === self::$oAuthenticatedUser) {
1298: if (!empty($sAuthToken)) {
1299: $iUserId = self::getAuthenticatedUserId($sAuthToken); // called for saving in session
1300: } elseif (!empty(self::$aUserSession['UserId'])) {
1301: $iUserId = self::$aUserSession['UserId'];
1302: }
1303:
1304: $oIntegrator = \Aurora\System\Managers\Integrator::getInstance();
1305: if ($oIntegrator) {
1306: self::$oAuthenticatedUser = $oIntegrator->getAuthenticatedUserByIdHelper($iUserId);
1307: }
1308: }
1309: return self::$oAuthenticatedUser;
1310: }
1311:
1312: public static function getAuthenticatedUserAuthToken()
1313: {
1314: $mResult = false;
1315:
1316: if (is_array(self::$aUserSession) && isset(self::$aUserSession['AuthToken'])) {
1317: $mResult = self::$aUserSession['AuthToken'];
1318: }
1319:
1320: return $mResult;
1321: }
1322:
1323: /**
1324: * @param int $iUserId
1325: * @return string
1326: */
1327: public static function getUserUUIDById($iUserId)
1328: {
1329: $sUUID = '';
1330: static $aUUIDs = []; // cache
1331:
1332: if (\is_numeric($iUserId)) {
1333: if (isset($aUUIDs[$iUserId])) {
1334: $sUUID = $aUUIDs[$iUserId];
1335: } else {
1336: $oUser = User::find($iUserId);
1337: if ($oUser) {
1338: $aUUIDs[$iUserId] = $sUUID = $oUser->UUID;
1339: }
1340: }
1341: } else {
1342: $sUUID = $iUserId;
1343: }
1344:
1345: return $sUUID;
1346: }
1347:
1348: /**
1349: * @param int $iUserId
1350: * @return string
1351: */
1352: public static function getUserPublicIdById($iUserId)
1353: {
1354: $sPublicId = '';
1355:
1356: if (\is_numeric($iUserId)) {
1357: $oUser = User::select('PublicId')->firstWhere('Id', $iUserId);
1358: if ($oUser) {
1359: return $oUser->PublicId;
1360: }
1361: } else {
1362: $sPublicId = $iUserId;
1363: }
1364:
1365: return $sPublicId;
1366: }
1367:
1368: /**
1369: * @param string $sPublicId
1370: * @return int
1371: */
1372: public static function getUserIdByPublicId($sPublicId)
1373: {
1374: $iUserId = false;
1375:
1376: if (Api::GetSettings()->GetValue('AdminLogin') === $sPublicId) { // superadmin user
1377: return -1;
1378: }
1379:
1380: $oUser = User::select('Id')->firstWhere('PublicId', $sPublicId);
1381: if ($oUser) {
1382: return $oUser->Id;
1383: }
1384:
1385: return $iUserId;
1386: }
1387:
1388: public static function getUserById($iUserId)
1389: {
1390: $mUser = false;
1391:
1392: try {
1393: $mUser = Managers\Integrator::getInstance()->getAuthenticatedUserByIdHelper($iUserId);
1394: } catch (\Exception $oEx) {
1395: $mUser = false;
1396: }
1397:
1398: return $mUser;
1399: }
1400:
1401: public static function getTenantById($iTenantId)
1402: {
1403: return Tenant::find($iTenantId);
1404: }
1405:
1406: public static function setTenantName($sTenantName)
1407: {
1408: self::$aUserSession['TenantName'] = $sTenantName;
1409: }
1410:
1411: public static function setUserId($iUserId)
1412: {
1413: self::$aUserSession['UserId'] = (int) $iUserId;
1414: }
1415:
1416: public static function setAuthToken($sAuthToken)
1417: {
1418: self::$aUserSession['AuthToken'] = $sAuthToken;
1419: }
1420:
1421: public static function getCurrentTenant()
1422: {
1423: static $bTenantInitialized = false;
1424: static $oTenant = null;
1425:
1426: if (!$bTenantInitialized) {
1427: $oUser = self::getAuthenticatedUser();
1428:
1429: if ($oUser && !$oUser->isAdmin()) {
1430: $oTenant = self::getTenantById($oUser->IdTenant);
1431: }
1432:
1433: if (!$oUser && !$oTenant) {
1434: $oTenant = self::getTenantByWebDomain();
1435: }
1436:
1437: // $bTenantInitialized = true;
1438: }
1439:
1440: return $oTenant;
1441: }
1442:
1443: public static function getTenantByWebDomain()
1444: {
1445: static $bTenantInitialized = false;
1446: static $oTenant = null;
1447:
1448: if (!$bTenantInitialized) {
1449: if (!empty($_SERVER['SERVER_NAME'])) {
1450: $oTenant = Tenant::firstWhere('WebDomain', $_SERVER['SERVER_NAME']);
1451: }
1452: $bTenantInitialized = true;
1453: }
1454:
1455: return $oTenant;
1456: }
1457:
1458: /**
1459: *
1460: * @return string
1461: */
1462: public static function getTenantName()
1463: {
1464: static $mResult = null;
1465:
1466: if (!isset($mResult)) {
1467: if (is_array(self::$aUserSession) && !empty(self::$aUserSession['TenantName'])) {
1468: $mResult = self::$aUserSession['TenantName'];
1469: } else {
1470: try {
1471: $oTenant = self::getCurrentTenant();
1472: if ($oTenant) {
1473: $mResult = $oTenant->Name;
1474: }
1475: } catch (\Exception $oEx) {
1476: $mResult = false;
1477: }
1478: }
1479: // $bTenantInitialized = true;
1480: }
1481:
1482: return $mResult;
1483: }
1484:
1485: public static function GetDbConfig($DbType, $DbHost, $DbName, $DbPrefix, $DbLogin, $DbPassword)
1486: {
1487: $aDbHost = \explode(':', $DbHost);
1488: if (isset($aDbHost[0])) {
1489: $DbHost = $aDbHost[0];
1490: }
1491: $aDbConfig = [
1492: 'driver' => DbType::PostgreSQL === $DbType ? 'pgsql' : 'mysql',
1493: 'host' => $DbHost,
1494: 'database' => $DbName,
1495: 'username' => $DbLogin,
1496: 'password' => $DbPassword,
1497: 'charset' => 'utf8',
1498: 'collation' => 'utf8_general_ci',
1499: 'prefix' => $DbPrefix,
1500: ];
1501: if (isset($aDbHost[1])) {
1502: $aDbConfig['port'] = $aDbHost[1];
1503: }
1504:
1505: return $aDbConfig;
1506: }
1507:
1508: private static function CreateContainer()
1509: {
1510: $container = new Container();
1511:
1512: $oSettings = &Api::GetSettings();
1513: if ($oSettings) {
1514: $container['db-config'] = self::GetDbConfig(
1515: $oSettings->DBType,
1516: $oSettings->DBHost,
1517: $oSettings->DBName,
1518: $oSettings->DBPrefix,
1519: $oSettings->DBLogin,
1520: $oSettings->DBPassword
1521: );
1522:
1523: $capsule = new \Illuminate\Database\Capsule\Manager();
1524: $capsule->addConnection($container['db-config']);
1525:
1526: //Make this Capsule instance available globally.
1527: $capsule->setAsGlobal();
1528:
1529: // Setup the Eloquent ORM.
1530: $capsule->bootEloquent();
1531:
1532: $container['connection'] = function ($c) use ($capsule) {
1533: return $capsule->getConnection('default');
1534: };
1535:
1536: $container['migration-table'] = 'migrations';
1537:
1538: $container['filesystem'] = function ($c) {
1539: return new \Illuminate\Filesystem\Filesystem();
1540: };
1541:
1542: $container['resolver'] = function ($c) {
1543: $r = new \Illuminate\Database\ConnectionResolver(['default' => $c['connection']]);
1544: $r->setDefaultConnection('default');
1545: return $r;
1546: };
1547:
1548: $container['migration-repo'] = function ($c) {
1549: return new \Illuminate\Database\Migrations\DatabaseMigrationRepository($c['resolver'], $c['migration-table']);
1550: };
1551:
1552: $container['migrator'] = function ($c) {
1553: return new \Illuminate\Database\Migrations\Migrator($c['migration-repo'], $c['resolver'], $c['filesystem']);
1554: };
1555:
1556: $container['migration-creator'] = function ($c) {
1557: return new \Illuminate\Database\Migrations\MigrationCreator($c['filesystem'], \Aurora\Api::RootPath() . 'Console' . DIRECTORY_SEPARATOR . 'stubs');
1558: };
1559:
1560: $container['composer'] = function ($c) {
1561: return new \Illuminate\Support\Composer($c['filesystem']);
1562: };
1563:
1564: $container['console'] = function ($c) {
1565: $app = new \Symfony\Component\Console\Application();
1566:
1567: $app->add(new Commands\Migrations\InstallCommand($c['migration-repo']));
1568: $app->add(new Commands\Migrations\MigrateCommand($c['migrator']));
1569: $app->add(new Commands\Migrations\RollbackCommand($c['migrator']));
1570: $app->add(new Commands\Migrations\MigrateMakeCommand($c['migration-creator'], $c['composer']));
1571:
1572: $app->add(new Commands\Seeds\SeedCommand($c['resolver']));
1573: $app->add(new Commands\Seeds\SeederMakeCommand($c['filesystem'], $c['composer']));
1574:
1575: $app->add(new Commands\Migrations\EavToSqlCommand());
1576: $app->add(new Commands\GetOrphansCommand());
1577:
1578: return $app;
1579: };
1580:
1581: self::$oContainer = $container;
1582: }
1583: }
1584:
1585: /**
1586: * @return Container
1587: */
1588: public static function GetContainer()
1589: {
1590: // if (self::$oContainer === null) {
1591: self::CreateContainer();
1592: // }
1593: return self::$oContainer;
1594: }
1595:
1596: public static function CheckAccess(&$UserId)
1597: {
1598: if (self::accessCheckIsSkipped()) {
1599: return;
1600: }
1601: $bAccessDenied = true;
1602:
1603: $oAuthenticatedUser = self::getAuthenticatedUser();
1604:
1605: if ($UserId === null) {
1606: $iUserId = $oAuthenticatedUser->Id;
1607: } else {
1608: $iUserId = (int) $UserId;
1609:
1610: $iUserRole = $oAuthenticatedUser instanceof \Aurora\Modules\Core\Models\User ? $oAuthenticatedUser->Role : \Aurora\System\Enums\UserRole::Anonymous;
1611: switch ($iUserRole) {
1612: case (\Aurora\System\Enums\UserRole::SuperAdmin):
1613: // everything is allowed for SuperAdmin
1614: $UserId = $iUserId;
1615: $bAccessDenied = false;
1616: break;
1617: case (\Aurora\System\Enums\UserRole::TenantAdmin):
1618: // everything is allowed for TenantAdmin
1619: $oUser = \Aurora\Modules\Core\Module::getInstance()->GetUser($iUserId);
1620: if ($oUser instanceof \Aurora\Modules\Core\Models\User) {
1621: if ($oAuthenticatedUser->IdTenant === $oUser->IdTenant) {
1622: $UserId = $iUserId;
1623: $bAccessDenied = false;
1624: }
1625: }
1626: break;
1627: case (\Aurora\System\Enums\UserRole::NormalUser):
1628: // User identifier shoud be checked
1629: if ($iUserId === $oAuthenticatedUser->Id) {
1630: $UserId = $iUserId;
1631: $bAccessDenied = false;
1632: }
1633: break;
1634: case (\Aurora\System\Enums\UserRole::Customer):
1635: case (\Aurora\System\Enums\UserRole::Anonymous):
1636: // everything is forbidden for Customer and Anonymous users
1637: break;
1638: }
1639: if ($bAccessDenied) {
1640: throw new \Aurora\System\Exceptions\ApiException(\Aurora\System\Notifications::AccessDenied);
1641: }
1642: }
1643: }
1644: }
1645: