Skip to content

Commit 20fcc4c

Browse files
committed
added org role tests
1 parent 86c4ec1 commit 20fcc4c

File tree

3 files changed

+227
-0
lines changed

3 files changed

+227
-0
lines changed

pkg/connector/org_role_test.go

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package connector
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
v2 "github.com/conductorone/baton-sdk/pb/c1/connector/v2"
8+
"github.com/conductorone/baton-sdk/pkg/pagination"
9+
entitlement2 "github.com/conductorone/baton-sdk/pkg/types/entitlement"
10+
"github.com/google/go-github/v63/github"
11+
"github.com/stretchr/testify/require"
12+
13+
"github.com/conductorone/baton-github/test"
14+
"github.com/conductorone/baton-github/test/mocks"
15+
)
16+
17+
func TestOrgRole(t *testing.T) {
18+
ctx := context.Background()
19+
20+
t.Run("should grant and revoke entitlements", func(t *testing.T) {
21+
mgh := mocks.NewMockGitHub()
22+
23+
githubOrganization, _, _, githubUser, _ := mgh.Seed()
24+
25+
githubClient := github.NewClient(mgh.Server())
26+
cache := newOrgNameCache(githubClient)
27+
client := orgRoleBuilder(githubClient, cache)
28+
29+
organization, _ := organizationResource(ctx, githubOrganization, nil)
30+
role, _ := orgRoleResource(ctx, &OrganizationRole{
31+
ID: 1,
32+
Name: "Test Role",
33+
Description: "Test Role Description",
34+
}, organization)
35+
user, _ := userResource(ctx, githubUser, *githubUser.Email, nil)
36+
37+
entitlement := v2.Entitlement{
38+
Id: entitlement2.NewEntitlementID(role, "assigned"),
39+
Resource: role,
40+
}
41+
42+
grantAnnotations, err := client.Grant(ctx, user, &entitlement)
43+
require.Nil(t, err)
44+
require.Empty(t, grantAnnotations)
45+
46+
grants, nextToken, grantsAnnotations, err := client.Grants(ctx, role, &pagination.Token{})
47+
require.Nil(t, err)
48+
test.AssertNoRatelimitAnnotations(t, grantsAnnotations)
49+
require.Equal(t, "", nextToken)
50+
require.Len(t, grants, 1)
51+
52+
grant := v2.Grant{
53+
Entitlement: &entitlement,
54+
Principal: user,
55+
}
56+
57+
revokeAnnotations, err := client.Revoke(ctx, &grant)
58+
require.Nil(t, err)
59+
require.Empty(t, revokeAnnotations)
60+
})
61+
62+
t.Run("should handle permission errors gracefully", func(t *testing.T) {
63+
mockGithub := mocks.NewMockGitHub()
64+
mockGithub.SimulateOrgRolePermErr = true
65+
66+
githubOrganization, _, _, _, _ := mockGithub.Seed()
67+
68+
githubClient := github.NewClient(mockGithub.Server())
69+
cache := newOrgNameCache(githubClient)
70+
client := orgRoleBuilder(githubClient, cache)
71+
72+
organization, _ := organizationResource(ctx, githubOrganization, nil)
73+
74+
// Test List with permission error
75+
resources, nextToken, annotations, err := client.List(ctx, organization.Id, &pagination.Token{})
76+
require.Nil(t, err)
77+
require.Empty(t, resources)
78+
require.Empty(t, nextToken)
79+
test.AssertNoRatelimitAnnotations(t, annotations)
80+
81+
// Test Grants with permission error
82+
role, _ := orgRoleResource(ctx, &OrganizationRole{
83+
ID: 1,
84+
Name: "Test Role",
85+
Description: "Test Role Description",
86+
}, organization)
87+
88+
grants, nextToken, grantsAnnotations, err := client.Grants(ctx, role, &pagination.Token{})
89+
require.Nil(t, err)
90+
require.Empty(t, grants)
91+
require.Empty(t, nextToken)
92+
test.AssertNoRatelimitAnnotations(t, grantsAnnotations)
93+
})
94+
}

test/mocks/endpointpattern.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,29 @@ var GetOrganizationsTeamsMembershipsByTeamIdByUsername = mock.EndpointPattern{
4141
Pattern: "/organizations/{org_id}/team/{team_id}/memberships/{username}",
4242
Method: "GET",
4343
}
44+
45+
// Organization role endpoints
46+
var GetOrgsRolesByOrg = mock.EndpointPattern{
47+
Pattern: "/orgs/{org}/organization-roles",
48+
Method: "GET",
49+
}
50+
51+
var GetOrgsRolesTeamsByOrgByRoleId = mock.EndpointPattern{
52+
Pattern: "/orgs/{org}/organization-roles/{role_id}/teams",
53+
Method: "GET",
54+
}
55+
56+
var GetOrgsRolesUsersByOrgByRoleId = mock.EndpointPattern{
57+
Pattern: "/orgs/{org}/organization-roles/{role_id}/users",
58+
Method: "GET",
59+
}
60+
61+
var PutOrgsRolesUsersByOrgByRoleIdByUsername = mock.EndpointPattern{
62+
Pattern: "/orgs/{org}/organization-roles/users/{username}/{role_id}",
63+
Method: "PUT",
64+
}
65+
66+
var DeleteOrgsRolesUsersByOrgByRoleIdByUsername = mock.EndpointPattern{
67+
Pattern: "/orgs/{org}/organization-roles/users/{username}/{role_id}",
68+
Method: "DELETE",
69+
}

test/mocks/github.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ type MockGitHub struct {
2222
repositories map[int64]github.Repository
2323
teams map[int64]github.Team
2424
users map[int64]github.User
25+
orgRoles map[int64]mapset.Set[int64] // Maps role ID to set of user IDs
26+
SimulateOrgRolePermErr bool // Simulate permission error for org roles
2527
}
2628

2729
func NewMockGitHub() *MockGitHub {
@@ -33,6 +35,7 @@ func NewMockGitHub() *MockGitHub {
3335
repositories: map[int64]github.Repository{},
3436
teams: map[int64]github.Team{},
3537
users: map[int64]github.User{},
38+
orgRoles: map[int64]mapset.Set[int64]{},
3639
}
3740
}
3841

@@ -494,6 +497,104 @@ func (mgh MockGitHub) removeRepositoryCollaborator(
494497
)
495498
}
496499

500+
type OrganizationRole struct {
501+
ID int64 `json:"id"`
502+
Name string `json:"name"`
503+
Description string `json:"description"`
504+
}
505+
506+
type OrganizationRoles struct {
507+
CustomRepoRoles []*OrganizationRole `json:"roles"`
508+
}
509+
510+
func (mgh MockGitHub) getOrgRoles(
511+
w http.ResponseWriter,
512+
variables map[string]string,
513+
) {
514+
if mgh.SimulateOrgRolePermErr {
515+
w.WriteHeader(http.StatusForbidden)
516+
return
517+
}
518+
orgID, _ := getCrossTableId(w, variables, "org")
519+
if _, ok := mgh.organizations[orgID]; !ok {
520+
w.WriteHeader(http.StatusNotFound)
521+
return
522+
}
523+
524+
// Return a mock role
525+
role := &OrganizationRole{
526+
ID: 1,
527+
Name: "Test Role",
528+
Description: "Test Role Description",
529+
}
530+
531+
roles := &OrganizationRoles{
532+
CustomRepoRoles: []*OrganizationRole{role},
533+
}
534+
535+
_, _ = w.Write(mock.MustMarshal(roles))
536+
}
537+
538+
func (mgh MockGitHub) getOrgRoleTeams(
539+
w http.ResponseWriter,
540+
variables map[string]string,
541+
) {
542+
roleID, _ := getCrossTableId(w, variables, "role_id")
543+
if _, ok := mgh.orgRoles[roleID]; !ok {
544+
w.WriteHeader(http.StatusNotFound)
545+
return
546+
}
547+
548+
// Return empty teams list for now
549+
_, _ = w.Write(mock.MustMarshal([]*github.Team{}))
550+
}
551+
552+
func (mgh MockGitHub) getOrgRoleUsers(
553+
w http.ResponseWriter,
554+
variables map[string]string,
555+
) {
556+
roleID, _ := getCrossTableId(w, variables, "role_id")
557+
memberships, ok := mgh.orgRoles[roleID]
558+
if !ok {
559+
w.WriteHeader(http.StatusNotFound)
560+
return
561+
}
562+
563+
users := make([]github.User, 0)
564+
for _, userID := range memberships.ToSlice() {
565+
if user, ok := mgh.users[userID]; ok {
566+
users = append(users, user)
567+
}
568+
}
569+
570+
_, _ = w.Write(mock.MustMarshal(users))
571+
}
572+
573+
func (mgh MockGitHub) addOrgRoleUser(
574+
w http.ResponseWriter,
575+
variables map[string]string,
576+
) {
577+
roleID, _ := getCrossTableId(w, variables, "role_id")
578+
userID, _ := getUserId(w, variables)
579+
580+
if _, ok := mgh.orgRoles[roleID]; !ok {
581+
mgh.orgRoles[roleID] = mapset.NewSet[int64]()
582+
}
583+
mgh.orgRoles[roleID].Add(userID)
584+
}
585+
586+
func (mgh MockGitHub) removeOrgRoleUser(
587+
w http.ResponseWriter,
588+
variables map[string]string,
589+
) {
590+
roleID, _ := getCrossTableId(w, variables, "role_id")
591+
userID, _ := getUserId(w, variables)
592+
593+
if memberships, ok := mgh.orgRoles[roleID]; ok {
594+
memberships.Remove(userID)
595+
}
596+
}
597+
497598
type handler = func(w http.ResponseWriter, variables map[string]string)
498599

499600
// addEndpointHandler takes a string interpolation pattern and a handler
@@ -540,6 +641,12 @@ func (mgh MockGitHub) Server() *http.Client {
540641
mock.PutReposCollaboratorsByOwnerByRepoByUsername: mgh.addRepositoryCollaborator,
541642
DeleteOrganizationsTeamsMembershipsByOrganizationByTeamIdByUsername: mgh.removeMembership,
542643
PutOrganizationsTeamsMembershipsByOrganizationByTeamIdByUsername: mgh.addMembership,
644+
// Add organization role endpoints
645+
GetOrgsRolesByOrg: mgh.getOrgRoles,
646+
GetOrgsRolesTeamsByOrgByRoleId: mgh.getOrgRoleTeams,
647+
GetOrgsRolesUsersByOrgByRoleId: mgh.getOrgRoleUsers,
648+
PutOrgsRolesUsersByOrgByRoleIdByUsername: mgh.addOrgRoleUser,
649+
DeleteOrgsRolesUsersByOrgByRoleIdByUsername: mgh.removeOrgRoleUser,
543650
}
544651

545652
options := make([]mock.MockBackendOption, 0)

0 commit comments

Comments
 (0)