1: | <?php |
2: | |
3: | |
4: | |
5: | |
6: | |
7: | namespace Aurora\Modules\SharedContacts; |
8: | |
9: | use Afterlogic\DAV\Constants; |
10: | use Aurora\Api; |
11: | use Aurora\Modules\Contacts\Enums\Access; |
12: | use Aurora\Modules\Contacts\Enums\SortField; |
13: | use Aurora\Modules\Contacts\Enums\StorageType; |
14: | use Aurora\Modules\Contacts\Models\AddressBook; |
15: | use Aurora\Modules\Contacts\Models\Contact; |
16: | use Aurora\Modules\Contacts\Module as ContactsModule; |
17: | use Aurora\Modules\Core\Models\Group; |
18: | use Aurora\Modules\Core\Models\User; |
19: | use Aurora\System\Enums\UserRole; |
20: | use Aurora\System\Exceptions\InvalidArgumentException; |
21: | use Aurora\System\Notifications; |
22: | use Illuminate\Database\Capsule\Manager as Capsule; |
23: | use Sabre\DAV\UUIDUtil; |
24: | use Aurora\Modules\Core\Module as CoreModule; |
25: | |
26: | |
27: | |
28: | |
29: | |
30: | |
31: | |
32: | class Module extends \Aurora\System\Module\AbstractModule |
33: | { |
34: | protected static $iStorageOrder = 10; |
35: | |
36: | protected $oBeforeDeleteUser = null; |
37: | |
38: | public function init() |
39: | { |
40: | $this->subscribeEvent('Contacts::GetStorages', array($this, 'onGetStorages')); |
41: | $this->subscribeEvent('Contacts::PrepareFiltersFromStorage', array($this, 'prepareFiltersFromStorage')); |
42: | |
43: | $this->subscribeEvent('Contacts::UpdateSharedContacts::after', array($this, 'onAfterUpdateSharedContacts')); |
44: | |
45: | $this->subscribeEvent('Contacts::CheckAccessToObject::after', array($this, 'onAfterCheckAccessToObject')); |
46: | $this->subscribeEvent('Contacts::GetContactSuggestions', array($this, 'onGetContactSuggestions')); |
47: | $this->subscribeEvent('Contacts::GetAddressBooks::after', array($this, 'onAfterGetAddressBooks'), 1000); |
48: | $this->subscribeEvent('Contacts::PopulateContactModel', array($this, 'onPopulateContactModel')); |
49: | |
50: | $this->subscribeEvent('Core::AddUsersToGroup::after', [$this, 'onAfterAddUsersToGroup']); |
51: | $this->subscribeEvent('Core::RemoveUsersFromGroup::after', [$this, 'onAfterRemoveUsersFromGroup']); |
52: | $this->subscribeEvent('Core::CreateUser::after', [$this, 'onAfterCreateUser']); |
53: | $this->subscribeEvent('Core::UpdateUser::after', [$this, 'onAfterUpdateUser']); |
54: | $this->subscribeEvent('Core::DeleteUser::before', [$this, 'onBeforeDeleteUser']); |
55: | $this->subscribeEvent('Core::DeleteUser::after', [$this, 'onAfterDeleteUser']); |
56: | $this->subscribeEvent('Core::DeleteGroup::after', [$this, 'onAfterDeleteGroup']); |
57: | } |
58: | |
59: | public function GetAddressbooks($UserId) |
60: | { |
61: | $mResult = []; |
62: | |
63: | Api::checkUserRoleIsAtLeast(UserRole::NormalUser); |
64: | Api::CheckAccess($UserId); |
65: | |
66: | $dBPrefix = Api::GetSettings()->DBPrefix; |
67: | $stmt = Api::GetPDO()->prepare(" |
68: | select ab.*, sab.access, sab.group_id, ca.Id as addressbook_id, cu.Id as UserId from " . $dBPrefix . "adav_shared_addressbooks sab |
69: | left join " . $dBPrefix . "adav_addressbooks ab on sab.addressbook_id = ab.id |
70: | left join " . $dBPrefix . "core_users cu on ab.principaluri = CONCAT('principals/', cu.PublicId) |
71: | left join " . $dBPrefix . "contacts_addressbooks ca on ca.UUID = ab.uri |
72: | where sab.principaluri = ? |
73: | "); |
74: | |
75: | $principalUri = Constants::PRINCIPALS_PREFIX . Api::getUserPublicIdById($UserId); |
76: | $stmt->execute([ |
77: | $principalUri |
78: | ]); |
79: | |
80: | $abooks = $stmt->fetchAll(\PDO::FETCH_ASSOC); |
81: | |
82: | foreach ($abooks as $abook) { |
83: | if ($abook['principaluri'] !== $principalUri) { |
84: | if (isset($abook['addressbook_id'])) { |
85: | $storage = StorageType::Shared . '-' . $abook['UserId'] . '-' . $abook['addressbook_id']; |
86: | } else { |
87: | $storage = StorageType::Shared . '-' . $abook['UserId'] . '-' . StorageType::Personal; |
88: | } |
89: | |
90: | if (count($mResult) > 0) { |
91: | foreach ($mResult as $key => $val) { |
92: | if ($val['Id'] === $storage) { |
93: | if ($val['GroupId'] != 0) { |
94: | if ($abook['access'] !== Access::Read) { |
95: | if ($val['Access'] > (int) $abook['access'] || (int) $abook['access'] === Access::NoAccess) { |
96: | $mResult[$key]['Access'] = (int) $abook['access']; |
97: | } |
98: | } elseif ($val['Access'] !== Access::Write) { |
99: | $mResult[$key]['Access'] = (int) $abook['access']; |
100: | } |
101: | } |
102: | continue 2; |
103: | } |
104: | } |
105: | } |
106: | |
107: | $prevState = Api::skipCheckUserRole(true); |
108: | $ctag = ContactsModule::Decorator()->GetCTag($abook['UserId'], $storage); |
109: | Api::skipCheckUserRole($prevState); |
110: | |
111: | $mResult[] = [ |
112: | 'Id' => $storage, |
113: | 'EntityId' => isset($abook['addressbook_id']) ? (int) $abook['addressbook_id'] : null, |
114: | 'CTag' => $ctag, |
115: | 'Display' => true, |
116: | 'Order' => 1, |
117: | 'DisplayName' => $abook['displayname'] . ' (' . basename($abook['principaluri']) . ')', |
118: | 'Shared' => true, |
119: | 'Access' => (int) $abook['access'], |
120: | 'Owner' => basename($abook['principaluri']), |
121: | 'GroupId' => (int) $abook['group_id'] |
122: | ]; |
123: | } |
124: | } |
125: | |
126: | return array_filter($mResult, function ($item) { |
127: | return ($item['Access'] !== Access::NoAccess); |
128: | }); |
129: | } |
130: | |
131: | public function GetSharesForAddressbook($UserId, $Id) |
132: | { |
133: | Api::checkUserRoleIsAtLeast(UserRole::NormalUser); |
134: | Api::CheckAccess($UserId); |
135: | |
136: | $aResult = []; |
137: | |
138: | $shares = $this->_getSharesForAddressbook($UserId, $Id); |
139: | if (count($shares) > 0) { |
140: | $oUser = Api::getUserById($UserId); |
141: | $groups = []; |
142: | foreach ($shares as $share) { |
143: | if ($share['group_id'] != 0) { |
144: | if (!in_array($share['group_id'], $groups)) { |
145: | $oGroup = CoreModule::Decorator()->GetGroup($oUser->IdTenant, (int) $share['group_id']); |
146: | if ($oGroup) { |
147: | $groups[] = $share['group_id']; |
148: | $aResult[] = [ |
149: | 'PublicId' => $oGroup->getName(), |
150: | 'Access' => (int) $share['access'], |
151: | 'IsGroup' => true, |
152: | 'IsAll' => !!$oGroup->IsAll, |
153: | 'GroupId' => (int) $share['group_id'] |
154: | ]; |
155: | } |
156: | } |
157: | } else { |
158: | $aResult[] = [ |
159: | 'PublicId' => basename($share['principaluri']), |
160: | 'Access' => (int) $share['access'] |
161: | ]; |
162: | } |
163: | } |
164: | } |
165: | |
166: | return $aResult; |
167: | } |
168: | |
169: | protected function _getSharesForAddressbook($iUserId, $abookComplexId) |
170: | { |
171: | $dBPrefix = Api::GetSettings()->DBPrefix; |
172: | $stmt = Api::GetPDO()->prepare(" |
173: | select * from (select sab.*, CASE WHEN ca.Id is null THEN ? ELSE CONCAT(?, ca.Id) END as storage |
174: | from " . $dBPrefix . "adav_shared_addressbooks sab |
175: | left join " . $dBPrefix . "adav_addressbooks ab on sab.addressbook_id = ab.id |
176: | left join " . $dBPrefix . "core_users cu on ab.principaluri = CONCAT('principals/', cu.PublicId) |
177: | left join " . $dBPrefix . "contacts_addressbooks ca on ca.UUID = ab.uri |
178: | where cu.Id = ?) as sub_select where storage = ? |
179: | "); |
180: | |
181: | $stmt->execute([ |
182: | StorageType::Personal, |
183: | StorageType::AddressBook . '-', |
184: | $iUserId, |
185: | $abookComplexId |
186: | ]); |
187: | |
188: | return $stmt->fetchAll(\PDO::FETCH_ASSOC); |
189: | } |
190: | |
191: | protected function getShareForAddressbook($iUserId, $abookComplexId, $principalUri, $groupId = 0) |
192: | { |
193: | $dBPrefix = Api::GetSettings()->DBPrefix; |
194: | $stmt = Api::GetPDO()->prepare(" |
195: | select * from (select sab.*, CASE WHEN ca.Id is null THEN ? ELSE CONCAT(?, ca.Id) END as storage |
196: | from " . $dBPrefix . "adav_shared_addressbooks sab |
197: | left join " . $dBPrefix . "adav_addressbooks ab on sab.addressbook_id = ab.id |
198: | left join " . $dBPrefix . "core_users cu on ab.principaluri = CONCAT('principals/', cu.PublicId) |
199: | left join " . $dBPrefix . "contacts_addressbooks ca on ca.UUID = ab.uri |
200: | where cu.Id = ? and sab.principaluri = ? and sab.group_id = ?) as sub_select where storage = ? |
201: | "); |
202: | |
203: | $stmt->execute([ |
204: | StorageType::Personal, |
205: | StorageType::AddressBook . '-', |
206: | $iUserId, |
207: | $principalUri, |
208: | $groupId, |
209: | $abookComplexId |
210: | ]); |
211: | |
212: | return $stmt->fetch(\PDO::FETCH_ASSOC); |
213: | } |
214: | |
215: | protected function deleteShareByPublicIds($userId, $abookComplexId, $publicIds) |
216: | { |
217: | $dBPrefix = Api::GetSettings()->DBPrefix; |
218: | |
219: | $sharesIds = []; |
220: | foreach ($publicIds as $publicId) { |
221: | $publicId = \json_decode($publicId); |
222: | $share = $this->getShareForAddressbook($userId, $abookComplexId, Constants::PRINCIPALS_PREFIX . $publicId[0], $publicId[1]); |
223: | if ($share) { |
224: | $sharesIds[] = $share['id']; |
225: | } |
226: | } |
227: | if (count($sharesIds) > 0) { |
228: | $stmt = Api::GetPDO()->prepare("delete from " . $dBPrefix . "adav_shared_addressbooks where id in (" . \implode(',', $sharesIds) . ")"); |
229: | $stmt->execute(); |
230: | } |
231: | } |
232: | |
233: | protected function getAddressbookByComplexId($iUserId, $abookComplexId) |
234: | { |
235: | $mResult = false; |
236: | |
237: | $dBPrefix = Api::GetSettings()->DBPrefix; |
238: | |
239: | $abookId = \explode('-', $abookComplexId); |
240: | |
241: | if (count($abookId) === 1 && $abookId[0] === StorageType::Personal) { |
242: | $abookId[] = StorageType::Personal; |
243: | } |
244: | |
245: | if (count($abookId) > 1) { |
246: | if (count($abookId) < 3) { |
247: | $abookId[2] = $abookId[1]; |
248: | } |
249: | |
250: | $iUserId = $abookId[0] === StorageType::Shared ? $abookId[1] : $iUserId; |
251: | if ($abookId[2] === StorageType::Personal) { |
252: | $addressbookUri = Constants::ADDRESSBOOK_DEFAULT_NAME; |
253: | } else { |
254: | $abook = AddressBook::where('UserId', $iUserId)->where('Id', $abookId[2])->first(); |
255: | if ($abook) { |
256: | $addressbookUri = $abook->UUID; |
257: | } |
258: | } |
259: | $userPublicId = Api::getUserPublicIdById($iUserId); |
260: | if (!empty($addressbookUri) && $userPublicId) { |
261: | $stmt = Api::GetPDO()->prepare("select * from " . $dBPrefix . "adav_addressbooks where principaluri = ? and uri = ?"); |
262: | $stmt->execute([Constants::PRINCIPALS_PREFIX . $userPublicId, $addressbookUri]); |
263: | $mResult = $stmt->fetch(\PDO::FETCH_ASSOC); |
264: | } |
265: | } |
266: | |
267: | return $mResult; |
268: | } |
269: | |
270: | protected function createShare($iUserId, $abookComplexId, $share) |
271: | { |
272: | $dBPrefix = Api::GetSettings()->DBPrefix; |
273: | |
274: | $book = $this->getAddressbookByComplexId($iUserId, $abookComplexId); |
275: | if ($book) { |
276: | $shareePublicId = $share['PublicId']; |
277: | $access = $share['Access']; |
278: | $groupId = $share['GroupId']; |
279: | $stmt = Api::GetPDO()->prepare("insert into " . $dBPrefix . "adav_shared_addressbooks |
280: | (principaluri, access, addressbook_id, addressbookuri, group_id) |
281: | values (?, ?, ?, ?, ?)"); |
282: | $stmt->execute([Constants::PRINCIPALS_PREFIX . $shareePublicId, $access, $book['id'], UUIDUtil::getUUID(), $groupId]); |
283: | } |
284: | } |
285: | |
286: | protected function updateShare($iUserId, $abookComplexId, $share) |
287: | { |
288: | $dBPrefix = Api::GetSettings()->DBPrefix; |
289: | $book = $this->getAddressbookByComplexId($iUserId, $abookComplexId); |
290: | if ($book) { |
291: | $shareePublicId = $share['PublicId']; |
292: | $access = $share['Access']; |
293: | $groupId = $share['GroupId']; |
294: | $stmt = Api::GetPDO()->prepare("update " . $dBPrefix . "adav_shared_addressbooks |
295: | set access = ? where principaluri = ? and addressbook_id = ? and group_id = ?"); |
296: | $stmt->execute([$access, Constants::PRINCIPALS_PREFIX . $shareePublicId, $book['id'], $groupId]); |
297: | } |
298: | } |
299: | |
300: | public function onGetStorages(&$aStorages) |
301: | { |
302: | $aStorages[self::$iStorageOrder] = StorageType::Shared; |
303: | } |
304: | |
305: | public function prepareFiltersFromStorage(&$aArgs, &$mResult) |
306: | { |
307: | if (!isset($mResult)) { |
308: | $mResult = \Aurora\Modules\Contacts\Models\Contact::query(); |
309: | } |
310: | if (isset($aArgs['Storage']) && ($aArgs['Storage'] === StorageType::Shared || $aArgs['Storage'] === StorageType::All)) { |
311: | $aArgs['IsValid'] = true; |
312: | |
313: | $oUser = \Aurora\System\Api::getAuthenticatedUser(); |
314: | $mResult = $mResult->orWhere(function ($query) use ($oUser, $aArgs) { |
315: | $query = $query->where('IdTenant', $oUser->IdTenant) |
316: | ->where('Storage', StorageType::Shared) |
317: | ->where( |
318: | function ($query) { |
319: | $query->where('Auto', false)->orWhereNull('Auto'); |
320: | } |
321: | ); |
322: | |
323: | |
324: | |
325: | |
326: | }); |
327: | } else { |
328: | $storageArray = \explode('-', $aArgs['Storage']); |
329: | if (count($storageArray) === 3 && $storageArray[0] === StorageType::Shared) { |
330: | $aArgs['IsValid'] = true; |
331: | $storage = $storageArray[2]; |
332: | |
333: | $iAddressBookId = 0; |
334: | if (isset($storage)) { |
335: | if ($storage === StorageType::Personal) { |
336: | $sStorage = StorageType::Personal; |
337: | } else { |
338: | $iAddressBookId = (int) $storage; |
339: | $sStorage = StorageType::AddressBook; |
340: | } |
341: | |
342: | $mResult = $mResult->orWhere(function ($query) use ($storageArray, $sStorage, $iAddressBookId, $aArgs) { |
343: | $query = $query->where('IdUser', $storageArray[1]) |
344: | ->where('Storage', $sStorage) |
345: | ->where( |
346: | function ($query) { |
347: | $query->where('Auto', false)->orWhereNull('Auto'); |
348: | } |
349: | ); |
350: | |
351: | if ($iAddressBookId > 0) { |
352: | $query = $query->where('AddressBookId', $iAddressBookId); |
353: | } |
354: | |
355: | |
356: | |
357: | }); |
358: | } |
359: | } |
360: | } |
361: | |
362: | if (isset($aArgs['Storage']) && $aArgs['Storage'] === StorageType::All) { |
363: | $aBooks = $this->GetAddressbooks($aArgs['UserId']); |
364: | |
365: | if (is_array($aBooks) && count($aBooks) > 0) { |
366: | $aArgs['IsValid'] = true; |
367: | |
368: | $aWhen = []; |
369: | foreach ($aBooks as $aBook) { |
370: | $storageArray = \explode('-', $aBook['Id']); |
371: | $storage = $storageArray[2]; |
372: | |
373: | $iAddressBookId = 0; |
374: | if (isset($storage)) { |
375: | if ($storage !== StorageType::Personal) { |
376: | $iAddressBookId = (int) $storage; |
377: | $storage = StorageType::AddressBook; |
378: | } |
379: | |
380: | $mResult = $mResult->orWhere(function ($query) use ($storageArray, $storage, $iAddressBookId, $aArgs, $aBook, &$aWhen) { |
381: | $query = $query->where('IdUser', $storageArray[1]) |
382: | ->where('Storage', $storage) |
383: | ->where( |
384: | function ($query) { |
385: | $query->where('Auto', false)->orWhereNull('Auto'); |
386: | } |
387: | ); |
388: | |
389: | if ($iAddressBookId > 0) { |
390: | $query = $query->where('AddressBookId', $iAddressBookId); |
391: | } |
392: | |
393: | |
394: | |
395: | if ($iAddressBookId > 0) { |
396: | $aWhen[] = "WHEN IdUser = ". $storageArray[1] . " AND Storage = '" . $storage . "' AND AddressBookId = " . $iAddressBookId . " THEN '" . $aBook['Id'] . "'"; |
397: | } else { |
398: | $aWhen[] = "WHEN IdUser = ". $storageArray[1] . " AND Storage = '" . $storage . "' THEN '" . $aBook['Id'] . "'"; |
399: | } |
400: | }); |
401: | } |
402: | } |
403: | $rawSql = Capsule::connection()->raw("*, CASE " . \implode("\r\n", $aWhen) . " ELSE Storage END as Storage"); |
404: | $mResult->addSelect($rawSql); |
405: | } |
406: | } |
407: | } |
408: | |
409: | public function onAfterUpdateSharedContacts($aArgs, &$mResult) |
410: | { |
411: | $oContacts = \Aurora\Modules\Contacts\Module::Decorator(); |
412: | $aUUIDs = isset($aArgs['UUIDs']) ? $aArgs['UUIDs'] : []; |
413: | |
414: | foreach ($aUUIDs as $sUUID) { |
415: | $oContact = $oContacts->GetContact($sUUID, $aArgs['UserId']); |
416: | if ($oContact instanceof Contact) { |
417: | $sOldStorage = $oContact->getStorageWithId(); |
418: | $iUserId = -1; |
419: | |
420: | if ($oContact->Storage === StorageType::Shared) { |
421: | $oContact->Storage = StorageType::Personal; |
422: | $iUserId = $oContact->IdTenant; |
423: | $oContact->IdUser = $aArgs['UserId']; |
424: | } elseif ($oContact->Storage === StorageType::Personal) { |
425: | $oContact->Storage = StorageType::Shared; |
426: | $iUserId = $oContact->IdUser; |
427: | } |
428: | |
429: | \Aurora\Modules\Contacts\Module::getInstance()->getManager()->updateCTag($iUserId, $sOldStorage); |
430: | $mResult = $oContacts->UpdateContact($aArgs['UserId'], $oContact->toArray()); |
431: | } |
432: | } |
433: | } |
434: | |
435: | public function onAfterCheckAccessToObject(&$aArgs, &$mResult) |
436: | { |
437: | $oUser = $aArgs['User']; |
438: | $oContact = isset($aArgs['Contact']) ? $aArgs['Contact'] : null; |
439: | $Access = isset($aArgs['Access']) ? (int) $aArgs['Access'] : null; |
440: | |
441: | if ($oContact instanceof \Aurora\Modules\Contacts\Models\Contact) { |
442: | if ($oContact->IdUser === $oUser->Id) { |
443: | $mResult = true; |
444: | return true; |
445: | } |
446: | if ($oContact->Storage === StorageType::Shared) { |
447: | if ($oUser->Role !== \Aurora\System\Enums\UserRole::SuperAdmin && $oUser->IdTenant !== $oContact->IdTenant) { |
448: | $mResult = false; |
449: | } else { |
450: | $mResult = true; |
451: | } |
452: | } elseif ($oContact->Storage === StorageType::Personal || $oContact->Storage === StorageType::AddressBook) { |
453: | $dBPrefix = Api::GetSettings()->DBPrefix; |
454: | $sql = "select ab.*, sab.access, ca.Id as addressbook_id, cu.Id as UserId from " . $dBPrefix . "adav_shared_addressbooks sab |
455: | left join " . $dBPrefix . "adav_addressbooks ab on sab.addressbook_id = ab.id |
456: | left join " . $dBPrefix . "core_users cu on ab.principaluri = CONCAT('principals/', cu.PublicId) |
457: | left join " . $dBPrefix . "contacts_addressbooks ca on ca.UUID = ab.uri |
458: | where sab.principaluri = ? and cu.Id = ?"; |
459: | if ($oContact->Storage === StorageType::AddressBook) { |
460: | $sql .= ' and ca.Id = ' . $oContact->AddressBookId; |
461: | } elseif ($oContact->Storage === StorageType::Personal) { |
462: | $sql .= ' and ca.Id is null'; |
463: | } |
464: | |
465: | $stmt = Api::GetPDO()->prepare($sql); |
466: | |
467: | $stmt->execute([ |
468: | Constants::PRINCIPALS_PREFIX . $oUser->PublicId, |
469: | $oContact->IdUser |
470: | ]); |
471: | |
472: | $abook = $stmt->fetch(\PDO::FETCH_ASSOC); |
473: | if ($abook) { |
474: | if ((int) $abook['access'] === Access::NoAccess) { |
475: | $mResult = false; |
476: | } elseif (isset($Access)) { |
477: | if ($Access === (int) $abook['access'] && $Access === Access::Write) { |
478: | $mResult = true; |
479: | } else { |
480: | $mResult = false; |
481: | } |
482: | } else { |
483: | $mResult = true; |
484: | } |
485: | |
486: | return true; |
487: | } |
488: | } |
489: | } |
490: | } |
491: | |
492: | public function onGetContactSuggestions(&$aArgs, &$mResult) |
493: | { |
494: | if ($aArgs['Storage'] === 'all' || $aArgs['Storage'] === StorageType::Shared) { |
495: | $mResult[StorageType::Shared] = \Aurora\Modules\Contacts\Module::Decorator()->GetContacts( |
496: | $aArgs['UserId'], |
497: | StorageType::Shared, |
498: | 0, |
499: | $aArgs['Limit'], |
500: | $aArgs['SortField'], |
501: | $aArgs['SortOrder'], |
502: | $aArgs['Search'] |
503: | ); |
504: | } |
505: | } |
506: | |
507: | public function onAfterGetAddressBooks(&$aArgs, &$mResult) |
508: | { |
509: | if (!is_array($mResult)) { |
510: | $mResult = []; |
511: | } |
512: | foreach ($mResult as $key => $abook) { |
513: | $mResult[$key]['Shares'] = self::Decorator()->GetSharesForAddressbook($aArgs['UserId'], $abook['Id']); |
514: | } |
515: | $mResult = array_merge( |
516: | $mResult, |
517: | $this->GetAddressbooks($aArgs['UserId']) |
518: | ); |
519: | } |
520: | |
521: | public function onPopulateContactModel(&$oContact, &$mResult) |
522: | { |
523: | if ($oContact instanceof Contact) { |
524: | $aStorageParts = \explode('-', $oContact->Storage); |
525: | if (is_array($aStorageParts) && count($aStorageParts) === 3 && $aStorageParts[0] === StorageType::Shared) { |
526: | $abooks = $this->GetAddressbooks($oContact->IdUser); |
527: | foreach ($abooks as $abook) { |
528: | if ($abook['Id'] === $oContact->Storage) { |
529: | if ($aStorageParts[2] === StorageType::Personal) { |
530: | $oContact->Storage = StorageType::Personal; |
531: | } else { |
532: | $oContact->Storage = StorageType::AddressBook; |
533: | $oContact->AddressBookId = (int) $aStorageParts[2]; |
534: | } |
535: | |
536: | $oContact->IdUser = (int) $aStorageParts[1]; |
537: | break; |
538: | } |
539: | } |
540: | } |
541: | } |
542: | } |
543: | |
544: | public function UpdateAddressBookShare($UserId, $Id, $Shares) |
545: | { |
546: | $mResult = true; |
547: | |
548: | Api::checkUserRoleIsAtLeast(UserRole::NormalUser); |
549: | Api::CheckAccess($UserId); |
550: | |
551: | if (!isset($Id) || !is_array($Shares)) { |
552: | throw new InvalidArgumentException("", Notifications::InvalidInputParameter); |
553: | } |
554: | |
555: | try { |
556: | $oUser = Api::getUserById($UserId); |
557: | $currentABookShares = $this->_getSharesForAddressbook($UserId, $Id); |
558: | |
559: | $newABookShares = []; |
560: | foreach ($Shares as $share) { |
561: | if (isset($share['GroupId'])) { |
562: | $aUsers = CoreModule::Decorator()->GetGroupUsers($oUser->IdTenant, (int) $share['GroupId']); |
563: | foreach ($aUsers as $aUser) { |
564: | $newABookShares[] = [ |
565: | 'PublicId' => $aUser['PublicId'], |
566: | 'Access' => (int) $share['Access'], |
567: | 'GroupId' => (int) $share['GroupId'], |
568: | ]; |
569: | } |
570: | } else { |
571: | $share['GroupId'] = 0; |
572: | $newABookShares[] = $share; |
573: | } |
574: | } |
575: | |
576: | $currentShares = array_map(function ($share) { |
577: | return \json_encode([ |
578: | basename($share['principaluri']), |
579: | $share['group_id'] |
580: | ]); |
581: | }, $currentABookShares); |
582: | |
583: | $newShares = array_map(function ($share) { |
584: | return \json_encode([ |
585: | $share['PublicId'], |
586: | $share['GroupId'] |
587: | ]); |
588: | }, $newABookShares); |
589: | |
590: | $sharesToDelete = array_diff($currentShares, $newShares); |
591: | $sharesToCreate = array_diff($newShares, $currentShares); |
592: | $sharesToUpdate = array_intersect($currentShares, $newShares); |
593: | |
594: | if (count($sharesToDelete) > 0) { |
595: | $this->deleteShareByPublicIds($UserId, $Id, $sharesToDelete); |
596: | } |
597: | |
598: | foreach ($newABookShares as $share) { |
599: | $sharePublicIdAndGroupId = \json_encode([ |
600: | $share['PublicId'], |
601: | $share['GroupId'] |
602: | ]); |
603: | if (in_array($sharePublicIdAndGroupId, $sharesToCreate)) { |
604: | $this->createShare($UserId, $Id, $share); |
605: | } |
606: | if (in_array($sharePublicIdAndGroupId, $sharesToUpdate)) { |
607: | $this->updateShare($UserId, $Id, $share); |
608: | } |
609: | } |
610: | |
611: | $mResult = true; |
612: | } catch (\Exception $oException) { |
613: | Api::LogException($oException); |
614: | $mResult = false; |
615: | } |
616: | |
617: | return $mResult; |
618: | } |
619: | |
620: | public function LeaveShare($UserId, $Id) |
621: | { |
622: | $mResult = false; |
623: | Api::checkUserRoleIsAtLeast(UserRole::NormalUser); |
624: | Api::CheckAccess($UserId); |
625: | |
626: | $abook = $this->getAddressbookByComplexId($UserId, $Id); |
627: | |
628: | if ($abook) { |
629: | $principalUri = Constants::PRINCIPALS_PREFIX . Api::getUserPublicIdById($UserId); |
630: | $dBPrefix = Api::GetSettings()->DBPrefix; |
631: | |
632: | $stmt = Api::GetPDO()->prepare("select count(*) from " . $dBPrefix . "adav_shared_addressbooks |
633: | where principaluri = ? and addressbook_id = ? and group_id = 0"); |
634: | $stmt->execute([$principalUri, $abook['id']]); |
635: | $cnt = $stmt->fetch(); |
636: | |
637: | if ((int) $cnt[0] > 0) { |
638: | $stmt = Api::GetPDO()->prepare("update " . $dBPrefix . "adav_shared_addressbooks |
639: | set access = ? |
640: | where principaluri = ? and addressbook_id = ? and group_id = 0"); |
641: | $mResult = $stmt->execute([Access::NoAccess, $principalUri, $abook['id']]); |
642: | } else { |
643: | $stmt = Api::GetPDO()->prepare("insert into " . $dBPrefix . "adav_shared_addressbooks |
644: | (principaluri, access, addressbook_id, addressbookuri, group_id) |
645: | values (?, ?, ?, ?, ?)"); |
646: | $mResult = $stmt->execute([$principalUri, Access::NoAccess, $abook['id'], UUIDUtil::getUUID(), 0]); |
647: | } |
648: | } |
649: | |
650: | return $mResult; |
651: | } |
652: | |
653: | public function onAfterDeleteGroup($aArgs, &$mResult) |
654: | { |
655: | if ($mResult) { |
656: | $dBPrefix = Api::GetSettings()->DBPrefix; |
657: | $stmt = Api::GetPDO()->prepare("delete from " . $dBPrefix . "adav_shared_addressbooks where group_id = ?"); |
658: | $stmt->execute([$aArgs['GroupId']]); |
659: | } |
660: | } |
661: | |
662: | |
663: | |
664: | |
665: | |
666: | |
667: | public function onBeforeDeleteUser($aArgs, &$mResult) |
668: | { |
669: | if (isset($aArgs['UserId'])) { |
670: | $this->oBeforeDeleteUser = Api::getUserById($aArgs['UserId']); |
671: | } |
672: | } |
673: | |
674: | |
675: | |
676: | |
677: | |
678: | |
679: | public function onAfterDeleteUser($aArgs, $mResult) |
680: | { |
681: | if ($mResult && $this->oBeforeDeleteUser instanceof User) { |
682: | $dBPrefix = Api::GetSettings()->DBPrefix; |
683: | $stmt = Api::GetPDO()->prepare("delete from " . $dBPrefix . "adav_shared_addressbooks where principaluri = ?"); |
684: | $stmt->execute([Constants::PRINCIPALS_PREFIX . $this->oBeforeDeleteUser->PublicId]); |
685: | } |
686: | } |
687: | |
688: | public function onAfterAddUsersToGroup($aArgs, &$mResult) |
689: | { |
690: | if ($mResult) { |
691: | foreach ($aArgs['UserIds'] as $iUserId) { |
692: | $userPublicId = Api::getUserPublicIdById($iUserId); |
693: | $sUserPrincipalUri = Constants::PRINCIPALS_PREFIX . $userPublicId; |
694: | |
695: | $dBPrefix = Api::GetSettings()->DBPrefix; |
696: | $stmt = Api::GetPDO()->prepare("select distinct addressbook_id, access from " . $dBPrefix . "adav_shared_addressbooks where group_id = ?"); |
697: | $stmt->execute([$aArgs['GroupId']]); |
698: | $shares = $stmt->fetchAll(\PDO::FETCH_ASSOC); |
699: | foreach ($shares as $share) { |
700: | if (is_array($share)) { |
701: | $stmt = Api::GetPDO()->prepare("insert into " . $dBPrefix . "adav_shared_addressbooks |
702: | (principaluri, access, addressbook_id, addressbookuri, group_id) |
703: | values (?, ?, ?, ?, ?)"); |
704: | $stmt->execute([$sUserPrincipalUri, $share['access'], $share['addressbook_id'], UUIDUtil::getUUID(), $aArgs['GroupId']]); |
705: | } |
706: | } |
707: | } |
708: | } |
709: | } |
710: | |
711: | public function onAfterCreateUser($aArgs, &$mResult) |
712: | { |
713: | if ($mResult) { |
714: | $oUser = User::find($mResult); |
715: | if ($oUser) { |
716: | $oGroup = CoreModule::getInstance()->GetAllGroup($oUser->IdTenant); |
717: | if ($oGroup) { |
718: | $newArgs = [ |
719: | 'GroupId' => $oGroup->Id, |
720: | 'UserIds' => [$mResult] |
721: | ]; |
722: | $newResult = true; |
723: | $this->onAfterAddUsersToGroup($newArgs, $newResult); |
724: | } |
725: | } |
726: | } |
727: | } |
728: | |
729: | public function onAfterUpdateUser($aArgs, &$mResult) |
730: | { |
731: | if ($mResult) { |
732: | $groupIds = $aArgs['GroupIds']; |
733: | $userId = $aArgs['UserId']; |
734: | |
735: | if ($groupIds !== null) { |
736: | $userPublicId = Api::getUserPublicIdById($userId); |
737: | $sUserPrincipalUri = Constants::PRINCIPALS_PREFIX . $userPublicId; |
738: | |
739: | $dBPrefix = Api::GetSettings()->DBPrefix; |
740: | $stmt = Api::GetPDO()->prepare("select * from " . $dBPrefix . "adav_shared_addressbooks where group_id <> 0 and principaluri = ?"); |
741: | $stmt->execute([$sUserPrincipalUri]); |
742: | $shares = $stmt->fetchAll(\PDO::FETCH_ASSOC); |
743: | |
744: | $currentGroupsIds = []; |
745: | if (is_array($shares)) { |
746: | $currentGroupsIds = array_map(function ($share) { |
747: | return $share['group_id']; |
748: | }, $shares); |
749: | } |
750: | |
751: | $groupsIdsToDelete = array_diff($currentGroupsIds, $groupIds); |
752: | $groupsIdsToCreate = array_diff($groupIds, $currentGroupsIds); |
753: | |
754: | if (count($groupsIdsToDelete) > 0) { |
755: | $stmt = Api::GetPDO()->prepare("delete from " . $dBPrefix . "adav_shared_addressbooks |
756: | where group_id in (" . \implode(',', $groupsIdsToDelete) . ") and principaluri = ?"); |
757: | $stmt->execute([$sUserPrincipalUri]); |
758: | } |
759: | |
760: | if (count($groupsIdsToCreate) > 0) { |
761: | $stmt = Api::GetPDO()->prepare("select distinct addressbook_id, access, group_id from " . $dBPrefix . "adav_shared_addressbooks where group_id in (" . \implode(',', $groupsIdsToCreate) . ")"); |
762: | $stmt->execute(); |
763: | $shares = $stmt->fetchAll(\PDO::FETCH_ASSOC); |
764: | foreach ($shares as $share) { |
765: | if (is_array($share)) { |
766: | $stmt = Api::GetPDO()->prepare("insert into " . $dBPrefix . "adav_shared_addressbooks |
767: | (principaluri, access, addressbook_id, addressbookuri, group_id) |
768: | values (?, ?, ?, ?, ?)"); |
769: | $stmt->execute([$sUserPrincipalUri, $share['access'], $share['addressbook_id'], UUIDUtil::getUUID(), $share['group_id']]); |
770: | } |
771: | } |
772: | } |
773: | } |
774: | } |
775: | } |
776: | |
777: | public function onAfterRemoveUsersFromGroup($aArgs, &$mResult) |
778: | { |
779: | if ($mResult) { |
780: | $principals = []; |
781: | foreach ($aArgs['UserIds'] as $iUserId) { |
782: | $oUser = Api::getUserById($iUserId); |
783: | $principals[] = Constants::PRINCIPALS_PREFIX . $oUser->PublicId; |
784: | } |
785: | |
786: | if (count($principals) > 0) { |
787: | $dBPrefix = Api::GetSettings()->DBPrefix; |
788: | $stmt = Api::GetPDO()->prepare("delete from " . $dBPrefix . "adav_shared_addressbooks where principaluri in (" . \implode(',', $principals) . ") and group_id = ?"); |
789: | $stmt->execute([$aArgs['GroupId']]); |
790: | } |
791: | } |
792: | } |
793: | } |
794: | |