@@ -24,7 +24,9 @@ import (
24
24
"github.com/coder/coder/v2/coderd/database/dbtestutil"
25
25
"github.com/coder/coder/v2/coderd/database/dbtime"
26
26
"github.com/coder/coder/v2/coderd/database/migrations"
27
+ "github.com/coder/coder/v2/coderd/httpmw"
27
28
"github.com/coder/coder/v2/coderd/rbac"
29
+ "github.com/coder/coder/v2/coderd/rbac/policy"
28
30
"github.com/coder/coder/v2/testutil"
29
31
)
30
32
@@ -612,70 +614,98 @@ func TestGetWorkspaceAgentUsageStatsAndLabels(t *testing.T) {
612
614
})
613
615
}
614
616
615
- func TestGetWorkspacesAndAgents (t * testing.T ) {
617
+ func TestGetAuthorizedWorkspacesAndAgents (t * testing.T ) {
616
618
t .Parallel ()
617
619
if testing .Short () {
618
620
t .SkipNow ()
619
621
}
620
622
623
+ ctx := testutil .Context (t ,testutil .WaitLong )
621
624
sqlDB := testSQLDB (t )
622
625
err := migrations .Up (sqlDB )
623
626
require .NoError (t ,err )
624
627
db := database .New (sqlDB )
625
628
626
629
org := dbgen .Organization (t ,db , database.Organization {})
630
+ owner := dbgen .User (t ,db , database.User {
631
+ RBACRoles : []string {rbac .RoleOwner ().String ()},
632
+ })
627
633
user := dbgen .User (t ,db , database.User {})
628
634
tpl := dbgen .Template (t ,db , database.Template {
629
635
OrganizationID :org .ID ,
630
- CreatedBy :user .ID ,
636
+ CreatedBy :owner .ID ,
631
637
})
632
638
633
- pending := createTemplateVersion (t ,db ,tpl ,tvArgs {
639
+ pendingID := uuid .New ()
640
+ createTemplateVersion (t ,db ,tpl ,tvArgs {
634
641
Status :database .ProvisionerJobStatusPending ,
635
642
CreateWorkspace :true ,
643
+ WorkspaceID :pendingID ,
636
644
CreateAgent :true ,
637
645
})
638
- failed := createTemplateVersion (t ,db ,tpl ,tvArgs {
646
+ failedID := uuid .New ()
647
+ createTemplateVersion (t ,db ,tpl ,tvArgs {
639
648
Status :database .ProvisionerJobStatusFailed ,
640
649
CreateWorkspace :true ,
641
650
CreateAgent :true ,
651
+ WorkspaceID :failedID ,
642
652
})
643
- succeeded := createTemplateVersion (t ,db ,tpl ,tvArgs {
653
+ succeededID := uuid .New ()
654
+ createTemplateVersion (t ,db ,tpl ,tvArgs {
644
655
Status :database .ProvisionerJobStatusSucceeded ,
645
656
WorkspaceTransition :database .WorkspaceTransitionStart ,
646
657
CreateWorkspace :true ,
658
+ WorkspaceID :succeededID ,
647
659
CreateAgent :true ,
648
660
ExtraAgents :1 ,
649
661
ExtraBuilds :2 ,
650
662
})
651
- deleted := createTemplateVersion (t ,db ,tpl ,tvArgs {
663
+ deletedID := uuid .New ()
664
+ createTemplateVersion (t ,db ,tpl ,tvArgs {
652
665
Status :database .ProvisionerJobStatusSucceeded ,
653
666
WorkspaceTransition :database .WorkspaceTransitionDelete ,
654
667
CreateWorkspace :true ,
668
+ WorkspaceID :deletedID ,
655
669
CreateAgent :false ,
656
670
})
657
671
658
- ctx := testutil .Context (t ,testutil .WaitLong )
659
- rows ,err := db .GetWorkspacesAndAgents (ctx )
672
+ authorizer := rbac .NewStrictCachingAuthorizer (prometheus .NewRegistry ())
673
+
674
+ userSubject ,_ ,err := httpmw .UserRBACSubject (ctx ,db ,user .ID ,rbac .ExpandableScope (rbac .ScopeAll ))
675
+ require .NoError (t ,err )
676
+ preparedUser ,err := authorizer .Prepare (ctx ,userSubject ,policy .ActionRead ,rbac .ResourceWorkspace .Type )
660
677
require .NoError (t ,err )
678
+ userCtx := dbauthz .As (ctx ,userSubject )
679
+ userRows ,err := db .GetAuthorizedWorkspacesAndAgents (userCtx ,preparedUser )
680
+ require .NoError (t ,err )
681
+ require .Len (t ,userRows ,0 )
661
682
662
- require .Len (t ,rows ,4 )
663
- for _ ,row := range rows {
683
+ ownerSubject ,_ ,err := httpmw .UserRBACSubject (ctx ,db ,owner .ID ,rbac .ExpandableScope (rbac .ScopeAll ))
684
+ require .NoError (t ,err )
685
+ preparedOwner ,err := authorizer .Prepare (ctx ,ownerSubject ,policy .ActionRead ,rbac .ResourceWorkspace .Type )
686
+ require .NoError (t ,err )
687
+ ownerCtx := dbauthz .As (ctx ,ownerSubject )
688
+ ownerRows ,err := db .GetAuthorizedWorkspacesAndAgents (ownerCtx ,preparedOwner )
689
+ require .NoError (t ,err )
690
+ require .Len (t ,ownerRows ,4 )
691
+ for _ ,row := range ownerRows {
664
692
switch row .WorkspaceID {
665
- case pending . ID :
693
+ case pendingID :
666
694
require .Len (t ,row .AgentIds ,1 )
667
695
require .Equal (t ,database .ProvisionerJobStatusPending ,row .JobStatus )
668
- case failed . ID :
696
+ case failedID :
669
697
require .Len (t ,row .AgentIds ,1 )
670
698
require .Equal (t ,database .ProvisionerJobStatusFailed ,row .JobStatus )
671
- case succeeded . ID :
699
+ case succeededID :
672
700
require .Len (t ,row .AgentIds ,2 )
673
701
require .Equal (t ,database .ProvisionerJobStatusSucceeded ,row .JobStatus )
674
702
require .Equal (t ,database .WorkspaceTransitionStart ,row .Transition )
675
- case deleted . ID :
703
+ case deletedID :
676
704
require .Len (t ,row .AgentIds ,0 )
677
705
require .Equal (t ,database .ProvisionerJobStatusSucceeded ,row .JobStatus )
678
706
require .Equal (t ,database .WorkspaceTransitionDelete ,row .Transition )
707
+ default :
708
+ t .Fatalf ("unexpected workspace ID: %s" ,row .WorkspaceID )
679
709
}
680
710
}
681
711
}
@@ -1605,6 +1635,7 @@ type tvArgs struct {
1605
1635
Status database.ProvisionerJobStatus
1606
1636
// CreateWorkspace is true if we should create a workspace for the template version
1607
1637
CreateWorkspace bool
1638
+ WorkspaceID uuid.UUID
1608
1639
CreateAgent bool
1609
1640
WorkspaceTransition database.WorkspaceTransition
1610
1641
ExtraAgents int
@@ -1625,49 +1656,18 @@ func createTemplateVersion(t testing.TB, db database.Store, tpl database.Templat
1625
1656
CreatedBy :tpl .CreatedBy ,
1626
1657
})
1627
1658
1628
- earlier := sql.NullTime {
1629
- Time :dbtime .Now ().Add (time .Second * - 30 ),
1630
- Valid :true ,
1631
- }
1632
- now := sql.NullTime {
1633
- Time :dbtime .Now (),
1634
- Valid :true ,
1635
- }
1636
- j := database.ProvisionerJob {
1659
+ latestJob := database.ProvisionerJob {
1637
1660
ID :version .JobID ,
1638
- CreatedAt :earlier .Time ,
1639
- UpdatedAt :earlier .Time ,
1640
1661
Error : sql.NullString {},
1641
1662
OrganizationID :tpl .OrganizationID ,
1642
1663
InitiatorID :tpl .CreatedBy ,
1643
1664
Type :database .ProvisionerJobTypeTemplateVersionImport ,
1644
1665
}
1645
-
1646
- switch args .Status {
1647
- case database .ProvisionerJobStatusRunning :
1648
- j .StartedAt = earlier
1649
- case database .ProvisionerJobStatusPending :
1650
- case database .ProvisionerJobStatusFailed :
1651
- j .StartedAt = earlier
1652
- j .CompletedAt = now
1653
- j .Error = sql.NullString {
1654
- String :"failed" ,
1655
- Valid :true ,
1656
- }
1657
- j .ErrorCode = sql.NullString {
1658
- String :"failed" ,
1659
- Valid :true ,
1660
- }
1661
- case database .ProvisionerJobStatusSucceeded :
1662
- j .StartedAt = earlier
1663
- j .CompletedAt = now
1664
- default :
1665
- t .Fatalf ("invalid status: %s" ,args .Status )
1666
- }
1667
-
1668
- dbgen .ProvisionerJob (t ,db ,nil ,j )
1666
+ setJobStatus (t ,args .Status ,& latestJob )
1667
+ dbgen .ProvisionerJob (t ,db ,nil ,latestJob )
1669
1668
if args .CreateWorkspace {
1670
1669
wrk := dbgen .Workspace (t ,db , database.Workspace {
1670
+ ID :args .WorkspaceID ,
1671
1671
CreatedAt : time.Time {},
1672
1672
UpdatedAt : time.Time {},
1673
1673
OwnerID :tpl .CreatedBy ,
@@ -1678,13 +1678,13 @@ func createTemplateVersion(t testing.TB, db database.Store, tpl database.Templat
1678
1678
if args .WorkspaceTransition != "" {
1679
1679
trans = args .WorkspaceTransition
1680
1680
}
1681
-
1682
- latestJob := dbgen .ProvisionerJob (t ,db ,nil , database.ProvisionerJob {
1681
+ latestJob = database.ProvisionerJob {
1683
1682
Type :database .ProvisionerJobTypeWorkspaceBuild ,
1684
- CompletedAt :now ,
1685
1683
InitiatorID :tpl .CreatedBy ,
1686
1684
OrganizationID :tpl .OrganizationID ,
1687
- })
1685
+ }
1686
+ setJobStatus (t ,args .Status ,& latestJob )
1687
+ latestJob = dbgen .ProvisionerJob (t ,db ,nil ,latestJob )
1688
1688
latestResource := dbgen .WorkspaceResource (t ,db , database.WorkspaceResource {
1689
1689
JobID :latestJob .ID ,
1690
1690
})
@@ -1697,12 +1697,13 @@ func createTemplateVersion(t testing.TB, db database.Store, tpl database.Templat
1697
1697
JobID :latestJob .ID ,
1698
1698
})
1699
1699
for i := 0 ;i < args .ExtraBuilds ;i ++ {
1700
- latestJob = dbgen . ProvisionerJob ( t , db , nil , database.ProvisionerJob {
1700
+ latestJob = database.ProvisionerJob {
1701
1701
Type :database .ProvisionerJobTypeWorkspaceBuild ,
1702
- CompletedAt :now ,
1703
1702
InitiatorID :tpl .CreatedBy ,
1704
1703
OrganizationID :tpl .OrganizationID ,
1705
- })
1704
+ }
1705
+ setJobStatus (t ,args .Status ,& latestJob )
1706
+ latestJob = dbgen .ProvisionerJob (t ,db ,nil ,latestJob )
1706
1707
latestResource = dbgen .WorkspaceResource (t ,db , database.WorkspaceResource {
1707
1708
JobID :latestJob .ID ,
1708
1709
})
@@ -1730,6 +1731,40 @@ func createTemplateVersion(t testing.TB, db database.Store, tpl database.Templat
1730
1731
return version
1731
1732
}
1732
1733
1734
+ func setJobStatus (t testing.TB ,status database.ProvisionerJobStatus ,j * database.ProvisionerJob ) {
1735
+ t .Helper ()
1736
+
1737
+ earlier := sql.NullTime {
1738
+ Time :dbtime .Now ().Add (time .Second * - 30 ),
1739
+ Valid :true ,
1740
+ }
1741
+ now := sql.NullTime {
1742
+ Time :dbtime .Now (),
1743
+ Valid :true ,
1744
+ }
1745
+ switch status {
1746
+ case database .ProvisionerJobStatusRunning :
1747
+ j .StartedAt = earlier
1748
+ case database .ProvisionerJobStatusPending :
1749
+ case database .ProvisionerJobStatusFailed :
1750
+ j .StartedAt = earlier
1751
+ j .CompletedAt = now
1752
+ j .Error = sql.NullString {
1753
+ String :"failed" ,
1754
+ Valid :true ,
1755
+ }
1756
+ j .ErrorCode = sql.NullString {
1757
+ String :"failed" ,
1758
+ Valid :true ,
1759
+ }
1760
+ case database .ProvisionerJobStatusSucceeded :
1761
+ j .StartedAt = earlier
1762
+ j .CompletedAt = now
1763
+ default :
1764
+ t .Fatalf ("invalid status: %s" ,status )
1765
+ }
1766
+ }
1767
+
1733
1768
func TestArchiveVersions (t * testing.T ) {
1734
1769
t .Parallel ()
1735
1770
if testing .Short () {