Skip to content
This repository was archived by the owner on Mar 19, 2024. It is now read-only.

Commit 376d52a

Browse files
authored
Merge pull request #481 from owncloud/feature/webfinger
add moshi classes for webfinger responses
2 parents 2c225d8 + e769684 commit 376d52a

File tree

10 files changed

+321
-1
lines changed

10 files changed

+321
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/* ownCloud Android Library is available under MIT license
2+
*
3+
* Copyright (C) 2022 ownCloud GmbH.
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19+
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20+
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
25+
package com.owncloud.android.lib.resources.webfinger
26+
27+
import android.net.Uri
28+
import com.owncloud.android.lib.common.OwnCloudClient
29+
import com.owncloud.android.lib.common.http.HttpConstants
30+
import com.owncloud.android.lib.common.http.methods.nonwebdav.GetMethod
31+
import com.owncloud.android.lib.common.http.methods.nonwebdav.HttpMethod
32+
import com.owncloud.android.lib.common.operations.RemoteOperation
33+
import com.owncloud.android.lib.common.operations.RemoteOperationResult
34+
import com.owncloud.android.lib.resources.webfinger.responses.WebfingerJrdResponse
35+
import com.squareup.moshi.Moshi
36+
import timber.log.Timber
37+
import java.net.URL
38+
39+
class GetOCInstanceViaWebfingerOperation(
40+
private val lockupServerDomain: String,
41+
private val rel: String,
42+
private val resource: String,
43+
) : RemoteOperation<String>() {
44+
45+
private fun buildRequestUri() =
46+
Uri.parse(lockupServerDomain).buildUpon()
47+
.path(ENDPOINT_WEBFINGER_PATH)
48+
.appendQueryParameter("rel", rel)
49+
.appendQueryParameter("resource", resource)
50+
.build()
51+
52+
private fun isSuccess(status: Int): Boolean = status == HttpConstants.HTTP_OK
53+
54+
private fun parseResponse(response: String): WebfingerJrdResponse {
55+
val moshi = Moshi.Builder().build()
56+
val adapter = moshi.adapter(WebfingerJrdResponse::class.java)
57+
return adapter.fromJson(response)!!
58+
}
59+
60+
private fun onResultUnsuccessful(
61+
method: HttpMethod,
62+
response: String?,
63+
status: Int
64+
): RemoteOperationResult<String> {
65+
Timber.e("Failed requesting webfinger info")
66+
if (response != null) {
67+
Timber.e("*** status code: $status; response message: $response")
68+
} else {
69+
Timber.e("*** status code: $status")
70+
}
71+
return RemoteOperationResult<String>(method)
72+
}
73+
74+
private fun onRequestSuccessful(rawResponse: String): RemoteOperationResult<String> {
75+
val response = parseResponse(rawResponse)
76+
for (i in response.links) {
77+
if (i.rel == rel) {
78+
val operationResult = RemoteOperationResult<String>(RemoteOperationResult.ResultCode.OK)
79+
operationResult.data = i.href
80+
return operationResult
81+
}
82+
}
83+
Timber.e("Could not find ownCloud relevant information in webfinger response: $rawResponse")
84+
throw java.lang.Exception("Could not find ownCloud relevant information in webfinger response")
85+
}
86+
87+
override fun run(client: OwnCloudClient): RemoteOperationResult<String> {
88+
val requestUri = buildRequestUri()
89+
val getMethod = GetMethod(URL(requestUri.toString()))
90+
return try {
91+
val status = client.executeHttpMethod(getMethod)
92+
val response = getMethod.getResponseBodyAsString()!!
93+
94+
if (isSuccess(status)) {
95+
onRequestSuccessful(response)
96+
} else {
97+
onResultUnsuccessful(getMethod, response, status)
98+
}
99+
} catch (e: Exception) {
100+
Timber.e(e, "Requesting webfinger info failed")
101+
RemoteOperationResult<String>(e)
102+
}
103+
}
104+
105+
companion object {
106+
private const val ENDPOINT_WEBFINGER_PATH = "/.well-known/webfinger"
107+
}
108+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/* ownCloud Android Library is available under MIT license
2+
*
3+
* Copyright (C) 2022 ownCloud GmbH.
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19+
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20+
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
25+
package com.owncloud.android.lib.resources.webfinger.responses
26+
27+
import com.squareup.moshi.JsonClass
28+
29+
@JsonClass(generateAdapter = true)
30+
data class WebfingerJrdResponse(
31+
val subject: String,
32+
val links: List<LinkItem>
33+
)
34+
35+
@JsonClass(generateAdapter = true)
36+
data class LinkItem(
37+
val href: String,
38+
val rel: String
39+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* ownCloud Android client application
3+
*
4+
* Copyright (C) 2022 ownCloud GmbH.
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License version 2,
8+
* as published by the Free Software Foundation.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package com.owncloud.android.lib.resources.webfinger.services
19+
20+
import com.owncloud.android.lib.common.OwnCloudClient
21+
import com.owncloud.android.lib.common.operations.RemoteOperationResult
22+
23+
interface WebfingerService {
24+
fun getInstanceFromWebfinger(
25+
lookupServer: String,
26+
username: String,
27+
client: OwnCloudClient,
28+
): RemoteOperationResult<String>
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* ownCloud Android client application
3+
*
4+
* Copyright (C) 2022 ownCloud GmbH.
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License version 2,
8+
* as published by the Free Software Foundation.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package com.owncloud.android.lib.resources.webfinger.services.implementation
19+
20+
import com.owncloud.android.lib.common.OwnCloudClient
21+
import com.owncloud.android.lib.common.operations.RemoteOperationResult
22+
import com.owncloud.android.lib.resources.webfinger.GetOCInstanceViaWebfingerOperation
23+
import com.owncloud.android.lib.resources.webfinger.services.WebfingerService
24+
25+
class OCWebfingerService : WebfingerService {
26+
27+
override fun getInstanceFromWebfinger(
28+
lookupServer: String,
29+
username: String,
30+
client: OwnCloudClient,
31+
): RemoteOperationResult<String> =
32+
GetOCInstanceViaWebfingerOperation(lookupServer, OWNCLOUD_REL, username).execute(client)
33+
34+
companion object {
35+
private const val OWNCLOUD_REL = "http://webfinger.owncloud/rel/server-instance"
36+
}
37+
38+
}

owncloudComLibrary/src/test/java/com/owncloud/android/lib/resources/shares/responses/ShareeResponseTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,4 @@ class ShareeResponseTest {
9090
val EXAMPLE_RESPONSE_JSON = "$RESOURCES_PATH/example_sharee_response.json"
9191
val EMPTY_RESPONSE_JSON = "$RESOURCES_PATH/empty_sharee_response.json"
9292
}
93-
}
93+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.owncloud.android.lib.resources.webfinger.responses
2+
3+
import com.squareup.moshi.JsonAdapter
4+
import com.squareup.moshi.JsonDataException
5+
import com.squareup.moshi.Moshi
6+
import org.junit.Assert
7+
import org.junit.Before
8+
import org.junit.Test
9+
import java.io.File
10+
11+
class WebfingerResponseTest {
12+
lateinit var adapter: JsonAdapter<WebfingerJrdResponse>
13+
14+
private fun loadResponses(fileName: String) = adapter.fromJson(File(fileName).readText())
15+
16+
@Before
17+
fun prepare() {
18+
val moshi = Moshi.Builder().build()
19+
adapter = moshi.adapter(WebfingerJrdResponse::class.java)
20+
}
21+
22+
@Test
23+
fun `check rel in too much information - ok`() {
24+
val response = loadResponses(TOO_MUCH_INFORMATION_JSON)!!
25+
Assert.assertEquals("https://gast.somedomain.de", response.links[0].href)
26+
Assert.assertEquals("http://webfinger.owncloud/rel/server-instance", response.links[0].rel)
27+
}
28+
29+
@Test(expected = JsonDataException::class)
30+
fun `check key value pairs - ko - no href key`() {
31+
val response = loadResponses(BROKEN_JSON)!!
32+
Assert.assertEquals("https://gast.somedomain.de", response.links[0].href)
33+
}
34+
35+
@Test(expected = JsonDataException::class)
36+
fun `check key value pairs - ko - no rel key`() {
37+
val response = loadResponses(BROKEN_JSON)!!
38+
Assert.assertEquals("https://gast.somedomain.de", response.links[0].href)
39+
}
40+
41+
companion object {
42+
private const val RESOURCES_PATH =
43+
"src/test/responses/com.owncloud.android.lib.resources.webfinger.responses"
44+
private const val EXAMPLE_RESPONSE_JSON = "$RESOURCES_PATH/simple_response.json"
45+
private const val TOO_MUCH_INFORMATION_JSON = "$RESOURCES_PATH/to_much_information_response.json"
46+
private const val BROKEN_JSON = "$RESOURCES_PATH/broken_response.json"
47+
private const val NOT_CONTAINING_RELEVANT_INFORMATION_JSON = "$RESOURCES_PATH/not_containing_relevant_info_response.json"
48+
}
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"subject": "acct:[email protected]",
3+
"aliases": [
4+
"https://www.example.com/~bob/"
5+
],
6+
"properties": {
7+
"http://example.com/ns/role": "employee"
8+
},
9+
"links": [
10+
{
11+
"lel": "http://webfinger.example/rel/profile-page",
12+
"foo": "https://www.example.com/~bob/"
13+
}
14+
]
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"subject": "acct:[email protected]",
3+
"links": [
4+
{
5+
"rel": "http://webfinger.example/rel/businesscard",
6+
"href": "https://www.example.com/~bob/bob.vcf"
7+
}
8+
]
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"links": [
3+
{
4+
"href": "https://gast.somedomain.de",
5+
"rel": "http://webfinger.owncloud/rel/server-instance"
6+
}
7+
],
8+
"subject": "acct:[email protected]"
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"subject": "acct:[email protected]",
3+
"aliases": [
4+
"https://www.example.com/~bob/"
5+
],
6+
"properties": {
7+
"http://example.com/ns/role": "employee"
8+
},
9+
"gurken": {
10+
"whatever": 42
11+
},
12+
"links": [
13+
{
14+
"gurken": "sallat",
15+
"href": "https://gast.somedomain.de",
16+
"rel": "http://webfinger.owncloud/rel/server-instance"
17+
},
18+
{
19+
"gurken": "sallat",
20+
"rel": "http://webfinger.example/rel/businesscard",
21+
"href": "https://www.example.com/~bob/bob.vcf"
22+
}
23+
]
24+
}

0 commit comments

Comments
 (0)