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\SharedFiles;
9:
10: use Afterlogic\DAV\Constants;
11: use Afterlogic\DAV\FS\Directory as Directory;
12: use Afterlogic\DAV\FS\File;
13: use Afterlogic\DAV\FS\Permission;
14: use Afterlogic\DAV\Server;
15: use Aurora\Api;
16: use Aurora\Modules\Core\Module as CoreModule;
17: use Aurora\Modules\Files\Module as FilesModule;
18: use Aurora\Modules\SharedFiles\Enums\ErrorCodes;
19: use Aurora\System\Enums\FileStorageType;
20: use Aurora\System\Enums\UserRole;
21: use Aurora\System\Exceptions\ApiException;
22: use Afterlogic\DAV\FS\Shared\File as SharedFile;
23: use Afterlogic\DAV\FS\Shared\Directory as SharedDirectory;
24: use Aurora\Modules\Core\Models\User;
25: use Aurora\Modules\SharedFiles\Enums\Access;
26: use Aurora\System\Router;
27:
28: use function Sabre\Uri\split;
29:
30: /**
31: * @license https://www.gnu.org/licenses/agpl-3.0.html AGPL-3.0
32: * @license https://afterlogic.com/products/common-licensing Afterlogic Software License
33: * @copyright Copyright (c) 2023, Afterlogic Corp.
34: *
35: * @property Settings $oModuleSettings
36: *
37: * @package Modules
38: */
39: class Module extends \Aurora\Modules\PersonalFiles\Module
40: {
41: /**
42: *
43: */
44: protected static $sStorageType = 'shared';
45:
46: /**
47: *
48: * @var integer
49: */
50: protected static $iStorageOrder = 30;
51:
52: /**
53: * Indicates if it's allowed to move files/folders to this storage.
54: * @var bool
55: */
56: protected static $bIsDroppable = false;
57:
58: /**
59: *
60: * @var \Afterlogic\DAV\FS\Backend\PDO
61: */
62: protected $oBackend;
63:
64: protected $oBeforeDeleteUser = null;
65:
66: public function getManager()
67: {
68: if ($this->oManager === null) {
69: $this->oManager = new Manager($this);
70: }
71:
72: return $this->oManager;
73: }
74:
75: /**
76: * @return Module
77: */
78: public static function getInstance()
79: {
80: return parent::getInstance();
81: }
82:
83: /**
84: * @return Module
85: */
86: public static function Decorator()
87: {
88: return parent::Decorator();
89: }
90:
91: /**
92: * @return Settings
93: */
94: public function getModuleSettings()
95: {
96: return $this->oModuleSettings;
97: }
98:
99: public function init()
100: {
101: parent::init();
102:
103: $this->oBackend = new \Afterlogic\DAV\FS\Backend\PDO();
104:
105: $this->aErrors = [
106: Enums\ErrorCodes::NotPossibleToShareWithYourself => $this->i18N('ERROR_NOT_POSSIBLE_TO_SHARE_WITH_YOURSELF'),
107: Enums\ErrorCodes::UnknownError => $this->i18N('ERROR_UNKNOWN_ERROR'),
108: Enums\ErrorCodes::UserNotExists => $this->i18N('ERROR_USER_NOT_EXISTS'),
109: Enums\ErrorCodes::DuplicatedUsers => $this->i18N('ERROR_DUPLICATE_USERS_BACKEND'),
110: Enums\ErrorCodes::NotPossibleToShareDirectoryInEcryptedStorage => $this->i18N('CANNOT_SHARE_DIRECTORY_IN_ECRYPTED_STORAGE'),
111: Enums\ErrorCodes::IncorrectFilename => $this->i18N('INCORRECT_FILE_NAME'),
112: ];
113:
114: $this->subscribeEvent('Files::GetFiles::after', [$this, 'onAfterGetFiles']);
115: $this->subscribeEvent('Files::GetItems::after', [$this, 'onAfterGetItems'], 10000);
116:
117: $this->subscribeEvent('Core::AddUsersToGroup::after', [$this, 'onAfterAddUsersToGroup']);
118: $this->subscribeEvent('Core::RemoveUsersFromGroup::after', [$this, 'onAfterRemoveUsersFromGroup']);
119: $this->subscribeEvent('Core::CreateUser::after', [$this, 'onAfterCreateUser']);
120: $this->subscribeEvent('Core::UpdateUser::after', [$this, 'onAfterUpdateUser']);
121: $this->subscribeEvent('Core::DeleteGroup::after', [$this, 'onAfterDeleteGroup']);
122: $this->subscribeEvent('Files::PopulateExtendedProps', [$this, 'onPopulateExtendedProps'], 10000);
123: $this->subscribeEvent('Files::LeaveShare', [$this, 'onLeaveShare']);
124:
125: $this->denyMethodsCallByWebApi([
126: 'getNonExistentFileName'
127: ]);
128: }
129:
130: protected function populateExtendedProps($userId, $type, $path, &$aExtendedProps)
131: {
132: $bSharedWithMe = isset($aExtendedProps['SharedWithMeAccess']) ? $aExtendedProps['SharedWithMeAccess'] === Permission::Reshare : false;
133: $aExtendedProps['Shares'] = $this->GetShares(
134: $userId,
135: $type,
136: $path,
137: $bSharedWithMe
138: );
139: }
140:
141: /**
142: * @ignore
143: * @param array $aArgs Arguments of event.
144: * @param mixed $mResult Is passed by reference.
145: */
146: public function onAfterGetItems($aArgs, &$mResult)
147: {
148: if (is_array($mResult)) {
149: foreach ($mResult as $oItem) {
150: $aExtendedProps = $oItem->ExtendedProps;
151: $this->populateExtendedProps($aArgs['UserId'], $aArgs['Type'], \rtrim($oItem->Path, '/') . '/' . $oItem->Id, $aExtendedProps);
152: $oItem->ExtendedProps = $aExtendedProps;
153: }
154: }
155: }
156:
157: protected function isNeedToReturnBody()
158: {
159: $sMethod = $this->oHttp->GetPost('Method', null);
160:
161: return ((string) Router::getItemByIndex(2, '') === 'thumb' ||
162: $sMethod === 'SaveFilesAsTempFiles' ||
163: $sMethod === 'GetFilesForUpload'
164: );
165: }
166:
167: protected function isNeedToReturnWithContectDisposition()
168: {
169: $sAction = (string) Router::getItemByIndex(2, 'download');
170: return $sAction === 'download';
171: }
172:
173: public function GetShares($UserId, $Storage, $Path, $SharedWithMe = false)
174: {
175: $aResult = [];
176:
177: Api::checkUserRoleIsAtLeast(UserRole::NormalUser);
178:
179: Api::CheckAccess($UserId);
180:
181: $sUserPublicId = Api::getUserPublicIdById($UserId);
182: $oUser = Api::getUserById($UserId);
183: $sFullPath = 'files/' . $Storage . '/' . \ltrim($Path, '/');
184: $oNode = Server::getNodeForPath($sFullPath, $sUserPublicId);
185:
186: $aShares = [];
187: if ($oNode instanceof File || $oNode instanceof Directory) {
188: if ($oNode->getAccess() === Enums\Access::Reshare) {
189: Server::checkPrivileges('files/' . $Storage . '/' . \ltrim($Path, '/'), '{DAV:}write-acl');
190: if ($oNode instanceof SharedFile || $oNode instanceof SharedDirectory) {
191: $aShares = $this->oBackend->getShares(Constants::PRINCIPALS_PREFIX . $oNode->getNode()->getUser(), $oNode->getStorage(), '/' . \ltrim($Path, '/'));
192: }
193: } else {
194: $aShares = $this->oBackend->getShares(Constants::PRINCIPALS_PREFIX . $sUserPublicId, $Storage, '/' . \ltrim($Path, '/'));
195: }
196:
197: if (count($aShares) === 0 && ($oNode instanceof SharedFile || $oNode instanceof SharedDirectory) && $SharedWithMe && !$oNode->isInherited()) {
198: $aSharedFile = $this->oBackend->getSharedFileByUidWithPath(
199: Constants::PRINCIPALS_PREFIX . $sUserPublicId,
200: $oNode->getName(),
201: $oNode->getSharePath()
202: );
203: if ($aSharedFile) {
204: $aShares = $this->oBackend->getShares(
205: $aSharedFile['owner'],
206: $aSharedFile['storage'],
207: $aSharedFile['path']
208: );
209: }
210: }
211: $aGroups = [];
212: foreach ($aShares as $aShare) {
213: if ($aShare['group_id'] != 0) {
214: if (!in_array($aShare['group_id'], $aGroups)) {
215: $oGroup = CoreModule::Decorator()->GetGroup((int) $aShare['group_id']);
216: if ($oGroup) {
217: $aGroups[] = $aShare['group_id'];
218: $aResult[] = [
219: 'PublicId' => $oGroup->getName(),
220: 'Access' => $aShare['access'],
221: 'IsGroup' => true,
222: 'IsAll' => !!$oGroup->IsAll,
223: 'GroupId' => (int) $aShare['group_id']
224: ];
225: }
226: }
227: } else {
228: $aResult[] = [
229: 'PublicId' => basename($aShare['principaluri']),
230: 'Access' => $aShare['access']
231: ];
232: }
233: }
234: }
235:
236: return $aResult;
237: }
238:
239: /**
240: * @param string $principalUri
241: * @param string $sFileName
242: * @param string $sPath
243: * @param bool $bWithoutGroup
244: *
245: * @return string
246: */
247: public function getNonExistentFileName($principalUri, $sFileName, $sPath = '', $bWithoutGroup = false)
248: {
249: $iIndex = 1;
250: $sFileNamePathInfo = pathinfo($sFileName);
251: $sExt = isset($sFileNamePathInfo['extension']) ? '.' . $sFileNamePathInfo['extension'] : '';
252: $sNameWOExt = isset($sFileNamePathInfo['filename']) ? $sFileNamePathInfo['filename'] : $sFileName;
253:
254: while ($this->oBackend->getSharedFileByUidWithPath($principalUri, $sFileName, $sPath, $bWithoutGroup)) {
255: $sFileName = $sNameWOExt . ' (' . $iIndex . ')' . $sExt;
256: $iIndex++;
257: }
258: list(, $sUserPublicId) = \Sabre\Uri\split($principalUri);
259: $oUser = CoreModule::getInstance()->GetUserByPublicId($sUserPublicId);
260:
261: if ($oUser) {
262: $sPrevState = Api::skipCheckUserRole(true);
263: $sFileName = FilesModule::Decorator()->GetNonExistentFileName(
264: $oUser->Id,
265: FileStorageType::Personal,
266: $sPath,
267: $sFileName,
268: $bWithoutGroup
269: );
270: Api::skipCheckUserRole($sPrevState);
271: }
272:
273: return $sFileName;
274: }
275:
276: public function UpdateShare($UserId, $Storage, $Path, $Id, $Shares, $IsDir = false)
277: {
278: $mResult = true;
279: $aGuests = [];
280: $aOwners = [];
281: $aReshare = [];
282: $aUpdateShares = [];
283:
284: Api::checkUserRoleIsAtLeast(UserRole::NormalUser);
285: Api::CheckAccess($UserId);
286:
287: $oUser = Api::getAuthenticatedUser();
288: if ($oUser instanceof User) {
289: $sUserPublicId = Api::getUserPublicIdById($UserId);
290: $sInitiator = $sUserPrincipalUri = Constants::PRINCIPALS_PREFIX . $sUserPublicId;
291: $FullPath = $Path . '/' . $Id;
292: Server::checkPrivileges('files/' . $Storage . '/' . \ltrim($FullPath, '/'), '{DAV:}write-acl');
293: $oNode = Server::getNodeForPath('files/' . $Storage . '/' . \ltrim($FullPath, '/'));
294: $bIsEncrypted = false;
295: if ($oNode instanceof File || $oNode instanceof Directory) {
296: $aExtendedProps = $oNode->getProperty('ExtendedProps');
297: $bIsEncrypted = (is_array($aExtendedProps) && isset($aExtendedProps['InitializationVector']));
298:
299: $aSharePublicIds = array_map(function ($share) {
300: return strtolower($share['PublicId']);
301: }, $Shares);
302: if (in_array(strtolower($oNode->getOwner()), $aSharePublicIds)) {
303: throw new ApiException(Enums\ErrorCodes::NotPossibleToShareWithYourself);
304: }
305: }
306: $bIsShared = false;
307: if (($oNode instanceof SharedFile || $oNode instanceof SharedDirectory)) {
308: $bIsShared = true;
309: $aSharedFile = $this->oBackend->getSharedFileByUidWithPath(
310: $sUserPrincipalUri,
311: $oNode->getName(),
312: $oNode->getSharePath()
313: );
314: if ($aSharedFile) {
315: $sUserPrincipalUri = $aSharedFile['owner'];
316: } else {
317: $sUserPrincipalUri = 'principals/' . $oNode->getOwner();
318: }
319: $ParentNode = $oNode->getNode();
320: $FullPath = $ParentNode->getRelativePath() . '/' . $ParentNode->getName();
321: $Storage = $oNode->getStorage();
322: }
323:
324: $aResultShares = [];
325: foreach ($Shares as $item) {
326: if (isset($item['GroupId'])) {
327: $aUsers = CoreModule::Decorator()->GetGroupUsers($oUser->IdTenant, (int) $item['GroupId']);
328: foreach ($aUsers as $aUser) {
329: $aResultShares[] = [
330: 'PublicId' => $aUser['PublicId'],
331: 'Access' => (int) $item['Access'],
332: 'GroupId' => (int) $item['GroupId'],
333: ];
334: }
335: } else {
336: $item['GroupId'] = 0;
337: $aResultShares[] = $item;
338: }
339: }
340:
341: $aDbShares = $this->oBackend->getShares(
342: $sUserPrincipalUri,
343: $Storage,
344: '/' . \ltrim($FullPath, '/')
345: );
346:
347: $aOldSharePrincipals = array_map(function ($aShareItem) {
348: if (isset($aShareItem['principaluri'])) {
349: return \json_encode([
350: $aShareItem['principaluri'],
351: $aShareItem['group_id']
352: ]);
353: }
354: }, $aDbShares);
355:
356: $aNewSharePrincipals = array_map(function ($aShareItem) {
357: if (isset($aShareItem['PublicId'])) {
358: return \json_encode([
359: Constants::PRINCIPALS_PREFIX . $aShareItem['PublicId'],
360: $aShareItem['GroupId']
361: ]);
362: }
363: }, $aResultShares);
364:
365: $aItemsToDelete = array_diff($aOldSharePrincipals, $aNewSharePrincipals);
366: $aItemsToCreate = array_diff($aNewSharePrincipals, $aOldSharePrincipals);
367: $aItemsToUpdate = array_intersect($aOldSharePrincipals, $aNewSharePrincipals);
368:
369: foreach ($aItemsToDelete as $aItem) {
370: $aItem = \json_decode($aItem);
371: $mResult = $this->oBackend->deleteSharedFileByPrincipalUri(
372: $aItem[0],
373: $Storage,
374: $FullPath,
375: $aItem[1]
376: );
377: }
378:
379: foreach ($aResultShares as $Share) {
380: if (!$bIsShared && $oUser->PublicId === $Share['PublicId'] && $Share['GroupId'] == 0) {
381: throw new ApiException(Enums\ErrorCodes::NotPossibleToShareWithYourself);
382: }
383: if (!CoreModule::Decorator()->GetUserByPublicId($Share['PublicId'])) {
384: throw new ApiException(Enums\ErrorCodes::UserNotExists);
385: }
386: if ($Share['Access'] === Enums\Access::Read) {
387: $aGuests[] = $Share['PublicId'];
388: } elseif ($Share['Access'] === Enums\Access::Write) {
389: $aOwners[] = $Share['PublicId'];
390: } elseif ($Share['Access'] === Enums\Access::Reshare) {
391: $aReshare[] = $Share['PublicId'];
392: }
393: $aUpdateShares[] = $Share['PublicId'];
394: }
395:
396: $aDuplicatedUsers = array_intersect($aOwners, $aGuests, $aReshare);
397: if (!empty($aDuplicatedUsers)) {
398: // throw new ApiException(Enums\ErrorCodes::DuplicatedUsers);
399: }
400:
401: $aGuestPublicIds = [];
402: foreach ($aResultShares as $aShare) {
403: $sPrincipalUri = Constants::PRINCIPALS_PREFIX . $aShare['PublicId'];
404:
405: $groupId = (int) $aShare['GroupId'];
406:
407: try {
408: $bCreate = false;
409: foreach ($aItemsToCreate as $aItemToCreate) {
410: $aItemToCreate = \json_decode($aItemToCreate);
411: if ($sPrincipalUri === $aItemToCreate[0] && $groupId == $aItemToCreate[1]) {
412: $bCreate = true;
413: break;
414: }
415: }
416: if ($bCreate) {
417: if ($groupId == 0) {
418: $sNonExistentFileName = $this->getNonExistentFileName($sPrincipalUri, $Id, '', true);
419: } else {
420: $sNonExistentFileName = $Id;
421: }
422: $mCreateResult = $this->oBackend->createSharedFile(
423: $sUserPrincipalUri,
424: $Storage,
425: $FullPath,
426: $sNonExistentFileName,
427: $sPrincipalUri,
428: $aShare['Access'],
429: $IsDir,
430: '',
431: $groupId,
432: $sInitiator
433: );
434: if ($mCreateResult) {
435: $aArgs = [
436: 'UserPrincipalUri' => $sUserPrincipalUri,
437: 'Storage' => $Storage,
438: 'FullPath' => $FullPath,
439: 'Share' => $aShare,
440: ];
441: $this->broadcastEvent($this->GetName() . '::CreateSharedFile', $aArgs);
442: }
443: $mResult = $mResult && $mCreateResult;
444: } else {
445: $bUpdate = false;
446: foreach ($aItemsToUpdate as $aItemToUpdate) {
447: $aItemToUpdate = \json_decode($aItemToUpdate);
448: if ($sPrincipalUri === $aItemToUpdate[0] && $groupId == $aItemToUpdate[1]) {
449: $bUpdate = true;
450: break;
451: }
452: }
453: if ($bUpdate) {
454: $mUpdateResult = $this->oBackend->updateSharedFile(
455: $sUserPrincipalUri,
456: $Storage,
457: $FullPath,
458: $sPrincipalUri,
459: $aShare['Access'],
460: $groupId
461: );
462: if ($mUpdateResult) {
463: $aArgs = [
464: 'UserPrincipalUri' => $sUserPrincipalUri,
465: 'Storage' => $Storage,
466: 'FullPath' => $FullPath,
467: 'Share' => $aShare,
468: ];
469: $this->broadcastEvent($this->GetName() . '::UpdateSharedFile', $aArgs);
470: }
471: $mResult = $mResult && $mUpdateResult;
472: }
473: }
474: } catch (\PDOException $oEx) {
475: if (isset($oEx->errorInfo[1]) && $oEx->errorInfo[1] === 1366) {
476: throw new ApiException(ErrorCodes::IncorrectFilename, $oEx);
477: } else {
478: throw $oEx;
479: }
480: }
481:
482: if ($mResult) {
483: switch ((int) $aShare['Access']) {
484: case Enums\Access::Read:
485: $sAccess = '(r)';
486: break;
487: case Enums\Access::Write:
488: $sAccess = '(r/w)';
489: break;
490: case Enums\Access::Reshare:
491: $sAccess = '(r/w/s)';
492: break;
493: default:
494: $sAccess = '(r/w)';
495: break;
496: }
497: $aGuestPublicIds[] = $aShare['PublicId'] . ' - ' . $sAccess;
498: }
499: }
500:
501: $sResourceId = $Storage . '/' . \ltrim(\ltrim($FullPath, '/'));
502: $aArgs = [
503: 'UserId' => $UserId,
504: 'ResourceType' => 'file',
505: 'ResourceId' => $sResourceId,
506: 'Action' => 'update-share',
507: 'GuestPublicId' => \implode(', ', $aGuestPublicIds)
508: ];
509: $this->broadcastEvent('AddToActivityHistory', $aArgs);
510: }
511:
512: return $mResult;
513: }
514:
515: /**
516: *
517: */
518: public function onAfterGetFiles(&$aArgs, &$mResult)
519: {
520: if ($mResult) {
521: try {
522: $oNode = Server::getNodeForPath('files/' . $aArgs['Type'] . $aArgs['Path']);
523: if ($oNode instanceof SharedFile || $oNode instanceof SharedDirectory) {
524: $mResult['Access'] = $oNode->getAccess();
525: }
526: if ($oNode instanceof SharedDirectory) {
527: $sResourceId = $oNode->getStorage() . '/' . \ltrim(\ltrim($oNode->getRelativeNodePath(), '/') . '/' . \ltrim($oNode->getName(), '/'), '/');
528: $oUser = CoreModule::Decorator()->GetUserByPublicId($oNode->getOwnerPublicId());
529: if ($oUser) {
530: $aArgs = [
531: 'UserId' => $oUser->Id,
532: 'ResourceType' => 'file',
533: 'ResourceId' => $sResourceId,
534: 'Action' => 'list-share'
535: ];
536: $this->broadcastEvent('AddToActivityHistory', $aArgs);
537: }
538: }
539: } catch (\Exception $oEx) {
540: }
541: }
542: }
543:
544: /**
545: * @ignore
546: * @param array $aArgs Arguments of event.
547: * @param mixed $mResult Is passed by reference.
548: */
549: public function onAfterDeleteUser($aArgs, $mResult)
550: {
551: if ($mResult && $this->oBeforeDeleteUser instanceof User) {
552: $this->oBackend->deleteSharesByPrincipal(Constants::PRINCIPALS_PREFIX . $this->oBeforeDeleteUser->PublicId);
553: }
554: }
555:
556: /**
557: * @ignore
558: * @param array $aArgs Arguments of event.
559: * @param mixed $mResult Is passed by reference.
560: */
561: public function onAfterGetSubModules($aArgs, &$mResult)
562: {
563: array_unshift($mResult, self::$sStorageType);
564: }
565:
566: public function onAfterAddUsersToGroup($aArgs, &$mResult)
567: {
568: if ($mResult) {
569: foreach ($aArgs['UserIds'] as $iUserId) {
570: $userPublicId = Api::getUserPublicIdById($iUserId);
571: $sUserPrincipalUri = 'principals/' . $userPublicId;
572: $aDbShares = $this->oBackend->getSharesByPrincipalUriAndGroupId($sUserPrincipalUri, $aArgs['GroupId']);
573:
574: foreach ($aDbShares as $aDbShare) {
575: $mResult = $mResult && $this->oBackend->createSharedFile(
576: $aDbShare['owner'],
577: $aDbShare['storage'],
578: $aDbShare['path'],
579: basename($aDbShare['path']),
580: $sUserPrincipalUri,
581: $aDbShare['access'],
582: $aDbShare['isdir'],
583: '',
584: $aDbShare['group_id'],
585: $aDbShare['initiator']
586: );
587: }
588: }
589: }
590: }
591:
592: public function onAfterUpdateUser($aArgs, &$mResult)
593: {
594: if ($mResult) {
595: $groupIds = $aArgs['GroupIds'] ?? null;
596: $userId = $aArgs['UserId'];
597:
598: $userPublicId = Api::getUserPublicIdById($userId);
599: $sUserPrincipalUri = 'principals/' . $userPublicId;
600:
601: if ($groupIds !== null) {
602: if (count($groupIds) > 0) {
603: $aDbCreateShares = [];
604: foreach ($groupIds as $groupId) {
605: $aDbCreateShares = array_merge(
606: $aDbCreateShares,
607: $this->oBackend->getSharesByPrincipalUriAndGroupId($sUserPrincipalUri, $groupId)
608: );
609: }
610:
611: foreach ($aDbCreateShares as $aShare) {
612: $mResult && $this->oBackend->createSharedFile(
613: $aShare['owner'],
614: $aShare['storage'],
615: $aShare['path'],
616: basename($aShare['path']),
617: $sUserPrincipalUri,
618: $aShare['access'],
619: $aShare['isdir'],
620: '',
621: $aShare['group_id'],
622: $aShare['initiator']
623: );
624: }
625: } else {
626: $groupIds[] = 0;
627: }
628: $this->oBackend->deleteShareNotInGroups($sUserPrincipalUri, $groupIds);
629: }
630: }
631: }
632:
633: public function onAfterRemoveUsersFromGroup($aArgs, &$mResult)
634: {
635: if ($mResult) {
636: foreach ($aArgs['UserIds'] as $iUserId) {
637: $oUser = Api::getUserById($iUserId);
638: $this->oBackend->deleteShareByPrincipaluriAndGroupId('principals/' . $oUser->PublicId, $aArgs['GroupId']);
639: }
640: }
641: }
642:
643: public function onAfterDeleteGroup($aArgs, &$mResult)
644: {
645: if ($mResult) {
646: $this->oBackend->deleteSharesByGroupId($aArgs['GroupId']);
647: }
648: }
649:
650: public function onPopulateExtendedProps(&$aArgs, &$mResult)
651: {
652: $oItem = $aArgs['Item'];
653: if ($oItem instanceof SharedFile || $oItem instanceof SharedDirectory) {
654: $mResult['SharedWithMeAccess'] = $oItem->getAccess();
655: }
656:
657: $this->populateExtendedProps(
658: $aArgs['UserId'],
659: $aArgs['Type'],
660: \rtrim($aArgs['Path'], '/') . '/' . $aArgs['Name'],
661: $mResult
662: );
663: }
664:
665: public function onLeaveShare(&$aArgs, &$mResult)
666: {
667: $UserId = $aArgs['UserId'];
668: Api::checkUserRoleIsAtLeast(UserRole::NormalUser);
669: Api::CheckAccess($UserId);
670:
671: $oUser = Api::getAuthenticatedUser();
672: if ($oUser instanceof User) {
673: $sUserPublicId = Api::getUserPublicIdById($UserId);
674: $sUserPrincipalUri = Constants::PRINCIPALS_PREFIX . $sUserPublicId;
675:
676: foreach ($aArgs['Items'] as $aItem) {
677: if ($aItem->getGroupId() > 0) {
678: $this->oBackend->createSharedFile(
679: 'principals/' . $aItem->getOwnerPublicId(),
680: $aItem->getStorage(),
681: $aItem->getNode()->getRelativePath() . '/' . $aItem->getNode()->getName(),
682: $aItem->getName(),
683: $sUserPrincipalUri,
684: Access::NoAccess,
685: ($aItem instanceof SharedDirectory),
686: '',
687: 0,
688: 'principals/' . $aItem->getOwnerPublicId()
689: );
690: } else {
691: $this->oBackend->updateSharedFile(
692: 'principals/' . $aItem->getOwnerPublicId(),
693: $aItem->getStorage(),
694: $aItem->getNode()->getRelativePath() . '/' . $aItem->getNode()->getName(),
695: $sUserPrincipalUri,
696: Access::NoAccess,
697: 0,
698: 'principals/' . $aItem->getOwnerPublicId()
699: );
700: }
701: }
702:
703: $mResult = true;
704: }
705: }
706:
707: public function onAfterCreateUser($aArgs, &$mResult)
708: {
709: if ($mResult) {
710: $oUser = User::find($mResult);
711: if ($oUser) {
712: $oGroup = CoreModule::getInstance()->GetAllGroup($oUser->IdTenant);
713: if ($oGroup) {
714: $newArgs = [
715: 'GroupId' => $oGroup->Id,
716: 'UserIds' => [$mResult]
717: ];
718: $newResult = true;
719: $this->onAfterAddUsersToGroup($newArgs, $newResult);
720: }
721: }
722: }
723: }
724: }
725: