1: <?php
2: /**
3: * This code is licensed under AGPLv3 license or Afterlogic Software License
4: * if commercial version of the product was purchased.
5: * For full statements of the licenses see LICENSE-AFTERLOGIC and LICENSE-AGPL3 files.
6: */
7:
8: namespace Aurora\Modules\Dav;
9:
10: /**
11: * Integrate SabreDav framework into Aurora platform.
12: *
13: * @license https://www.gnu.org/licenses/agpl-3.0.html AGPL-3.0
14: * @license https://afterlogic.com/products/common-licensing Afterlogic Software License
15: * @copyright Copyright (c) 2023, Afterlogic Corp.
16: *
17: * @property Settings $oModuleSettings
18: *
19: * @package Modules
20: */
21: class Module extends \Aurora\System\Module\AbstractModule
22: {
23: public $oManager = null;
24:
25: /**
26: * @return Module
27: */
28: public static function getInstance()
29: {
30: return parent::getInstance();
31: }
32:
33: /**
34: * @return Module
35: */
36: public static function Decorator()
37: {
38: return parent::Decorator();
39: }
40:
41: /**
42: * @return Settings
43: */
44: public function getModuleSettings()
45: {
46: return $this->oModuleSettings;
47: }
48:
49: /**
50: * @return Manager
51: */
52: public function getManager()
53: {
54: if ($this->oManager === null) {
55: $this->oManager = new Manager($this);
56: }
57:
58: return $this->oManager;
59: }
60:
61: public function GetModuleManager()
62: {
63: return parent::GetModuleManager();
64: }
65:
66: /***** private functions *****/
67: /**
68: * Initializes DAV Module.
69: *
70: * @ignore
71: */
72: public function init()
73: {
74: $this->AddEntry('dav', 'EntryDav');
75:
76: $this->subscribeEvent('Calendar::GetCalendars::after', array($this, 'onAfterGetCalendars'));
77: $this->subscribeEvent('MobileSync::GetInfo', array($this, 'onGetMobileSyncInfo'));
78: }
79:
80: /**
81: * Writes in $aParameters DAV server URL.
82: *
83: * @ignore
84: * @param array $aArgs
85: */
86: public function onAfterGetCalendars(&$aArgs, &$mResult)
87: {
88: if (isset($mResult) && $mResult !== false) {
89: $mResult['ServerUrl'] = $this->GetServerUrl();
90: }
91: }
92:
93: /**
94: * Writes in $aData information about DAV server.
95: *
96: * @ignore
97: * @param array $mResult
98: */
99: public function onGetMobileSyncInfo($aArgs, &$mResult)
100: {
101: $mResult['EnableDav'] = true;
102: $mResult['Dav']['Login'] = $this->GetLogin();
103: $mResult['Dav']['Server'] = $this->GetServerUrl();
104: $mResult['Dav']['PrincipalUrl'] = $this->GetPrincipalUrl();
105: }
106:
107: /**
108: * Creates tables required for module work. Called by event subscribe.
109: *
110: * @ignore
111: * @param array $aArgs Parameters
112: * @param mixed $mResult
113: */
114: public function onAfterCreateTables($aArgs, &$mResult)
115: {
116: // if ($mResult)
117: // {
118: // $mResult = self::Decorator()->CreateTables();
119: // }
120: }
121: /***** private functions *****/
122:
123: /***** public functions *****/
124:
125: /**
126: * @ignore
127: * @return void
128: */
129: public function EntryDav()
130: {
131: set_error_handler(function ($errno, $errstr, $errfile, $errline) {
132: throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
133: });
134:
135: @set_time_limit(3000);
136:
137: $sRequestUri = empty($_SERVER['REQUEST_URI']) ? '' : \trim($_SERVER['REQUEST_URI']);
138:
139: $oServer = \Afterlogic\DAV\Server::getInstance();
140: $oServer->setBaseUri($sRequestUri);
141:
142: \Afterlogic\DAV\Server::getInstance()->exec();
143: }
144:
145: /**
146: * Returns DAV client.
147: *
148: * @return \Aurora\Modules\Dav\Client|false
149: */
150: public function GetDavClient()
151: {
152: \Aurora\System\Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::NormalUser);
153:
154: return $this->getManager()->GetDAVClient(\Aurora\System\Api::getAuthenticatedUserId());
155: }
156:
157: /**
158: * Returns VCARD object.
159: *
160: * @param string|resource $Data
161: * @return \Sabre\VObject\Document
162: */
163: public function GetVCardObject($Data)
164: {
165: \Aurora\System\Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::NormalUser);
166:
167: return $this->getManager()->getVCardObject($Data);
168: }
169: /***** public functions *****/
170:
171: /***** public functions might be called with web API *****/
172: /**
173: * @apiDefine Dav Dav Module
174: * Integrate SabreDav framework into Aurora platform
175: */
176:
177: /**
178: * @api {post} ?/Api/ GetSettings
179: * @apiName GetSettings
180: * @apiGroup Dav
181: * @apiDescription Obtains list of module settings for authenticated user.
182: *
183: * @apiHeader {string} [Authorization] "Bearer " + Authentication token which was received as the result of Core.Login method.
184: * @apiHeaderExample {json} Header-Example:
185: * {
186: * "Authorization": "Bearer 32b2ecd4a4016fedc4abee880425b6b8"
187: * }
188: *
189: * @apiParam {string=Dav} Module Module name.
190: * @apiParam {string=GetSettings} Method Method name.
191: *
192: * @apiParamExample {json} Request-Example:
193: * {
194: * Module: 'Dav',
195: * Method: 'GetSettings'
196: * }
197: *
198: * @apiSuccess {object[]} Result Array of response objects.
199: * @apiSuccess {string} Result.Module Module name.
200: * @apiSuccess {string} Result.Method Method name.
201: * @apiSuccess {mixed} Result.Result Object in case of success, otherwise **false**.
202: * @apiSuccess {string} Result.Result.ExternalHostNameOfDAVServer External host name of DAV server.
203: * @apiSuccess {int} [Result.ErrorCode] Error code.
204: *
205: * @apiSuccessExample {json} Success response example:
206: * {
207: * Module: 'Dav',
208: * Method: 'GetSettings',
209: * Result: [{ExternalHostNameOfDAVServer: 'host_value'}]
210: * }
211: *
212: * @apiSuccessExample {json} Error response example:
213: * {
214: * Module: 'Dav',
215: * Method: 'GetSettings',
216: * Result: false,
217: * ErrorCode: 102
218: * }
219: */
220: /**
221: * Obtains list of module settings for authenticated user.
222: *
223: * @return array
224: */
225: public function GetSettings()
226: {
227: \Aurora\System\Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::Anonymous);
228:
229: return array(
230: 'ExternalHostNameOfDAVServer' => $this->GetServerUrl()
231: );
232: }
233:
234: /**
235: * @api {post} ?/Api/ UpdateSettings
236: * @apiName UpdateSettings
237: * @apiGroup Dav
238: * @apiDescription Updates module's settings - saves them to config.json file.
239: *
240: * @apiHeader {string} Authorization "Bearer " + Authentication token which was received as the result of Core.Login method.
241: * @apiHeaderExample {json} Header-Example:
242: * {
243: * "Authorization": "Bearer 32b2ecd4a4016fedc4abee880425b6b8"
244: * }
245: *
246: * @apiParam {string=Dav} Module Module name.
247: * @apiParam {string=UpdateSettings} Method Method name.
248: * @apiParam {string} Parameters JSON.stringified object <br>
249: * {<br>
250: * &emsp; **ExternalHostNameOfDAVServer** *string* External host name of DAV server.<br>
251: * }
252: *
253: * @apiParamExample {json} Request-Example:
254: * {
255: * Module: 'Dav',
256: * Method: 'UpdateSettings',
257: * Parameters: '{ ExternalHostNameOfDAVServer: "host_value" }'
258: * }
259: *
260: * @apiSuccess {object[]} Result Array of response objects.
261: * @apiSuccess {string} Result.Module Module name.
262: * @apiSuccess {string} Result.Method Method name.
263: * @apiSuccess {bool} Result.Result Indicates if settings were updated successfully.
264: * @apiSuccess {int} [Result.ErrorCode] Error code.
265: *
266: * @apiSuccessExample {json} Success response example:
267: * {
268: * Module: 'Dav',
269: * Method: 'UpdateSettings',
270: * Result: true
271: * }
272: *
273: * @apiSuccessExample {json} Error response example:
274: * {
275: * Module: 'Dav',
276: * Method: 'UpdateSettings',
277: * Result: false,
278: * ErrorCode: 102
279: * }
280: */
281: /**
282: * Updates module's settings - saves them to config.json file.
283: *
284: * @param string $ExternalHostNameOfDAVServer External host name of DAV server.
285: * @return bool
286: */
287: public function UpdateSettings($ExternalHostNameOfDAVServer)
288: {
289: \Aurora\System\Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::TenantAdmin);
290:
291: if (!empty($ExternalHostNameOfDAVServer)) {
292: $this->setConfig('ExternalHostNameOfDAVServer', $ExternalHostNameOfDAVServer);
293: $this->saveModuleConfig();
294: return true;
295: }
296:
297: return false;
298: }
299:
300: /**
301: * @api {post} ?/Api/ GetServerUrl
302: * @apiName GetServerUrl
303: * @apiGroup Dav
304: * @apiDescription Returns DAV server URL.
305: *
306: * @apiParam {string=Dav} Module Module name.
307: * @apiParam {string=GetServerUrl} Method Method name.
308: *
309: * @apiParamExample {json} Request-Example:
310: * {
311: * Module: 'Dav',
312: * Method: 'GetServerUrl'
313: * }
314: *
315: * @apiSuccess {object[]} Result Array of response objects.
316: * @apiSuccess {string} Result.Module Module name.
317: * @apiSuccess {string} Result.Method Method name.
318: * @apiSuccess {mixed} Result.Result DAV server URL in case of success, otherwise **false**.
319: * @apiSuccess {int} [Result.ErrorCode] Error code.
320: *
321: * @apiSuccessExample {json} Success response example:
322: * {
323: * Module: 'Dav',
324: * Method: 'GetServerUrl',
325: * Result: 'url_value'
326: * }
327: *
328: * @apiSuccessExample {json} Error response example:
329: * {
330: * Module: 'Dav',
331: * Method: 'GetServerUrl',
332: * Result: false,
333: * ErrorCode: 102
334: * }
335: */
336: /**
337: * Returns DAV server URL.
338: *
339: * @return string
340: */
341: public function GetServerUrl()
342: {
343: \Aurora\System\Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::Anonymous);
344:
345: return $this->getManager()->getServerUrl();
346: }
347:
348: /**
349: * @api {post} ?/Api/ GetServerHost
350: * @apiName GetServerHost
351: * @apiGroup Dav
352: * @apiDescription Returns DAV server host.
353: *
354: * @apiParam {string=Dav} Module Module name.
355: * @apiParam {string=GetServerHost} Method Method name.
356: *
357: * @apiParamExample {json} Request-Example:
358: * {
359: * Module: 'Dav',
360: * Method: 'GetServerHost'
361: * }
362: *
363: * @apiSuccess {object[]} Result Array of response objects.
364: * @apiSuccess {string} Result.Module Module name.
365: * @apiSuccess {string} Result.Method Method name.
366: * @apiSuccess {mixed} Result.Result DAV server host in case of success, otherwise **false**.
367: * @apiSuccess {int} [Result.ErrorCode] Error code.
368: *
369: * @apiSuccessExample {json} Success response example:
370: * {
371: * Module: 'Dav',
372: * Method: 'GetServerHost',
373: * Result: 'host_value'
374: * }
375: *
376: * @apiSuccessExample {json} Error response example:
377: * {
378: * Module: 'Dav',
379: * Method: 'GetServerHost',
380: * Result: false,
381: * ErrorCode: 102
382: * }
383: */
384: /**
385: * Returns DAV server host.
386: *
387: * @return string
388: */
389: public function GetServerHost()
390: {
391: \Aurora\System\Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::Anonymous);
392:
393: return $this->getManager()->getServerHost();
394: }
395:
396: /**
397: * @api {post} ?/Api/ GetServerPort
398: * @apiName GetServerPort
399: * @apiGroup Dav
400: * @apiDescription Returns DAV server port.
401: *
402: * @apiParam {string=Dav} Module Module name.
403: * @apiParam {string=GetServerPort} Method Method name.
404: *
405: * @apiParamExample {json} Request-Example:
406: * {
407: * Module: 'Dav',
408: * Method: 'GetServerPort'
409: * }
410: *
411: * @apiSuccess {object[]} Result Array of response objects.
412: * @apiSuccess {string} Result.Module Module name.
413: * @apiSuccess {string} Result.Method Method name.
414: * @apiSuccess {mixed} Result.Result DAV server post in case of success, otherwise **false**.
415: * @apiSuccess {int} [Result.ErrorCode] Error code.
416: *
417: * @apiSuccessExample {json} Success response example:
418: * {
419: * Module: 'Dav',
420: * Method: 'GetServerPort',
421: * Result: 'port_value'
422: * }
423: *
424: * @apiSuccessExample {json} Error response example:
425: * {
426: * Module: 'Dav',
427: * Method: 'GetServerPort',
428: * Result: false,
429: * ErrorCode: 102
430: * }
431: */
432: /**
433: * Returns DAV server port.
434: *
435: * @return int
436: */
437: public function GetServerPort()
438: {
439: \Aurora\System\Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::Anonymous);
440:
441: return $this->getManager()->getServerPort();
442: }
443:
444: /**
445: * Returns DAV principal URL.
446: *
447: * @return string
448: */
449: public function GetPrincipalUrl()
450: {
451: \Aurora\System\Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::NormalUser);
452: $mResult = null;
453:
454: $oUser = \Aurora\System\Api::getAuthenticatedUser();
455: if ($oUser) {
456: $mResult = $this->getManager()->getPrincipalUrl($oUser->PublicId);
457: }
458: return $mResult;
459: }
460:
461: /**
462: * Returns **true** if connection to DAV should use SSL.
463: *
464: * @return bool
465: */
466: public function IsSsl()
467: {
468: \Aurora\System\Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::NormalUser);
469:
470: return $this->getManager()->isSsl();
471: }
472:
473: /**
474: * Returns DAV login.
475: *
476: * @return string
477: */
478: public function GetLogin()
479: {
480: \Aurora\System\Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::NormalUser);
481: $mResult = null;
482: $oEntity = \Aurora\Modules\Core\Models\User::find(\Aurora\System\Api::getAuthenticatedUserId());
483: if ($oEntity) {
484: $mResult = $oEntity->PublicId;
485: }
486:
487: return $mResult;
488: }
489:
490: /**
491: * Returns **true** if mobile sync enabled.
492: *
493: * @return bool
494: */
495: public function IsMobileSyncEnabled()
496: {
497: \Aurora\System\Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::NormalUser);
498:
499: return $this->getManager()->isMobileSyncEnabled();
500: }
501:
502: /**
503: * Sets mobile sync enabled/disabled.
504: *
505: * @param bool $MobileSyncEnable Indicates if mobile sync should be enabled.
506: * @return bool
507: */
508: public function SetMobileSyncEnable($MobileSyncEnable)
509: {
510: \Aurora\System\Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::NormalUser);
511:
512: $oMobileSyncModule = \Aurora\System\Api::GetModule('MobileSync');
513: $oMobileSyncModule->setConfig('Disabled', !$MobileSyncEnable);
514: return $oMobileSyncModule->saveModuleConfig();
515: }
516:
517: /**
518: * Tests connection and returns **true** if connection was successful.
519: *
520: * @return bool
521: */
522: public function TestConnection()
523: {
524: \Aurora\System\Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::NormalUser);
525:
526: return $this->getManager()->testConnection(
527: \Aurora\System\Api::getAuthenticatedUserId()
528: );
529: }
530:
531: /**
532: * Deletes principal.
533: *
534: * @return bool
535: */
536: public function DeletePrincipal()
537: {
538: \Aurora\System\Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::NormalUser);
539:
540: return $this->getManager()->deletePrincipal(
541: \Aurora\System\Api::getAuthenticatedUserId()
542: );
543: }
544:
545: /**
546: * Returns public user.
547: *
548: * @return string
549: */
550: public function GetPublicUser()
551: {
552: \Aurora\System\Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::NormalUser);
553:
554: return \Afterlogic\DAV\Constants::DAV_PUBLIC_PRINCIPAL;
555: }
556:
557: /**
558: *
559: */
560: public function Login($Login, $Password)
561: {
562: \Aurora\System\Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::Anonymous);
563:
564: $oTenant = \Aurora\System\Api::getTenantByWebDomain();
565:
566: if (!$this->oModuleSettings->UseFullEmailForLogin) {
567: $Login = $Login . '@' . $this->oModuleSettings->DomainForLoginWithoutEmail;
568: }
569:
570: $mResult = \Aurora\Modules\Core\Module::Decorator()->Login($Login, $Password, '', false);
571:
572: if (is_array($mResult) && isset($mResult[\Aurora\System\Application::AUTH_TOKEN_KEY])) {
573: $sAuthToken = $mResult[\Aurora\System\Application::AUTH_TOKEN_KEY];
574:
575: //this will store user data in static variable of Api class for later usage
576: $oUser = \Aurora\System\Api::getAuthenticatedUser($sAuthToken);
577:
578: return array(
579: \Aurora\System\Application::AUTH_TOKEN_KEY => $sAuthToken
580: );
581: }
582:
583: \Aurora\System\Api::LogEvent('login-failed: ' . $Login, self::GetName());
584: if (!is_writable(\Aurora\System\Api::DataPath())) {
585: throw new \Aurora\System\Exceptions\ApiException(\Aurora\System\Notifications::SystemNotConfigured);
586: }
587: throw new \Aurora\System\Exceptions\ApiException(\Aurora\System\Notifications::AuthError);
588: }
589: /***** public functions might be called with web API *****/
590: }
591: