Skip to content

Commit

Permalink
Implement granting and revoking user roles
Browse files Browse the repository at this point in the history
  • Loading branch information
martinalbert committed Aug 10, 2023
1 parent aa38327 commit 84af7b3
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 2 deletions.
49 changes: 47 additions & 2 deletions pkg/cloudamqp/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"strings"

"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

const BaseURL = "https://customer.cloudamqp.com/api"
const UsersBaseURL = BaseURL + "/team"
const UserBaseURL = BaseURL + "/team/%s"

type Client struct {
httpClient *http.Client
Expand All @@ -32,7 +35,7 @@ func NewClient(httpClient *http.Client, password string) *Client {
func (c *Client) GetUsers(ctx context.Context) ([]User, error) {
var usersResponse UsersResponse

err := c.doRequest(
err := c.get(
ctx,
UsersBaseURL,
&usersResponse,
Expand All @@ -45,12 +48,54 @@ func (c *Client) GetUsers(ctx context.Context) ([]User, error) {
return usersResponse, nil
}

func NewUpdateUserRolePayload(role string) url.Values {
payload := url.Values{}

payload.Set("role", role)

return payload
}

// UpdateUserRole updates role of provided user.
func (c *Client) UpdateUserRole(ctx context.Context, userId string, role string) error {
err := c.put(
ctx,
fmt.Sprintf(UserBaseURL, userId),
NewUpdateUserRolePayload(role),
nil,
)

if err != nil {
return err
}

return nil
}

func (c *Client) get(ctx context.Context, urlAddress string, resourceResponse interface{}) error {
return c.doRequest(ctx, urlAddress, http.MethodGet, nil, resourceResponse)
}

func (c *Client) put(ctx context.Context, urlAddress string, data url.Values, resourceResponse interface{}) error {
return c.doRequest(ctx, urlAddress, http.MethodPut, data, resourceResponse)
}

func (c *Client) doRequest(
ctx context.Context,
urlAddress string,
method string,
data url.Values,
resourceResponse interface{},
) error {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, urlAddress, nil)
var body strings.Reader

if data != nil {
encodedData := data.Encode()
bodyReader := strings.NewReader(encodedData)
body = *bodyReader
}

req, err := http.NewRequestWithContext(ctx, method, urlAddress, &body)
if err != nil {
return err
}
Expand Down
49 changes: 49 additions & 0 deletions pkg/connector/role.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
ent "github.com/conductorone/baton-sdk/pkg/types/entitlement"
"github.com/conductorone/baton-sdk/pkg/types/grant"
rs "github.com/conductorone/baton-sdk/pkg/types/resource"
"github.com/grpc-ecosystem/go-grpc-middleware/logging/zap/ctxzap"
"go.uber.org/zap"
)

const (
Expand Down Expand Up @@ -114,6 +116,53 @@ func (r *roleResourceType) Grants(ctx context.Context, resource *v2.Resource, _
return rv, "", nil, nil
}

func (r *roleResourceType) Grant(ctx context.Context, principal *v2.Resource, entitlement *v2.Entitlement) (annotations.Annotations, error) {
l := ctxzap.Extract(ctx)

if principal.Id.ResourceType != resourceTypeUser.Id {
l.Warn(
"cloudamqp-connector: only users can be granted roles",
zap.String("principal_id", principal.Id.String()),
zap.String("principal_type", principal.Id.ResourceType),
)

return nil, fmt.Errorf("cloudamqp-connector: only users can be granted roles")
}

userId, roleId := principal.Id.Resource, entitlement.Resource.Id.Resource
err := r.client.UpdateUserRole(ctx, userId, roleId)
if err != nil {
return nil, fmt.Errorf("cloudamqp-connector: failed to update user role: %w", err)
}

return nil, nil
}

// Since user always has a role, this function will assign the user to the default role - member.
func (r *roleResourceType) Revoke(ctx context.Context, grant *v2.Grant) (annotations.Annotations, error) {
l := ctxzap.Extract(ctx)

principal := grant.Principal

if principal.Id.ResourceType != resourceTypeUser.Id {
l.Warn(
"cloudamqp-connector: only users can have roles revoked",
zap.String("principal_id", principal.Id.String()),
zap.String("principal_type", principal.Id.ResourceType),
)

return nil, fmt.Errorf("cloudamqp-connector: only users can have roles revoked")
}

userId, roleId := principal.Id.Resource, roleMember
err := r.client.UpdateUserRole(ctx, userId, roleId)
if err != nil {
return nil, fmt.Errorf("cloudamqp-connector: failed to update user role: %w", err)
}

return nil, nil
}

func roleBuilder(client *cloudamqp.Client) *roleResourceType {
return &roleResourceType{
resourceType: resourceTypeRole,
Expand Down

0 comments on commit 84af7b3

Please sign in to comment.