Skip to content

Commit

Permalink
Merge pull request #4 from ConductorOne/mchavez-newrelic
Browse files Browse the repository at this point in the history
Fixed Missing Resource when assigning groups to unverified users
  • Loading branch information
ggreer authored Feb 22, 2024
2 parents 1811f85 + 11f0a8e commit 5323c60
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 19 deletions.
21 changes: 20 additions & 1 deletion pkg/connector/users.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ func userResource(ctx context.Context, pId *v2.ResourceId, user *newrelic.User)
// List returns all the users from the database as resource objects.
// Users include a UserTrait because they are the 'shape' of a standard user.
func (u *userBuilder) List(ctx context.Context, parentResourceID *v2.ResourceId, pToken *pagination.Token) ([]*v2.Resource, string, annotations.Annotations, error) {
var (
nextCursor, domainID string
users []newrelic.User
)
if parentResourceID == nil {
return nil, "", nil, nil
}
Expand All @@ -62,7 +66,22 @@ func (u *userBuilder) List(ctx context.Context, parentResourceID *v2.ResourceId,
return nil, "", nil, err
}

users, nextCursor, err := u.client.ListUsers(ctx, bag.PageToken())
domains, _, err := u.client.ListDomains(ctx, bag.PageToken())
if err != nil {
return nil, "", nil, err
}

if len(domains) == 1 {
for _, domain := range domains {
domainID = domain.ID
}
}

if len(domains) == 0 || len(domains) > 1 { // no domains or multiple domains
domainID = ""
}

users, nextCursor, err = u.client.ListUsers(ctx, domainID, bag.PageToken())
if err != nil {
return nil, "", nil, err
}
Expand Down
55 changes: 45 additions & 10 deletions pkg/newrelic/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,20 +96,45 @@ func GetAccountId(ctx context.Context, httpClient *http.Client, url string, apik
}

// ListUsers return users across whole organization.
func (c *Client) ListUsers(ctx context.Context, cursor string) ([]User, string, error) {
var res UsersResponse
func (c *Client) ListUsers(ctx context.Context, domainId string, cursor string) ([]User, string, error) {
var (
res UsersResponse
resV2 UsersResponseV2
users []User
nextCursor string
err error
)
variables := map[string]interface{}{}

if cursor != "" {
variables["userCursor"] = cursor
variables["domainId"] = domainId
}

err := c.doRequest(
ctx,
composeUsersQuery(),
variables,
&res,
)
if domainId != "" { // It has domain
err = c.getResponse(ctx, composeUsersQueryV2, variables, &resV2)
if err != nil {
return nil, "", err
}

authenticationDomains := resV2.Data.Actor.Organization.UserManagement.AuthenticationDomains.AuthenticationDomains
if len(authenticationDomains) == 1 {
for _, domain := range authenticationDomains {
nextCursor = domain.Users.NextCursor
for _, user := range domain.Users.Users {
users = append(users, User{
Name: user.Name,
Email: user.Email,
ID: user.ID,
})
}
}

return users, nextCursor, nil
}
}

// no domains or multiple domains
err = c.getResponse(ctx, composeUsersQuery, variables, &res)
if err != nil {
return nil, "", err
}
Expand All @@ -119,6 +144,17 @@ func (c *Client) ListUsers(ctx context.Context, cursor string) ([]User, string,
nil
}

func (c *Client) getResponse(ctx context.Context, query func() string, variables map[string]interface{}, res interface{}) error {
err := c.doRequest(
ctx,
query(),
variables,
&res,
)

return err
}

// GetOrg returns organization details.
func (c *Client) GetOrg(ctx context.Context) (*Org, error) {
var res OrgDetailResponse
Expand Down Expand Up @@ -494,7 +530,6 @@ func (c *Client) doRequest(ctx context.Context, q string, v map[string]interface
Query: q,
Variables: v,
}

reqBody, err := json.Marshal(body)
if err != nil {
return err
Expand Down
59 changes: 51 additions & 8 deletions pkg/newrelic/graphql.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,36 @@ const (
actorBaseQ = "actor { %s }"

usersQuery = `users {
userSearch(cursor: $userCursor) {
nextCursor
totalCount
users {
email
name
userId
}
userSearch(cursor: $userCursor) {
nextCursor
totalCount
users {
email
name
userId
}
}
}`

usersQueryV2 = `organization {
userManagement {
authenticationDomains(id: $domainId) {
authenticationDomains {
users(cursor: $userCursor) {
users {
email
id
name
emailVerificationState
}
nextCursor
totalCount
}
}
}
}
}`

accountsQuery = `accounts {
id
}`
Expand Down Expand Up @@ -189,6 +208,7 @@ var (
AccountsQ = fmt.Sprintf(actorBaseQ, accountsQuery)

UsersQ = fmt.Sprintf(actorBaseQ, usersQuery)
UsersQV2 = fmt.Sprintf(actorBaseQ, usersQueryV2)
OrgDetailQ = fmt.Sprintf(actorBaseQ, orgDetailQuery)

RolesQ = fmt.Sprintf(ManagementsQ, rolesQuery)
Expand All @@ -213,6 +233,14 @@ func composeAccountsQuery() string {
}`, AccountsQ)
}

// https://docs.newrelic.com/docs/apis/nerdgraph/examples/nerdgraph-manage-users/
func composeUsersQueryV2() string {
return fmt.Sprintf(
`query ListUsers($userCursor: String, $domainId: [ID!]) {
%s
}`, UsersQV2)
}

func composeUsersQuery() string {
return fmt.Sprintf(
`query ListUsers($userCursor: String) {
Expand Down Expand Up @@ -351,6 +379,21 @@ type UsersResponse = QueryResponse[struct {
} `json:"users"`
}]

type UsersResponseV2 = QueryResponse[struct {
Organization struct {
UserManagement struct {
AuthenticationDomains struct {
AuthenticationDomains []struct {
Users struct {
ListBase
Users []UserV2 `json:"users"`
} `json:"users"`
} `json:"authenticationDomains"`
} `json:"authenticationDomains"`
} `json:"userManagement"`
} `json:"organization"`
}]

type OrgResponse[T any] QueryResponse[struct {
Organization T `json:"organization"`
}]
Expand Down
7 changes: 7 additions & 0 deletions pkg/newrelic/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ type User struct {
Name string `json:"name"`
}

type UserV2 struct {
ID string `json:"id"`
Email string `json:"email"`
Name string `json:"name"`
EmailVerificationState string `json:"emailVerificationState"`
}

type Org struct {
BaseResource
Name string `json:"name"`
Expand Down

0 comments on commit 5323c60

Please sign in to comment.