@@ -8,11 +8,13 @@ import (
88 "net/http"
99 "testing"
1010
11+ "github.com/golang-jwt/jwt/v4"
1112 "github.com/stretchr/testify/assert"
1213 "github.com/stretchr/testify/require"
1314
1415 "github.com/coder/coder/v2/coderd/audit"
1516 "github.com/coder/coder/v2/coderd/coderdtest"
17+ "github.com/coder/coder/v2/coderd/coderdtest/oidctest"
1618 "github.com/coder/coder/v2/coderd/database"
1719 "github.com/coder/coder/v2/codersdk"
1820 "github.com/coder/coder/v2/cryptorand"
@@ -364,5 +366,82 @@ func TestScim(t *testing.T) {
364366 require .Len (t , userRes .Users , 1 )
365367 assert .Equal (t , codersdk .UserStatusSuspended , userRes .Users [0 ].Status )
366368 })
369+
370+ // Create a user via SCIM, which starts as dormant.
371+ // Log in as the user, making them active.
372+ // Then patch the user again and the user should still be active.
373+ t .Run ("ActiveIsActive" , func (t * testing.T ) {
374+ t .Parallel ()
375+
376+ ctx , cancel := context .WithTimeout (context .Background (), testutil .WaitLong )
377+ defer cancel ()
378+
379+ scimAPIKey := []byte ("hi" )
380+
381+ mockAudit := audit .NewMock ()
382+ fake := oidctest .NewFakeIDP (t , oidctest .WithServing ())
383+ client , _ := coderdenttest .New (t , & coderdenttest.Options {
384+ Options : & coderdtest.Options {
385+ Auditor : mockAudit ,
386+ OIDCConfig : fake .OIDCConfig (t , []string {}),
387+ },
388+ SCIMAPIKey : scimAPIKey ,
389+ AuditLogging : true ,
390+ LicenseOptions : & coderdenttest.LicenseOptions {
391+ AccountID : "coolin" ,
392+ Features : license.Features {
393+ codersdk .FeatureSCIM : 1 ,
394+ codersdk .FeatureAuditLog : 1 ,
395+ },
396+ },
397+ })
398+ mockAudit .ResetLogs ()
399+
400+ // User is dormant on create
401+ sUser := makeScimUser (t )
402+ res , err := client .Request (ctx , "POST" , "/scim/v2/Users" , sUser , setScimAuth (scimAPIKey ))
403+ require .NoError (t , err )
404+ defer res .Body .Close ()
405+ assert .Equal (t , http .StatusOK , res .StatusCode )
406+
407+ err = json .NewDecoder (res .Body ).Decode (& sUser )
408+ require .NoError (t , err )
409+
410+ // Check the audit log
411+ aLogs := mockAudit .AuditLogs ()
412+ require .Len (t , aLogs , 1 )
413+ assert .Equal (t , database .AuditActionCreate , aLogs [0 ].Action )
414+
415+ // Verify the user is dormant
416+ scimUser , err := client .User (ctx , sUser .UserName )
417+ require .NoError (t , err )
418+ require .Equal (t , codersdk .UserStatusDormant , scimUser .Status , "user starts as dormant" )
419+
420+ // Log in as the user, making them active
421+ //nolint:bodyclose
422+ scimUserClient , _ := fake .Login (t , client , jwt.MapClaims {
423+ "email" : sUser .Emails [0 ].Value ,
424+ })
425+ scimUser , err = scimUserClient .User (ctx , codersdk .Me )
426+ require .NoError (t , err )
427+ require .Equal (t , codersdk .UserStatusActive , scimUser .Status , "user should now be active" )
428+
429+ // Patch the user
430+ mockAudit .ResetLogs ()
431+ res , err = client .Request (ctx , "PATCH" , "/scim/v2/Users/" + sUser .ID , sUser , setScimAuth (scimAPIKey ))
432+ require .NoError (t , err )
433+ _ , _ = io .Copy (io .Discard , res .Body )
434+ _ = res .Body .Close ()
435+ assert .Equal (t , http .StatusOK , res .StatusCode )
436+
437+ // Should be no audit logs since there is no diff
438+ aLogs = mockAudit .AuditLogs ()
439+ require .Len (t , aLogs , 0 )
440+
441+ // Verify the user is still active.
442+ scimUser , err = client .User (ctx , sUser .UserName )
443+ require .NoError (t , err )
444+ require .Equal (t , codersdk .UserStatusActive , scimUser .Status , "user is still active" )
445+ })
367446 })
368447}
0 commit comments