[CalendarServer-users] Questions regarding delegation, attachments and time errors

Ian Baker ibaker at eem.ca
Mon May 29 12:44:18 PDT 2017


Just wondering if there are any suggestions about this “You are not authorized to access this resource” issue wjem trying to delete this corrupt event.

Thanks in advance,

Ian

> On May 13, 2017, at 5:19 PM, Ian Baker <ibaker at eem.ca> wrote:
> 
> André,
> 
> I can confirm that the problematic event doesn’t seem to crash the boss’s Calendar.app.  It just doesn’t show up in his calendar, nor does the associated event wit the same UID.  He is running 10.11.6, and I accessed his calendar to confirm, and I’m running 10.12.5. Again, no crash.  To avoid the erroneous notifications mentioned earlier, I used the macOS Guest account with no mail accounts configured.
> 
> I was able to get the event's resource_id, and then establish its URL.  I even validated that the URL was correct by getting it using Safari and comparing the result with the expected event.  I authenticated in Safari with both the boss’s userid/password as well as the Bonus round #1 AdminPrincipal's userid/password, so both authentications were working correctly.
> 
> However, I am truly hesitant to report that when attempting the curl -X delete, and authenticating either way, I get this:
> 
> 	<html><head><title>Unauthorized</title></head><body><h1>Unauthorized</h1><p>You are not authorized to access this resource.</p></body></html>
> 
> Not sure where to go from here.
> 
> TIA
> 
> Ian
> 
> 
>> On May 11, 2017, at 5:10 PM, Andre LaBranche <dre at apple.com <mailto:dre at apple.com>> wrote:
>> 
>> 
>>> On May 11, 2017, at 7:46 AM, Ian Baker <ibaker at eem.ca <mailto:ibaker at eem.ca>> wrote:
>>> 
>>>> On May 10, 2017, at 8:27 PM, Andre LaBranche <dre at apple.com <mailto:dre at apple.com>> wrote:
>>>> 
>>>> Yeah, wow. There are actually two distinct VCALENDAR objects here - both with the same UID. I've never seen this happen.
>> 
>> I was embarrassingly mistaken in my characterization of this. The psql output clearly indicates there are two rows, and it is not abnormal to have multiple calendar_object rows for events with the same UID; the organizer and attendees all get their own copy.
>> 
>> Both of the events, when placed into discrete ics files, validate successfully.
>> 
>> Anyhow, even though the pycalendar validator is OK with both of these events, the one that has no organizer / attendee information but does have a RECURRENCE-ID crashes Calendar.app if I try to import it. That's bad, and I sent a bug to Calendar to remedy that.
>> 
>> It's unclear why this event is in the state that it's in, but it's not a good state. The easiest option for unblocking the web calendar is probably to just delete the problem event. Since it's just a (seemingly broken) cancel, there should be no harm in this. Never make changes to calendar data using direct database access; stick with HTTP to keep everything coherent. An HTTP "delete" request should work fine, the only tricky part is finding the URL to delete, since the event in question is likely returned in a batch request, in which case the individual URLs won't appear in the access.log.
>> 
>> The first step is to find the resource_id of the event, which is another column on calendar_object. We'll use the event UID and a substring search for RECURRENCE-ID as the predicates. In the example below, use your event's UID instead (which is 040000008200E00074C5B7101A82E008000000004020622BEB7AD201000000000000000010000000C05F922AF30E4145839AF52B293ABFFB)
>> 
>> caldav=# select resource_id, calendar_resource_id from calendar_object where icalendar_text LIKE '%RECURRENCE-ID%' and icalendar_uid = '8F98441F-3890-457E-B0E6-6875EE527951';
>>  resource_id | calendar_resource_id 
>> -------------+----------------------
>>           26 |                    2
>> (1 row)
>> 
>> (calendar_resource_id is a reference to the calendar that contains the event. There shouldn't be multiple results for this query in your case, but if there are, this value would probably vary).
>> 
>> With the resource_id in hand, you can compose a URL by traversing the CalendarServer resource hierarchy using something like the following, substituting your resource_id on the last line of the query, and changing 'example.com <http://example.com/>' to something correct.
>> 
>> SELECT '"https://example.com:8443/calendars/__uids__/' <https://example.com:8443/calendars/__uids__/'>
>>        || owner_uid 
>>        || '/' 
>>        || calendar_resource_name 
>>        || '/' 
>>        || resource_name
>>        || '"' as URL
>> FROM   calendar_bind 
>>        JOIN calendar_home 
>>          ON calendar_bind.calendar_home_resource_id = calendar_home.resource_id 
>>        JOIN calendar_object 
>>          ON calendar_bind.calendar_resource_id = 
>>             calendar_object.calendar_resource_id 
>> WHERE  calendar_object.resource_id = 26;
>> 
>> Example:
>> 
>> caldav=# SELECT '"https://example.com:8443/calendars/__uids__/' <https://example.com:8443/calendars/__uids__/'>
>> caldav-#        || owner_uid 
>> caldav-#        || '/' 
>> caldav-#        || calendar_resource_name 
>> caldav-#        || '/' 
>> caldav-#        || resource_name
>> caldav-#        || '"' as URL
>> caldav-# FROM   calendar_bind 
>> caldav-#        JOIN calendar_home 
>> caldav-#          ON calendar_bind.calendar_home_resource_id = calendar_home.resource_id 
>> caldav-#        JOIN calendar_object 
>> caldav-#          ON calendar_bind.calendar_resource_id = 
>> caldav-#             calendar_object.calendar_resource_id 
>> caldav-# WHERE  calendar_object.resource_id = 26;
>>                                                                     url                                                                    
>> -------------------------------------------------------------------------------------------------------------------------------------------
>>  "https://example.com:8443/calendars/__uids__/E1CB3592-E7BD-41C4-A27C-6E23FEFFD197/calendar/8F98441F-3890-457E-B0E6-6875EE527951.ics <https://example.com:8443/calendars/__uids__/E1CB3592-E7BD-41C4-A27C-6E23FEFFD197/calendar/8F98441F-3890-457E-B0E6-6875EE527951.ics>"
>> (1 row)
>> 
>> Now with an URL, you can fire a DELETE using curl. Such a request usually needs to be authenticated with the credentials of the user whose GUID is shown after the __uids__ portion of the URL (in the DB, this is calendar_home.owner_uid). To confirm that username:
>> 
>> % dscl /Search search /Users GeneratedUID E1CB3592-E7BD-41C4-A27C-6E23FEFFD197
>> andre		GeneratedUID = (
>>     "E1CB3592-E7BD-41C4-A27C-6E23FEFFD197"
>> )
>> 
>> Now you can run curl, supplying the password when prompted:
>> 
>> curl -u <username> -X DELETE <url>
>> 
>> With this seemingly invalid event out of the way, the web calendar should now load (or at least, get stuck on something else).
>> 
>> 
>> Bonus round #1
>> 
>> ... but you might want to do this on behalf of your boss, without knowing his password. To do that, add yourself as an AdminPrincipal using the following CalendarServer config in the file:
>> "/Library/Server/Calendar and Contacts/Config/caldavd-user.plist"  (this file doesn't exist by default, and is read after caldavd-system.plist, overriding anything defined there)
>> 
>> <?xml version="1.0" encoding="UTF-8"?>
>> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd <http://www.apple.com/DTDs/PropertyList-1.0.dtd>">
>> <plist version="1.0">
>> <dict>
>> 
>>     <key>AdminPrincipals</key>
>>     <array>
>>         <string>/principals/__uids__/AEB68DD7-D2B8-4D4D-A574-2A4533DF36A4/</string>
>>     </array>
>> 
>> </dict>
>> </plist>
>> 
>> Specify your own GUID instead of the one shown above, which you can find with a dscl query using your username, e.g.:
>> 
>> $ dscl /Search read /Users/andre GeneratedUID
>> GeneratedUID: E1CB3592-E7BD-41C4-A27C-6E23FEFFD197
>> 
>> Finally, restart CalendarServer to activate the new config:
>> 
>> sudo calendarserver_config --restart
>> 
>> After doing the delete, to disable the AdminPrincipal config, either rename the caldavd-user.plist file, or comment out the array elements like this:
>> 
>> <!-- <string>/principals/__uids__/AEB68DD7-D2B8-4D4D-A574-2A4533DF36A4/</string> -->
>> 
>> ... then bounce the service.
>> 
>> Bonus round #2
>> 
>> Also I confirmed that the validation steps included in my prior email work as written; the second 'cd' is not optional, and I was trying to do that as an alternative to 'installing' the module. But now that I remember that virtualenv <https://virtualenv.pypa.io/en/stable/> exists, here's a more standard approach:
>> 
>> # provision a new virtualenv, use it, install pycalendar from git using pip
>> virtualenv pycalendar-env
>> cd pycalendar-env
>> source bin/activate
>> pip install git+https://github.com/apple/ccs-pycalendar.git@master <git+https://github.com/apple/ccs-pycalendar.git@master>
>> 
>> # verify - this should print the path to the pycalendar module that was just installed
>> python -c 'import pycalendar ; print pycalendar.__path__'
>> 
>> # run the validator
>> % python -m pycalendar.validator ~/1.ics
>> No problems
>> 
>> Bonus round #3
>> 
>> The icalendar_text returned previously by psql isn't in proper iCalendar form. Even though there are psql options for raw output, I would have to look those up, while the following vim commands flow like water onto my keyboard:
>> 
>> :%s/+$//g
>> :%s/\\r//g
>> :%s/^ //g
>> :1,2d
>> :$-2,$d
>> :%s/[ ]*$//g
>> 
>> ... ok I looked it up, and it's easier than the above: just start psql like this: sudo psql -A -t -h /var/run/caldavd/PostgresSocket -U caldav caldav
>> 
>> e.g.
>> 
>> # psql -A -t -h /var/run/caldavd/PostgresSocket -U caldav caldav -c 'select icalendar_text from calendar_object limit 1;'
>> BEGIN:VCALENDAR
>> VERSION:2.0
>> PRODID:-//Apple Inc.//Web Calendar Client//
>> BEGIN:VEVENT
>> UID:c6b8d8ac-c23b-23b1-ade0-2756d3ca8fee
>> DTSTART;TZID=America/Los_Angeles:20150814T080000
>> DURATION:PT1H30M
>> DTSTAMP:20150813T182156Z
>> SEQUENCE:2
>> SUMMARY:New Event
>> END:VEVENT
>> BEGIN:X-CALENDARSERVER-PERUSER
>> UID:c6b8d8ac-c23b-23b1-ade0-2756d3ca8fee
>> X-CALENDARSERVER-PERUSER-UID:E1CB3592-E7BD-41C4-A27C-6E23FEFFD197
>> BEGIN:X-CALENDARSERVER-PERINSTANCE
>> TRANSP:OPAQUE
>> END:X-CALENDARSERVER-PERINSTANCE
>> END:X-CALENDARSERVER-PERUSER
>> END:VCALENDAR
>> 
>> (and finally, the X-CALENDARSERVER-PERINSTANCE component would not be exposed to clients; this component is internal to CalendarServer and is stripped from event bodies as they leave the server)
>> 
>> -dre
>> 
>> 
>>> 
>>> What is particularly weird is that this event was also sent to another of our users ‘Robert Cole’, and I can load his calendar in WebCal and view the event without trouble. There were no errors on Rob’s javascript console in Safari.
>>> 
>>> 	
>>> <PastedGraphic-1.png>
>>> 
>>> I exported Rob's calendar and found one of the 2 events. The ‘cancelled" event was not in Rob’s calendar that I could find.  I’ve attached Rob's event as an .ics file.  From what I could see Rob’s version didn’t have lines related to the following properties:
>>> VCALENDAR
>>> X-CALENDARSERVER-PERUSER
>>> X-CALENDARSERVER-PERINSTANCE
>>> and there seemed to be minor parsing differences (quotes around certain fields e.g. email addresses).
>>> 
>>> If these are not the source of the error on the boss’s ('Paul MacLean’) WebCal display, might it be something else that is causing the error? The event just before or the event just after this one? Or perhaps the volume of events in the boss’s calendar - he never throws anything away!
>>> 
>>> TIA
>>> 
>>> Ian
>>> 450-465-1641
>>> 
>>> <Robs Event.ics>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-users/attachments/20170529/42cb5196/attachment-0001.html>


More information about the calendarserver-users mailing list