diff --git a/src/main/kotlin/com/nylas/resources/Attachments.kt b/src/main/kotlin/com/nylas/resources/Attachments.kt index bf9938e8..0edcca17 100644 --- a/src/main/kotlin/com/nylas/resources/Attachments.kt +++ b/src/main/kotlin/com/nylas/resources/Attachments.kt @@ -2,6 +2,7 @@ package com.nylas.resources import com.nylas.NylasClient import com.nylas.models.* +import com.nylas.util.PathEncoder import okhttp3.ResponseBody /** @@ -23,7 +24,7 @@ class Attachments(client: NylasClient) : Resource(client, Attachment @Throws(NylasOAuthError::class, NylasSdkTimeoutError::class) @JvmOverloads fun find(identifier: String, attachmentId: String, queryParams: FindAttachmentQueryParams, overrides: RequestOverrides? = null): Response { - val path = String.format("v3/grants/%s/attachments/%s", identifier, attachmentId) + val path = String.format("v3/grants/%s/attachments/%s", identifier, PathEncoder.encode(attachmentId)) return findResource(path, queryParams, overrides = overrides) } @@ -45,7 +46,7 @@ class Attachments(client: NylasClient) : Resource(client, Attachment @Throws(NylasOAuthError::class, NylasSdkTimeoutError::class) @JvmOverloads fun download(identifier: String, attachmentId: String, queryParams: FindAttachmentQueryParams, overrides: RequestOverrides? = null): ResponseBody { - val path = String.format("v3/grants/%s/attachments/%s/download", identifier, attachmentId) + val path = String.format("v3/grants/%s/attachments/%s/download", identifier, PathEncoder.encode(attachmentId)) return client.downloadResponse(path, queryParams, overrides = overrides) } diff --git a/src/main/kotlin/com/nylas/resources/Bookings.kt b/src/main/kotlin/com/nylas/resources/Bookings.kt index 14b44ee0..90ba249c 100644 --- a/src/main/kotlin/com/nylas/resources/Bookings.kt +++ b/src/main/kotlin/com/nylas/resources/Bookings.kt @@ -3,6 +3,7 @@ package com.nylas.resources import com.nylas.NylasClient import com.nylas.models.* import com.nylas.util.JsonHelper +import com.nylas.util.PathEncoder /** * Nylas Bookings API @@ -25,7 +26,7 @@ class Bookings(client: NylasClient) : Resource(client, Booking::class.j queryParams: FindBookingQueryParams? = null, overrides: RequestOverrides? = null, ): Response { - val path = String.format("v3/scheduling/bookings/%s", bookingId) + val path = String.format("v3/scheduling/bookings/%s", PathEncoder.encode(bookingId)) return findResource(path, queryParams, overrides = overrides) } @@ -65,7 +66,7 @@ class Bookings(client: NylasClient) : Resource(client, Booking::class.j queryParams: ConfirmBookingQueryParams? = null, overrides: RequestOverrides? = null, ): Response { - val path = String.format("v3/scheduling/bookings/%s", bookingId) + val path = String.format("v3/scheduling/bookings/%s", PathEncoder.encode(bookingId)) val adapter = JsonHelper.moshi().adapter(ConfirmBookingRequest::class.java) val serializedRequestBody = adapter.toJson(requestBody) return updateResource(path, serializedRequestBody, queryParams, overrides = overrides) @@ -87,7 +88,7 @@ class Bookings(client: NylasClient) : Resource(client, Booking::class.j queryParams: RescheduleBookingQueryParams? = null, overrides: RequestOverrides? = null, ): Response { - val path = String.format("v3/scheduling/bookings/%s", bookingId) + val path = String.format("v3/scheduling/bookings/%s", PathEncoder.encode(bookingId)) val adapter = JsonHelper.moshi().adapter(RescheduleBookingRequest::class.java) val serializedRequestBody = adapter.toJson(requestBody) return patchResource(path, serializedRequestBody, queryParams, overrides = overrides) @@ -132,7 +133,7 @@ class Bookings(client: NylasClient) : Resource(client, Booking::class.j queryParams: DestroyBookingQueryParams?, overrides: RequestOverrides?, ): DeleteResponse { - val path = String.format("v3/scheduling/bookings/%s", bookingId) + val path = String.format("v3/scheduling/bookings/%s", PathEncoder.encode(bookingId)) val adapter = JsonHelper.moshi().adapter(DestroyBookingRequest::class.java) val serializedRequestBody = adapter.toJson(requestBody) return client.executeDelete(path, DeleteResponse::class.java, serializedRequestBody, queryParams, overrides) @@ -151,7 +152,7 @@ class Bookings(client: NylasClient) : Resource(client, Booking::class.j * @return The DeleteResponse object */ fun destroy(bookingId: String, queryParams: DestroyBookingQueryParams? = null, overrides: RequestOverrides? = null): DeleteResponse { - val path = String.format("v3/scheduling/bookings/%s", bookingId) + val path = String.format("v3/scheduling/bookings/%s", PathEncoder.encode(bookingId)) return destroyResource(path, queryParams, overrides = overrides) } } diff --git a/src/main/kotlin/com/nylas/resources/Calendars.kt b/src/main/kotlin/com/nylas/resources/Calendars.kt index 6572e261..8b9c6d14 100644 --- a/src/main/kotlin/com/nylas/resources/Calendars.kt +++ b/src/main/kotlin/com/nylas/resources/Calendars.kt @@ -4,6 +4,7 @@ import com.nylas.NylasClient import com.nylas.models.* import com.nylas.models.GetFreeBusyResponse.Companion.GET_FREE_BUSY_RESPONSE_ADAPTER import com.nylas.util.JsonHelper +import com.nylas.util.PathEncoder import com.squareup.moshi.Types /** @@ -39,7 +40,7 @@ class Calendars(client: NylasClient) : Resource(client, Calendar::clas @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun find(identifier: String, calendarId: String, overrides: RequestOverrides? = null): Response { - val path = String.format("v3/grants/%s/calendars/%s", identifier, calendarId) + val path = String.format("v3/grants/%s/calendars/%s", identifier, PathEncoder.encode(calendarId)) return findResource(path, overrides = overrides) } @@ -70,7 +71,7 @@ class Calendars(client: NylasClient) : Resource(client, Calendar::clas @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun update(identifier: String, calendarId: String, requestBody: UpdateCalendarRequest, overrides: RequestOverrides? = null): Response { - val path = String.format("v3/grants/%s/calendars/%s", identifier, calendarId) + val path = String.format("v3/grants/%s/calendars/%s", identifier, PathEncoder.encode(calendarId)) val adapter = JsonHelper.moshi().adapter(UpdateCalendarRequest::class.java) val serializedRequestBody = adapter.toJson(requestBody) return updateResource(path, serializedRequestBody, overrides = overrides) @@ -85,7 +86,7 @@ class Calendars(client: NylasClient) : Resource(client, Calendar::clas */ @Throws(NylasApiError::class, NylasSdkTimeoutError::class) fun destroy(identifier: String, calendarId: String, overrides: RequestOverrides? = null): DeleteResponse { - val path = String.format("v3/grants/%s/calendars/%s", identifier, calendarId) + val path = String.format("v3/grants/%s/calendars/%s", identifier, PathEncoder.encode(calendarId)) return destroyResource(path, overrides = overrides) } diff --git a/src/main/kotlin/com/nylas/resources/Configurations.kt b/src/main/kotlin/com/nylas/resources/Configurations.kt index cffc1ee4..3ac49384 100644 --- a/src/main/kotlin/com/nylas/resources/Configurations.kt +++ b/src/main/kotlin/com/nylas/resources/Configurations.kt @@ -3,6 +3,7 @@ package com.nylas.resources import com.nylas.NylasClient import com.nylas.models.* import com.nylas.util.JsonHelper +import com.nylas.util.PathEncoder /** * Nylas Configurations API @@ -49,7 +50,7 @@ class Configurations(client: NylasClient) : Resource(client, Conf configId: String, overrides: RequestOverrides? = null, ): Response { - val path = String.format("v3/grants/%s/scheduling/configurations/%s", identifier, configId) + val path = String.format("v3/grants/%s/scheduling/configurations/%s", identifier, PathEncoder.encode(configId)) return findResource(path, overrides = overrides) } @@ -89,7 +90,7 @@ class Configurations(client: NylasClient) : Resource(client, Conf requestBody: UpdateConfigurationRequest, overrides: RequestOverrides? = null, ): Response { - val path = String.format("v3/grants/%s/scheduling/configurations/%s", identifier, configId) + val path = String.format("v3/grants/%s/scheduling/configurations/%s", identifier, PathEncoder.encode(configId)) val adapter = JsonHelper.moshi().adapter(UpdateConfigurationRequest::class.java) val serializedRequestBody = adapter.toJson(requestBody) return updateResource(path, serializedRequestBody, overrides = overrides) @@ -108,7 +109,7 @@ class Configurations(client: NylasClient) : Resource(client, Conf configId: String, overrides: RequestOverrides? = null, ): DeleteResponse { - val path = String.format("v3/grants/%s/scheduling/configurations/%s", identifier, configId) + val path = String.format("v3/grants/%s/scheduling/configurations/%s", identifier, PathEncoder.encode(configId)) return destroyResource(path, overrides = overrides) } } diff --git a/src/main/kotlin/com/nylas/resources/Contacts.kt b/src/main/kotlin/com/nylas/resources/Contacts.kt index b3314bc8..6175ff29 100644 --- a/src/main/kotlin/com/nylas/resources/Contacts.kt +++ b/src/main/kotlin/com/nylas/resources/Contacts.kt @@ -3,6 +3,7 @@ package com.nylas.resources import com.nylas.NylasClient import com.nylas.models.* import com.nylas.util.JsonHelper +import com.nylas.util.PathEncoder import com.squareup.moshi.Types class Contacts(client: NylasClient) : Resource(client, Contact::class.java) { @@ -31,7 +32,7 @@ class Contacts(client: NylasClient) : Resource(client, Contact::class.j @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun find(identifier: String, contactId: String, queryParams: FindContactQueryParams? = null, overrides: RequestOverrides? = null): Response { - val path = String.format("v3/grants/%s/contacts/%s", identifier, contactId) + val path = String.format("v3/grants/%s/contacts/%s", identifier, PathEncoder.encode(contactId)) return findResource(path, queryParams, overrides) } @@ -62,7 +63,7 @@ class Contacts(client: NylasClient) : Resource(client, Contact::class.j @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun update(identifier: String, contactId: String, requestBody: UpdateContactRequest, overrides: RequestOverrides? = null): Response { - val path = String.format("v3/grants/%s/contacts/%s", identifier, contactId) + val path = String.format("v3/grants/%s/contacts/%s", identifier, PathEncoder.encode(contactId)) val adapter = JsonHelper.moshi().adapter(UpdateContactRequest::class.java) val serializedRequestBody = adapter.toJson(requestBody) return updateResource(path, serializedRequestBody, overrides = overrides) @@ -78,7 +79,7 @@ class Contacts(client: NylasClient) : Resource(client, Contact::class.j @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun destroy(identifier: String, contactId: String, overrides: RequestOverrides? = null): DeleteResponse { - val path = String.format("v3/grants/%s/contacts/%s", identifier, contactId) + val path = String.format("v3/grants/%s/contacts/%s", identifier, PathEncoder.encode(contactId)) return destroyResource(path, overrides = overrides) } diff --git a/src/main/kotlin/com/nylas/resources/Credentials.kt b/src/main/kotlin/com/nylas/resources/Credentials.kt index 70dc510a..ba6ca676 100644 --- a/src/main/kotlin/com/nylas/resources/Credentials.kt +++ b/src/main/kotlin/com/nylas/resources/Credentials.kt @@ -3,6 +3,7 @@ package com.nylas.resources import com.nylas.NylasClient import com.nylas.models.* import com.nylas.util.JsonHelper +import com.nylas.util.PathEncoder class Credentials(client: NylasClient) : Resource(client, Credential::class.java) { /** @@ -29,7 +30,7 @@ class Credentials(client: NylasClient) : Resource(client, Credential @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun find(provider: AuthProvider, credentialsId: String, overrides: RequestOverrides? = null): Response { - val path = String.format("v3/connectors/%s/creds/%s", provider.value, credentialsId) + val path = String.format("v3/connectors/%s/creds/%s", provider.value, PathEncoder.encode(credentialsId)) return findResource(path, overrides = overrides) } @@ -62,7 +63,7 @@ class Credentials(client: NylasClient) : Resource(client, Credential @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun update(provider: AuthProvider, credentialsId: String, requestBody: UpdateCredentialRequest, overrides: RequestOverrides? = null): Response { - val path = String.format("v3/connectors/%s/creds/%s", provider.value, credentialsId) + val path = String.format("v3/connectors/%s/creds/%s", provider.value, PathEncoder.encode(credentialsId)) val serializedRequestBody = JsonHelper.moshi() .adapter(UpdateCredentialRequest::class.java) .toJson(requestBody) @@ -80,7 +81,7 @@ class Credentials(client: NylasClient) : Resource(client, Credential @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun destroy(provider: AuthProvider, credentialsId: String, overrides: RequestOverrides? = null): DeleteResponse { - val path = String.format("v3/connectors/%s/creds/%s", provider.value, credentialsId) + val path = String.format("v3/connectors/%s/creds/%s", provider.value, PathEncoder.encode(credentialsId)) return destroyResource(path, overrides = overrides) } } diff --git a/src/main/kotlin/com/nylas/resources/Drafts.kt b/src/main/kotlin/com/nylas/resources/Drafts.kt index 8deb654a..70065bd6 100644 --- a/src/main/kotlin/com/nylas/resources/Drafts.kt +++ b/src/main/kotlin/com/nylas/resources/Drafts.kt @@ -4,6 +4,7 @@ import com.nylas.NylasClient import com.nylas.models.* import com.nylas.util.FileUtils import com.nylas.util.JsonHelper +import com.nylas.util.PathEncoder import com.squareup.moshi.Types class Drafts(client: NylasClient) : Resource(client, Draft::class.java) { @@ -31,7 +32,7 @@ class Drafts(client: NylasClient) : Resource(client, Draft::class.java) { @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun find(identifier: String, draftId: String, overrides: RequestOverrides? = null): Response { - val path = String.format("v3/grants/%s/drafts/%s", identifier, draftId) + val path = String.format("v3/grants/%s/drafts/%s", identifier, PathEncoder.encode(draftId)) return findResource(path, overrides = overrides) } @@ -75,7 +76,7 @@ class Drafts(client: NylasClient) : Resource(client, Draft::class.java) { @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun update(identifier: String, draftId: String, requestBody: UpdateDraftRequest, overrides: RequestOverrides? = null): Response { - val path = String.format("v3/grants/%s/drafts/%s", identifier, draftId) + val path = String.format("v3/grants/%s/drafts/%s", identifier, PathEncoder.encode(draftId)) val responseType = Types.newParameterizedType(Response::class.java, Draft::class.java) val adapter = JsonHelper.moshi().adapter(UpdateDraftRequest::class.java) @@ -104,7 +105,7 @@ class Drafts(client: NylasClient) : Resource(client, Draft::class.java) { @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun destroy(identifier: String, draftId: String, overrides: RequestOverrides? = null): DeleteResponse { - val path = String.format("v3/grants/%s/drafts/%s", identifier, draftId) + val path = String.format("v3/grants/%s/drafts/%s", identifier, PathEncoder.encode(draftId)) return destroyResource(path, overrides = overrides) } @@ -118,7 +119,7 @@ class Drafts(client: NylasClient) : Resource(client, Draft::class.java) { @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun send(identifier: String, draftId: String, overrides: RequestOverrides? = null): Response { - val path = String.format("v3/grants/%s/drafts/%s", identifier, draftId) + val path = String.format("v3/grants/%s/drafts/%s", identifier, PathEncoder.encode(draftId)) val responseType = Types.newParameterizedType(Response::class.java, Message::class.java) return client.executePost(path, responseType, overrides = overrides) } diff --git a/src/main/kotlin/com/nylas/resources/Events.kt b/src/main/kotlin/com/nylas/resources/Events.kt index cb2037a3..93d06528 100644 --- a/src/main/kotlin/com/nylas/resources/Events.kt +++ b/src/main/kotlin/com/nylas/resources/Events.kt @@ -3,6 +3,7 @@ package com.nylas.resources import com.nylas.NylasClient import com.nylas.models.* import com.nylas.util.JsonHelper +import com.nylas.util.PathEncoder /** * Nylas Events API @@ -54,7 +55,7 @@ class Events(client: NylasClient) : Resource(client, Event::class.java) { @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun find(identifier: String, eventId: String, queryParams: FindEventQueryParams, overrides: RequestOverrides? = null): Response { - val path = String.format("v3/grants/%s/events/%s", identifier, eventId) + val path = String.format("v3/grants/%s/events/%s", identifier, PathEncoder.encode(eventId)) return findResource(path, queryParams, overrides) } @@ -87,7 +88,7 @@ class Events(client: NylasClient) : Resource(client, Event::class.java) { @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun update(identifier: String, eventId: String, requestBody: UpdateEventRequest, queryParams: UpdateEventQueryParams, overrides: RequestOverrides? = null): Response { - val path = String.format("v3/grants/%s/events/%s", identifier, eventId) + val path = String.format("v3/grants/%s/events/%s", identifier, PathEncoder.encode(eventId)) val adapter = JsonHelper.moshi().adapter(UpdateEventRequest::class.java) val serializedRequestBody = adapter.toJson(requestBody) return updateResource(path, serializedRequestBody, queryParams, overrides) @@ -104,7 +105,7 @@ class Events(client: NylasClient) : Resource(client, Event::class.java) { @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun destroy(identifier: String, eventId: String, queryParams: DestroyEventQueryParams, overrides: RequestOverrides? = null): DeleteResponse { - val path = String.format("v3/grants/%s/events/%s", identifier, eventId) + val path = String.format("v3/grants/%s/events/%s", identifier, PathEncoder.encode(eventId)) return destroyResource(path, queryParams, overrides) } @@ -120,7 +121,7 @@ class Events(client: NylasClient) : Resource(client, Event::class.java) { @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun sendRsvp(identifier: String, eventId: String, requestBody: SendRsvpRequest, queryParams: SendRsvpQueryParams, overrides: RequestOverrides? = null): DeleteResponse { - val path = String.format("v3/grants/%s/events/%s/send-rsvp", identifier, eventId) + val path = String.format("v3/grants/%s/events/%s/send-rsvp", identifier, PathEncoder.encode(eventId)) val adapter = JsonHelper.moshi().adapter(SendRsvpRequest::class.java) val serializedRequestBody = adapter.toJson(requestBody) diff --git a/src/main/kotlin/com/nylas/resources/Folders.kt b/src/main/kotlin/com/nylas/resources/Folders.kt index 31bfae3b..d479716d 100644 --- a/src/main/kotlin/com/nylas/resources/Folders.kt +++ b/src/main/kotlin/com/nylas/resources/Folders.kt @@ -3,6 +3,7 @@ package com.nylas.resources import com.nylas.NylasClient import com.nylas.models.* import com.nylas.util.JsonHelper +import com.nylas.util.PathEncoder class Folders(client: NylasClient) : Resource(client, Folder::class.java) { /** @@ -29,7 +30,7 @@ class Folders(client: NylasClient) : Resource(client, Folder::class.java @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun find(identifier: String, folderId: String, overrides: RequestOverrides? = null): Response { - val path = String.format("v3/grants/%s/folders/%s", identifier, folderId) + val path = String.format("v3/grants/%s/folders/%s", identifier, PathEncoder.encode(folderId)) return findResource(path, overrides = overrides) } @@ -60,7 +61,7 @@ class Folders(client: NylasClient) : Resource(client, Folder::class.java @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun update(identifier: String, folderId: String, requestBody: UpdateFolderRequest, overrides: RequestOverrides? = null): Response { - val path = String.format("v3/grants/%s/folders/%s", identifier, folderId) + val path = String.format("v3/grants/%s/folders/%s", identifier, PathEncoder.encode(folderId)) val adapter = JsonHelper.moshi().adapter(UpdateFolderRequest::class.java) val serializedRequestBody = adapter.toJson(requestBody) return updateResource(path, serializedRequestBody, overrides = overrides) @@ -76,7 +77,7 @@ class Folders(client: NylasClient) : Resource(client, Folder::class.java @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun destroy(identifier: String, folderId: String, overrides: RequestOverrides? = null): DeleteResponse { - val path = String.format("v3/grants/%s/folders/%s", identifier, folderId) + val path = String.format("v3/grants/%s/folders/%s", identifier, PathEncoder.encode(folderId)) return destroyResource(path, overrides = overrides) } } diff --git a/src/main/kotlin/com/nylas/resources/Messages.kt b/src/main/kotlin/com/nylas/resources/Messages.kt index 0632490b..f66f904c 100644 --- a/src/main/kotlin/com/nylas/resources/Messages.kt +++ b/src/main/kotlin/com/nylas/resources/Messages.kt @@ -4,6 +4,7 @@ import com.nylas.NylasClient import com.nylas.models.* import com.nylas.util.FileUtils import com.nylas.util.JsonHelper +import com.nylas.util.PathEncoder import com.squareup.moshi.Types class Messages(client: NylasClient) : Resource(client, Message::class.java) { @@ -40,7 +41,7 @@ class Messages(client: NylasClient) : Resource(client, Message::class.j @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun find(identifier: String, messageId: String, queryParams: FindMessageQueryParams? = null, overrides: RequestOverrides? = null): Response { - val path = String.format("v3/grants/%s/messages/%s", identifier, messageId) + val path = String.format("v3/grants/%s/messages/%s", identifier, PathEncoder.encode(messageId)) return findResource(path, queryParams, overrides = overrides) } @@ -55,7 +56,7 @@ class Messages(client: NylasClient) : Resource(client, Message::class.j @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun update(identifier: String, messageId: String, requestBody: UpdateMessageRequest, overrides: RequestOverrides? = null): Response { - val path = String.format("v3/grants/%s/messages/%s", identifier, messageId) + val path = String.format("v3/grants/%s/messages/%s", identifier, PathEncoder.encode(messageId)) val adapter = JsonHelper.moshi().adapter(UpdateMessageRequest::class.java) val serializedRequestBody = adapter.toJson(requestBody) return updateResource(path, serializedRequestBody, overrides = overrides) @@ -71,7 +72,7 @@ class Messages(client: NylasClient) : Resource(client, Message::class.j @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun destroy(identifier: String, messageId: String, overrides: RequestOverrides? = null): DeleteResponse { - val path = String.format("v3/grants/%s/messages/%s", identifier, messageId) + val path = String.format("v3/grants/%s/messages/%s", identifier, PathEncoder.encode(messageId)) return destroyResource(path, overrides = overrides) } @@ -128,7 +129,7 @@ class Messages(client: NylasClient) : Resource(client, Message::class.j @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun findScheduledMessage(identifier: String, scheduleId: String, overrides: RequestOverrides? = null): Response { - val path = String.format("v3/grants/%s/messages/schedules/%s", identifier, scheduleId) + val path = String.format("v3/grants/%s/messages/schedules/%s", identifier, PathEncoder.encode(scheduleId)) val responseType = Types.newParameterizedType(Response::class.java, ScheduledMessage::class.java) return client.executeGet(path, responseType, overrides = overrides) } @@ -142,7 +143,7 @@ class Messages(client: NylasClient) : Resource(client, Message::class.j */ @Throws(NylasApiError::class, NylasSdkTimeoutError::class) fun stopScheduledMessage(identifier: String, scheduleId: String, overrides: RequestOverrides? = null): Response { - val path = String.format("v3/grants/%s/messages/schedules/%s", identifier, scheduleId) + val path = String.format("v3/grants/%s/messages/schedules/%s", identifier, PathEncoder.encode(scheduleId)) val responseType = Types.newParameterizedType(Response::class.java, StopScheduledMessageResponse::class.java) return client.executeDelete(path, responseType, overrides = overrides) } diff --git a/src/main/kotlin/com/nylas/resources/Notetakers.kt b/src/main/kotlin/com/nylas/resources/Notetakers.kt index f84f0529..f66c27ad 100644 --- a/src/main/kotlin/com/nylas/resources/Notetakers.kt +++ b/src/main/kotlin/com/nylas/resources/Notetakers.kt @@ -3,6 +3,7 @@ package com.nylas.resources import com.nylas.NylasClient import com.nylas.models.* import com.nylas.util.JsonHelper +import com.nylas.util.PathEncoder import com.squareup.moshi.Types class Notetakers(client: NylasClient) : Resource(client, Notetaker::class.java) { @@ -38,7 +39,7 @@ class Notetakers(client: NylasClient) : Resource(client, Notetaker::c identifier: String? = null, overrides: RequestOverrides? = null, ): Response { - val path = identifier?.let { String.format("v3/grants/%s/notetakers/%s", it, notetakerId) } ?: String.format("v3/notetakers/%s", notetakerId) + val path = identifier?.let { String.format("v3/grants/%s/notetakers/%s", it, PathEncoder.encode(notetakerId)) } ?: String.format("v3/notetakers/%s", PathEncoder.encode(notetakerId)) return findResource(path, overrides = overrides) } @@ -78,7 +79,7 @@ class Notetakers(client: NylasClient) : Resource(client, Notetaker::c identifier: String? = null, overrides: RequestOverrides? = null, ): Response { - val path = identifier?.let { String.format("v3/grants/%s/notetakers/%s", it, notetakerId) } ?: String.format("v3/notetakers/%s", notetakerId) + val path = identifier?.let { String.format("v3/grants/%s/notetakers/%s", it, PathEncoder.encode(notetakerId)) } ?: String.format("v3/notetakers/%s", PathEncoder.encode(notetakerId)) val adapter = JsonHelper.moshi().adapter(UpdateNotetakerRequest::class.java) val serializedRequestBody = adapter.toJson(requestBody) return updateResource(path, serializedRequestBody, overrides = overrides) @@ -98,7 +99,7 @@ class Notetakers(client: NylasClient) : Resource(client, Notetaker::c identifier: String? = null, overrides: RequestOverrides? = null, ): Response { - val path = identifier?.let { String.format("v3/grants/%s/notetakers/%s/leave", it, notetakerId) } ?: String.format("v3/notetakers/%s/leave", notetakerId) + val path = identifier?.let { String.format("v3/grants/%s/notetakers/%s/leave", it, PathEncoder.encode(notetakerId)) } ?: String.format("v3/notetakers/%s/leave", PathEncoder.encode(notetakerId)) val responseType = Types.newParameterizedType(Response::class.java, LeaveNotetakerResponse::class.java) return client.executePost(path, responseType, null, null, overrides) } @@ -117,7 +118,7 @@ class Notetakers(client: NylasClient) : Resource(client, Notetaker::c identifier: String? = null, overrides: RequestOverrides? = null, ): Response { - val path = identifier?.let { String.format("v3/grants/%s/notetakers/%s/media", it, notetakerId) } ?: String.format("v3/notetakers/%s/media", notetakerId) + val path = identifier?.let { String.format("v3/grants/%s/notetakers/%s/media", it, PathEncoder.encode(notetakerId)) } ?: String.format("v3/notetakers/%s/media", PathEncoder.encode(notetakerId)) val type = Types.newParameterizedType(Response::class.java, NotetakerMediaResponse::class.java) return client.executeGet(path, type, null, overrides) } @@ -136,7 +137,7 @@ class Notetakers(client: NylasClient) : Resource(client, Notetaker::c identifier: String? = null, overrides: RequestOverrides? = null, ): DeleteResponse { - val path = identifier?.let { String.format("v3/grants/%s/notetakers/%s/cancel", it, notetakerId) } ?: String.format("v3/notetakers/%s/cancel", notetakerId) + val path = identifier?.let { String.format("v3/grants/%s/notetakers/%s/cancel", it, PathEncoder.encode(notetakerId)) } ?: String.format("v3/notetakers/%s/cancel", PathEncoder.encode(notetakerId)) return destroyResource(path, overrides = overrides) } } diff --git a/src/main/kotlin/com/nylas/resources/RedirectUris.kt b/src/main/kotlin/com/nylas/resources/RedirectUris.kt index 9b2bae65..3a61b7bb 100644 --- a/src/main/kotlin/com/nylas/resources/RedirectUris.kt +++ b/src/main/kotlin/com/nylas/resources/RedirectUris.kt @@ -3,6 +3,7 @@ package com.nylas.resources import com.nylas.NylasClient import com.nylas.models.* import com.nylas.util.JsonHelper +import com.nylas.util.PathEncoder /** * A collection of redirect URI related API endpoints. @@ -33,7 +34,7 @@ class RedirectUris(client: NylasClient) : Resource(client, Redirect @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun find(redirectUriId: String, overrides: RequestOverrides? = null): Response { - val path = String.format("v3/applications/redirect-uris/%s", redirectUriId) + val path = String.format("v3/applications/redirect-uris/%s", PathEncoder.encode(redirectUriId)) return findResource(path, overrides = overrides) } @@ -64,7 +65,7 @@ class RedirectUris(client: NylasClient) : Resource(client, Redirect @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun update(redirectUriId: String, requestBody: UpdateRedirectUriRequest, overrides: RequestOverrides? = null): Response { - val path = String.format("v3/applications/redirect-uris/%s", redirectUriId) + val path = String.format("v3/applications/redirect-uris/%s", PathEncoder.encode(redirectUriId)) val serializedRequestBody = JsonHelper.moshi() .adapter(UpdateRedirectUriRequest::class.java) .toJson(requestBody) @@ -81,7 +82,7 @@ class RedirectUris(client: NylasClient) : Resource(client, Redirect @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun destroy(redirectUriId: String, overrides: RequestOverrides? = null): DeleteResponse { - val path = String.format("v3/applications/redirect-uris/%s", redirectUriId) + val path = String.format("v3/applications/redirect-uris/%s", PathEncoder.encode(redirectUriId)) return destroyResource(path, overrides = overrides) } } diff --git a/src/main/kotlin/com/nylas/resources/Sessions.kt b/src/main/kotlin/com/nylas/resources/Sessions.kt index 2deea690..b34c3851 100644 --- a/src/main/kotlin/com/nylas/resources/Sessions.kt +++ b/src/main/kotlin/com/nylas/resources/Sessions.kt @@ -3,6 +3,7 @@ package com.nylas.resources import com.nylas.NylasClient import com.nylas.models.* import com.nylas.util.JsonHelper +import com.nylas.util.PathEncoder /** * Nylas Sessions API * @@ -35,7 +36,7 @@ class Sessions(client: NylasClient) : Resource(client, Session::class.j @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun destroy(sessionId: String, overrides: RequestOverrides? = null): DeleteResponse { - val path = String.format("v3/scheduling/sessions/%s", sessionId) + val path = String.format("v3/scheduling/sessions/%s", PathEncoder.encode(sessionId)) return destroyResource(path, overrides = overrides) } } diff --git a/src/main/kotlin/com/nylas/resources/Threads.kt b/src/main/kotlin/com/nylas/resources/Threads.kt index 020fc208..3c49c2dc 100644 --- a/src/main/kotlin/com/nylas/resources/Threads.kt +++ b/src/main/kotlin/com/nylas/resources/Threads.kt @@ -3,6 +3,7 @@ package com.nylas.resources import com.nylas.NylasClient import com.nylas.models.* import com.nylas.util.JsonHelper +import com.nylas.util.PathEncoder class Threads(client: NylasClient) : Resource(client, Thread::class.java) { /** @@ -29,7 +30,7 @@ class Threads(client: NylasClient) : Resource(client, Thread::class.java @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun find(identifier: String, threadId: String, overrides: RequestOverrides? = null): Response { - val path = String.format("v3/grants/%s/threads/%s", identifier, threadId) + val path = String.format("v3/grants/%s/threads/%s", identifier, PathEncoder.encode(threadId)) return findResource(path, overrides = overrides) } @@ -44,7 +45,7 @@ class Threads(client: NylasClient) : Resource(client, Thread::class.java @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun update(identifier: String, threadId: String, requestBody: UpdateThreadRequest, overrides: RequestOverrides? = null): Response { - val path = String.format("v3/grants/%s/threads/%s", identifier, threadId) + val path = String.format("v3/grants/%s/threads/%s", identifier, PathEncoder.encode(threadId)) val adapter = JsonHelper.moshi().adapter(UpdateThreadRequest::class.java) val serializedRequestBody = adapter.toJson(requestBody) return updateResource(path, serializedRequestBody, overrides = overrides) @@ -60,7 +61,7 @@ class Threads(client: NylasClient) : Resource(client, Thread::class.java @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun destroy(identifier: String, threadId: String, overrides: RequestOverrides? = null): DeleteResponse { - val path = String.format("v3/grants/%s/threads/%s", identifier, threadId) + val path = String.format("v3/grants/%s/threads/%s", identifier, PathEncoder.encode(threadId)) return destroyResource(path, overrides = overrides) } } diff --git a/src/main/kotlin/com/nylas/resources/Webhooks.kt b/src/main/kotlin/com/nylas/resources/Webhooks.kt index 0b12c74f..5bedbf9f 100644 --- a/src/main/kotlin/com/nylas/resources/Webhooks.kt +++ b/src/main/kotlin/com/nylas/resources/Webhooks.kt @@ -3,6 +3,7 @@ package com.nylas.resources import com.nylas.NylasClient import com.nylas.models.* import com.nylas.util.JsonHelper +import com.nylas.util.PathEncoder import com.squareup.moshi.Types import java.net.URI import java.util.* @@ -34,7 +35,7 @@ class Webhooks(client: NylasClient) : Resource(client, Webhook::class.j @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun find(webhookId: String, overrides: RequestOverrides? = null): Response { - val path = String.format("v3/webhooks/%s", webhookId) + val path = String.format("v3/webhooks/%s", PathEncoder.encode(webhookId)) return findResource(path, overrides = overrides) } @@ -64,7 +65,7 @@ class Webhooks(client: NylasClient) : Resource(client, Webhook::class.j @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun update(webhookId: String, requestBody: UpdateWebhookRequest, overrides: RequestOverrides? = null): Response { - val path = String.format("v3/webhooks/%s", webhookId) + val path = String.format("v3/webhooks/%s", PathEncoder.encode(webhookId)) val adapter = JsonHelper.moshi().adapter(UpdateWebhookRequest::class.java) val serializedRequestBody = adapter.toJson(requestBody) return updateResource(path, serializedRequestBody, overrides = overrides) @@ -79,7 +80,7 @@ class Webhooks(client: NylasClient) : Resource(client, Webhook::class.j @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun destroy(webhookId: String, overrides: RequestOverrides? = null): WebhookDeleteResponse { - val path = String.format("v3/webhooks/%s", webhookId) + val path = String.format("v3/webhooks/%s", PathEncoder.encode(webhookId)) return client.executeDelete(path, WebhookDeleteResponse::class.java, overrides = overrides) } @@ -92,7 +93,7 @@ class Webhooks(client: NylasClient) : Resource(client, Webhook::class.j @Throws(NylasApiError::class, NylasSdkTimeoutError::class) @JvmOverloads fun rotateSecret(webhookId: String, overrides: RequestOverrides? = null): Response { - val path = String.format("v3/webhooks/rotate-secret/%s", webhookId) + val path = String.format("v3/webhooks/rotate-secret/%s", PathEncoder.encode(webhookId)) val responseType = Types.newParameterizedType(Response::class.java, WebhookWithSecret::class.java) return client.executePost(path, responseType, overrides = overrides) } diff --git a/src/main/kotlin/com/nylas/util/PathEncoder.kt b/src/main/kotlin/com/nylas/util/PathEncoder.kt new file mode 100644 index 00000000..6c221a2d --- /dev/null +++ b/src/main/kotlin/com/nylas/util/PathEncoder.kt @@ -0,0 +1,13 @@ +package com.nylas.util + +import java.io.UnsupportedEncodingException +import java.net.URLEncoder + +object PathEncoder { + fun encode(segment: String): String = + try { + URLEncoder.encode(segment, "UTF-8").replace("+", "%20") + } catch (e: UnsupportedEncodingException) { + throw RuntimeException(e) + } +} diff --git a/src/test/kotlin/com/nylas/resources/AttachmentsTests.kt b/src/test/kotlin/com/nylas/resources/AttachmentsTests.kt index 865616f5..c04c61fb 100644 --- a/src/test/kotlin/com/nylas/resources/AttachmentsTests.kt +++ b/src/test/kotlin/com/nylas/resources/AttachmentsTests.kt @@ -140,5 +140,26 @@ class AttachmentsTests { assertEquals("v3/grants/$grantId/attachments/$attachmentId/download", pathCaptor.firstValue) assertEquals(byteArray, bytes) } + + @Test + fun `finding an attachment URL-encodes an attachment id containing slashes`() { + val slashedAttachmentId = "INBOX/attach-123" + val slashedQueryParams = FindAttachmentQueryParams(messageId = "msg-1") + + attachments.find(grantId, slashedAttachmentId, slashedQueryParams) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executeGet>( + pathCaptor.capture(), + typeCaptor.capture(), + queryParamCaptor.capture(), + overrideParamCaptor.capture(), + ) + + assertEquals("v3/grants/$grantId/attachments/INBOX%2Fattach-123", pathCaptor.firstValue) + } } } diff --git a/src/test/kotlin/com/nylas/resources/BookingsTest.kt b/src/test/kotlin/com/nylas/resources/BookingsTest.kt index 754996cf..fc8f943f 100644 --- a/src/test/kotlin/com/nylas/resources/BookingsTest.kt +++ b/src/test/kotlin/com/nylas/resources/BookingsTest.kt @@ -215,5 +215,25 @@ class BookingsTest { assertEquals(adapter.toJson(requestBody), requestBodyCaptor.firstValue) assertEquals(queryParams, queryParamCaptor.firstValue) } + + @Test + fun `finding a booking URL-encodes a booking id containing slashes`() { + val slashedBookingId = "prefix/booking-123" + + bookings.find(slashedBookingId) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executeGet>( + pathCaptor.capture(), + typeCaptor.capture(), + queryParamCaptor.capture(), + overrideParamCaptor.capture(), + ) + + assertEquals("v3/scheduling/bookings/prefix%2Fbooking-123", pathCaptor.firstValue) + } } } diff --git a/src/test/kotlin/com/nylas/resources/CalendarsTest.kt b/src/test/kotlin/com/nylas/resources/CalendarsTest.kt index 3e267487..6458fc06 100644 --- a/src/test/kotlin/com/nylas/resources/CalendarsTest.kt +++ b/src/test/kotlin/com/nylas/resources/CalendarsTest.kt @@ -469,6 +469,46 @@ class CalendarsTest { assertEquals("v3/grants/$grantId/calendars/$calendarId", pathCaptor.firstValue) assertEquals(DeleteResponse::class.java, typeCaptor.firstValue) } + + @Test + fun `finding a calendar URL-encodes a calendar id containing slashes`() { + val calendarId = "prefix/cal-123" + + calendars.find(grantId, calendarId) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executeGet>( + pathCaptor.capture(), + typeCaptor.capture(), + queryParamCaptor.capture(), + overrideParamCaptor.capture(), + ) + + assertEquals("v3/grants/$grantId/calendars/prefix%2Fcal-123", pathCaptor.firstValue) + } + + @Test + fun `destroying a calendar URL-encodes a calendar id containing slashes`() { + val calendarId = "prefix/cal-123" + + calendars.destroy(grantId, calendarId) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executeDelete>( + pathCaptor.capture(), + typeCaptor.capture(), + queryParamCaptor.capture(), + overrideParamCaptor.capture(), + ) + + assertEquals("v3/grants/$grantId/calendars/prefix%2Fcal-123", pathCaptor.firstValue) + } } @Nested diff --git a/src/test/kotlin/com/nylas/resources/ConfigurationsTest.kt b/src/test/kotlin/com/nylas/resources/ConfigurationsTest.kt index cb34cde1..a2edde00 100644 --- a/src/test/kotlin/com/nylas/resources/ConfigurationsTest.kt +++ b/src/test/kotlin/com/nylas/resources/ConfigurationsTest.kt @@ -669,5 +669,25 @@ class ConfigurationsTest { assert(serializedRequest.contains("\"Project Information\"")) assert(serializedRequest.contains("\"additional_fields\"")) } + + @Test + fun `finding a configuration URL-encodes a config id containing slashes`() { + val slashedConfigId = "prefix/config-123" + + configurations.find(grantId, slashedConfigId) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executeGet>( + pathCaptor.capture(), + typeCaptor.capture(), + queryParamCaptor.capture(), + overrideParamCaptor.capture(), + ) + + assertEquals("v3/grants/$grantId/scheduling/configurations/prefix%2Fconfig-123", pathCaptor.firstValue) + } } } diff --git a/src/test/kotlin/com/nylas/resources/ContactsTests.kt b/src/test/kotlin/com/nylas/resources/ContactsTests.kt index c2710025..b53b7601 100644 --- a/src/test/kotlin/com/nylas/resources/ContactsTests.kt +++ b/src/test/kotlin/com/nylas/resources/ContactsTests.kt @@ -515,5 +515,45 @@ class ContactsTests { assertEquals(Types.newParameterizedType(ListResponse::class.java, ContactGroup::class.java), typeCaptor.firstValue) assertNull(queryParamCaptor.firstValue) } + + @Test + fun `finding a contact URL-encodes a contact id containing slashes`() { + val contactId = "prefix/contact-123" + + contacts.find(grantId, contactId) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executeGet>( + pathCaptor.capture(), + typeCaptor.capture(), + queryParamCaptor.capture(), + overrideParamCaptor.capture(), + ) + + assertEquals("v3/grants/$grantId/contacts/prefix%2Fcontact-123", pathCaptor.firstValue) + } + + @Test + fun `destroying a contact URL-encodes a contact id containing slashes`() { + val contactId = "prefix/contact-123" + + contacts.destroy(grantId, contactId) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executeDelete>( + pathCaptor.capture(), + typeCaptor.capture(), + queryParamCaptor.capture(), + overrideParamCaptor.capture(), + ) + + assertEquals("v3/grants/$grantId/contacts/prefix%2Fcontact-123", pathCaptor.firstValue) + } } } diff --git a/src/test/kotlin/com/nylas/resources/CredentialsTests.kt b/src/test/kotlin/com/nylas/resources/CredentialsTests.kt index a3af419f..789d9952 100644 --- a/src/test/kotlin/com/nylas/resources/CredentialsTests.kt +++ b/src/test/kotlin/com/nylas/resources/CredentialsTests.kt @@ -442,5 +442,25 @@ class CredentialsTests { assertEquals("new-client-secret", credentialData["client_secret"]) assertEquals("my-tenant", credentialData["tenant"]) } + + @Test + fun `finding a credential URL-encodes a credential id containing slashes`() { + val slashedCredentialId = "prefix/cred-123" + + credentials.find(AuthProvider.IMAP, slashedCredentialId) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executeGet>( + pathCaptor.capture(), + typeCaptor.capture(), + queryParamCaptor.capture(), + overrideParamCaptor.capture(), + ) + + assertEquals("v3/connectors/imap/creds/prefix%2Fcred-123", pathCaptor.firstValue) + } } } diff --git a/src/test/kotlin/com/nylas/resources/DraftsTests.kt b/src/test/kotlin/com/nylas/resources/DraftsTests.kt index 23878253..0cf30bee 100644 --- a/src/test/kotlin/com/nylas/resources/DraftsTests.kt +++ b/src/test/kotlin/com/nylas/resources/DraftsTests.kt @@ -630,5 +630,45 @@ class DraftsTests { assertEquals(Types.newParameterizedType(Response::class.java, Message::class.java), typeCaptor.firstValue) assertNull(requestBodyCaptor.firstValue) } + + @Test + fun `finding a draft URL-encodes a draft id containing slashes`() { + val draftId = "INBOX/draft-123" + + drafts.find(grantId, draftId) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executeGet>( + pathCaptor.capture(), + typeCaptor.capture(), + queryParamCaptor.capture(), + overrideParamCaptor.capture(), + ) + + assertEquals("v3/grants/$grantId/drafts/INBOX%2Fdraft-123", pathCaptor.firstValue) + } + + @Test + fun `destroying a draft URL-encodes a draft id containing slashes`() { + val draftId = "INBOX/draft-123" + + drafts.destroy(grantId, draftId) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executeDelete>( + pathCaptor.capture(), + typeCaptor.capture(), + queryParamCaptor.capture(), + overrideParamCaptor.capture(), + ) + + assertEquals("v3/grants/$grantId/drafts/INBOX%2Fdraft-123", pathCaptor.firstValue) + } } } diff --git a/src/test/kotlin/com/nylas/resources/EventsTests.kt b/src/test/kotlin/com/nylas/resources/EventsTests.kt index 8f6ffac5..a3aa2087 100644 --- a/src/test/kotlin/com/nylas/resources/EventsTests.kt +++ b/src/test/kotlin/com/nylas/resources/EventsTests.kt @@ -1249,5 +1249,47 @@ class EventsTests { assertEquals(DeleteResponse::class.java, typeCaptor.firstValue) assertEquals(adapter.toJson(sendRsvpRequest), requestBodyCaptor.firstValue) } + + @Test + fun `finding an event URL-encodes an event id containing slashes`() { + val eventId = "prefix/event-123" + val queryParams = FindEventQueryParams(calendarId = "cal-1") + + events.find(grantId, eventId, queryParams) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executeGet>( + pathCaptor.capture(), + typeCaptor.capture(), + queryParamCaptor.capture(), + overrideParamCaptor.capture(), + ) + + assertEquals("v3/grants/$grantId/events/prefix%2Fevent-123", pathCaptor.firstValue) + } + + @Test + fun `destroying an event URL-encodes an event id containing slashes`() { + val eventId = "prefix/event-123" + val queryParams = DestroyEventQueryParams(calendarId = "cal-1") + + events.destroy(grantId, eventId, queryParams) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executeDelete>( + pathCaptor.capture(), + typeCaptor.capture(), + queryParamCaptor.capture(), + overrideParamCaptor.capture(), + ) + + assertEquals("v3/grants/$grantId/events/prefix%2Fevent-123", pathCaptor.firstValue) + } } } diff --git a/src/test/kotlin/com/nylas/resources/FoldersTests.kt b/src/test/kotlin/com/nylas/resources/FoldersTests.kt index 3c12f845..c5f35cc9 100644 --- a/src/test/kotlin/com/nylas/resources/FoldersTests.kt +++ b/src/test/kotlin/com/nylas/resources/FoldersTests.kt @@ -389,5 +389,45 @@ class FoldersTests { assertEquals(DeleteResponse::class.java, typeCaptor.firstValue) assertNull(queryParamCaptor.firstValue) } + + @Test + fun `finding a folder URL-encodes a folder id containing slashes`() { + val folderId = "INBOX/folder-123" + + folders.find(grantId, folderId) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executeGet>( + pathCaptor.capture(), + typeCaptor.capture(), + queryParamCaptor.capture(), + overrideParamCaptor.capture(), + ) + + assertEquals("v3/grants/$grantId/folders/INBOX%2Ffolder-123", pathCaptor.firstValue) + } + + @Test + fun `destroying a folder URL-encodes a folder id containing slashes`() { + val folderId = "INBOX/folder-123" + + folders.destroy(grantId, folderId) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executeDelete>( + pathCaptor.capture(), + typeCaptor.capture(), + queryParamCaptor.capture(), + overrideParamCaptor.capture(), + ) + + assertEquals("v3/grants/$grantId/folders/INBOX%2Ffolder-123", pathCaptor.firstValue) + } } } diff --git a/src/test/kotlin/com/nylas/resources/MessagesTests.kt b/src/test/kotlin/com/nylas/resources/MessagesTests.kt index 8c2808b5..9efe3052 100644 --- a/src/test/kotlin/com/nylas/resources/MessagesTests.kt +++ b/src/test/kotlin/com/nylas/resources/MessagesTests.kt @@ -429,6 +429,46 @@ class MessagesTests { assertEquals(DeleteResponse::class.java, typeCaptor.firstValue) assertNull(queryParamCaptor.firstValue) } + + @Test + fun `finding a message URL-encodes a message id containing slashes`() { + val messageId = "INBOX/message-123" + + messages.find(grantId, messageId) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executeGet>( + pathCaptor.capture(), + typeCaptor.capture(), + queryParamCaptor.capture(), + overrideParamCaptor.capture(), + ) + + assertEquals("v3/grants/$grantId/messages/INBOX%2Fmessage-123", pathCaptor.firstValue) + } + + @Test + fun `destroying a message URL-encodes a message id containing slashes`() { + val messageId = "INBOX/message-123" + + messages.destroy(grantId, messageId) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executeDelete>( + pathCaptor.capture(), + typeCaptor.capture(), + queryParamCaptor.capture(), + overrideParamCaptor.capture(), + ) + + assertEquals("v3/grants/$grantId/messages/INBOX%2Fmessage-123", pathCaptor.firstValue) + } } @Nested diff --git a/src/test/kotlin/com/nylas/resources/NotetakersTests.kt b/src/test/kotlin/com/nylas/resources/NotetakersTests.kt index 221fb91c..4ceea497 100644 --- a/src/test/kotlin/com/nylas/resources/NotetakersTests.kt +++ b/src/test/kotlin/com/nylas/resources/NotetakersTests.kt @@ -333,5 +333,24 @@ class NotetakersTests { assertEquals(DeleteResponse::class.java, typeCaptor.firstValue) assertNull(queryParamCaptor.firstValue) } + + @Test + fun `finding a notetaker URL-encodes a notetaker id containing slashes`() { + val slashedNotetakerId = "prefix/notetaker-123" + + notetakers.find(slashedNotetakerId, grantId) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executeGet>( + pathCaptor.capture(), + typeCaptor.capture(), + isNull(), + overrideParamCaptor.capture(), + ) + + assertEquals("v3/grants/$grantId/notetakers/prefix%2Fnotetaker-123", pathCaptor.firstValue) + } } } diff --git a/src/test/kotlin/com/nylas/resources/RedirectUriTests.kt b/src/test/kotlin/com/nylas/resources/RedirectUriTests.kt index 3212ada4..e124a862 100644 --- a/src/test/kotlin/com/nylas/resources/RedirectUriTests.kt +++ b/src/test/kotlin/com/nylas/resources/RedirectUriTests.kt @@ -216,5 +216,25 @@ class RedirectUriTests { assertEquals("v3/applications/redirect-uris/$redirectUriId", pathCaptor.firstValue) assertEquals(DeleteResponse::class.java, typeCaptor.firstValue) } + + @Test + fun `finding a redirectUri URL-encodes a redirectUri id containing slashes`() { + val slashedRedirectUriId = "prefix/uri-123" + + redirectUris.find(slashedRedirectUriId) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executeGet>( + pathCaptor.capture(), + typeCaptor.capture(), + queryParamCaptor.capture(), + overrideParamCaptor.capture(), + ) + + assertEquals("v3/applications/redirect-uris/prefix%2Furi-123", pathCaptor.firstValue) + } } } diff --git a/src/test/kotlin/com/nylas/resources/SessionsTest.kt b/src/test/kotlin/com/nylas/resources/SessionsTest.kt index 8a32f673..af7837c6 100644 --- a/src/test/kotlin/com/nylas/resources/SessionsTest.kt +++ b/src/test/kotlin/com/nylas/resources/SessionsTest.kt @@ -99,5 +99,25 @@ class SessionsTest { assertEquals("v3/scheduling/sessions/$sessionId", pathCaptor.firstValue) assertEquals(DeleteResponse::class.java, typeCaptor.firstValue) } + + @Test + fun `deleting a session URL-encodes a session id containing slashes`() { + val slashedSessionId = "prefix/session-123" + + sessions.destroy(slashedSessionId) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executeDelete( + pathCaptor.capture(), + typeCaptor.capture(), + queryParamCaptor.capture(), + overrideParamCaptor.capture(), + ) + + assertEquals("v3/scheduling/sessions/prefix%2Fsession-123", pathCaptor.firstValue) + } } } diff --git a/src/test/kotlin/com/nylas/resources/ThreadsTests.kt b/src/test/kotlin/com/nylas/resources/ThreadsTests.kt index e90b77c3..e430954f 100644 --- a/src/test/kotlin/com/nylas/resources/ThreadsTests.kt +++ b/src/test/kotlin/com/nylas/resources/ThreadsTests.kt @@ -266,6 +266,62 @@ class ThreadsTests { assertNull(queryParamCaptor.firstValue) } + @Test + fun `finding a thread URL-encodes a thread id containing slashes`() { + val threadId = "INBOX/thread-123" + + threads.find(grantId, threadId) + + val pathCaptor = argumentCaptor() + verify(mockNylasClient).executeGet>( + pathCaptor.capture(), + any(), + anyOrNull(), + anyOrNull(), + ) + + assertEquals("v3/grants/$grantId/threads/INBOX%2Fthread-123", pathCaptor.firstValue) + } + + @Test + fun `updating a thread URL-encodes a thread id containing slashes`() { + val threadId = "INBOX/thread-123" + val updateThreadRequest = UpdateThreadRequest(starred = true) + + threads.update(grantId, threadId, updateThreadRequest) + + val pathCaptor = argumentCaptor() + verify(mockNylasClient).executePut>( + pathCaptor.capture(), + any(), + any(), + anyOrNull(), + anyOrNull(), + ) + + assertEquals("v3/grants/$grantId/threads/INBOX%2Fthread-123", pathCaptor.firstValue) + } + + @Test + fun `destroying a thread URL-encodes a thread id containing slashes`() { + val threadId = "INBOX/thread-123" + + threads.destroy(grantId, threadId) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executeDelete>( + pathCaptor.capture(), + typeCaptor.capture(), + queryParamCaptor.capture(), + overrideParamCaptor.capture(), + ) + + assertEquals("v3/grants/$grantId/threads/INBOX%2Fthread-123", pathCaptor.firstValue) + } + @Test fun `updating a thread calls requests with the correct params`() { val threadId = "thread-123" diff --git a/src/test/kotlin/com/nylas/resources/WebhooksTests.kt b/src/test/kotlin/com/nylas/resources/WebhooksTests.kt index c9131cec..54180419 100644 --- a/src/test/kotlin/com/nylas/resources/WebhooksTests.kt +++ b/src/test/kotlin/com/nylas/resources/WebhooksTests.kt @@ -288,5 +288,25 @@ class WebhooksTests { assertIs(e) } } + + @Test + fun `finding a webhook URL-encodes a webhook id containing slashes`() { + val webhookId = "prefix/webhook-123" + + webhooks.find(webhookId) + + val pathCaptor = argumentCaptor() + val typeCaptor = argumentCaptor() + val queryParamCaptor = argumentCaptor() + val overrideParamCaptor = argumentCaptor() + verify(mockNylasClient).executeGet>( + pathCaptor.capture(), + typeCaptor.capture(), + queryParamCaptor.capture(), + overrideParamCaptor.capture(), + ) + + assertEquals("v3/webhooks/prefix%2Fwebhook-123", pathCaptor.firstValue) + } } } diff --git a/src/test/kotlin/com/nylas/util/PathEncoderTest.kt b/src/test/kotlin/com/nylas/util/PathEncoderTest.kt new file mode 100644 index 00000000..2fdfdd67 --- /dev/null +++ b/src/test/kotlin/com/nylas/util/PathEncoderTest.kt @@ -0,0 +1,47 @@ +package com.nylas.util + +import kotlin.test.Test +import kotlin.test.assertEquals + +class PathEncoderTest { + @Test + fun `plain ASCII strings are returned unchanged`() { + assertEquals("thread-123", PathEncoder.encode("thread-123")) + } + + @Test + fun `forward slash is encoded as %2F`() { + assertEquals("INBOX%2Fthread-123", PathEncoder.encode("INBOX/thread-123")) + } + + @Test + fun `multiple slashes are all encoded`() { + assertEquals("a%2Fb%2Fc", PathEncoder.encode("a/b/c")) + } + + @Test + fun `space is encoded as %20 not plus`() { + assertEquals("hello%20world", PathEncoder.encode("hello world")) + } + + @Test + fun `at sign is encoded as %40`() { + assertEquals("user%40example.com", PathEncoder.encode("user@example.com")) + } + + @Test + fun `plus sign is encoded as %2B`() { + assertEquals("a%2Bb", PathEncoder.encode("a+b")) + } + + @Test + fun `empty string returns empty string`() { + assertEquals("", PathEncoder.encode("")) + } + + @Test + fun `UUID-style IDs are returned unchanged`() { + val uuid = "ca8f1733-6063-40cc-a2e3-ec7274abef11" + assertEquals(uuid, PathEncoder.encode(uuid)) + } +}