@@ -20,9 +20,11 @@ import (
20
20
"cdr.dev/slog/sloggers/slogtest"
21
21
"github.com/coder/coder/v2/coderd/audit"
22
22
"github.com/coder/coder/v2/coderd/coderdtest"
23
+ "github.com/coder/coder/v2/coderd/coderdtest/oidctest"
23
24
"github.com/coder/coder/v2/coderd/database"
24
25
"github.com/coder/coder/v2/coderd/database/dbauthz"
25
26
"github.com/coder/coder/v2/coderd/database/dbtime"
27
+ "github.com/coder/coder/v2/coderd/externalauth"
26
28
"github.com/coder/coder/v2/coderd/rbac"
27
29
"github.com/coder/coder/v2/codersdk"
28
30
"github.com/coder/coder/v2/provisioner/echo"
@@ -711,6 +713,78 @@ func TestWorkspaceBuildStatus(t *testing.T) {
711
713
require .EqualValues (t , codersdk .WorkspaceStatusDeleted , workspace .LatestBuild .Status )
712
714
}
713
715
716
+ func TestWorkspaceDeleteSuspendedUser (t * testing.T ) {
717
+ t .Parallel ()
718
+ const providerID = "fake-github"
719
+ fake := oidctest .NewFakeIDP (t , oidctest .WithServing ())
720
+
721
+ validateCalls := 0
722
+ userSuspended := false
723
+ owner := coderdtest .New (t , & coderdtest.Options {
724
+ IncludeProvisionerDaemon : true ,
725
+ ExternalAuthConfigs : []* externalauth.Config {
726
+ fake .ExternalAuthConfig (t , providerID , & oidctest.ExternalAuthConfigOptions {
727
+ ValidatePayload : func (email string ) (interface {}, int , error ) {
728
+ validateCalls ++
729
+ if userSuspended {
730
+ // Simulate the user being suspended from the IDP too.
731
+ return "" , http .StatusForbidden , fmt .Errorf ("user is suspended" )
732
+ }
733
+ return "OK" , 0 , nil
734
+ },
735
+ }),
736
+ },
737
+ })
738
+
739
+ first := coderdtest .CreateFirstUser (t , owner )
740
+
741
+ // New user that we will suspend when we try to delete the workspace.
742
+ client , user := coderdtest .CreateAnotherUser (t , owner , first .OrganizationID , rbac .RoleTemplateAdmin ())
743
+ fake .ExternalLogin (t , client )
744
+
745
+ version := coderdtest .CreateTemplateVersion (t , client , first .OrganizationID , & echo.Responses {
746
+ Parse : echo .ParseComplete ,
747
+ ProvisionApply : echo .ApplyComplete ,
748
+ ProvisionPlan : []* proto.Response {{
749
+ Type : & proto.Response_Plan {
750
+ Plan : & proto.PlanComplete {
751
+ Error : "" ,
752
+ Resources : nil ,
753
+ Parameters : nil ,
754
+ ExternalAuthProviders : []* proto.ExternalAuthProviderResource {
755
+ {
756
+ Id : providerID ,
757
+ Optional : false ,
758
+ },
759
+ },
760
+ },
761
+ },
762
+ }},
763
+ })
764
+
765
+ validateCalls = 0 // Reset
766
+ coderdtest .AwaitTemplateVersionJobCompleted (t , client , version .ID )
767
+ template := coderdtest .CreateTemplate (t , client , first .OrganizationID , version .ID )
768
+ workspace := coderdtest .CreateWorkspace (t , client , first .OrganizationID , template .ID )
769
+ coderdtest .AwaitWorkspaceBuildJobCompleted (t , client , workspace .LatestBuild .ID )
770
+ require .Equal (t , 1 , validateCalls ) // Ensure the external link is working
771
+
772
+ // Suspend the user
773
+ ctx := testutil .Context (t , testutil .WaitLong )
774
+ _ , err := owner .UpdateUserStatus (ctx , user .ID .String (), codersdk .UserStatusSuspended )
775
+ require .NoError (t , err , "suspend user" )
776
+
777
+ // Now delete the workspace build
778
+ userSuspended = true
779
+ build , err := owner .CreateWorkspaceBuild (ctx , workspace .ID , codersdk.CreateWorkspaceBuildRequest {
780
+ Transition : codersdk .WorkspaceTransitionDelete ,
781
+ })
782
+ require .NoError (t , err )
783
+ build = coderdtest .AwaitWorkspaceBuildJobCompleted (t , owner , build .ID )
784
+ require .Equal (t , 2 , validateCalls )
785
+ require .Equal (t , codersdk .WorkspaceStatusDeleted , build .Status )
786
+ }
787
+
714
788
func TestWorkspaceBuildDebugMode (t * testing.T ) {
715
789
t .Parallel ()
716
790
0 commit comments