pimutils / vdirsyncer

📇 Synchronize calendars and contacts.
https://vdirsyncer.pimutils.org/
Other
1.58k stars 163 forks source link

error: 400, message='Bad Request' #1005

Open mgrant0 opened 2 years ago

mgrant0 commented 2 years ago

I'm trying to sync 2 google calendars. When I run vdirsyncer discover calendar, I am asked the following:

warning: No collection "myself1@gmail.com" found for storage gmail2_calendar.
Should vdirsyncer attempt to create it? [y/N]:

Answering Y, I get:

error: 400, message='Bad Request', url=URL('https://apidata.googleusercontent.com/caldav/v2/myself2@gmail.com/myself1@gmail.com')
critical: Unable to find or create collection "myself1@gmail.com" for storage "gmail2_calendar". Please create the collection yourself.

I've tried creating this manually by adding a calendar with the name myself1@gmail.com in myself2's gmail calendar. I have given all the caldav scopes to the oauth consent screen. I see when I run discover that it is indeed accessing my account because I can see it's reading my calendar names. Here's the last line with debug:

debug: Sending request...
debug: 400
debug: <CIMultiDictProxy('Content-Type': 'text/html; charset=UTF-8', 'Referrer-Policy': 'no-referrer', 'Content-Length': '1555', 'Date': 'Sat, 10 Sep 2022 03:46:00 GMT')>
debug: <StreamReader 1555 bytes eof>
error: 400, message='Bad Request', url=URL('https://apidata.googleusercontent.com/caldav/v2/myself2@gmail.com/myself1@gmail.com')
critical: Unable to find or create collection "myself1@gmail.com" for storage "gmail2_calendar". Please create the collection yourself.

I'm running the version in git using Python 3.10.4 on Ubuntu 22.04.1 LTS

status_path = "~/.vdirsyncer/status/"

[pair calendar]
a = "gmail1_calendar"
b = "gmail2_calendar"
collections = ["from a", "from b"]
metadata = ["color"]

[storage gmail1_calendar]
type = "google_calendar"
token_file = "~/.vdirsyncer/gmail1_token"
client_id = "redacted"
client_secret = "redacted"

[storage gmail2_calendar]
type = "google_calendar"
token_file = "~/.vdirsyncer/gmail2_token"
client_id = "redacted"
client_secret = "redacted"

I'm using the same client_id and client_secret for both. It's a little confusing because it's a little difficult to tell which account it's asking credentials for but I have tried deleting the tokens and tried both ways around. I don't think the oauth is the problem at this point.

My example shows 2 gmail accts, but one of them is a google workspace acct, not sure if that makes a difference. Again, the oauth part seems to be working. vdirsyncer is able to read my list of calendars. The problem seems like a permission problem, yet I've added all the scopes I can find that have to do with writing and creating calendar entries.

API | Scope | User-facing description
CalDAV API | .../auth/calendar | See, edit, share, and permanently delete all the calendars you can access using Google Calendar
CalDAV API | .../auth/calendar.readonly | See and download any calendar you can access using your Google Calendar
CalDAV API | .../auth/calendar.app.created | Make secondary Google calendars, and see, create, change, and delete events on them
CalDAV API | .../auth/calendar.events | View and edit events on all your calendars
CalDAV API | .../auth/calendar.events.freebusy | See the availability on Google calendars you have access to
CalDAV API | .../auth/calendar.events.owned | See, create, change, and delete events on Google calendars you own
CalDAV API | .../auth/calendar.events.owned.readonly | See the events on Google calendars you own
CalDAV API | .../auth/calendar.events.public.readonly | See the events on public calendars
CalDAV API | .../auth/calendar.events.readonly | View events on all your calendars
CalDAV API | .../auth/calendar.calendarlist | See, add, and remove Google calendars you’re subscribed to
CalDAV API | .../auth/calendar.calendarlist.readonly | See the list of Google calendars you’re subscribed to
CalDAV API | .../auth/calendar.calendars | See and change the properties of Google calendars you have access to, and create secondary calendars
CalDAV API | .../auth/calendar.calendars.readonly | See the title, description, default time zone, and other properties of Google calendars you have access to

Or maybe vdirsyncer is not naming the remote calendar it's trying to create properly? I have tried creating the calendars manually and vdirsyncer does not see them. I noticed that I can create multiple calendars with the same name! So I think the name of the calendar is probably not the name vdirsyncer is using which is maybe why I can't just manually create a calendar and hope that the names match.

WhyNotHugo commented 2 years ago

Does discover not find any existing calendars?

There's a secret permissions page where you enable access to individual calendars via *Dav, can you check that one looks correct? https://calendar.google.com/calendar/u/0/syncselect

mgrant0 commented 2 years ago

It absolutely discovers and finds all the existing calendars!

Yes, I know about the "secret" page and I have enabled access to these individual calendars. This did not help.

It looks like vdirsyncer is having problems creating the calendar in the other calendar where to sync to.

I think either there's a permission problem, as in, maybe I am missing a scope, but I have added all the CalDav scopes. Maybe there is a non-CalDav scope that's required to create calendars?

Or maybe there's a bug in vdirsyncer with respect to the arguments it's providing to the API call to create the calendar. Hence the "Bad Request".

mgrant0 commented 2 years ago

Any further ideas how I might debug this issue? I'd really love to get this working!

WhyNotHugo commented 2 years ago

I'm not sure that google allows creating new calendars via the API, this should be tested / confirmed.

You can create the calendars manually (with matching names on both sides) to work around this in the meantime.

mgrant0 commented 2 years ago

I definitely tried to create the calendar manually. I did just what you said, named them the same. However I think there must be some sort of hashing going on behind the scene because vdirsyncer couldn't find the calendar I created by hand and I could create multiple calendars in google with the exact same name but they were separate calendars!

If vdirsyncher ultimately can't create calendars in google, maybe you have to ask the user to create it manually, then, list the calendars and ask them which one to use.

I'm surprised though that vdirsyncher can't create the calendar, I believe it should have the permissions to do that based on what I granted.

WhyNotHugo commented 2 years ago

My bad, I just realise I've been thinking about this all wrong.

vdirsyncer synchronised collections on both sides based on their ID, not on their name.

So if on one side if have collection(id=1, name=hello) and on another side you have collection(id=8, name=hello), they won't sync to each other.

So when creating the calendar on google, what we care about is the id, not the name. However, AFAIK, google won't let you specify the UI when creating a calendar via the UI.

What I'm worrying about now, is whether IDs are globally unique. E.g.; if you have a calendar with id 1234, am I allowed to have one with the same name? I suspect they might not and that's causing the issue here -- though this needs to be tested to confirm it.