11package com.coder.toolbox
22
33import com.coder.toolbox.cli.CoderCLIManager
4+ import com.coder.toolbox.oauth.TokenEndpointAuthMethod
45import com.coder.toolbox.sdk.CoderRestClient
56import com.coder.toolbox.sdk.v2.models.Workspace
67import com.coder.toolbox.sdk.v2.models.WorkspaceAgent
@@ -10,6 +11,8 @@ import com.coder.toolbox.sdk.v2.models.WorkspaceBuild
1011import com.coder.toolbox.sdk.v2.models.WorkspaceResource
1112import com.coder.toolbox.sdk.v2.models.WorkspaceStatus
1213import com.coder.toolbox.views.CoderSetupWizardPage
14+ import com.coder.toolbox.views.state.StoredOAuthSession
15+ import com.coder.toolbox.views.state.WizardStep
1316import io.mockk.clearAllMocks
1417import io.mockk.coEvery
1518import io.mockk.coVerify
@@ -256,6 +259,130 @@ class CoderRemoteProviderTest {
256259 verify { mockContext.popupPluginMainPage() }
257260 }
258261
262+ @Test
263+ fun `given mTLS is required when auto setup has stored credentials then mTLS takes precedence` () {
264+ // given
265+ val url = URI (" https://coder.example.com" ).toURL()
266+ every { mockContext.deploymentUrl } returns url
267+ every { mockContext.settingsStore.requiresMTlsAuth } returns true
268+ every { mockContext.settingsStore.requiresTokenAuth } returns false
269+ every { mockContext.settingsStore.preferOAuth2IfAvailable } returns true
270+ every { mockContext.secrets.apiTokenFor(url) } returns " token"
271+ every { mockContext.secrets.oauthSessionFor(url.toString()) } returns storedOAuthSession()
272+ val provider = CoderRemoteProvider (mockContext)
273+
274+ // when
275+ val overridePage = provider.getOverrideUiPage() as CoderSetupWizardPage
276+
277+ // then
278+ assertEquals(WizardStep .CONNECT , overridePage.model.currentStep())
279+ assertNull(overridePage.model.token)
280+ assertNull(overridePage.model.oauthSession)
281+ }
282+
283+ @Test
284+ fun `given OAuth is preferred when auto setup has token and OAuth session then OAuth is used` () {
285+ // given
286+ val url = URI (" https://coder.example.com" ).toURL()
287+ every { mockContext.deploymentUrl } returns url
288+ every { mockContext.settingsStore.requiresMTlsAuth } returns false
289+ every { mockContext.settingsStore.requiresTokenAuth } returns true
290+ every { mockContext.settingsStore.preferOAuth2IfAvailable } returns true
291+ every { mockContext.secrets.apiTokenFor(url) } returns " token"
292+ every { mockContext.secrets.oauthSessionFor(url.toString()) } returns storedOAuthSession()
293+ val provider = CoderRemoteProvider (mockContext)
294+
295+ // when
296+ val overridePage = provider.getOverrideUiPage() as CoderSetupWizardPage
297+
298+ // then
299+ assertEquals(WizardStep .CONNECT , overridePage.model.currentStep())
300+ assertNull(overridePage.model.token)
301+ assertNotNull(overridePage.model.oauthSession)
302+ }
303+
304+ @Test
305+ fun `given OAuth is not preferred when auto setup has token and OAuth session then token is used` () {
306+ // given
307+ val url = URI (" https://coder.example.com" ).toURL()
308+ every { mockContext.deploymentUrl } returns url
309+ every { mockContext.settingsStore.requiresMTlsAuth } returns false
310+ every { mockContext.settingsStore.requiresTokenAuth } returns true
311+ every { mockContext.settingsStore.preferOAuth2IfAvailable } returns false
312+ every { mockContext.secrets.apiTokenFor(url) } returns " token"
313+ every { mockContext.secrets.oauthSessionFor(url.toString()) } returns storedOAuthSession()
314+ val provider = CoderRemoteProvider (mockContext)
315+
316+ // when
317+ val overridePage = provider.getOverrideUiPage() as CoderSetupWizardPage
318+
319+ // then
320+ assertEquals(WizardStep .CONNECT , overridePage.model.currentStep())
321+ assertEquals(" token" , overridePage.model.token)
322+ assertNull(overridePage.model.oauthSession)
323+ }
324+
325+ @Test
326+ fun `given OAuth is not preferred when auto setup has API token then token is used` () {
327+ // given
328+ val url = URI (" https://coder.example.com" ).toURL()
329+ every { mockContext.deploymentUrl } returns url
330+ every { mockContext.settingsStore.requiresMTlsAuth } returns false
331+ every { mockContext.settingsStore.requiresTokenAuth } returns true
332+ every { mockContext.settingsStore.preferOAuth2IfAvailable } returns false
333+ every { mockContext.secrets.apiTokenFor(url) } returns " api-token"
334+ val provider = CoderRemoteProvider (mockContext)
335+
336+ // when
337+ val overridePage = provider.getOverrideUiPage() as CoderSetupWizardPage
338+
339+ // then
340+ assertEquals(WizardStep .CONNECT , overridePage.model.currentStep())
341+ assertEquals(" api-token" , overridePage.model.token)
342+ assertNull(overridePage.model.oauthSession)
343+ }
344+
345+ @Test
346+ fun `given OAuth is not preferred when auto setup has no API token then wizard starts at URL step` () {
347+ // given
348+ val url = URI (" https://coder.example.com" ).toURL()
349+ every { mockContext.deploymentUrl } returns url
350+ every { mockContext.settingsStore.requiresMTlsAuth } returns false
351+ every { mockContext.settingsStore.requiresTokenAuth } returns true
352+ every { mockContext.settingsStore.preferOAuth2IfAvailable } returns false
353+ every { mockContext.secrets.apiTokenFor(url) } returns null
354+ val provider = CoderRemoteProvider (mockContext)
355+
356+ // when
357+ val overridePage = provider.getOverrideUiPage() as CoderSetupWizardPage
358+
359+ // then
360+ assertEquals(WizardStep .URL_REQUEST , overridePage.model.currentStep())
361+ assertNull(overridePage.model.token)
362+ assertNull(overridePage.model.oauthSession)
363+ }
364+
365+ @Test
366+ fun `given OAuth is not preferred when auto setup only has OAuth session then wizard starts at URL step` () {
367+ // given
368+ val url = URI (" https://coder.example.com" ).toURL()
369+ every { mockContext.deploymentUrl } returns url
370+ every { mockContext.settingsStore.requiresMTlsAuth } returns false
371+ every { mockContext.settingsStore.requiresTokenAuth } returns true
372+ every { mockContext.settingsStore.preferOAuth2IfAvailable } returns false
373+ every { mockContext.secrets.apiTokenFor(url) } returns null
374+ every { mockContext.secrets.oauthSessionFor(url.toString()) } returns storedOAuthSession()
375+ val provider = CoderRemoteProvider (mockContext)
376+
377+ // when
378+ val overridePage = provider.getOverrideUiPage() as CoderSetupWizardPage
379+
380+ // then
381+ assertEquals(WizardStep .URL_REQUEST , overridePage.model.currentStep())
382+ assertNull(overridePage.model.token)
383+ assertNull(overridePage.model.oauthSession)
384+ }
385+
259386 @Test
260387 fun `given no existing environment then one is created` () = runTest {
261388 // given
@@ -411,4 +538,12 @@ class CoderRemoteProviderTest {
411538 set(target, value)
412539 }
413540 }
541+
542+ private fun storedOAuthSession (): StoredOAuthSession = StoredOAuthSession (
543+ clientId = " client-id" ,
544+ clientSecret = " client-secret" ,
545+ refreshToken = " refresh-token" ,
546+ tokenAuthMethod = TokenEndpointAuthMethod .CLIENT_SECRET_BASIC ,
547+ tokenEndpoint = " https://coder.example.com/oauth/token"
548+ )
414549}
0 commit comments