diff --git a/Documentation/connectors/github.md b/Documentation/connectors/github.md index fa8f0eb2..78f7def4 100644 --- a/Documentation/connectors/github.md +++ b/Documentation/connectors/github.md @@ -59,12 +59,13 @@ connectors: # Flag which indicates that all user groups and teams should be loaded. loadAllGroups: false - # Optional choice between 'name' (default) or 'slug'. + # Optional choice between 'name' (default), 'slug', or 'both'. # # As an example, group claims for member of 'Site Reliability Engineers' in # Acme organization would yield: # - ['acme:Site Reliability Engineers'] for 'name' # - ['acme:site-reliability-engineers'] for 'slug' + # - ['acme:Site Reliability Engineers', 'acme:site-reliability-engineers'] for 'both' teamNameField: slug ``` diff --git a/connector/github/github.go b/connector/github/github.go index 48efd52d..07db4b3b 100644 --- a/connector/github/github.go +++ b/connector/github/github.go @@ -16,11 +16,10 @@ import ( "strings" "time" + "github.com/sirupsen/logrus" "golang.org/x/oauth2" "golang.org/x/oauth2/github" - "github.com/sirupsen/logrus" - "github.com/dexidp/dex/connector" ) @@ -111,7 +110,7 @@ func (c *Config) Open(id string, logger logrus.FieldLogger) (connector.Connector g.loadAllGroups = c.LoadAllGroups switch c.TeamNameField { - case "name", "slug", "": + case "name", "slug", "both", "": g.teamNameField = c.TeamNameField default: return nil, fmt.Errorf("invalid connector config: unsupported team name field value `%s`", c.TeamNameField) @@ -449,7 +448,7 @@ func (c *githubConnector) userOrgTeams(ctx context.Context, client *http.Client) } for _, t := range teams { - groups[t.Org.Login] = append(groups[t.Org.Login], c.teamGroupClaim(t)) + groups[t.Org.Login] = append(groups[t.Org.Login], c.teamGroupClaims(t)...) } if apiURL == "" { @@ -686,7 +685,7 @@ func (c *githubConnector) teamsForOrg(ctx context.Context, client *http.Client, for _, t := range teams { if t.Org.Login == orgName { - groups = append(groups, c.teamGroupClaim(t)) + groups = append(groups, c.teamGroupClaims(t)...) } } @@ -698,12 +697,16 @@ func (c *githubConnector) teamsForOrg(ctx context.Context, client *http.Client, return groups, nil } -// teamGroupClaim returns team slag if 'teamNameField; option is set to 'slug' otherwise returns team name. -func (c *githubConnector) teamGroupClaim(t team) string { +// teamGroupClaims returns team slug if 'teamNameField' option is set to +// 'slug', returns the slug *and* name if set to 'both', otherwise returns team +// name. +func (c *githubConnector) teamGroupClaims(t team) []string { switch c.teamNameField { + case "both": + return []string{t.Name, t.Slug} case "slug": - return t.Slug + return []string{t.Slug} default: - return t.Name + return []string{t.Name} } } diff --git a/connector/github/github_test.go b/connector/github/github_test.go index 9220cc62..38a9a6cf 100644 --- a/connector/github/github_test.go +++ b/connector/github/github_test.go @@ -64,7 +64,6 @@ func TestUserGroups(t *testing.T) { } func TestUserGroupsWithoutOrgs(t *testing.T) { - s := newTestServer(map[string]testResponse{ "/user/orgs": {data: []org{}}, "/user/teams": {data: []team{}}, @@ -76,7 +75,6 @@ func TestUserGroupsWithoutOrgs(t *testing.T) { expectNil(t, err) expectEquals(t, len(groups), 0) - } func TestUserGroupsWithTeamNameFieldConfig(t *testing.T) { @@ -102,6 +100,30 @@ func TestUserGroupsWithTeamNameFieldConfig(t *testing.T) { }) } +func TestUserGroupsWithTeamNameAndSlugFieldConfig(t *testing.T) { + s := newTestServer(map[string]testResponse{ + "/user/orgs": { + data: []org{{Login: "org-1"}}, + }, + "/user/teams": { + data: []team{ + {Name: "Team 1", Slug: "team-1", Org: org{Login: "org-1"}}, + }, + }, + }) + defer s.Close() + + c := githubConnector{apiURL: s.URL, teamNameField: "both"} + groups, err := c.userGroups(context.Background(), newClient()) + + expectNil(t, err) + expectEquals(t, groups, []string{ + "org-1", + "org-1:Team 1", + "org-1:team-1", + }) +} + func TestUsernameIncludedInFederatedIdentity(t *testing.T) { s := newTestServer(map[string]testResponse{