6
6
"context"
7
7
"database/sql"
8
8
"encoding/json"
9
+ "fmt"
9
10
"sort"
10
11
"testing"
11
12
"time"
@@ -14,6 +15,7 @@ import (
14
15
"github.com/stretchr/testify/require"
15
16
16
17
"github.com/coder/coder/v2/coderd/database"
18
+ "github.com/coder/coder/v2/coderd/database/db2sdk"
17
19
"github.com/coder/coder/v2/coderd/database/dbgen"
18
20
"github.com/coder/coder/v2/coderd/database/dbtime"
19
21
"github.com/coder/coder/v2/coderd/database/migrations"
@@ -514,6 +516,234 @@ func TestDefaultOrg(t *testing.T) {
514
516
require .True (t ,all [0 ].IsDefault ,"first org should always be default" )
515
517
}
516
518
519
+ // TestReadCustomRoles tests the input params returns the correct set of roles.
520
+ func TestReadCustomRoles (t * testing.T ) {
521
+ t .Parallel ()
522
+
523
+ if testing .Short () {
524
+ t .SkipNow ()
525
+ }
526
+
527
+ sqlDB := testSQLDB (t )
528
+ err := migrations .Up (sqlDB )
529
+ require .NoError (t ,err )
530
+
531
+ db := database .New (sqlDB )
532
+ ctx := testutil .Context (t ,testutil .WaitLong )
533
+
534
+ // Make a few site roles, and a few org roles
535
+ orgIDs := make ([]uuid.UUID ,3 )
536
+ for i := range orgIDs {
537
+ orgIDs [i ]= uuid .New ()
538
+ }
539
+
540
+ allRoles := make ([]database.CustomRole ,0 )
541
+ siteRoles := make ([]database.CustomRole ,0 )
542
+ orgRoles := make ([]database.CustomRole ,0 )
543
+ for i := 0 ;i < 15 ;i ++ {
544
+ orgID := uuid.NullUUID {
545
+ UUID :orgIDs [i % len (orgIDs )],
546
+ Valid :true ,
547
+ }
548
+ if i % 4 == 0 {
549
+ // Some should be site wide
550
+ orgID = uuid.NullUUID {}
551
+ }
552
+
553
+ role ,err := db .UpsertCustomRole (ctx , database.UpsertCustomRoleParams {
554
+ Name :fmt .Sprintf ("role-%d" ,i ),
555
+ OrganizationID :orgID ,
556
+ })
557
+ require .NoError (t ,err )
558
+ allRoles = append (allRoles ,role )
559
+ if orgID .Valid {
560
+ orgRoles = append (orgRoles ,role )
561
+ }else {
562
+ siteRoles = append (siteRoles ,role )
563
+ }
564
+ }
565
+
566
+ // normalizedRoleName allows for the simple ElementsMatch to work properly.
567
+ normalizedRoleName := func (role database.CustomRole )string {
568
+ return role .Name + ":" + role .OrganizationID .UUID .String ()
569
+ }
570
+
571
+ roleToLookup := func (role database.CustomRole ) database.NameOrganizationPair {
572
+ return database.NameOrganizationPair {
573
+ Name :role .Name ,
574
+ OrganizationID :role .OrganizationID .UUID ,
575
+ }
576
+ }
577
+
578
+ testCases := []struct {
579
+ Name string
580
+ Params database.CustomRolesParams
581
+ Match func (role database.CustomRole )bool
582
+ }{
583
+ {
584
+ Name :"NilRoles" ,
585
+ Params : database.CustomRolesParams {
586
+ LookupRoles :nil ,
587
+ ExcludeOrgRoles :false ,
588
+ OrganizationID : uuid.UUID {},
589
+ },
590
+ Match :func (role database.CustomRole )bool {
591
+ return true
592
+ },
593
+ },
594
+ {
595
+ // Empty params should return all roles
596
+ Name :"Empty" ,
597
+ Params : database.CustomRolesParams {
598
+ LookupRoles : []database.NameOrganizationPair {},
599
+ ExcludeOrgRoles :false ,
600
+ OrganizationID : uuid.UUID {},
601
+ },
602
+ Match :func (role database.CustomRole )bool {
603
+ return true
604
+ },
605
+ },
606
+ {
607
+ Name :"Organization" ,
608
+ Params : database.CustomRolesParams {
609
+ LookupRoles : []database.NameOrganizationPair {},
610
+ ExcludeOrgRoles :false ,
611
+ OrganizationID :orgIDs [1 ],
612
+ },
613
+ Match :func (role database.CustomRole )bool {
614
+ return role .OrganizationID .UUID == orgIDs [1 ]
615
+ },
616
+ },
617
+ {
618
+ Name :"SpecificOrgRole" ,
619
+ Params : database.CustomRolesParams {
620
+ LookupRoles : []database.NameOrganizationPair {
621
+ {
622
+ Name :orgRoles [0 ].Name ,
623
+ OrganizationID :orgRoles [0 ].OrganizationID .UUID ,
624
+ },
625
+ },
626
+ },
627
+ Match :func (role database.CustomRole )bool {
628
+ return role .Name == orgRoles [0 ].Name && role .OrganizationID .UUID == orgRoles [0 ].OrganizationID .UUID
629
+ },
630
+ },
631
+ {
632
+ Name :"SpecificSiteRole" ,
633
+ Params : database.CustomRolesParams {
634
+ LookupRoles : []database.NameOrganizationPair {
635
+ {
636
+ Name :siteRoles [0 ].Name ,
637
+ OrganizationID :siteRoles [0 ].OrganizationID .UUID ,
638
+ },
639
+ },
640
+ },
641
+ Match :func (role database.CustomRole )bool {
642
+ return role .Name == siteRoles [0 ].Name && role .OrganizationID .UUID == siteRoles [0 ].OrganizationID .UUID
643
+ },
644
+ },
645
+ {
646
+ Name :"FewSpecificRoles" ,
647
+ Params : database.CustomRolesParams {
648
+ LookupRoles : []database.NameOrganizationPair {
649
+ {
650
+ Name :orgRoles [0 ].Name ,
651
+ OrganizationID :orgRoles [0 ].OrganizationID .UUID ,
652
+ },
653
+ {
654
+ Name :orgRoles [1 ].Name ,
655
+ OrganizationID :orgRoles [1 ].OrganizationID .UUID ,
656
+ },
657
+ {
658
+ Name :siteRoles [0 ].Name ,
659
+ OrganizationID :siteRoles [0 ].OrganizationID .UUID ,
660
+ },
661
+ },
662
+ },
663
+ Match :func (role database.CustomRole )bool {
664
+ return (role .Name == orgRoles [0 ].Name && role .OrganizationID .UUID == orgRoles [0 ].OrganizationID .UUID )||
665
+ (role .Name == orgRoles [1 ].Name && role .OrganizationID .UUID == orgRoles [1 ].OrganizationID .UUID )||
666
+ (role .Name == siteRoles [0 ].Name && role .OrganizationID .UUID == siteRoles [0 ].OrganizationID .UUID )
667
+ },
668
+ },
669
+ {
670
+ Name :"AllRolesByLookup" ,
671
+ Params : database.CustomRolesParams {
672
+ LookupRoles :db2sdk .List (allRoles ,roleToLookup ),
673
+ },
674
+ Match :func (role database.CustomRole )bool {
675
+ return true
676
+ },
677
+ },
678
+ {
679
+ Name :"NotExists" ,
680
+ Params : database.CustomRolesParams {
681
+ LookupRoles : []database.NameOrganizationPair {
682
+ {
683
+ Name :"not-exists" ,
684
+ OrganizationID :uuid .New (),
685
+ },
686
+ {
687
+ Name :"not-exists" ,
688
+ OrganizationID :uuid .Nil ,
689
+ },
690
+ },
691
+ },
692
+ Match :func (role database.CustomRole )bool {
693
+ return false
694
+ },
695
+ },
696
+ {
697
+ Name :"Mixed" ,
698
+ Params : database.CustomRolesParams {
699
+ LookupRoles : []database.NameOrganizationPair {
700
+ {
701
+ Name :"not-exists" ,
702
+ OrganizationID :uuid .New (),
703
+ },
704
+ {
705
+ Name :"not-exists" ,
706
+ OrganizationID :uuid .Nil ,
707
+ },
708
+ {
709
+ Name :orgRoles [0 ].Name ,
710
+ OrganizationID :orgRoles [0 ].OrganizationID .UUID ,
711
+ },
712
+ {
713
+ Name :siteRoles [0 ].Name ,
714
+ },
715
+ },
716
+ },
717
+ Match :func (role database.CustomRole )bool {
718
+ return (role .Name == orgRoles [0 ].Name && role .OrganizationID .UUID == orgRoles [0 ].OrganizationID .UUID )||
719
+ (role .Name == siteRoles [0 ].Name && role .OrganizationID .UUID == siteRoles [0 ].OrganizationID .UUID )
720
+ },
721
+ },
722
+ }
723
+
724
+ for _ ,tc := range testCases {
725
+ tc := tc
726
+
727
+ t .Run (tc .Name ,func (t * testing.T ) {
728
+ t .Parallel ()
729
+
730
+ ctx := testutil .Context (t ,testutil .WaitLong )
731
+ found ,err := db .CustomRoles (ctx ,tc .Params )
732
+ require .NoError (t ,err )
733
+ filtered := make ([]database.CustomRole ,0 )
734
+ for _ ,role := range allRoles {
735
+ if tc .Match (role ) {
736
+ filtered = append (filtered ,role )
737
+ }
738
+ }
739
+
740
+ a := db2sdk .List (filtered ,normalizedRoleName )
741
+ b := db2sdk .List (found ,normalizedRoleName )
742
+ require .Equal (t ,a ,b )
743
+ })
744
+ }
745
+ }
746
+
517
747
type tvArgs struct {
518
748
Status database.ProvisionerJobStatus
519
749
// CreateWorkspace is true if we should create a workspace for the template version