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: | |