| 149 | } |
| 150 | |
| 151 | static async createAddressBook( |
| 152 | userId: string, |
| 153 | name: string, |
| 154 | ): Promise<void> { |
| 155 | const addressBookId = crypto.randomUUID(); |
| 156 | const addressBookUrl = `${contactsConfig.cardDavUrl}/${userId}/${addressBookId}/`; |
| 157 | |
| 158 | // For some reason this sends invalid XML |
| 159 | // await client.makeCollection({ |
| 160 | // url: addressBookUrl, |
| 161 | // props: { |
| 162 | // displayName: name, |
| 163 | // }, |
| 164 | // }); |
| 165 | |
| 166 | // Make "manual" request (https://www.rfc-editor.org/rfc/rfc6352.html#page-14) |
| 167 | const xmlBody = `<?xml version="1.0" encoding="utf-8"?> |
| 168 | <d:mkcol xmlns:d="DAV:" xmlns:card="urn:ietf:params:xml:ns:carddav"> |
| 169 | <d:set> |
| 170 | <d:prop> |
| 171 | <d:displayname>${encodeURIComponent(name)}</d:displayname> |
| 172 | <d:resourcetype> |
| 173 | <d:collection/> |
| 174 | <card:addressbook/> |
| 175 | </d:resourcetype> |
| 176 | </d:prop> |
| 177 | </d:set> |
| 178 | </d:mkcol>`; |
| 179 | |
| 180 | await fetch(addressBookUrl, { |
| 181 | method: 'MKCOL', |
| 182 | headers: { |
| 183 | 'Content-Type': 'application/xml; charset=utf-8', |
| 184 | 'X-Remote-User': userId, |
| 185 | }, |
| 186 | body: xmlBody, |
| 187 | }); |
| 188 | } |
| 189 | |
| 190 | static async deleteAddressBook( |
| 191 | userId: string, |