Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -467,17 +467,21 @@ open class PretixApi(url: String, key: String, orgaSlug: String, version: Int, h
throw FinalApiException("Server error: " + response.code + ".")
}
if (response.code == 401) {
if (body.startsWith("{")) {
val detail = if (body.startsWith("{")) {
try {
val err = JSONObject(body)
if (err.optString("detail", "") == "Device access has been revoked.") {
response.close()
throw DeviceAccessRevokedException("Device access has been revoked.")
}
JSONObject(body).optString("detail", "")
} catch (e: JSONException) {
e.printStackTrace()
""
}
} else {
""
}
response.close()
if (detail == "Device access has been revoked.") {
throw DeviceAccessRevokedException("Device access has been revoked.")
}
throw UnauthorizedApiException(detail.ifEmpty { "Server error: Unauthorized." })
}
return try {
if (json && response.code != 204) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package eu.pretix.libpretixsync.api;

public class UnauthorizedApiException extends FinalApiException {

public UnauthorizedApiException(String msg) {
super(msg);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package eu.pretix.libpretixsync.api

import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Protocol
import okhttp3.Response
import okhttp3.ResponseBody
import okio.Buffer
import okio.BufferedSource
import org.junit.Assert.assertEquals
import org.junit.Assert.assertThrows
import org.junit.Assert.assertTrue
import org.junit.Test

class PretixApiUnauthorizedTest {

private class CannedBody(content: String) : ResponseBody() {
private val buffer = Buffer().writeUtf8(content)
var closed = false

override fun contentType() = "application/json".toMediaType()

override fun contentLength() = -1L

override fun source(): BufferedSource = buffer

override fun close() {
closed = true
super.close()
}
}

private fun apiResponding(code: Int, body: CannedBody): PretixApi {
val factory = object : HttpClientFactory {
override fun buildClient(ignore_ssl: Boolean): OkHttpClient =
OkHttpClient.Builder()
.addInterceptor { chain ->
Response.Builder()
.request(chain.request())
.protocol(Protocol.HTTP_1_1)
.code(code)
.message("Canned")
.body(body)
.build()
}
.build()
}
return PretixApi("https://pretix.example/", "token", "demo", PretixApi.SUPPORTED_API_VERSION, factory)
}

@Test
fun invalidTokenThrowsUnauthorizedWithServerDetail() {
val body = CannedBody("{\"detail\":\"Invalid token.\"}")
val api = apiResponding(401, body)

val e = assertThrows(UnauthorizedApiException::class.java) { api.fetchResource(api.apiURL("device/info")) }

assertEquals("Invalid token.", e.message)
assertTrue(body.closed)
}

@Test
fun revokedDeviceThrowsDeviceAccessRevoked() {
val body = CannedBody("{\"detail\":\"Device access has been revoked.\"}")
val api = apiResponding(401, body)

val e = assertThrows(DeviceAccessRevokedException::class.java) { api.fetchResource(api.apiURL("device/info")) }

assertEquals("Device access has been revoked.", e.message)
assertTrue(body.closed)
}

@Test
fun unauthorizedWithoutJsonDetailThrowsGenericMessage() {
val body = CannedBody("<html>Unauthorized</html>")
val api = apiResponding(401, body)

val e = assertThrows(UnauthorizedApiException::class.java) { api.fetchResource(api.apiURL("device/info")) }

assertEquals("Server error: Unauthorized.", e.message)
assertTrue(body.closed)
}

@Test
fun unauthorizedDownloadClosesUnreadResponse() {
val body = CannedBody("{\"detail\":\"Invalid token.\"}")
val api = apiResponding(401, body)

val e = assertThrows(UnauthorizedApiException::class.java) { api.downloadFile(api.apiURL("device/info")) }

assertEquals("Server error: Unauthorized.", e.message)
assertTrue(body.closed)
}

@Test
fun successfulResponseReturnsParsedJson() {
val api = apiResponding(200, CannedBody("{\"name\":\"Scanner\"}"))

val result = api.fetchResource(api.apiURL("device/info"))

assertEquals(200, result.response.code)
assertEquals("Scanner", result.data!!.getString("name"))
}
}