1
0
mirror of https://github.com/owncloud/android-library.git synced 2025-06-07 16:06:08 +00:00

Merge pull request #481 from owncloud/feature/webfinger

add moshi classes for webfinger responses
This commit is contained in:
Jesús Recio 2022-11-02 11:16:57 +01:00 committed by GitHub
commit 376d52ac5b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 321 additions and 1 deletions

View File

@ -0,0 +1,108 @@
/* ownCloud Android Library is available under MIT license
*
* Copyright (C) 2022 ownCloud GmbH.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.owncloud.android.lib.resources.webfinger
import android.net.Uri
import com.owncloud.android.lib.common.OwnCloudClient
import com.owncloud.android.lib.common.http.HttpConstants
import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod
import com.owncloud.android.lib.common.http.methods.nonwebdav.HttpMethod
import com.owncloud.android.lib.common.operations.RemoteOperation
import com.owncloud.android.lib.common.operations.RemoteOperationResult
import com.owncloud.android.lib.resources.webfinger.responses.WebfingerJrdResponse
import com.squareup.moshi.Moshi
import timber.log.Timber
import java.net.URL
class GetOCInstanceViaWebfingerOperation(
private val lockupServerDomain: String,
private val rel: String,
private val resource: String,
) : RemoteOperation<String>() {
private fun buildRequestUri() =
Uri.parse(lockupServerDomain).buildUpon()
.path(ENDPOINT_WEBFINGER_PATH)
.appendQueryParameter("rel", rel)
.appendQueryParameter("resource", resource)
.build()
private fun isSuccess(status: Int): Boolean = status == HttpConstants.HTTP_OK
private fun parseResponse(response: String): WebfingerJrdResponse {
val moshi = Moshi.Builder().build()
val adapter = moshi.adapter(WebfingerJrdResponse::class.java)
return adapter.fromJson(response)!!
}
private fun onResultUnsuccessful(
method: HttpMethod,
response: String?,
status: Int
): RemoteOperationResult<String> {
Timber.e("Failed requesting webfinger info")
if (response != null) {
Timber.e("*** status code: $status; response message: $response")
} else {
Timber.e("*** status code: $status")
}
return RemoteOperationResult<String>(method)
}
private fun onRequestSuccessful(rawResponse: String): RemoteOperationResult<String> {
val response = parseResponse(rawResponse)
for (i in response.links) {
if (i.rel == rel) {
val operationResult = RemoteOperationResult<String>(RemoteOperationResult.ResultCode.OK)
operationResult.data = i.href
return operationResult
}
}
Timber.e("Could not find ownCloud relevant information in webfinger response: $rawResponse")
throw java.lang.Exception("Could not find ownCloud relevant information in webfinger response")
}
override fun run(client: OwnCloudClient): RemoteOperationResult<String> {
val requestUri = buildRequestUri()
val getMethod = GetMethod(URL(requestUri.toString()))
return try {
val status = client.executeHttpMethod(getMethod)
val response = getMethod.getResponseBodyAsString()!!
if (isSuccess(status)) {
onRequestSuccessful(response)
} else {
onResultUnsuccessful(getMethod, response, status)
}
} catch (e: Exception) {
Timber.e(e, "Requesting webfinger info failed")
RemoteOperationResult<String>(e)
}
}
companion object {
private const val ENDPOINT_WEBFINGER_PATH = "/.well-known/webfinger"
}
}

View File

@ -0,0 +1,39 @@
/* ownCloud Android Library is available under MIT license
*
* Copyright (C) 2022 ownCloud GmbH.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.owncloud.android.lib.resources.webfinger.responses
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class WebfingerJrdResponse(
val subject: String,
val links: List<LinkItem>
)
@JsonClass(generateAdapter = true)
data class LinkItem(
val href: String,
val rel: String
)

View File

@ -0,0 +1,29 @@
/**
* ownCloud Android client application
*
* Copyright (C) 2022 ownCloud GmbH.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.owncloud.android.lib.resources.webfinger.services
import com.owncloud.android.lib.common.OwnCloudClient
import com.owncloud.android.lib.common.operations.RemoteOperationResult
interface WebfingerService {
fun getInstanceFromWebfinger(
lookupServer: String,
username: String,
client: OwnCloudClient,
): RemoteOperationResult<String>
}

View File

@ -0,0 +1,38 @@
/**
* ownCloud Android client application
*
* Copyright (C) 2022 ownCloud GmbH.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.owncloud.android.lib.resources.webfinger.services.implementation
import com.owncloud.android.lib.common.OwnCloudClient
import com.owncloud.android.lib.common.operations.RemoteOperationResult
import com.owncloud.android.lib.resources.webfinger.GetOCInstanceViaWebfingerOperation
import com.owncloud.android.lib.resources.webfinger.services.WebfingerService
class OCWebfingerService : WebfingerService {
override fun getInstanceFromWebfinger(
lookupServer: String,
username: String,
client: OwnCloudClient,
): RemoteOperationResult<String> =
GetOCInstanceViaWebfingerOperation(lookupServer, OWNCLOUD_REL, username).execute(client)
companion object {
private const val OWNCLOUD_REL = "http://webfinger.owncloud/rel/server-instance"
}
}

View File

@ -0,0 +1,49 @@
package com.owncloud.android.lib.resources.webfinger.responses
import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.JsonDataException
import com.squareup.moshi.Moshi
import org.junit.Assert
import org.junit.Before
import org.junit.Test
import java.io.File
class WebfingerResponseTest {
lateinit var adapter: JsonAdapter<WebfingerJrdResponse>
private fun loadResponses(fileName: String) = adapter.fromJson(File(fileName).readText())
@Before
fun prepare() {
val moshi = Moshi.Builder().build()
adapter = moshi.adapter(WebfingerJrdResponse::class.java)
}
@Test
fun `check rel in too much information - ok`() {
val response = loadResponses(TOO_MUCH_INFORMATION_JSON)!!
Assert.assertEquals("https://gast.somedomain.de", response.links[0].href)
Assert.assertEquals("http://webfinger.owncloud/rel/server-instance", response.links[0].rel)
}
@Test(expected = JsonDataException::class)
fun `check key value pairs - ko - no href key`() {
val response = loadResponses(BROKEN_JSON)!!
Assert.assertEquals("https://gast.somedomain.de", response.links[0].href)
}
@Test(expected = JsonDataException::class)
fun `check key value pairs - ko - no rel key`() {
val response = loadResponses(BROKEN_JSON)!!
Assert.assertEquals("https://gast.somedomain.de", response.links[0].href)
}
companion object {
private const val RESOURCES_PATH =
"src/test/responses/com.owncloud.android.lib.resources.webfinger.responses"
private const val EXAMPLE_RESPONSE_JSON = "$RESOURCES_PATH/simple_response.json"
private const val TOO_MUCH_INFORMATION_JSON = "$RESOURCES_PATH/to_much_information_response.json"
private const val BROKEN_JSON = "$RESOURCES_PATH/broken_response.json"
private const val NOT_CONTAINING_RELEVANT_INFORMATION_JSON = "$RESOURCES_PATH/not_containing_relevant_info_response.json"
}
}

View File

@ -0,0 +1,15 @@
{
"subject": "acct:bob@example.com",
"aliases": [
"https://www.example.com/~bob/"
],
"properties": {
"http://example.com/ns/role": "employee"
},
"links": [
{
"lel": "http://webfinger.example/rel/profile-page",
"foo": "https://www.example.com/~bob/"
}
]
}

View File

@ -0,0 +1,9 @@
{
"subject": "acct:peter.sine@gurken.xxx",
"links": [
{
"rel": "http://webfinger.example/rel/businesscard",
"href": "https://www.example.com/~bob/bob.vcf"
}
]
}

View File

@ -0,0 +1,9 @@
{
"links": [
{
"href": "https://gast.somedomain.de",
"rel": "http://webfinger.owncloud/rel/server-instance"
}
],
"subject": "acct:peter.sine@gurken.xxx"
}

View File

@ -0,0 +1,24 @@
{
"subject": "acct:peter.sine@gurken.xxx",
"aliases": [
"https://www.example.com/~bob/"
],
"properties": {
"http://example.com/ns/role": "employee"
},
"gurken": {
"whatever": 42
},
"links": [
{
"gurken": "sallat",
"href": "https://gast.somedomain.de",
"rel": "http://webfinger.owncloud/rel/server-instance"
},
{
"gurken": "sallat",
"rel": "http://webfinger.example/rel/businesscard",
"href": "https://www.example.com/~bob/bob.vcf"
}
]
}