From 0a3df39d3573bd1d804e7fe65553bdcd16de27e3 Mon Sep 17 00:00:00 2001 From: mayorjay Date: Mon, 13 Nov 2023 22:19:18 +0100 Subject: [PATCH 1/3] feat: Implement Organizations API --- Readme.md | 11 + src/main/kotlin/Novu.kt | 3 + src/main/kotlin/api/OrganizationsApi.kt | 50 ++++ src/main/kotlin/dto/Branding.kt | 10 + src/main/kotlin/dto/InviteDetails.kt | 12 + src/main/kotlin/dto/PartnerConfigurations.kt | 9 + src/main/kotlin/dto/UserDetails.kt | 11 + .../dto/request/CreateOrganizationRequest.kt | 6 + .../dto/request/UpdateMemberRoleRequest.kt | 5 + .../request/UpdateOrganizationBrandRequest.kt | 9 + .../request/UpdateOrganizationNameRequest.kt | 5 + .../kotlin/dto/response/MemberResponse.kt | 18 ++ .../dto/response/OrganizationResponse.kt | 11 + .../UpdateOrganizationNameResponse.kt | 5 + .../extensions/OrganizationsExtensions.kt | 56 ++++ src/test/kotlin/OrganizationsApiTest.kt | 242 ++++++++++++++++++ 16 files changed, 463 insertions(+) create mode 100644 src/main/kotlin/api/OrganizationsApi.kt create mode 100644 src/main/kotlin/dto/Branding.kt create mode 100644 src/main/kotlin/dto/InviteDetails.kt create mode 100644 src/main/kotlin/dto/PartnerConfigurations.kt create mode 100644 src/main/kotlin/dto/UserDetails.kt create mode 100644 src/main/kotlin/dto/request/CreateOrganizationRequest.kt create mode 100644 src/main/kotlin/dto/request/UpdateMemberRoleRequest.kt create mode 100644 src/main/kotlin/dto/request/UpdateOrganizationBrandRequest.kt create mode 100644 src/main/kotlin/dto/request/UpdateOrganizationNameRequest.kt create mode 100644 src/main/kotlin/dto/response/MemberResponse.kt create mode 100644 src/main/kotlin/dto/response/OrganizationResponse.kt create mode 100644 src/main/kotlin/dto/response/UpdateOrganizationNameResponse.kt create mode 100644 src/main/kotlin/extensions/OrganizationsExtensions.kt create mode 100644 src/test/kotlin/OrganizationsApiTest.kt diff --git a/Readme.md b/Readme.md index 1a5b32c..4749473 100644 --- a/Readme.md +++ b/Readme.md @@ -207,6 +207,17 @@ The client methods map directly to the Novu API endpoints. Here is a list of all - `updateTenant(identifier)` - `deleteTenant(identifier)` +### Organizations + +- `createOrganization(body)` +- `fetchAllOrganizations()` +- `updateOrganizationName(body)` +- `fetchCurrentOrganization()` +- `removeMemberWithId(identifier)` +- `updateMemberRole(identifier, body)` +- `fetchMembersOfOrganization()` +- `updateOrganizationBrand(body)` + ### For more information about these methods and their parameters, see the [API documentation](https://docs.novu.co/api-reference/overview). ## Contributing diff --git a/src/main/kotlin/Novu.kt b/src/main/kotlin/Novu.kt index 3e85ca9..f50a24d 100644 --- a/src/main/kotlin/Novu.kt +++ b/src/main/kotlin/Novu.kt @@ -13,6 +13,7 @@ import co.novu.api.MessagesApi import co.novu.api.NotificationGroupsApi import co.novu.api.NotificationTemplatesApi import co.novu.api.NotificationsApi +import co.novu.api.OrganizationsApi import co.novu.api.SubscribersApi import co.novu.api.TenantsApi import co.novu.api.TopicsApi @@ -65,4 +66,6 @@ class Novu( internal val blueprintsApi by lazy { retrofitInstance.create(BlueprintsApi::class.java) } internal val tenantsApi by lazy { retrofitInstance.create(TenantsApi::class.java) } + + internal val organizationsApi by lazy { retrofitInstance.create(OrganizationsApi::class.java) } } diff --git a/src/main/kotlin/api/OrganizationsApi.kt b/src/main/kotlin/api/OrganizationsApi.kt new file mode 100644 index 0000000..77720ed --- /dev/null +++ b/src/main/kotlin/api/OrganizationsApi.kt @@ -0,0 +1,50 @@ +package co.novu.api + +import co.novu.dto.request.CreateOrganizationRequest +import co.novu.dto.response.ResponseWrapper +import dto.Branding +import dto.request.UpdateMemberRoleRequest +import dto.request.UpdateOrganizationBrandRequest +import dto.request.UpdateOrganizationNameRequest +import dto.response.MemberResponse +import dto.response.OrganizationResponse +import dto.response.UpdateOrganizationNameResponse +import retrofit2.Response +import retrofit2.http.Body +import retrofit2.http.DELETE +import retrofit2.http.GET +import retrofit2.http.PATCH +import retrofit2.http.POST +import retrofit2.http.PUT +import retrofit2.http.Path + +interface OrganizationsApi { + + companion object { + const val ENDPOINT = "organizations" + } + + @POST(ENDPOINT) + suspend fun createOrganization(@Body request: CreateOrganizationRequest): Response> + + @GET(ENDPOINT) + suspend fun fetchAllOrganizations(): Response>> + + @PATCH(ENDPOINT) + suspend fun updateOrganizationName(@Body request: UpdateOrganizationNameRequest): Response> + + @GET("$ENDPOINT/me") + suspend fun fetchCurrentOrganization(): Response> + + @DELETE("$ENDPOINT/members/{memberId}") + suspend fun removeMemberWithId(@Path("memberId") memberId: String): Response> + + @PUT("$ENDPOINT/members/{memberId}/roles") + suspend fun updateMemberRole(@Path("memberId") memberId: String, @Body request: UpdateMemberRoleRequest): Response> + + @GET("$ENDPOINT/members") + suspend fun fetchMembersOfOrganization(): Response>> + + @PUT("$ENDPOINT/branding") + suspend fun updateOrganizationBrand(@Body request: UpdateOrganizationBrandRequest): Response> +} diff --git a/src/main/kotlin/dto/Branding.kt b/src/main/kotlin/dto/Branding.kt new file mode 100644 index 0000000..b7fe2e1 --- /dev/null +++ b/src/main/kotlin/dto/Branding.kt @@ -0,0 +1,10 @@ +package dto + +data class Branding( + var direction: String? = null, + var logo: String? = null, + var color: String? = null, + var fontColor: String? = null, + var contentBackground: String? = null, + var fontFamily: String? = null +) diff --git a/src/main/kotlin/dto/InviteDetails.kt b/src/main/kotlin/dto/InviteDetails.kt new file mode 100644 index 0000000..242e3e1 --- /dev/null +++ b/src/main/kotlin/dto/InviteDetails.kt @@ -0,0 +1,12 @@ +package dto + +import com.google.gson.annotations.SerializedName + +data class InviteDetails( + var email: String? = null, + var token: String? = null, + var invitationDate: String? = null, + var answerDate: String? = null, + @SerializedName("_inviterId") + var inviterId: String? = null +) diff --git a/src/main/kotlin/dto/PartnerConfigurations.kt b/src/main/kotlin/dto/PartnerConfigurations.kt new file mode 100644 index 0000000..24f4b94 --- /dev/null +++ b/src/main/kotlin/dto/PartnerConfigurations.kt @@ -0,0 +1,9 @@ +package dto + +data class PartnerConfigurations( + var projectIds: List? = null, + var accessToken: String? = null, + var configurationId: String? = null, + var teamId: String? = null, + var partnerType: String? = null +) diff --git a/src/main/kotlin/dto/UserDetails.kt b/src/main/kotlin/dto/UserDetails.kt new file mode 100644 index 0000000..2d83b02 --- /dev/null +++ b/src/main/kotlin/dto/UserDetails.kt @@ -0,0 +1,11 @@ +package dto + +import com.google.gson.annotations.SerializedName + +data class UserDetails( + @SerializedName("_id") + var id: String? = null, + var firstName: String? = null, + var lastName: String? = null, + var email: String? = null +) diff --git a/src/main/kotlin/dto/request/CreateOrganizationRequest.kt b/src/main/kotlin/dto/request/CreateOrganizationRequest.kt new file mode 100644 index 0000000..837568e --- /dev/null +++ b/src/main/kotlin/dto/request/CreateOrganizationRequest.kt @@ -0,0 +1,6 @@ +package co.novu.dto.request + +data class CreateOrganizationRequest( + var name: String? = null, + var logo: String? = null +) diff --git a/src/main/kotlin/dto/request/UpdateMemberRoleRequest.kt b/src/main/kotlin/dto/request/UpdateMemberRoleRequest.kt new file mode 100644 index 0000000..13fc35f --- /dev/null +++ b/src/main/kotlin/dto/request/UpdateMemberRoleRequest.kt @@ -0,0 +1,5 @@ +package dto.request + +data class UpdateMemberRoleRequest( + var role: String? = null +) diff --git a/src/main/kotlin/dto/request/UpdateOrganizationBrandRequest.kt b/src/main/kotlin/dto/request/UpdateOrganizationBrandRequest.kt new file mode 100644 index 0000000..b6d8876 --- /dev/null +++ b/src/main/kotlin/dto/request/UpdateOrganizationBrandRequest.kt @@ -0,0 +1,9 @@ +package dto.request + +data class UpdateOrganizationBrandRequest( + var logo: String? = null, + var color: String? = null, + var fontColor: String? = null, + var contentBackground: String? = null, + var fontFamily: String? = null +) diff --git a/src/main/kotlin/dto/request/UpdateOrganizationNameRequest.kt b/src/main/kotlin/dto/request/UpdateOrganizationNameRequest.kt new file mode 100644 index 0000000..413d592 --- /dev/null +++ b/src/main/kotlin/dto/request/UpdateOrganizationNameRequest.kt @@ -0,0 +1,5 @@ +package dto.request + +data class UpdateOrganizationNameRequest( + var name: String? = null +) diff --git a/src/main/kotlin/dto/response/MemberResponse.kt b/src/main/kotlin/dto/response/MemberResponse.kt new file mode 100644 index 0000000..da5c97f --- /dev/null +++ b/src/main/kotlin/dto/response/MemberResponse.kt @@ -0,0 +1,18 @@ +package dto.response + +import com.google.gson.annotations.SerializedName +import dto.InviteDetails +import dto.UserDetails + +data class MemberResponse( + @SerializedName("_id") + var id: String? = null, + @SerializedName("_userId") + var userId: String? = null, + var user: UserDetails? = null, + var roles: List? = null, + var invite: InviteDetails? = null, + var memberStatus: String? = null, + @SerializedName("_organizationId") + var organizationId: String? = null +) diff --git a/src/main/kotlin/dto/response/OrganizationResponse.kt b/src/main/kotlin/dto/response/OrganizationResponse.kt new file mode 100644 index 0000000..1f53806 --- /dev/null +++ b/src/main/kotlin/dto/response/OrganizationResponse.kt @@ -0,0 +1,11 @@ +package dto.response + +import dto.Branding +import dto.PartnerConfigurations + +data class OrganizationResponse( + var name: String? = null, + var logo: String? = null, + var branding: Branding? = null, + var partnerConfigurations: List? = null +) diff --git a/src/main/kotlin/dto/response/UpdateOrganizationNameResponse.kt b/src/main/kotlin/dto/response/UpdateOrganizationNameResponse.kt new file mode 100644 index 0000000..1b62863 --- /dev/null +++ b/src/main/kotlin/dto/response/UpdateOrganizationNameResponse.kt @@ -0,0 +1,5 @@ +package dto.response + +data class UpdateOrganizationNameResponse( + var name: String? = null +) diff --git a/src/main/kotlin/extensions/OrganizationsExtensions.kt b/src/main/kotlin/extensions/OrganizationsExtensions.kt new file mode 100644 index 0000000..680cca4 --- /dev/null +++ b/src/main/kotlin/extensions/OrganizationsExtensions.kt @@ -0,0 +1,56 @@ +package co.novu.extensions + +import co.novu.Novu +import co.novu.dto.request.CreateOrganizationRequest +import co.novu.dto.response.ResponseWrapper +import co.novu.helpers.extractResponse +import dto.Branding +import dto.request.UpdateMemberRoleRequest +import dto.request.UpdateOrganizationBrandRequest +import dto.request.UpdateOrganizationNameRequest +import dto.response.MemberResponse +import dto.response.OrganizationResponse +import dto.response.UpdateOrganizationNameResponse +import mu.KotlinLogging + +private val logger = KotlinLogging.logger {} + +suspend fun Novu.createOrganization(request: CreateOrganizationRequest): ResponseWrapper? { + val response = organizationsApi.createOrganization(request) + return response.extractResponse(logger) +} + +suspend fun Novu.fetchAllOrganizations(): ResponseWrapper>? { + val response = organizationsApi.fetchAllOrganizations() + return response.extractResponse(logger) +} + +suspend fun Novu.updateOrganizationName(request: UpdateOrganizationNameRequest): ResponseWrapper? { + val response = organizationsApi.updateOrganizationName(request) + return response.extractResponse(logger) +} + +suspend fun Novu.fetchCurrentOrganization(): ResponseWrapper? { + val response = organizationsApi.fetchCurrentOrganization() + return response.extractResponse(logger) +} + +suspend fun Novu.removeMemberWithId(memberId: String): ResponseWrapper? { + val response = organizationsApi.removeMemberWithId(memberId) + return response.extractResponse(logger) +} + +suspend fun Novu.updateMemberRole(memberId: String, request: UpdateMemberRoleRequest): ResponseWrapper? { + val response = organizationsApi.updateMemberRole(memberId, request) + return response.extractResponse(logger) +} + +suspend fun Novu.fetchMembersOfOrganization(): ResponseWrapper>? { + val response = organizationsApi.fetchMembersOfOrganization() + return response.extractResponse(logger) +} + +suspend fun Novu.updateOrganizationBrand(request: UpdateOrganizationBrandRequest): ResponseWrapper? { + val response = organizationsApi.updateOrganizationBrand(request) + return response.extractResponse(logger) +} diff --git a/src/test/kotlin/OrganizationsApiTest.kt b/src/test/kotlin/OrganizationsApiTest.kt new file mode 100644 index 0000000..b95a91d --- /dev/null +++ b/src/test/kotlin/OrganizationsApiTest.kt @@ -0,0 +1,242 @@ +import co.novu.Novu +import co.novu.NovuConfig +import co.novu.dto.request.CreateOrganizationRequest +import co.novu.dto.response.ResponseWrapper +import co.novu.extensions.createOrganization +import co.novu.extensions.fetchAllOrganizations +import co.novu.extensions.fetchCurrentOrganization +import co.novu.extensions.fetchMembersOfOrganization +import co.novu.extensions.removeMemberWithId +import co.novu.extensions.updateMemberRole +import co.novu.extensions.updateOrganizationBrand +import co.novu.extensions.updateOrganizationName +import com.google.gson.Gson +import dto.Branding +import dto.request.UpdateMemberRoleRequest +import dto.request.UpdateOrganizationBrandRequest +import dto.request.UpdateOrganizationNameRequest +import dto.response.MemberResponse +import dto.response.OrganizationResponse +import dto.response.UpdateOrganizationNameResponse +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runTest +import okhttp3.mockwebserver.MockResponse +import okhttp3.mockwebserver.MockWebServer +import org.junit.jupiter.api.Test + +@OptIn(ExperimentalCoroutinesApi::class) +class OrganizationsApiTest { + private val mockWebServer = MockWebServer() + private val mockNovu = Novu( + NovuConfig(apiKey = "1245", backendUrl = mockWebServer.url("").toString()) + ) + private val gson = Gson() + + @Test + fun testCreateOrganization() = runTest { + val responseBody = ResponseWrapper( + data = OrganizationResponse( + name = "Org. name", + logo = "logo URI", + branding = Branding( + color = "#ffffff", + fontColor = "#000000", + logo = "logo URI" + ) + ) + ) + + val requestBody = CreateOrganizationRequest( + name = "Org. name", + logo = "logo URI" + ) + + mockWebServer.enqueue(MockResponse().setResponseCode(200).setBody(gson.toJson(responseBody))) + val result = mockNovu.createOrganization(requestBody) + val request = mockWebServer.takeRequest() + + assert(request.method == "POST") + assert(request.path == "/organizations") + assert(request.body.readUtf8() == gson.toJson(requestBody)) + assert(gson.toJson(responseBody) == gson.toJson(result)) + } + + @Test + fun testFetchAllOrganizations() = runTest { + val responseBody = ResponseWrapper( + data = listOf( + OrganizationResponse( + name = "Org. name1", + logo = "logo URI", + branding = Branding( + color = "#ffffff", + fontColor = "#000000", + logo = "logo URI" + ) + ), + OrganizationResponse( + name = "Org. name2", + logo = "logo URI", + branding = Branding( + color = "#ffffff", + fontColor = "#000000", + logo = "logo URI" + ) + ) + ) + ) + + mockWebServer.enqueue(MockResponse().setResponseCode(200).setBody(gson.toJson(responseBody))) + val result = mockNovu.fetchAllOrganizations() + val request = mockWebServer.takeRequest() + + assert(request.method == "GET") + assert(request.path == "/organizations") + assert(gson.toJson(responseBody) == gson.toJson(result)) + } + + @Test + fun testUpdateOrganizationName() = runTest { + val responseBody = ResponseWrapper( + data = UpdateOrganizationNameResponse( + name = "Org. new name" + ) + ) + + mockWebServer.enqueue(MockResponse().setResponseCode(200).setBody(gson.toJson(responseBody))) + val requestBody = UpdateOrganizationNameRequest( + name = "Org. new name" + ) + val result = mockNovu.updateOrganizationName(requestBody) + val request = mockWebServer.takeRequest() + + assert(request.method == "PATCH") + assert(request.path == "/organizations") + assert(request.body.readUtf8() == gson.toJson(requestBody)) + assert(gson.toJson(responseBody) == gson.toJson(result)) + } + + @Test + fun testFetchCurrentOrganization() = runTest { + val responseBody = ResponseWrapper( + data = OrganizationResponse( + name = "Org. name", + logo = "logo URI", + branding = Branding( + color = "#ffffff", + fontColor = "#000000", + logo = "logo URI" + ) + ) + ) + + mockWebServer.enqueue(MockResponse().setResponseCode(200).setBody(gson.toJson(responseBody))) + + val result = mockNovu.fetchCurrentOrganization() + val request = mockWebServer.takeRequest() + + assert(request.method == "GET") + assert(request.path == "/organizations/me") + assert(gson.toJson(responseBody) == gson.toJson(result)) + } + + @Test + fun testRemoveMemberWithId() = runTest { + val responseBody = ResponseWrapper( + data = MemberResponse( + id = "id", + userId = "userId", + organizationId = "orgId" + ) + ) + mockWebServer.enqueue(MockResponse().setResponseCode(200).setBody(gson.toJson(responseBody))) + + val memberId = "_id" + val result = mockNovu.removeMemberWithId(memberId) + val request = mockWebServer.takeRequest() + + assert(request.method == "DELETE") + assert(request.path == "/organizations/members/$memberId") + assert(gson.toJson(responseBody) == gson.toJson(result)) + } + + @Test + fun testUpdateMemberRole() = runTest { + val responseBody = ResponseWrapper( + data = MemberResponse( + id = "id", + userId = "userId", + organizationId = "orgId" + ) + ) + + mockWebServer.enqueue(MockResponse().setResponseCode(200).setBody(gson.toJson(responseBody))) + + val memberId = "_id" + val requestBody = UpdateMemberRoleRequest( + role = "New Role" + ) + + val result = mockNovu.updateMemberRole(memberId, requestBody) + val request = mockWebServer.takeRequest() + + assert(request.method == "PUT") + assert(request.path == "/organizations/members/$memberId/roles") + assert(request.body.readUtf8() == gson.toJson(requestBody)) + assert(gson.toJson(responseBody) == gson.toJson(result)) + } + + @Test + fun testFetchMembersOfOrganization() = runTest { + val responseBody = ResponseWrapper( + data = listOf( + MemberResponse( + id = "id1", + userId = "userId", + organizationId = "orgId" + ), + MemberResponse( + id = "id2", + userId = "userId", + organizationId = "orgId" + ) + ) + ) + + mockWebServer.enqueue(MockResponse().setResponseCode(200).setBody(gson.toJson(responseBody))) + + val result = mockNovu.fetchMembersOfOrganization() + val request = mockWebServer.takeRequest() + + assert(request.method == "GET") + assert(request.path == "/organizations/members") + assert(gson.toJson(responseBody) == gson.toJson(result)) + } + + @Test + fun testUpdateOrganizationBrand() = runTest { + val responseBody = ResponseWrapper( + data = Branding( + logo = "New logo URI", + color = "#deklhd", + fontFamily = "Sans Serif" + ) + ) + + mockWebServer.enqueue(MockResponse().setResponseCode(200).setBody(gson.toJson(responseBody))) + + val requestBody = UpdateOrganizationBrandRequest( + logo = "New logo URI", + color = "#deklhd", + fontFamily = "Sans Serif" + ) + + val result = mockNovu.updateOrganizationBrand(requestBody) + val request = mockWebServer.takeRequest() + + assert(request.method == "PUT") + assert(request.path == "/organizations/branding") + assert(request.body.readUtf8() == gson.toJson(requestBody)) + assert(gson.toJson(responseBody) == gson.toJson(result)) + } +} From 5687d82feb700a9f954a7f41a37a1b49c1b5f849 Mon Sep 17 00:00:00 2001 From: mayorjay Date: Mon, 13 Nov 2023 22:20:21 +0100 Subject: [PATCH 2/3] feat: Extract endpoint variable --- src/main/kotlin/api/BlueprintsApi.kt | 8 +++-- src/main/kotlin/api/ChangesApi.kt | 12 ++++--- src/main/kotlin/api/EnvironmentsApi.kt | 18 +++++++---- src/main/kotlin/api/EventsApi.kt | 12 ++++--- src/main/kotlin/api/ExecutionDetailsApi.kt | 7 +++- src/main/kotlin/api/FeedsApi.kt | 10 ++++-- src/main/kotlin/api/InboundParseApi.kt | 6 +++- src/main/kotlin/api/IntegrationsApi.kt | 19 +++++++---- src/main/kotlin/api/LayoutsApi.kt | 16 ++++++---- src/main/kotlin/api/MessagesApi.kt | 9 ++++-- src/main/kotlin/api/NotificationGroupsApi.kt | 15 ++++++--- .../kotlin/api/NotificationTemplatesApi.kt | 16 ++++++---- src/main/kotlin/api/NotificationsApi.kt | 12 ++++--- src/main/kotlin/api/SubscribersApi.kt | 32 +++++++++++-------- src/main/kotlin/api/TenantsApi.kt | 14 +++++--- src/main/kotlin/api/TopicsApi.kt | 20 +++++++----- src/main/kotlin/api/WorkflowsApi.kt | 16 ++++++---- 17 files changed, 157 insertions(+), 85 deletions(-) diff --git a/src/main/kotlin/api/BlueprintsApi.kt b/src/main/kotlin/api/BlueprintsApi.kt index 92720f3..78e2feb 100644 --- a/src/main/kotlin/api/BlueprintsApi.kt +++ b/src/main/kotlin/api/BlueprintsApi.kt @@ -9,9 +9,13 @@ import retrofit2.http.Path interface BlueprintsApi { - @GET("blueprints/group-by-category") + companion object { + const val ENDPOINT = "blueprints" + } + + @GET("$ENDPOINT/group-by-category") suspend fun getBlueprintsByCategory(): Response> - @GET("blueprints/{templateId}") + @GET("$ENDPOINT/{templateId}") suspend fun getBlueprint(@Path("templateId") templateId: String): Response } diff --git a/src/main/kotlin/api/ChangesApi.kt b/src/main/kotlin/api/ChangesApi.kt index d310ef7..a628365 100644 --- a/src/main/kotlin/api/ChangesApi.kt +++ b/src/main/kotlin/api/ChangesApi.kt @@ -14,15 +14,19 @@ import java.math.BigInteger interface ChangesApi { - @GET("changes") + companion object { + const val ENDPOINT = "changes" + } + + @GET(ENDPOINT) suspend fun getChanges(@Query("page") page: BigInteger? = null, @Query("limit") limit: BigInteger? = null, @Query("promoted") promoted: String? = null): Response> - @GET("changes/count") + @GET("$ENDPOINT/count") suspend fun getChangesCount(): Response> - @POST("changes/bulk/apply") + @POST("$ENDPOINT/bulk/apply") suspend fun applyBulkChanges(@Body request: ChangesRequest): Response>> - @POST("changes/{changedId}/apply") + @POST("$ENDPOINT/{changedId}/apply") suspend fun applyChange(@Path("changedId") changedId: String): Response>> } diff --git a/src/main/kotlin/api/EnvironmentsApi.kt b/src/main/kotlin/api/EnvironmentsApi.kt index 0a60cff..adbb433 100644 --- a/src/main/kotlin/api/EnvironmentsApi.kt +++ b/src/main/kotlin/api/EnvironmentsApi.kt @@ -15,24 +15,28 @@ import retrofit2.http.Path interface EnvironmentsApi { - @GET("environments/me") + companion object { + const val ENDPOINT = "environments" + } + + @GET("$ENDPOINT/me") suspend fun getCurrentEnvironment(): Response> - @POST("environments") + @POST(ENDPOINT) suspend fun createEnvironment(@Body request: CreateEnvironmentRequest): Response> - @GET("environments") + @GET(ENDPOINT) suspend fun getEnvironments(): Response>> - @PUT("environments/{environmentId}") + @PUT("$ENDPOINT/{environmentId}") suspend fun updateEnvironment(@Path("environmentId") environmentId: String, @Body request: UpdateEnvironmentRequest): Response> - @GET("environments/api-keys") + @GET("$ENDPOINT/api-keys") suspend fun getApiKeys(): Response>> - @POST("environments/api-keys/regenerate") + @POST("$ENDPOINT/api-keys/regenerate") suspend fun regenerateApiKey(): Response>> - @PUT("environments/api-keys/widget/settings") + @PUT("$ENDPOINT/api-keys/widget/settings") suspend fun updateWidgetSettings(@Body request: Widget): Response> } diff --git a/src/main/kotlin/api/EventsApi.kt b/src/main/kotlin/api/EventsApi.kt index ee046f8..731b726 100644 --- a/src/main/kotlin/api/EventsApi.kt +++ b/src/main/kotlin/api/EventsApi.kt @@ -13,15 +13,19 @@ import retrofit2.http.Path interface EventsApi { - @POST("events/trigger") + companion object { + const val ENDPOINT = "events" + } + + @POST("$ENDPOINT/trigger") suspend fun triggerEvent(@Body body: TriggerEventRequest): Response> - @POST("events/trigger/bulk") + @POST("$ENDPOINT/trigger/bulk") suspend fun bulkTriggerEvent(@Body body: BulkTriggerEventRequest): Response> - @POST("events/trigger/broadcast") + @POST("$ENDPOINT/trigger/broadcast") suspend fun broadcastEvent(@Body body: BroadcastEventRequest): Response> - @DELETE("events/trigger/{transactionId}") + @DELETE("$ENDPOINT/trigger/{transactionId}") suspend fun cancelTriggerEvent(@Path("transactionId") transactionId: String): Response> } diff --git a/src/main/kotlin/api/ExecutionDetailsApi.kt b/src/main/kotlin/api/ExecutionDetailsApi.kt index 7c0a7a7..923bbd9 100644 --- a/src/main/kotlin/api/ExecutionDetailsApi.kt +++ b/src/main/kotlin/api/ExecutionDetailsApi.kt @@ -7,7 +7,12 @@ import retrofit2.http.GET import retrofit2.http.Query interface ExecutionDetailsApi { - @GET("execution-details") + + companion object { + const val ENDPOINT = "execution-details" + } + + @GET(ENDPOINT) suspend fun getExecutionDetails( @Query("notificationId") notificationId: String, @Query("subscriberId") subscriberId: String diff --git a/src/main/kotlin/api/FeedsApi.kt b/src/main/kotlin/api/FeedsApi.kt index 98d046c..72f331d 100644 --- a/src/main/kotlin/api/FeedsApi.kt +++ b/src/main/kotlin/api/FeedsApi.kt @@ -12,12 +12,16 @@ import retrofit2.http.Path interface FeedsApi { - @POST("feeds") + companion object { + const val ENDPOINT = "feeds" + } + + @POST(ENDPOINT) suspend fun createFeed(@Body body: CreateByNameRequest): Response> - @GET("feeds") + @GET(ENDPOINT) suspend fun getFeeds(): Response>> - @DELETE("feeds/{feedId}") + @DELETE("$ENDPOINT/{feedId}") suspend fun deleteFeed(@Path("feedId") feedId: String): Response> } diff --git a/src/main/kotlin/api/InboundParseApi.kt b/src/main/kotlin/api/InboundParseApi.kt index 9fab30a..d600230 100644 --- a/src/main/kotlin/api/InboundParseApi.kt +++ b/src/main/kotlin/api/InboundParseApi.kt @@ -6,6 +6,10 @@ import retrofit2.http.GET interface InboundParseApi { - @GET("inbound-parse/mx/status") + companion object { + const val ENDPOINT = "inbound-parse" + } + + @GET("$ENDPOINT/mx/status") suspend fun validateMxRecordSetupForInboundParse(): Response } diff --git a/src/main/kotlin/api/IntegrationsApi.kt b/src/main/kotlin/api/IntegrationsApi.kt index 4315e0c..6aeb84f 100644 --- a/src/main/kotlin/api/IntegrationsApi.kt +++ b/src/main/kotlin/api/IntegrationsApi.kt @@ -12,24 +12,29 @@ import retrofit2.http.PUT import retrofit2.http.Path interface IntegrationsApi { - @GET("integrations") + + companion object { + const val ENDPOINT = "integrations" + } + + @GET(ENDPOINT) suspend fun getIntegrations(): Response>> - @POST("integrations") + @POST(ENDPOINT) suspend fun createIntegration(@Body request: IntegrationRequest): Response> - @GET("integrations/active") + @GET("$ENDPOINT/active") suspend fun getActiveIntegrations(): Response>> - @GET("integrations/webhook/provider/{providerId}/status") + @GET("$ENDPOINT/webhook/provider/{providerId}/status") suspend fun getProviderWebhook(@Path("providerId") providerId: String): Response> - @PUT("integrations/{integrationId}") + @PUT("$ENDPOINT/{integrationId}") suspend fun updateIntegration(@Path("integrationId") integrationId: String, @Body request: IntegrationRequest): Response> - @DELETE("integrations/{integrationId}") + @DELETE("$ENDPOINT/{integrationId}") suspend fun deleteIntegration(@Path("integrationId") integrationId: String): Response>> - @POST("integrations/{integrationId}/set-primary") + @POST("$ENDPOINT/{integrationId}/set-primary") suspend fun setPrimaryIntegration(@Path("integrationId") integrationId: String): Response> } diff --git a/src/main/kotlin/api/LayoutsApi.kt b/src/main/kotlin/api/LayoutsApi.kt index 6f604d4..da6761b 100644 --- a/src/main/kotlin/api/LayoutsApi.kt +++ b/src/main/kotlin/api/LayoutsApi.kt @@ -17,21 +17,25 @@ import java.math.BigInteger interface LayoutsApi { - @POST("layouts") + companion object { + const val ENDPOINT = "layouts" + } + + @POST(ENDPOINT) suspend fun createLayout(@Body request: CreateLayoutRequest): Response> - @GET("layouts") + @GET(ENDPOINT) suspend fun filterLayouts(@Query("page") page: BigInteger, @Query("pageSize") pageSize: BigInteger, @Query("sortBy") sortBy: String, @Query("orderBy") orderBy: BigInteger): Response> - @GET("layouts/{layoutId}") + @GET("$ENDPOINT/{layoutId}") suspend fun getLayout(@Path("layoutId") layoutId: String): Response> - @DELETE("layouts/{layoutId}") + @DELETE("$ENDPOINT/{layoutId}") suspend fun deleteLayout(@Path("layoutId") layoutId: String): Response - @PATCH("layouts/{layoutId}") + @PATCH("$ENDPOINT/{layoutId}") suspend fun updateLayout(@Path("layoutId") layoutId: String, @Body request: CreateLayoutRequest): Response> - @POST("layouts/{layoutId}/default") + @POST("$ENDPOINT/{layoutId}/default") suspend fun setDefaultLayout(@Path("layoutId") layoutId: String): Response } diff --git a/src/main/kotlin/api/MessagesApi.kt b/src/main/kotlin/api/MessagesApi.kt index be15c42..c0077f5 100644 --- a/src/main/kotlin/api/MessagesApi.kt +++ b/src/main/kotlin/api/MessagesApi.kt @@ -12,7 +12,12 @@ import retrofit2.http.Query import java.math.BigInteger interface MessagesApi { - @GET("messages") + + companion object { + const val ENDPOINT = "messages" + } + + @GET(ENDPOINT) suspend fun getMessages( @Query("channel") channel: String? = null, @Query("subscriberId") subscriberId: String? = null, @@ -21,6 +26,6 @@ interface MessagesApi { @Query("transactionId") transactionId: String? = null ): Response> - @DELETE("messages/{messageId}") + @DELETE("$ENDPOINT/{messageId}") suspend fun deleteMessage(@Path("messageId") messageId: String): Response> } diff --git a/src/main/kotlin/api/NotificationGroupsApi.kt b/src/main/kotlin/api/NotificationGroupsApi.kt index c7a73c2..14df243 100644 --- a/src/main/kotlin/api/NotificationGroupsApi.kt +++ b/src/main/kotlin/api/NotificationGroupsApi.kt @@ -13,18 +13,23 @@ import retrofit2.http.POST import retrofit2.http.Path interface NotificationGroupsApi { - @GET("notification-groups") + + companion object { + const val ENDPOINT = "notification-groups" + } + + @GET(ENDPOINT) suspend fun getNotificationGroups(): Response>> - @POST("notification-groups") + @POST(ENDPOINT) suspend fun createNotificationGroup(@Body request: CreateByNameRequest): Response> - @GET("notification-groups/{id}") + @GET("$ENDPOINT/{id}") suspend fun getWorkflowGroup(@Path("id") id: String): Response> - @PATCH("notification-groups/{id}") + @PATCH("$ENDPOINT/{id}") suspend fun updateWorkflowGroup(@Path("id") id: String, @Body request: CreateByNameRequest): Response> - @DELETE("notification-groups/{id}") + @DELETE("$ENDPOINT/{id}") suspend fun deleteWorkflowGroup(@Path("id") id: String): Response> } diff --git a/src/main/kotlin/api/NotificationTemplatesApi.kt b/src/main/kotlin/api/NotificationTemplatesApi.kt index 0fd582e..fb945c8 100644 --- a/src/main/kotlin/api/NotificationTemplatesApi.kt +++ b/src/main/kotlin/api/NotificationTemplatesApi.kt @@ -16,21 +16,25 @@ import java.math.BigInteger interface NotificationTemplatesApi { - @GET("notification-templates") + companion object { + const val ENDPOINT = "notification-templates" + } + + @GET(ENDPOINT) suspend fun getNotificationTemplates(@Query("page") page: BigInteger? = BigInteger.valueOf(1), @Query("limit") limit: BigInteger? = BigInteger.valueOf(10)): Response> - @POST("notification-templates") + @POST(ENDPOINT) suspend fun createNotificationTemplates(@Body request: NotificationTemplates): Response> - @PUT("notification-templates/{templateId}") + @PUT("$ENDPOINT/{templateId}") suspend fun updateNotificationTemplates(@Path("templateId") templateId: String, @Body request: NotificationTemplates): Response> - @DELETE("notification-templates/{templateId}") + @DELETE("$ENDPOINT/{templateId}") suspend fun deleteNotificationTemplate(@Path("templateId") templateId: String): Response> - @GET("notification-templates/{templateId}") + @GET("$ENDPOINT/{templateId}") suspend fun getNotificationTemplate(@Path("templateId") templateId: String): Response> - @PUT("notification-templates/{templateId}/status") + @PUT("$ENDPOINT/{templateId}/status") suspend fun updateNotificationTemplateStatus(@Path("templateId") templateId: String, @Body request: UpdateNotificationTemplateStatusRequest): Response> } diff --git a/src/main/kotlin/api/NotificationsApi.kt b/src/main/kotlin/api/NotificationsApi.kt index a2c0794..fb84d63 100644 --- a/src/main/kotlin/api/NotificationsApi.kt +++ b/src/main/kotlin/api/NotificationsApi.kt @@ -13,7 +13,11 @@ import java.math.BigInteger interface NotificationsApi { - @GET("notifications") + companion object { + const val ENDPOINT = "notifications" + } + + @GET(ENDPOINT) suspend fun getNotifications( @Query("channels") channels: List?, @Query("templates") templates: List?, @@ -23,12 +27,12 @@ interface NotificationsApi { @Query("transactionId") transactionId: String? ): Response> - @GET("notifications/stats") + @GET("$ENDPOINT/stats") suspend fun getNotificationsStats(): Response> - @GET("notifications/graph/stats") + @GET("$ENDPOINT/graph/stats") suspend fun getNotificationGraphStats(): Response>> - @GET("notifications/{notificationId}") + @GET("$ENDPOINT/{notificationId}") suspend fun getNotification(@Path("notificationId") notificationId: String): Response> } diff --git a/src/main/kotlin/api/SubscribersApi.kt b/src/main/kotlin/api/SubscribersApi.kt index 92fe491..3be7a9e 100644 --- a/src/main/kotlin/api/SubscribersApi.kt +++ b/src/main/kotlin/api/SubscribersApi.kt @@ -29,53 +29,57 @@ import java.math.BigInteger interface SubscribersApi { - @GET("subscribers") + companion object { + const val ENDPOINT = "subscribers" + } + + @GET(ENDPOINT) suspend fun getSubscribers(@Query("page") page: BigInteger?): Response> - @POST("subscribers") + @POST(ENDPOINT) suspend fun createSubscriber(@Body subscriberRequest: SubscriberRequest): Response> - @POST("subscribers/bulk") + @POST("$ENDPOINT/bulk") suspend fun createSubscriberBulk(@Body request: BulkSubscriberRequest): Response - @GET("subscribers/{subscriberId}") + @GET("$ENDPOINT/{subscriberId}") suspend fun getSubscriber(@Path("subscriberId") subscriberId: String): Response> - @PUT("subscribers/{subscriberId}") + @PUT("$ENDPOINT/{subscriberId}") suspend fun updateSubscriber(@Path("subscriberId") subscriberId: String, @Body request: UpdateSubscriberRequest): Response> - @DELETE("subscribers/{subscriberId}") + @DELETE("$ENDPOINT/{subscriberId}") suspend fun deleteSubscriber(@Path("subscriberId") subscriberId: String): Response> - @PUT("subscribers/{subscriberId}/credentials") + @PUT("$ENDPOINT/{subscriberId}/credentials") suspend fun updateSubscriberCredentials(@Path("subscriberId") subscriberId: String, @Body request: UpdateSubscriberCredentialsRequest): Response> - @PATCH("subscribers/{subscriberId}/online-status") + @PATCH("$ENDPOINT/{subscriberId}/online-status") suspend fun updateSubscriberOnlineStatus(@Path("subscriberId")subscriberId: String, @Body request: UpdateSubscriberOnlineStatusRequest): Response> - @GET("subscribers/{subscriberId}/preferences") + @GET("$ENDPOINT/{subscriberId}/preferences") suspend fun getSubscriberPreferences(@Path("subscriberId") subscriberId: String): Response>> - @PATCH("subscribers/{subscriberId}/preferences/{templateId}") + @PATCH("$ENDPOINT/{subscriberId}/preferences/{templateId}") suspend fun updateSubscriberPreferences( @Path("subscriberId") subscriberId: String, @Path("templateId") templateId: String, @Body request: UpdateSubscriberPreferencesRequest ): Response> - @GET("subscribers/{subscriberId}/notifications/feed") + @GET("$ENDPOINT/{subscriberId}/notifications/feed") suspend fun getSubscriberNotificationsFeed(@Path("subscriberId") subscriberId: String): Response> - @GET("subscribers/{subscriberId}/notifications/unseen") + @GET("$ENDPOINT/{subscriberId}/notifications/unseen") suspend fun getSubscriberUnseenNotificationsCount(@Path("subscriberId") subscriberId: String): Response> - @POST("subscribers/{subscriberId}/messages/markAs") + @POST("$ENDPOINT/{subscriberId}/messages/markAs") suspend fun markSubscriberMessageFeedAs( @Path("subscriberId") subscriberId: String, @Body request: MarkSubscriberFeedAsRequest ): Response> - @POST("subscribers/{subscriberId}/messages/{messageId}/actions/{type}") + @POST("$ENDPOINT/{subscriberId}/messages/{messageId}/actions/{type}") suspend fun markMessageActionAsSeen( @Path("subscriberId") subscriberId: String, @Path("messageId") messageId: String, diff --git a/src/main/kotlin/api/TenantsApi.kt b/src/main/kotlin/api/TenantsApi.kt index 6bfd513..2d1403e 100644 --- a/src/main/kotlin/api/TenantsApi.kt +++ b/src/main/kotlin/api/TenantsApi.kt @@ -15,24 +15,28 @@ import retrofit2.http.Query interface TenantsApi { - @GET("tenants") + companion object { + const val ENDPOINT = "tenants" + } + + @GET(ENDPOINT) suspend fun getTenants( @Query("page") page: Int? = null, @Query("limit") limit: Int? = null ): Response> - @POST("tenants") + @POST(ENDPOINT) suspend fun createTenant(@Body request: TenantRequest): Response> - @GET("tenants/{identifier}") + @GET("$ENDPOINT/{identifier}") suspend fun getTenant(@Path("identifier") identifier: String): Response> - @PATCH("tenants/{identifier}") + @PATCH("$ENDPOINT/{identifier}") suspend fun updateTenant( @Path("identifier") identifier: String, @Body request: TenantRequest ): Response> - @DELETE("tenants/{identifier}") + @DELETE("$ENDPOINT/{identifier}") suspend fun deleteTenant(@Path("identifier") identifier: String): Response } diff --git a/src/main/kotlin/api/TopicsApi.kt b/src/main/kotlin/api/TopicsApi.kt index 6ad2ee5..df33cef 100644 --- a/src/main/kotlin/api/TopicsApi.kt +++ b/src/main/kotlin/api/TopicsApi.kt @@ -21,31 +21,35 @@ import java.math.BigInteger interface TopicsApi { - @GET("topics") + companion object { + const val ENDPOINT = "topics" + } + + @GET(ENDPOINT) suspend fun filterTopics( @Query("page") page: BigInteger? = null, @Query("pageSize")pageSize: BigInteger? = null, @Query("key") key: String? = null ): Response> - @POST("topics") + @POST(ENDPOINT) suspend fun createTopic(@Body request: CreateTopicRequest): Response> - @POST("topics/{topicKey}/subscribers") + @POST("$ENDPOINT/{topicKey}/subscribers") suspend fun addSubscriber(@Path("topicKey") topicKey: String, @Body request: SubscriberList): Response> - @POST("topics/{topicKey}/subscribers/removal") + @POST("$ENDPOINT/{topicKey}/subscribers/removal") suspend fun removeSubscribers(@Path("topicKey") topicKey: String, @Body request: SubscriberList): Response - @GET("topics/{topicKey}/subscribers/{externalSubscriberId}") + @GET("$ENDPOINT/{topicKey}/subscribers/{externalSubscriberId}") suspend fun checkSubscriber(@Path("topicKey") topicKey: String, @Path("externalSubscriberId") externalSubscriberId: String): Response - @GET("topics/{topicKey}") + @GET("$ENDPOINT/{topicKey}") suspend fun getTopic(@Path("topicKey") topicKey: String): Response> - @PATCH("topics/{topicKey}") + @PATCH("$ENDPOINT/{topicKey}") suspend fun renameTopic(@Path("topicKey") topicKey: String, @Body request: CreateByNameRequest): Response> - @DELETE("topics/{topicKey}") + @DELETE("$ENDPOINT/{topicKey}") suspend fun deleteTopic(@Path("topicKey") topicKey: String): Response } diff --git a/src/main/kotlin/api/WorkflowsApi.kt b/src/main/kotlin/api/WorkflowsApi.kt index 3a502ae..913ca65 100644 --- a/src/main/kotlin/api/WorkflowsApi.kt +++ b/src/main/kotlin/api/WorkflowsApi.kt @@ -17,21 +17,25 @@ import retrofit2.http.Query interface WorkflowsApi { - @GET("workflows") + companion object { + const val ENDPOINT = "workflows" + } + + @GET(ENDPOINT) suspend fun getWorkflows(@Query("page") page: Int? = null, @Query("limit") limit: Int? = null): Response> - @POST("workflows") + @POST(ENDPOINT) suspend fun createWorkflow(@Body request: WorkflowRequest): Response> - @PUT("workflows/{workflowId}") + @PUT("$ENDPOINT/{workflowId}") suspend fun updateWorkflow(@Path("workflowId") workflowId: String, @Body request: UpdateWorkflowRequest): Response> - @DELETE("workflows/{workflowId}") + @DELETE("$ENDPOINT/{workflowId}") suspend fun deleteWorkflow(@Path("workflowId") workflowId: String): Response> - @GET("workflows/{workflowId}") + @GET("$ENDPOINT/{workflowId}") suspend fun getWorkflow(@Path("workflowId") workflowId: String): Response> - @PUT("workflows/{workflowId}/status") + @PUT("$ENDPOINT/{workflowId}/status") suspend fun updateWorkflowStatus(@Path("workflowId") workflowId: String, @Body request: UpdateWorkflowStatusRequest): Response> } From 5f5b61b3be4f17e36c986eb652eb3df86d7f3114 Mon Sep 17 00:00:00 2001 From: mayorjay Date: Wed, 22 Nov 2023 23:46:37 +0100 Subject: [PATCH 3/3] feat: Implement Organizations API --- src/main/kotlin/dto/response/OrganizationResponse.kt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/dto/response/OrganizationResponse.kt b/src/main/kotlin/dto/response/OrganizationResponse.kt index 1f53806..41abae6 100644 --- a/src/main/kotlin/dto/response/OrganizationResponse.kt +++ b/src/main/kotlin/dto/response/OrganizationResponse.kt @@ -1,11 +1,18 @@ package dto.response +import com.google.gson.annotations.SerializedName import dto.Branding import dto.PartnerConfigurations data class OrganizationResponse( + @SerializedName("_id") + var id: String? = null, var name: String? = null, var logo: String? = null, var branding: Branding? = null, - var partnerConfigurations: List? = null + var partnerConfigurations: List? = null, + var createdAt: String? = null, + var updatedAt: String? = null, + @SerializedName("__v") + var version: Long? = null )