From d91beb38e63825fe0e16d56576e227841eeb29af Mon Sep 17 00:00:00 2001 From: Matt Chowning Date: Mon, 23 Mar 2020 14:22:13 -0400 Subject: [PATCH] Update fluxc to enable authenticated rest api request to self-hosted sites --- .../reactnative/ReactNativeRequestHandler.kt | 32 +------ .../posts/reactnative/ReactNativeUrlUtil.kt | 50 ---------- .../ReactNativeRequestHandlerTest.kt | 91 ++----------------- .../reactnative/ReactNativeUrlUtilTest.kt | 68 -------------- build.gradle | 2 +- 5 files changed, 9 insertions(+), 234 deletions(-) delete mode 100644 WordPress/src/main/java/org/wordpress/android/ui/posts/reactnative/ReactNativeUrlUtil.kt delete mode 100644 WordPress/src/test/java/org/wordpress/android/ui/posts/reactnative/ReactNativeUrlUtilTest.kt diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/reactnative/ReactNativeRequestHandler.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/reactnative/ReactNativeRequestHandler.kt index 0b4620b9fcdf..145c89f32554 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/reactnative/ReactNativeRequestHandler.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/posts/reactnative/ReactNativeRequestHandler.kt @@ -19,7 +19,6 @@ import javax.inject.Named class ReactNativeRequestHandler @Inject constructor( private val reactNativeStore: ReactNativeStore, - private val urlUtil: ReactNativeUrlUtil, @Named(BG_THREAD) private val bgDispatcher: CoroutineDispatcher ) : CoroutineScope { override val coroutineContext = bgDispatcher + Job() @@ -31,11 +30,8 @@ class ReactNativeRequestHandler @Inject constructor( onError: Consumer ) { launch { - if (mSite.isUsingWpComRestApi) { - performGetRequestForWPComSite(pathWithParams, mSite.siteId, onSuccess::accept, onError::accept) - } else { - performGetRequestForSelfHostedSite(pathWithParams, mSite.url, onSuccess::accept, onError::accept) - } + val response = reactNativeStore.executeRequest(mSite, pathWithParams) + handleResponse(response, onSuccess::accept, onError::accept) } } @@ -49,30 +45,6 @@ class ReactNativeRequestHandler @Inject constructor( coroutineContext[Job]!!.cancel() } - private suspend fun performGetRequestForWPComSite( - pathWithParams: String, - wpComSiteId: Long, - onSuccess: (String) -> Unit, - onError: (Bundle) -> Unit - ) { - urlUtil.parseUrlAndParamsForWPCom(pathWithParams, wpComSiteId)?.let { (url, params) -> - val response = reactNativeStore.performWPComRequest(url, params) - handleResponse(response, onSuccess, onError) - } - } - - private suspend fun performGetRequestForSelfHostedSite( - pathWithParams: String, - siteUrl: String, - onSuccess: (String) -> Unit, - onError: (Bundle) -> Unit - ) { - urlUtil.parseUrlAndParamsForWPOrg(pathWithParams, siteUrl)?.let { (url, params) -> - val response = reactNativeStore.performWPAPIRequest(url, params) - handleResponse(response, onSuccess, onError) - } - } - private fun handleResponse( response: ReactNativeFetchResponse, onSuccess: (String) -> Unit, diff --git a/WordPress/src/main/java/org/wordpress/android/ui/posts/reactnative/ReactNativeUrlUtil.kt b/WordPress/src/main/java/org/wordpress/android/ui/posts/reactnative/ReactNativeUrlUtil.kt deleted file mode 100644 index aa920e654a4a..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/ui/posts/reactnative/ReactNativeUrlUtil.kt +++ /dev/null @@ -1,50 +0,0 @@ -package org.wordpress.android.ui.posts.reactnative - -import android.net.Uri -import javax.inject.Inject - -private const val WPCOM_ENDPOINT = "https://public-api.wordpress.com" - -class ReactNativeUrlUtil @Inject constructor() { - internal fun parseUrlAndParamsForWPCom( - pathWithParams: String, - wpComSiteId: Long - ): Pair>? = - parsePathAndParams(pathWithParams)?.let { (path, params) -> - val url = WPCOM_ENDPOINT + path.replace("wp/v2/", "wp/v2/sites/$wpComSiteId/") - Pair(url, params) - } - - internal fun parseUrlAndParamsForWPOrg( - pathWithParams: String, - siteUrl: String - ): Pair>? = - parsePathAndParams(pathWithParams)?.let { (path, params) -> - val url = "$siteUrl/wp-json$path" - val updatedParams = updateUrlForWPOrgRequest(params) - Pair(url, updatedParams) - } - - /* - * We cannot make authorized requests to self-hosted sites. A "context" of - * "edit" requires authorization, so changing the context to "view" since that does not need - * authorizations and still has the data we need. - */ - private fun updateUrlForWPOrgRequest(params: Map): Map = - params.mapValues { (key, value) -> - val hasEditContext = key == "context" && value == "edit" - if (hasEditContext) { - "view" - } else { - value - } - } - - private fun parsePathAndParams(pathWithParams: String): Pair> { - val uri = Uri.parse(pathWithParams) - val paramMap = uri.queryParameterNames.map { name -> - name to uri.getQueryParameter(name) - }.toMap() - return Pair(uri.path, paramMap) - } -} diff --git a/WordPress/src/test/java/org/wordpress/android/ui/posts/reactnative/ReactNativeRequestHandlerTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/posts/reactnative/ReactNativeRequestHandlerTest.kt index c2ca681eeb54..306cbaa1d67b 100644 --- a/WordPress/src/test/java/org/wordpress/android/ui/posts/reactnative/ReactNativeRequestHandlerTest.kt +++ b/WordPress/src/test/java/org/wordpress/android/ui/posts/reactnative/ReactNativeRequestHandlerTest.kt @@ -29,31 +29,20 @@ import org.wordpress.android.util.NoDelayCoroutineDispatcher @RunWith(RobolectricTestRunner::class) class ReactNativeRequestHandlerTest { private val reactNativeStore = mock() - private val reactNativeUrlUtil = mock() private val site = mock() - private val pathWithParams = "/wp/v2/media?context=edit" - private val siteId: Long = 1111 - private val siteUrl = "a_site_url" - private val parsedPath = "/wp/v2/media" - private val paramsMap = mapOf("context" to "edit") - private lateinit var subject: ReactNativeRequestHandler @Before fun setUp() { subject = ReactNativeRequestHandler( reactNativeStore, - reactNativeUrlUtil, NoDelayCoroutineDispatcher() ) - - whenever(site.siteId).thenReturn(siteId) - whenever(site.url).thenReturn(siteUrl) } @Test - fun `WPcom get request that succeeds`() = test { + fun `successful request`() = test { whenever(site.isUsingWpComRestApi).thenReturn(true) var calledSuccess = false @@ -67,14 +56,11 @@ class ReactNativeRequestHandlerTest { fail("Error handler should not be called") } - whenever(reactNativeUrlUtil.parseUrlAndParamsForWPCom(pathWithParams, siteId)).thenReturn( - Pair(parsedPath, paramsMap) - ) - val successfulResponseJson = mock() whenever(successfulResponseJson.toString()).thenReturn(jsonAsString) + val fetchResponse = ReactNativeFetchResponse.Success(successfulResponseJson) - whenever(reactNativeStore.performWPComRequest(parsedPath, paramsMap)).thenReturn(fetchResponse) + whenever(reactNativeStore.executeRequest(site, pathWithParams)).thenReturn(fetchResponse) subject.performGetRequest(pathWithParams, site, successHandler, errorHandler) @@ -82,7 +68,7 @@ class ReactNativeRequestHandlerTest { } @Test - fun `WPcom get request that fails`() = test { + fun `failed request`() = test { whenever(site.isUsingWpComRestApi).thenReturn(true) var calledError = false @@ -98,80 +84,15 @@ class ReactNativeRequestHandlerTest { fail("Success handler should not be called") } - whenever(reactNativeUrlUtil.parseUrlAndParamsForWPCom(pathWithParams, siteId)).thenReturn( - Pair(parsedPath, paramsMap) - ) - - val fetchResponse = getFetchResponseError(errorMessage, statusCode) - whenever(reactNativeStore.performWPComRequest(parsedPath, paramsMap)).thenReturn(fetchResponse) - - subject.performGetRequest(pathWithParams, site, successHandler, errorHandler) - - assertTrue(calledError) - } - - @Test - fun `WPorg get request that succeeds`() = test { - whenever(site.isUsingWpComRestApi).thenReturn(false) - - var calledSuccess = false - val jsonAsString = "json_as_string" - val successHandler = Consumer { - if (it != jsonAsString) { fail("expected json was not returned: $it") } - calledSuccess = true - } - - val errorHandler = Consumer { - fail("Error handler should not be called") - } - - whenever(reactNativeUrlUtil.parseUrlAndParamsForWPOrg(pathWithParams, siteUrl)).thenReturn( - Pair(parsedPath, paramsMap) - ) - - val successfulResponseJson = mock() - whenever(successfulResponseJson.toString()).thenReturn(jsonAsString) - val fetchResponse = ReactNativeFetchResponse.Success(successfulResponseJson) - whenever(reactNativeStore.performWPAPIRequest(parsedPath, paramsMap)).thenReturn(fetchResponse) - - subject.performGetRequest(pathWithParams, site, successHandler, errorHandler) - - assertTrue(calledSuccess) - } - - @Test - fun `WPorg get request that fails`() = test { - whenever(site.isUsingWpComRestApi).thenReturn(false) - - var calledError = false - val statusCode = 505 - val errorMessage = "error_message" - val errorHandler = Consumer { - assertEquals(statusCode, it.getInt("code")) - assertEquals(errorMessage, it.getString("message")) - calledError = true - } - - val successHandler = Consumer { - fail("Success handler should not be called") - } - - whenever(reactNativeUrlUtil.parseUrlAndParamsForWPOrg(pathWithParams, siteUrl)).thenReturn( - Pair(parsedPath, paramsMap) - ) - val fetchResponse = getFetchResponseError(errorMessage, statusCode) - whenever(reactNativeStore.performWPAPIRequest(parsedPath, paramsMap)).thenReturn(fetchResponse) + whenever(reactNativeStore.executeRequest(site, pathWithParams)).thenReturn(fetchResponse) subject.performGetRequest(pathWithParams, site, successHandler, errorHandler) assertTrue(calledError) } - private fun getFetchResponseError( - errorMessage: String, - statusCode: Int - ): Error { + private fun getFetchResponseError(errorMessage: String, statusCode: Int): Error { val volleyNetworkResponse = NetworkResponse(statusCode, null, false, 0L, null) val volleyError = VolleyError(volleyNetworkResponse) diff --git a/WordPress/src/test/java/org/wordpress/android/ui/posts/reactnative/ReactNativeUrlUtilTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/posts/reactnative/ReactNativeUrlUtilTest.kt deleted file mode 100644 index 9fe2b1376f6b..000000000000 --- a/WordPress/src/test/java/org/wordpress/android/ui/posts/reactnative/ReactNativeUrlUtilTest.kt +++ /dev/null @@ -1,68 +0,0 @@ -package org.wordpress.android.ui.posts.reactnative - -import android.os.Build -import org.junit.Assert.assertEquals -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner -import org.robolectric.annotation.Config -import org.wordpress.android.TestApplication - -private const val INPUT_PATH = "/wp/v2/media/54" -private const val INPUT_QUERY_PARAMS = "?context=edit&_locale=user" -private val INPUT_QUERY_PARAMS_MAP = mapOf("context" to "edit", "_locale" to "user") - -@Config(application = TestApplication::class, sdk = [Build.VERSION_CODES.LOLLIPOP]) -@RunWith(RobolectricTestRunner::class) -class ReactNativeUrlUtilTest { - private lateinit var subject: ReactNativeUrlUtil - - @Before - fun setUp() { - subject = ReactNativeUrlUtil() - } - - @Test - fun `successfully generates url and query params for WPcom`() { - val siteId = 555L - - val expectedUrl = "https://public-api.wordpress.com/wp/v2/sites/$siteId/media/54" - val expected = Pair(expectedUrl, INPUT_QUERY_PARAMS_MAP) - - assertEquals(expected, subject.parseUrlAndParamsForWPCom(INPUT_PATH + INPUT_QUERY_PARAMS, siteId)) - } - - @Test - fun `successfully generates url missing query params for WPcom`() { - val siteId = 555L - - val expectedUrl = "https://public-api.wordpress.com/wp/v2/sites/$siteId/media/54" - val expected = Pair(expectedUrl, emptyMap()) - - assertEquals(expected, subject.parseUrlAndParamsForWPCom(INPUT_PATH, siteId)) - } - - @Test - fun `successfully generates url and query params for WPorg`() { - val siteUrl = "https://jurassic.ninja" - - val expectedUrl = "$siteUrl/wp-json/wp/v2/media/54" - - // changes context from edit to view - val expectedParams = INPUT_QUERY_PARAMS_MAP.plus("context" to "view") - - val expected = Pair(expectedUrl, expectedParams) - assertEquals(expected, subject.parseUrlAndParamsForWPOrg(INPUT_PATH + INPUT_QUERY_PARAMS, siteUrl)) - } - - @Test - fun `successfully generates url missing query params for WPorg`() { - val siteUrl = "https://jurassic.ninja" - - val expectedUrl = "$siteUrl/wp-json/wp/v2/media/54" - val expected = Pair(expectedUrl, emptyMap()) - - assertEquals(expected, subject.parseUrlAndParamsForWPOrg(INPUT_PATH, siteUrl)) - } -} diff --git a/build.gradle b/build.gradle index e0e4b1b4e598..17ff59a08374 100644 --- a/build.gradle +++ b/build.gradle @@ -106,7 +106,7 @@ ext { targetSdkVersion = 28 daggerVersion = '2.22.1' - fluxCVersion = '1.6.9' + fluxCVersion = '1.6.10-beta-1' appCompatVersion = '1.0.2' constraintLayoutVersion = '1.1.3'