github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.0/pkg/iam/roles.go (about)

     1  package iam
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"net/http"
     8  	"net/url"
     9  	"strconv"
    10  
    11  	validation "github.com/go-ozzo/ozzo-validation/v4"
    12  )
    13  
    14  type (
    15  	// Roles is the IAM role API interface
    16  	Roles interface {
    17  		// CreateRole creates a custom role
    18  		//
    19  		// See: https://techdocs.akamai.com/iam-user-admin/reference/post-role
    20  		CreateRole(context.Context, CreateRoleRequest) (*Role, error)
    21  
    22  		// GetRole gets details for a specific role
    23  		//
    24  		// See: https://techdocs.akamai.com/iam-user-admin/reference/get-role
    25  		GetRole(context.Context, GetRoleRequest) (*Role, error)
    26  
    27  		// UpdateRole adds or removes permissions from a role and updates other parameters
    28  		//
    29  		// See: https://techdocs.akamai.com/iam-user-admin/reference/put-role
    30  		UpdateRole(context.Context, UpdateRoleRequest) (*Role, error)
    31  
    32  		// DeleteRole deletes a role. This operation is only allowed if the role isn't assigned to any users.
    33  		//
    34  		// See: https://techdocs.akamai.com/iam-user-admin/reference/delete-role
    35  		DeleteRole(context.Context, DeleteRoleRequest) error
    36  
    37  		// ListRoles lists roles for the current account and contract type
    38  		//
    39  		// See: https://techdocs.akamai.com/iam-user-admin/reference/get-roles
    40  		ListRoles(context.Context, ListRolesRequest) ([]Role, error)
    41  
    42  		// ListGrantableRoles lists which grantable roles can be included in a new custom role or added to an existing custom role
    43  		//
    44  		// See: https://techdocs.akamai.com/iam-user-admin/reference/get-grantable-roles
    45  		ListGrantableRoles(context.Context) ([]RoleGrantedRole, error)
    46  	}
    47  
    48  	// RoleRequest describes request parameters of the create and update role endpoint
    49  	RoleRequest struct {
    50  		Name         string          `json:"roleName,omitempty"`
    51  		Description  string          `json:"roleDescription,omitempty"`
    52  		GrantedRoles []GrantedRoleID `json:"grantedRoles,omitempty"`
    53  	}
    54  
    55  	// CreateRoleRequest describes the request parameters of the create role endpoint
    56  	CreateRoleRequest RoleRequest
    57  
    58  	// GrantedRoleID describes a unique identifier for a granted role
    59  	GrantedRoleID struct {
    60  		ID int64 `json:"grantedRoleId"`
    61  	}
    62  
    63  	// GetRoleRequest describes the request parameters of the get role endpoint
    64  	GetRoleRequest struct {
    65  		ID           int64
    66  		Actions      bool
    67  		GrantedRoles bool
    68  		Users        bool
    69  	}
    70  
    71  	// UpdateRoleRequest describes the request parameters of the update role endpoint.
    72  	// It works as patch request. You need to provide only fields which you want to update.
    73  	UpdateRoleRequest struct {
    74  		ID int64
    75  		RoleRequest
    76  	}
    77  
    78  	// DeleteRoleRequest describes the request parameters of the delete role endpoint
    79  	DeleteRoleRequest struct {
    80  		ID int64
    81  	}
    82  
    83  	// ListRolesRequest describes the request parameters of the list roles endpoint
    84  	ListRolesRequest struct {
    85  		GroupID       *int64
    86  		Actions       bool
    87  		IgnoreContext bool
    88  		Users         bool
    89  	}
    90  
    91  	// RoleAction encapsulates permissions available to the user for this role
    92  	RoleAction struct {
    93  		Delete bool `json:"delete"`
    94  		Edit   bool `json:"edit"`
    95  	}
    96  
    97  	// RoleGrantedRole is a list of granted roles, giving the user access to objects in a group
    98  	RoleGrantedRole struct {
    99  		Description string `json:"grantedRoleDescription,omitempty"`
   100  		RoleID      int64  `json:"grantedRoleId"`
   101  		RoleName    string `json:"grantedRoleName"`
   102  	}
   103  
   104  	// RoleUser user who shares the same role
   105  	RoleUser struct {
   106  		AccountID     string `json:"accountId"`
   107  		Email         string `json:"email"`
   108  		FirstName     string `json:"firstName"`
   109  		LastLoginDate string `json:"lastLoginDate"`
   110  		LastName      string `json:"lastName"`
   111  		UIIdentityID  string `json:"uiIdentityId"`
   112  	}
   113  
   114  	// Role encapsulates the response of the list roles endpoint
   115  	Role struct {
   116  		Actions         *RoleAction       `json:"actions,omitempty"`
   117  		CreatedBy       string            `json:"createdBy"`
   118  		CreatedDate     string            `json:"createdDate"`
   119  		GrantedRoles    []RoleGrantedRole `json:"grantedRoles,omitempty"`
   120  		ModifiedBy      string            `json:"modifiedBy"`
   121  		ModifiedDate    string            `json:"modifiedDate"`
   122  		RoleDescription string            `json:"roleDescription"`
   123  		RoleID          int64             `json:"roleId"`
   124  		RoleName        string            `json:"roleName"`
   125  		Users           []RoleUser        `json:"users,omitempty"`
   126  		RoleType        RoleType          `json:"type"`
   127  	}
   128  
   129  	// RoleType is an enum of role types
   130  	RoleType string
   131  )
   132  
   133  // Validate validates CreateRoleRequest
   134  func (r CreateRoleRequest) Validate() error {
   135  	return validation.Errors{
   136  		"Name":         validation.Validate(r.Name, validation.Required),
   137  		"Description":  validation.Validate(r.Description, validation.Required),
   138  		"GrantedRoles": validation.Validate(r.GrantedRoles, validation.Required),
   139  	}.Filter()
   140  }
   141  
   142  // Validate validates GetRoleRequest
   143  func (r GetRoleRequest) Validate() error {
   144  	return validation.Errors{
   145  		"ID": validation.Validate(r.ID, validation.Required),
   146  	}.Filter()
   147  }
   148  
   149  // Validate validates UpdateRoleRequest
   150  func (r UpdateRoleRequest) Validate() error {
   151  	return validation.Errors{
   152  		"ID": validation.Validate(r.ID, validation.Required),
   153  	}.Filter()
   154  }
   155  
   156  // Validate validates DeleteRoleRequest
   157  func (r DeleteRoleRequest) Validate() error {
   158  	return validation.Errors{
   159  		"ID": validation.Validate(r.ID, validation.Required),
   160  	}.Filter()
   161  }
   162  
   163  var (
   164  	// RoleTypeStandard is a standard type provided by Akamai
   165  	RoleTypeStandard RoleType = "standard"
   166  
   167  	// RoleTypeCustom is a custom role provided by the account
   168  	RoleTypeCustom RoleType = "custom"
   169  )
   170  
   171  var (
   172  	// ErrCreateRole is returned when CreateRole fails
   173  	ErrCreateRole = errors.New("create a role")
   174  	// ErrGetRole is returned when GetRole fails
   175  	ErrGetRole = errors.New("get a role")
   176  	// ErrUpdateRole is returned when UpdateRole fails
   177  	ErrUpdateRole = errors.New("update a role")
   178  	// ErrDeleteRole is returned when DeleteRole fails
   179  	ErrDeleteRole = errors.New("delete a role")
   180  	// ErrListRoles is returned when ListRoles fails
   181  	ErrListRoles = errors.New("list roles")
   182  	// ErrListGrantableRoles is returned when ListGrantableRoles fails
   183  	ErrListGrantableRoles = errors.New("list grantable roles")
   184  )
   185  
   186  func (i *iam) CreateRole(ctx context.Context, params CreateRoleRequest) (*Role, error) {
   187  	logger := i.Log(ctx)
   188  	logger.Debug("CreateRole")
   189  
   190  	if err := params.Validate(); err != nil {
   191  		return nil, fmt.Errorf("%s: %w:\n%s", ErrCreateRole, ErrStructValidation, err)
   192  	}
   193  
   194  	uri, err := url.Parse("/identity-management/v2/user-admin/roles")
   195  	if err != nil {
   196  		return nil, fmt.Errorf("%w: failed to parse url: %s", ErrCreateRole, err)
   197  	}
   198  
   199  	req, err := http.NewRequestWithContext(ctx, http.MethodPost, uri.String(), nil)
   200  	if err != nil {
   201  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrCreateRole, err)
   202  	}
   203  
   204  	var result Role
   205  	resp, err := i.Exec(req, &result, params)
   206  	if err != nil {
   207  		return nil, fmt.Errorf("%w: request failed: %s", ErrCreateRole, err)
   208  	}
   209  
   210  	if resp.StatusCode != http.StatusCreated {
   211  		return nil, fmt.Errorf("%s: %w", ErrCreateRole, i.Error(resp))
   212  	}
   213  
   214  	return &result, nil
   215  }
   216  
   217  func (i *iam) GetRole(ctx context.Context, params GetRoleRequest) (*Role, error) {
   218  	logger := i.Log(ctx)
   219  	logger.Debug("GetRole")
   220  
   221  	if err := params.Validate(); err != nil {
   222  		return nil, fmt.Errorf("%s: %w:\n%s", ErrGetRole, ErrStructValidation, err)
   223  	}
   224  
   225  	uri, err := url.Parse(fmt.Sprintf("/identity-management/v2/user-admin/roles/%d", params.ID))
   226  	if err != nil {
   227  		return nil, fmt.Errorf("%w: failed to parse url: %s", ErrGetRole, err)
   228  	}
   229  
   230  	q := uri.Query()
   231  	q.Add("actions", strconv.FormatBool(params.Actions))
   232  	q.Add("grantedRoles", strconv.FormatBool(params.GrantedRoles))
   233  	q.Add("users", strconv.FormatBool(params.Users))
   234  
   235  	uri.RawQuery = q.Encode()
   236  
   237  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri.String(), nil)
   238  	if err != nil {
   239  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrGetRole, err)
   240  	}
   241  
   242  	var result Role
   243  	resp, err := i.Exec(req, &result)
   244  	if err != nil {
   245  		return nil, fmt.Errorf("%w: request failed: %s", ErrGetRole, err)
   246  	}
   247  
   248  	if resp.StatusCode != http.StatusOK {
   249  		return nil, fmt.Errorf("%s: %w", ErrGetRole, i.Error(resp))
   250  	}
   251  
   252  	return &result, nil
   253  }
   254  
   255  func (i *iam) UpdateRole(ctx context.Context, params UpdateRoleRequest) (*Role, error) {
   256  	logger := i.Log(ctx)
   257  	logger.Debug("UpdateRole")
   258  
   259  	if err := params.Validate(); err != nil {
   260  		return nil, fmt.Errorf("%s: %w:\n%s", ErrUpdateRole, ErrStructValidation, err)
   261  	}
   262  
   263  	uri, err := url.Parse(fmt.Sprintf("/identity-management/v2/user-admin/roles/%d", params.ID))
   264  	if err != nil {
   265  		return nil, fmt.Errorf("%w: failed to parse url: %s", ErrUpdateRole, err)
   266  	}
   267  
   268  	req, err := http.NewRequestWithContext(ctx, http.MethodPut, uri.String(), nil)
   269  	if err != nil {
   270  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrUpdateRole, err)
   271  	}
   272  
   273  	var result Role
   274  	resp, err := i.Exec(req, &result, params.RoleRequest)
   275  	if err != nil {
   276  		return nil, fmt.Errorf("%w: request failed: %s", ErrUpdateRole, err)
   277  	}
   278  
   279  	if resp.StatusCode != http.StatusOK {
   280  		return nil, fmt.Errorf("%s: %w", ErrUpdateRole, i.Error(resp))
   281  	}
   282  
   283  	return &result, nil
   284  }
   285  
   286  func (i *iam) DeleteRole(ctx context.Context, params DeleteRoleRequest) error {
   287  	logger := i.Log(ctx)
   288  	logger.Debug("DeleteRole")
   289  
   290  	if err := params.Validate(); err != nil {
   291  		return fmt.Errorf("%s: %w:\n%s", ErrDeleteRole, ErrStructValidation, err)
   292  	}
   293  
   294  	uri, err := url.Parse(fmt.Sprintf("/identity-management/v2/user-admin/roles/%d", params.ID))
   295  	if err != nil {
   296  		return fmt.Errorf("%w: failed to parse url: %s", ErrDeleteRole, err)
   297  	}
   298  
   299  	req, err := http.NewRequestWithContext(ctx, http.MethodDelete, uri.String(), nil)
   300  	if err != nil {
   301  		return fmt.Errorf("%w: failed to create request: %s", ErrDeleteRole, err)
   302  	}
   303  
   304  	resp, err := i.Exec(req, nil)
   305  	if err != nil {
   306  		return fmt.Errorf("%w: request failed: %s", ErrDeleteRole, err)
   307  	}
   308  
   309  	if resp.StatusCode != http.StatusNoContent {
   310  		return fmt.Errorf("%s: %w", ErrDeleteRole, i.Error(resp))
   311  	}
   312  
   313  	return nil
   314  }
   315  
   316  func (i *iam) ListRoles(ctx context.Context, params ListRolesRequest) ([]Role, error) {
   317  	logger := i.Log(ctx)
   318  	logger.Debug("ListRoles")
   319  
   320  	u, err := url.Parse("/identity-management/v2/user-admin/roles")
   321  	if err != nil {
   322  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrListRoles, err)
   323  	}
   324  	q := u.Query()
   325  	q.Add("actions", strconv.FormatBool(params.Actions))
   326  	q.Add("ignoreContext", strconv.FormatBool(params.IgnoreContext))
   327  	q.Add("users", strconv.FormatBool(params.Users))
   328  
   329  	if params.GroupID != nil {
   330  		q.Add("groupId", strconv.FormatInt(*params.GroupID, 10))
   331  	}
   332  
   333  	u.RawQuery = q.Encode()
   334  
   335  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
   336  	if err != nil {
   337  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrListRoles, err)
   338  	}
   339  
   340  	var result []Role
   341  	resp, err := i.Exec(req, &result)
   342  	if err != nil {
   343  		return nil, fmt.Errorf("%w: request failed: %s", ErrListRoles, err)
   344  	}
   345  
   346  	if resp.StatusCode != http.StatusOK {
   347  		return nil, fmt.Errorf("%s: %w", ErrListRoles, i.Error(resp))
   348  	}
   349  
   350  	return result, nil
   351  }
   352  
   353  func (i *iam) ListGrantableRoles(ctx context.Context) ([]RoleGrantedRole, error) {
   354  	logger := i.Log(ctx)
   355  	logger.Debug("ListGrantableRoles")
   356  
   357  	uri, err := url.Parse("/identity-management/v2/user-admin/roles/grantable-roles")
   358  	if err != nil {
   359  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrListGrantableRoles, err)
   360  	}
   361  
   362  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri.String(), nil)
   363  	if err != nil {
   364  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrListGrantableRoles, err)
   365  	}
   366  
   367  	var result []RoleGrantedRole
   368  	resp, err := i.Exec(req, &result)
   369  	if err != nil {
   370  		return nil, fmt.Errorf("%w: request failed: %s", ErrListGrantableRoles, err)
   371  	}
   372  
   373  	if resp.StatusCode != http.StatusOK {
   374  		return nil, fmt.Errorf("%s: %w", ErrListGrantableRoles, i.Error(resp))
   375  	}
   376  
   377  	return result, nil
   378  }