8080use Sabre \CalDAV \Backend \SchedulingSupport ;
8181use Sabre \CalDAV \Backend \SubscriptionSupport ;
8282use Sabre \CalDAV \Backend \SyncSupport ;
83+ use Sabre \CalDAV \Backend \SharingSupport ;
8384use Sabre \CalDAV \Xml \Property \ScheduleCalendarTransp ;
8485use Sabre \CalDAV \Xml \Property \SupportedCalendarComponentSet ;
8586use Sabre \DAV ;
8687use Sabre \DAV \Exception \BadRequest ;
8788use Sabre \DAV \Exception \Forbidden ;
8889use Sabre \DAV \Exception \NotFound ;
8990use Sabre \DAV \PropPatch ;
91+ use Sabre \DAV \Xml \Element \Sharee ;
9092use Sabre \Uri ;
9193use Sabre \VObject \Component ;
9294use Sabre \VObject \Component \VCalendar ;
118120 *
119121 * @package OCA\DAV\CalDAV
120122 */
121- class CalDavBackend extends AbstractBackend implements SyncSupport, SubscriptionSupport, SchedulingSupport {
123+ class CalDavBackend extends AbstractBackend implements SyncSupport, SubscriptionSupport, SchedulingSupport, SharingSupport {
122124 use TTransactional;
123125
124126 public const CALENDAR_TYPE_CALENDAR = 0 ;
@@ -362,6 +364,9 @@ public function getCalendarsForUser($principalUri) {
362364 $ calendar = $ this ->addOwnerPrincipalToCalendar ($ calendar );
363365 $ calendar = $ this ->addResourceTypeToCalendar ($ row , $ calendar );
364366
367+ $ calendar ['{DAV:}share-resource-uri ' ] = '/ns/share/ ' . $ calendar ['id ' ];
368+ $ calendar ['{DAV:}share-access ' ] = \Sabre \DAV \Sharing \Plugin::ACCESS_SHAREDOWNER ;
369+
365370 if (!isset ($ calendars [$ calendar ['id ' ]])) {
366371 $ calendars [$ calendar ['id ' ]] = $ calendar ;
367372 }
@@ -436,6 +441,9 @@ public function getCalendarsForUser($principalUri) {
436441 $ calendar = $ this ->addOwnerPrincipalToCalendar ($ calendar );
437442 $ calendar = $ this ->addResourceTypeToCalendar ($ row , $ calendar );
438443
444+ $ calendar ['{DAV:}share-resource-uri ' ] = '/ns/share/ ' . $ calendar ['id ' ];
445+ $ calendar ['{DAV:}share-access ' ] = $ row ['access ' ];
446+
439447 $ calendars [$ calendar ['id ' ]] = $ calendar ;
440448 }
441449 $ result ->closeCursor ();
@@ -658,7 +666,7 @@ public function getCalendarByUri($principal, $uri) {
658666 }
659667
660668 /**
661- * @return array{id: int, uri: string, '{http://calendarserver.org/ns/}getctag': string, '{http://sabredav.org/ns}sync-token': int, '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set': SupportedCalendarComponentSet, '{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp': ScheduleCalendarTransp, '{urn:ietf:params:xml:ns:caldav}calendar-timezone': ?string }|null
669+ * @return array{id: int, uri: string, principaluri: string, '{http://calendarserver.org/ns/}getctag': string, '{http://sabredav.org/ns}sync-token': int, '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set': SupportedCalendarComponentSet, '{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp': ScheduleCalendarTransp, '{urn:ietf:params:xml:ns:caldav}calendar-timezone': ?string }|null
662670 */
663671 public function getCalendarById (int $ calendarId ): ?array {
664672 $ fields = array_column ($ this ->propertyMap , 0 );
@@ -2854,23 +2862,28 @@ public function getShares(int $resourceId): array {
28542862 }
28552863
28562864 /**
2857- * @param boolean $value
2858- * @param \OCA\DAV\CalDAV\Calendar $calendar
2859- * @return string|null
2860- */
2861- public function setPublishStatus ($ value , $ calendar ) {
2862- $ calendarId = $ calendar ->getResourceId ();
2865+ * Publishes a calendar.
2866+ *
2867+ * @param mixed $calendarId
2868+ * @param bool $value
2869+ * @return null|string
2870+ */
2871+ public function setPublishStatus ($ calendarId , $ value )
2872+ {
28632873 $ calendarData = $ this ->getCalendarById ($ calendarId );
2874+ if ($ calendarData === null ) {
2875+ return null ;
2876+ }
28642877
28652878 $ query = $ this ->db ->getQueryBuilder ();
28662879 if ($ value ) {
28672880 $ publicUri = $ this ->random ->generate (16 , ISecureRandom::CHAR_HUMAN_READABLE );
28682881 $ query ->insert ('dav_shares ' )
28692882 ->values ([
2870- 'principaluri ' => $ query ->createNamedParameter ($ calendar -> getPrincipalURI () ),
2883+ 'principaluri ' => $ query ->createNamedParameter ($ calendarData [ ' principaluri ' ] ),
28712884 'type ' => $ query ->createNamedParameter ('calendar ' ),
28722885 'access ' => $ query ->createNamedParameter (self ::ACCESS_PUBLIC ),
2873- 'resourceid ' => $ query ->createNamedParameter ($ calendar -> getResourceId () ),
2886+ 'resourceid ' => $ query ->createNamedParameter ($ calendarId ),
28742887 'publicuri ' => $ query ->createNamedParameter ($ publicUri )
28752888 ]);
28762889 $ query ->executeStatement ();
@@ -2879,7 +2892,7 @@ public function setPublishStatus($value, $calendar) {
28792892 return $ publicUri ;
28802893 }
28812894 $ query ->delete ('dav_shares ' )
2882- ->where ($ query ->expr ()->eq ('resourceid ' , $ query ->createNamedParameter ($ calendar -> getResourceId () )))
2895+ ->where ($ query ->expr ()->eq ('resourceid ' , $ query ->createNamedParameter ($ calendarId )))
28832896 ->andWhere ($ query ->expr ()->eq ('access ' , $ query ->createNamedParameter (self ::ACCESS_PUBLIC )));
28842897 $ query ->executeStatement ();
28852898
@@ -2913,6 +2926,87 @@ public function applyShareAcl(int $resourceId, array $acl): array {
29132926 return $ this ->calendarSharingBackend ->applyShareAcl ($ resourceId , $ acl );
29142927 }
29152928
2929+ /**
2930+ * Updates the list of shares.
2931+ *
2932+ * @param mixed $calendarId
2933+ * @param \Sabre\DAV\Xml\Element\Sharee[] $sharees
2934+ * @return void
2935+ */
2936+ public function updateInvites ($ calendarId , array $ sharees ) {
2937+ $ currentShares = $ this ->getShares ($ calendarId );
2938+
2939+ $ removals = [];
2940+ $ additions = [];
2941+
2942+ foreach ($ sharees as $ sharee ) {
2943+ if (\Sabre \DAV \Sharing \Plugin::ACCESS_NOACCESS === $ sharee ->access ) {
2944+ // if access was set no NOACCESS, it means access for an
2945+ // existing sharee was removed.
2946+ $ removals [] = $ sharee ->href ;
2947+ continue ;
2948+ }
2949+
2950+ if (is_null ($ sharee ->principal )) {
2951+ // If the server could not determine the principal automatically,
2952+ // we will mark the invite status as invalid.
2953+ continue ;
2954+ }
2955+
2956+ $ additions [] = [
2957+ 'href ' => $ sharee ->href ,
2958+ 'commonName ' => $ sharee ->properties ['{DAV:}displayname ' ] ?? '' ,
2959+ 'status ' => 1 ,
2960+ 'readOnly ' => $ sharee ->access == \Sabre \DAV \Sharing \Plugin::ACCESS_READ ,
2961+ '{ ' . \OCA \DAV \DAV \Sharing \Plugin::NS_OWNCLOUD . '}principal ' => $ sharee ->principal ,
2962+ '{ ' . \OCA \DAV \DAV \Sharing \Plugin::NS_OWNCLOUD . '}group-share ' => false ,
2963+ ];
2964+ }
2965+ // updateShares() needs a IShareable, i.e. a Calendar object. This is
2966+ // really hacky now ... and inefficient ...
2967+ $ calendarInfo = $ this ->getCalendarById ($ calendarId );
2968+ if ($ calendarInfo === null ) {
2969+ return ;
2970+ }
2971+ $ principalUri = $ calendarInfo ['principaluri ' ];
2972+ $ calendarUri = $ calendarInfo ['uri ' ];
2973+ $ shareable = new Calendar ($ this , $ calendarInfo , \OCP \Util::getL10N ('dav ' ), $ this ->config , $ this ->logger );
2974+ $ this ->updateShares ($ shareable , $ additions , $ removals );
2975+ }
2976+
2977+ /**
2978+ * Returns the list of people whom this calendar is shared with.
2979+ *
2980+ * Every item in the returned list must be a Sharee object with at
2981+ * least the following properties set:
2982+ * $href
2983+ * $shareAccess
2984+ * $inviteStatus
2985+ *
2986+ * and optionally:
2987+ * $properties
2988+ *
2989+ * @param mixed $calendarId
2990+ *
2991+ * @return \Sabre\DAV\Xml\Element\Sharee[]
2992+ */
2993+ public function getInvites ($ calendarId ) {
2994+ $ shares = $ this ->getShares ($ calendarId );
2995+ $ result = [];
2996+ foreach ($ shares as $ share ) {
2997+ $ result [] = new Sharee ([
2998+ 'href ' => $ share ['href ' ],
2999+ 'access ' => $ share ['readOnly ' ] ? \Sabre \DAV \Sharing \Plugin::ACCESS_READ : \Sabre \DAV \Sharing \Plugin::ACCESS_READWRITE ,
3000+ 'inviteStatus ' => \Sabre \DAV \Sharing \Plugin::INVITE_ACCEPTED ,
3001+ 'properties ' => !empty ($ share ['commonName ' ])
3002+ ? [ '{DAV:}displayname ' => $ share ['commonName ' ] ]
3003+ : [],
3004+ 'principal ' => $ share ['{ ' . \OCA \DAV \DAV \Sharing \Plugin::NS_OWNCLOUD . '}principal ' ],
3005+ ]);
3006+ }
3007+ return $ result ;
3008+ }
3009+
29163010 /**
29173011 * update properties table
29183012 *
0 commit comments