Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ACCT-4459: Support for domain scoped roles #1095

Merged
merged 26 commits into from
Oct 13, 2022

Conversation

ianmobbs
Copy link

As we begin to GA domain-scoped roles, we'd like to add support for these new controls to the Cloudflare Go SDK.

Description

The primary changes here are:

  • Update AccountMember to contain both AccountRoles and Policies, our new struct for representing access control
  • Add structs for Policies and all required sub-structs

Has your change been tested?

Yes, we have extended existing tests, added new tests, and written a verification script

Screenshots (if appropriate):

n/a

Types of changes

What sort of change does your code introduce/modify?

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • This change is using publicly documented (api.cloudflare.com or developers.cloudflare.com) and stable APIs.

@github-actions
Copy link
Contributor

github-actions bot commented Sep 29, 2022

changelog detected ✅

@codecov-commenter
Copy link

codecov-commenter commented Sep 29, 2022

Codecov Report

Merging #1095 (6f4b50f) into master (e39278e) will increase coverage by 0.34%.
The diff coverage is 62.19%.

@@            Coverage Diff             @@
##           master    #1095      +/-   ##
==========================================
+ Coverage   49.94%   50.29%   +0.34%     
==========================================
  Files         115      119       +4     
  Lines       10991    11455     +464     
==========================================
+ Hits         5490     5761     +271     
- Misses       4338     4463     +125     
- Partials     1163     1231      +68     
Impacted Files Coverage Δ
access_organization.go 64.70% <ø> (ø)
device_posture_rule.go 61.80% <ø> (ø)
errors.go 40.57% <ø> (ø)
pages_project.go 50.81% <ø> (ø)
rulesets.go 35.09% <ø> (ø)
stream.go 64.91% <ø> (ø)
teams_accounts.go 53.84% <ø> (ø)
teams_devices.go 52.63% <ø> (ø)
user_agent.go 0.00% <0.00%> (ø)
split_tunnel.go 40.38% <26.92%> (-13.47%) ⬇️
... and 18 more

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

@ianmobbs ianmobbs self-assigned this Sep 29, 2022
// upon member invitation. We recommend upgrading to CreateAccountMemberWithPolicies to use policies.
//
// API reference: https://api.cloudflare.com/#account-members-add-member
func (api *API) CreateAccountMember(ctx context.Context, accountID string, emailAddress string, roles []string) (AccountMember, error) {
Copy link
Member

@jacobbednarz jacobbednarz Sep 29, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we're overhauling the invitations, let's update CreateAccountMember method signature to match the experimental client. this will also allow you to cut down on some of the boilerplate code we're repeating and putting into CreateAccountMemberInternal.

(incomplete but hopefully enough to get you started example)

type CreateAccountMemberParams struct {
	Email    string   `json:"email"`
	Roles    []string `json:"roles,omitempty"`
	Policies []Policy `json:"policies,omitempty"`
	Status   string   `json:"status,omitempty"`
}

func (api *API) CreateAccountMember(ctx context.Context, rc *ResourceContainer, params CreateAccountMemberParams) (AccountMember, error) {
	invite := AccountMemberInvitation{
		Email: params.Email,
	}

	if len(params.Roles) > 0 {
		invite.Roles = params.Roles
	}

	// ... etc
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call, thanks! Can you confirm that this is the right way to go about things?

  • Re-write CreateAccountMember to match the experimental client
  • Remove the CreateAccountMemberInternal method
  • Re-factor utility methods (CreateAccountMemberWithStatus, CreateAccountMemberWithRoles, etc) to just call CreateAccountMember - the alternative I supposed is just removing the utility methods?

Here's my current CreateAccountMember impl, let me know if it looks okay and the above is correct and I'll push :)

func (api *API) CreateAccountMember(ctx context.Context, rc *ResourceContainer, params CreateAccountMemberParams) (AccountMember, error) {
	if rc.Level != AccountRouteLevel {
		return AccountMember{}, fmt.Errorf(errInvalidResourceContainerAccess, rc.Level)
	}

	invite := AccountMemberInvitation{
		Email:  params.EmailAddress,
		Status: params.Status,
	}

	roles := []AccountRole{}
	for i := 0; i < len(params.Roles); i++ {
		roles = append(roles, AccountRole{ID: invite.Roles[i]})
	}
	err := validateRolesAndPolicies(roles, params.Policies)
	if err != nil {
		return AccountMember{}, err
	}

	if params.Roles != nil {
		invite.Roles = params.Roles
	} else if params.Policies != nil {
		invite.Policies = params.Policies
	}

	uri := fmt.Sprintf("/accounts/%s/members", rc.Identifier)
	res, err := api.makeRequestContext(ctx, http.MethodPost, uri, invite)
	if err != nil {
		return AccountMember{}, err
	}

	var accountMemberListResponse AccountMemberDetailResponse
	err = json.Unmarshal(res, &accountMemberListResponse)
	if err != nil {
		return AccountMember{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
	}

	return accountMemberListResponse.Result, nil
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks spot on! nice one.

account_members.go Outdated Show resolved Hide resolved
errors.go Outdated Show resolved Hide resolved
@ianmobbs ianmobbs force-pushed the imobbs/ACCT-4459-domain-scoped-roles branch from abc8db2 to c4f8f2e Compare September 30, 2022 23:19
@@ -215,8 +252,12 @@ func TestCreateAccountMemberWithStatus(t *testing.T) {
}

mux.HandleFunc("/accounts/01a7362d577a6c3019a474fd6f485823/members", handler)
accountResource := &ResourceContainer{
Copy link
Member

@jacobbednarz jacobbednarz Oct 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from the code docs - https://github.com/cloudflare/cloudflare-go/blob/master/resource.go#L12-L14

// ResourceContainer defines an API resource you wish to target. Should not be
// used directly, use `UserIdentifier`, `ZoneIdentifier` and `AccountIdentifier`
// instead.

while you can do this, i'd recommend using the helpers instead incase we expand this struct. it's also a bit nicer to read 😄 AccountIdentifier("01a7362d577a6c3019a474fd6f485823")

@jacobbednarz jacobbednarz merged commit 40a64a8 into master Oct 13, 2022
@jacobbednarz jacobbednarz deleted the imobbs/ACCT-4459-domain-scoped-roles branch October 13, 2022 00:03
@github-actions github-actions bot added this to the v0.53.0 milestone Oct 13, 2022
github-actions bot pushed a commit that referenced this pull request Oct 13, 2022
@github-actions
Copy link
Contributor

This functionality has been released in v0.53.0.

For further feature requests or bug reports with this functionality, please create a new GitHub issue following the template. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants