Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose Horde Api calendars (timeobjects) to DAV in readonly mode #226

Open
wants to merge 12 commits into
base: master
Choose a base branch
from

Conversation

ralflang
Copy link
Member

@ralflang ralflang commented Aug 13, 2017

Expose Horde Api calendars (timeobjects) to DAV in readonly mode
Omit tasks as they already have their own backend.

External calendars are attributed to the viewing user's principal.

External calendar IDs are transformed as they may contain slash / which is interpreted as directory separator and breaks stuff.

Tested this patch against a production horde 5.2 but there is no real difference with current master.

@ralflang ralflang requested a review from mrubinsk August 13, 2017 16:58
'principaluri' => 'principals/' . $user,
'{http://sabredav.org/ns}owner-principal' =>
'principals/-system-', // TODO: Not sure who should really own these, system or the calling user
'{DAV:}displayname' => sprintf("%s: %s", ucfirst($calendar->api()), $calendar->name()),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be $registry->get('name', $calendar->api()).

'{http://sabredav.org/ns}owner-principal' =>
'principals/-system-', // TODO: Not sure who should really own these, system or the calling user
'{DAV:}displayname' => sprintf("%s: %s", ucfirst($calendar->api()), $calendar->name()),
'{' . CalDAV\Plugin::NS_CALDAV . '}calendar-description' =>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would actually leave this off until there is a better value to get than the duplication of the calendar name.

$calendar->caldavUrl(),
'principaluri' => 'principals/' . $user,
'{http://sabredav.org/ns}owner-principal' =>
'principals/-system-', // TODO: Not sure who should really own these, system or the calling user
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tend to own this to the user. In fact we have both, global and per-user resourced provided through the timeobjects API. But it makes more sense IMO to have different per-user calendars with the same data, than single global calendars with individual data.

@@ -945,6 +945,35 @@ public function davGetCollections($user)
'{http://sabredav.org/ns}read-only' => !$share->hasPermission($hordeUser, Horde_Perms::EDIT),
);
}
// External Calendars from other Horde Apps
foreach ($calendar_manager->get(Kronolith::ALL_EXTERNAL_CALENDARS) as $calendarId => $calendar) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indention

'principaluri' => 'principals/' . $user,
'{http://sabredav.org/ns}owner-principal' =>
'principals/-system-', // TODO: Not sure who should really own these, system or the calling user
'{DAV:}displayname' => sprintf("%s: %s", ucfirst($calendar->api()), $calendar->name()),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Single quotes please; spacing.

$exploded = explode(':', $internal, 2);
$driverType = null;
if ($exploded[0] == "external") {
$driverType = "Horde";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Single quotes please.

$driverType = null;
if ($exploded[0] == "external") {
$driverType = "Horde";
$internalName = str_replace(':', '/', $exploded[1]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why using a different separator in Kronolith_Calendar_External in the first place?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When using the original separator "/", caldav misbehaves as it uses the calendar id string in several occassions for creating URLs. Calendars won't be accessible without creating additional caldav directory hierarchies.

if ($share) {
$ical->setAttribute('X-WR-CALNAME', $share->get('name'));
} else {
// TODO: Get Calendar object and run ->name()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be implemented.

@@ -96,6 +96,24 @@ public function api()
{
return $this->_api;
}
/**
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vertical spacing

*/
public function internalId()
{
return sprintf("external:%s:%s", $this->_api, str_replace('/', ':', $this->_id));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above about the different separator.

'{DAV:}displayname' => sprintf("%s: %s", ucfirst($calendar->api()), $calendar->name()),
'{' . CalDAV\Plugin::NS_CALDAV . '}calendar-description' =>
$calendar->name(), // TODO: Implement an interface for description and fallback to name if none given
'', // TODO: Implement an interface for description and fallback to empty if none given
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can leave that property out completely.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

$internalName = str_replace(':', '/', $exploded[1]);
} elseif (!Kronolith::hasPermission($internal, Horde_Perms::SHOW)) {
throw new Kronolith_Exception(_("Calendar does not exist or no permission to edit"));
throw new Kronolith_Exception(_('Calendar does not exist or no permission to edit'));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gettext strings OTOH must have double quotes :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. I was not aware.

CODING_STANDARDS shows the double quote example in section 23 internatl. , but does not instruct to use double quotes. In 27 quotes it says Should be used in the gettext shortcut _("") format.

@yunosh
Copy link
Member

yunosh commented Aug 16, 2017

The patch is fine now, many thanks!
It doesn't work as expected yet, though. One of my address books returning anniversaries results in a 500 error from Sabre, stating "The objectData argument must contain an 'uri' property". Other paths to events (like anniversaries from address books) return a 404 right away.

@ralflang
Copy link
Member Author

ralflang commented Aug 16, 2017 via email

@ralflang
Copy link
Member Author

ralflang commented Aug 16, 2017 via email

root and others added 3 commits August 16, 2017 16:31
…n exception.

Fixes whups items in horde 5.2
TODO: prevent eternal recursion for birthdays in turba, probably due to recurrences
TODO: Test again against master
@ralflang
Copy link
Member Author

ralflang commented Aug 17, 2017 via email

@yunosh
Copy link
Member

yunosh commented Aug 25, 2017

I still see a few issues:

  • The external calendars now show up both unter the -system- and the personal namespace.
  • The Application prefix of the calendar names always is "Horde", not "Address Book" etc.
  • The calculation of birthdays/anniversaries is off (a 200o years).
  • The event IDs (not UIDs) seem to be missing some prefix, e.g.: _contactsFaG7igYk1U2zDEzVgN_SUUO.ics. The leading underscore looks like there is missing something? Or is it simply superfluous?

We also need to think about the UIDs once again. First of all, the timeobject APIs should probably export any existing UIDs. On the other hand, this would lead to the same UIDs for two different kind of objects (contact + event). This is probably a bad idea.

@ralflang
Copy link
Member Author

  • The external calendars now show up both unter the -system- and the personal namespace.
  • The Application prefix of the calendar names always is "Horde", not "Address Book" etc.

Both fixed.

  • The calculation of birthdays/anniversaries is off (a 200o years).
    Cannot reproduce against master nor 5.3 - can you provide an example addressbook entry?

  • The event IDs (not UIDs) seem to be missing some prefix, e.g.: _contactsFaG7igYk1U2zDEzVgN_SUUO.ics. The leading underscore looks like there is missing something? Or is it simply superfluous?

_contacts (_api) is a prefix added to the item id to prevent any clashes with existing IDs.
See

$this->id = '_' . $this->_api . $event['id'];

It gets removed for toTimeObject.

--
We also need to think about the UIDs once again. First of all, the timeobject APIs should probably export any existing UIDs. On the other hand, this would lead to the same UIDs for two different kind of objects (contact + event). This is probably a bad idea.

I think we should not mix this patch with concerns of the exporting applications. These should be independent follow-up patches. Currently, if the application exports no UID to timeobjects (which seems standard case), we craft a uid. The fallback for application-provided UIDs is already there.

It is either the exporting application's responsibility to make sure the timeobjects, cost objects etc do not have the same uid as the original application object (like a contact or ticket) or it needs to be handled by the infrastructure. Either way it should not be the receiver's (kronolith's) task. For example, the uid could be (originalitemuid)@TimeObjectCategory.Api

@yunosh
Copy link
Member

yunosh commented Aug 28, 2017

It is either the exporting application's responsibility to make sure the timeobjects, cost objects etc do not have the same uid as the original application object (like a contact or ticket) or it needs to be handled by the infrastructure. Either way it should not be the receiver's (kronolith's) task. For example, the uid could be (originalitemuid)@TimeObjectCategory.Api

I don't agree. If Kronolith is converting this object from one format to a different (incompatible) format, it basically creates a new object, and thus shouldn't reuse the original UiD. Unless we agree it's perfectly fine to have a contact (or any other object FWIW) and an event with the same UID.

@ralflang
Copy link
Member Author

ralflang commented Aug 28, 2017 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants