2 files changed
+144
-7
No files matched your search
@@ -4,8 +4,10 @@ import com.m57.hermescontrol.data.local.AuthManager
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.mockwebserver.Dispatcher
|
||||
import okhttp3.mockwebserver.MockResponse
|
||||
import okhttp3.mockwebserver.MockWebServer
|
||||
import okhttp3.mockwebserver.RecordedRequest
|
||||
import org.junit.After
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNull
|
||||
@@ -49,6 +51,21 @@ class ProfileScopeInterceptorTest {
|
||||
return server.takeRequest().requestUrl!!
|
||||
}
|
||||
|
||||
private fun requestedUrl(
|
||||
client: OkHttpClient,
|
||||
path: String,
|
||||
method: String = "GET",
|
||||
): HttpUrl {
|
||||
server.enqueue(MockResponse().setResponseCode(200).setBody("{}"))
|
||||
val builder = Request.Builder().url(server.url(path))
|
||||
when (method) {
|
||||
"DELETE" -> builder.delete()
|
||||
else -> builder.get()
|
||||
}
|
||||
client.newCall(builder.build()).execute().close()
|
||||
return server.takeRequest().requestUrl!!
|
||||
}
|
||||
|
||||
@Test
|
||||
fun scopedEndpoint_appendsProfile() {
|
||||
val client = clientFor("work")
|
||||
@@ -131,6 +148,100 @@ class ProfileScopeInterceptorTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun newlyScopedReads_followActiveProfileAcrossSwitches() {
|
||||
val client = clientFor("alpha")
|
||||
|
||||
assertEquals("alpha", requestedUrl(client, "api/webhooks").queryParameter("profile"))
|
||||
AuthManager.setActiveProfileId("beta")
|
||||
assertEquals("beta", requestedUrl(client, "api/credentials/pool").queryParameter("profile"))
|
||||
AuthManager.setActiveProfileId("alpha")
|
||||
assertEquals("alpha", requestedUrl(client, "api/ops/hooks").queryParameter("profile"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun newlyScopedMutations_followActiveProfileAcrossSwitches() {
|
||||
val client = clientFor("alpha")
|
||||
|
||||
assertEquals(
|
||||
"alpha",
|
||||
requestedUrl(client, "api/webhooks/build-events", method = "DELETE").queryParameter("profile"),
|
||||
)
|
||||
AuthManager.setActiveProfileId("beta")
|
||||
assertEquals(
|
||||
"beta",
|
||||
requestedUrl(client, "api/credentials/pool/openai/1", method = "DELETE").queryParameter("profile"),
|
||||
)
|
||||
AuthManager.setActiveProfileId("alpha")
|
||||
assertEquals(
|
||||
"alpha",
|
||||
requestedUrl(client, "api/ops/hooks", method = "DELETE").queryParameter("profile"),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun mobileUsedOpsRoutes_areScopedWithoutBlanketOpsMatch() {
|
||||
val client = clientFor("work")
|
||||
val paths =
|
||||
listOf(
|
||||
"api/ops/backup",
|
||||
"api/ops/backup/download",
|
||||
"api/ops/doctor",
|
||||
"api/ops/security-audit",
|
||||
"api/ops/prompt-size",
|
||||
"api/ops/dump",
|
||||
"api/ops/config-migrate",
|
||||
"api/ops/import-upload",
|
||||
"api/ops/debug-share",
|
||||
"api/ops/checkpoints",
|
||||
"api/ops/checkpoints/prune",
|
||||
"api/ops/hooks",
|
||||
)
|
||||
|
||||
for (path in paths) {
|
||||
val url = requestedUrl(client, path)
|
||||
assertEquals("work", url.queryParameter("profile"))
|
||||
}
|
||||
|
||||
val unclassified = requestedUrl(client, "api/ops/machine-global")
|
||||
assertNull(unclassified.queryParameter("profile"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun destructiveWebhookDelete_avoidsMultiplexUnnamedProfile400() {
|
||||
server.dispatcher =
|
||||
object : Dispatcher() {
|
||||
override fun dispatch(request: RecordedRequest): MockResponse =
|
||||
if (request.requestUrl?.queryParameter("profile").isNullOrBlank()) {
|
||||
MockResponse().setResponseCode(400)
|
||||
} else {
|
||||
MockResponse().setResponseCode(200)
|
||||
}
|
||||
}
|
||||
|
||||
val unscopedClient = clientFor(null)
|
||||
val unscopedRequest =
|
||||
Request
|
||||
.Builder()
|
||||
.url(server.url("api/webhooks/build-events"))
|
||||
.delete()
|
||||
.build()
|
||||
unscopedClient.newCall(unscopedRequest).execute().use { response ->
|
||||
assertEquals(400, response.code)
|
||||
}
|
||||
|
||||
val scopedClient = clientFor("beta")
|
||||
val scopedRequest =
|
||||
Request
|
||||
.Builder()
|
||||
.url(server.url("api/webhooks/build-events"))
|
||||
.delete()
|
||||
.build()
|
||||
scopedClient.newCall(scopedRequest).execute().use { response ->
|
||||
assertEquals(200, response.code)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun lookalikePath_notScoped() {
|
||||
// Sourcery review (PR #540): `startsWith` must not match non-segment
|
||||
|
||||
Reference in new issue
Block a user