github.com/akamai/AkamaiOPEN-edgegrid-golang/v2@v2.17.0/pkg/iam/user.go (about)

     1  package iam
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"net/http"
     8  	"net/url"
     9  	"path"
    10  	"strconv"
    11  
    12  	validation "github.com/go-ozzo/ozzo-validation/v4"
    13  	"github.com/go-ozzo/ozzo-validation/v4/is"
    14  )
    15  
    16  type (
    17  	// Users is the IAM user identity API interface
    18  	Users interface {
    19  		// CreateUser creates a user in the account specified in your own API client credentials or clone an existing user's role assignments
    20  		//
    21  		// See: https://techdocs.akamai.com/iam-user-admin/reference/post-ui-identity
    22  		CreateUser(context.Context, CreateUserRequest) (*User, error)
    23  
    24  		// GetUser gets  a specific user's profile
    25  		//
    26  		// See: https://techdocs.akamai.com/iam-user-admin/reference/get-ui-identity
    27  		GetUser(context.Context, GetUserRequest) (*User, error)
    28  
    29  		// ListUsers returns a list of users who have access on this account
    30  		//
    31  		// See: https://techdocs.akamai.com/iam-user-admin/reference/get-ui-identities
    32  		ListUsers(context.Context, ListUsersRequest) ([]UserListItem, error)
    33  
    34  		// RemoveUser removes a user identity
    35  		//
    36  		// See: https://techdocs.akamai.com/iam-user-admin/reference/delete-ui-identity
    37  		RemoveUser(context.Context, RemoveUserRequest) error
    38  
    39  		// UpdateUserAuthGrants edits what groups a user has access to, and how the user can interact with the objects in those groups
    40  		//
    41  		// See: https://techdocs.akamai.com/iam-user-admin/reference/put-ui-uiidentity-auth-grants
    42  		UpdateUserAuthGrants(context.Context, UpdateUserAuthGrantsRequest) ([]AuthGrant, error)
    43  
    44  		// UpdateUserInfo updates a user's information
    45  		//
    46  		// See: https://techdocs.akamai.com/iam-user-admin/reference/put-ui-identity-basic-info
    47  		UpdateUserInfo(context.Context, UpdateUserInfoRequest) (*UserBasicInfo, error)
    48  
    49  		// UpdateUserNotifications subscribes or un-subscribe user to product notification emails
    50  		//
    51  		// See: https://techdocs.akamai.com/iam-user-admin/reference/put-notifications
    52  		UpdateUserNotifications(context.Context, UpdateUserNotificationsRequest) (*UserNotifications, error)
    53  
    54  		// UpdateTFA updates a user's two-factor authentication setting and can reset tfa
    55  		//
    56  		// See: https://techdocs.akamai.com/iam-user-admin/reference/put-ui-identity-tfa
    57  		UpdateTFA(context.Context, UpdateTFARequest) error
    58  	}
    59  
    60  	// CreateUserRequest contains the request parameters for the create user endpoint
    61  	CreateUserRequest struct {
    62  		UserBasicInfo
    63  		AuthGrants    []AuthGrantRequest `json:"authGrants,omitempty"`
    64  		Notifications UserNotifications  `json:"notifications,omitempty"`
    65  		SendEmail     bool               `json:"-"`
    66  	}
    67  
    68  	// ListUsersRequest contains the request parameters for the list users endpoint
    69  	ListUsersRequest struct {
    70  		GroupID    *int64
    71  		AuthGrants bool
    72  		Actions    bool
    73  	}
    74  
    75  	// GetUserRequest contains the request parameters of the get user endpoint
    76  	GetUserRequest struct {
    77  		IdentityID    string
    78  		Actions       bool
    79  		AuthGrants    bool
    80  		Notifications bool
    81  	}
    82  
    83  	// UpdateUserInfoRequest contains the request parameters of the update user endpoint
    84  	UpdateUserInfoRequest struct {
    85  		IdentityID string
    86  		User       UserBasicInfo
    87  	}
    88  
    89  	// UpdateUserNotificationsRequest contains the request parameters of the update user notifications endpoint
    90  	UpdateUserNotificationsRequest struct {
    91  		IdentityID    string
    92  		Notifications UserNotifications
    93  	}
    94  
    95  	// UpdateUserAuthGrantsRequest contains the request parameters of the update user auth grants endpoint
    96  	UpdateUserAuthGrantsRequest struct {
    97  		IdentityID string
    98  		AuthGrants []AuthGrantRequest
    99  	}
   100  
   101  	// RemoveUserRequest contains the request parameters of the remove user endpoint
   102  	RemoveUserRequest struct {
   103  		IdentityID string
   104  	}
   105  
   106  	// User describes the response of the get and create user endpoints
   107  	User struct {
   108  		UserBasicInfo
   109  		IdentityID         string            `json:"uiIdentityId"`
   110  		IsLocked           bool              `json:"isLocked"`
   111  		LastLoginDate      string            `json:"lastLoginDate,omitempty"`
   112  		PasswordExpiryDate string            `json:"passwordExpiryDate,omitempty"`
   113  		TFAConfigured      bool              `json:"tfaConfigured"`
   114  		EmailUpdatePending bool              `json:"emailUpdatePending"`
   115  		AuthGrants         []AuthGrant       `json:"authGrants,omitempty"`
   116  		Notifications      UserNotifications `json:"notifications,omitempty"`
   117  	}
   118  
   119  	// UserListItem describes the response of the list endpoint
   120  	UserListItem struct {
   121  		FirstName     string       `json:"firstName"`
   122  		LastName      string       `json:"lastName"`
   123  		UserName      string       `json:"uiUserName,omitempty"`
   124  		Email         string       `json:"email"`
   125  		TFAEnabled    bool         `json:"tfaEnabled"`
   126  		IdentityID    string       `json:"uiIdentityId"`
   127  		IsLocked      bool         `json:"isLocked"`
   128  		LastLoginDate string       `json:"lastLoginDate,omitempty"`
   129  		TFAConfigured bool         `json:"tfaConfigured"`
   130  		AccountID     string       `json:"accountId"`
   131  		Actions       *UserActions `json:"actions,omitempty"`
   132  		AuthGrants    []AuthGrant  `json:"authGrants,omitempty"`
   133  	}
   134  
   135  	// UserBasicInfo is the user basic info structure
   136  	UserBasicInfo struct {
   137  		FirstName         string `json:"firstName"`
   138  		LastName          string `json:"lastName"`
   139  		UserName          string `json:"uiUserName,omitempty"`
   140  		Email             string `json:"email"`
   141  		Phone             string `json:"phone,omitempty"`
   142  		TimeZone          string `json:"timeZone,omitempty"`
   143  		JobTitle          string `json:"jobTitle"`
   144  		TFAEnabled        bool   `json:"tfaEnabled"`
   145  		SecondaryEmail    string `json:"secondaryEmail,omitempty"`
   146  		MobilePhone       string `json:"mobilePhone,omitempty"`
   147  		Address           string `json:"address,omitempty"`
   148  		City              string `json:"city,omitempty"`
   149  		State             string `json:"state,omitempty"`
   150  		ZipCode           string `json:"zipCode,omitempty"`
   151  		Country           string `json:"country"`
   152  		ContactType       string `json:"contactType,omitempty"`
   153  		PreferredLanguage string `json:"preferredLanguage,omitempty"`
   154  		SessionTimeOut    *int   `json:"sessionTimeOut,omitempty"`
   155  	}
   156  
   157  	// UserActions encapsulates permissions available to the user for this group
   158  	UserActions struct {
   159  		APIClient        bool `json:"apiClient"`
   160  		Delete           bool `json:"delete"`
   161  		Edit             bool `json:"edit"`
   162  		IsCloneable      bool `json:"isCloneable"`
   163  		ResetPassword    bool `json:"resetPassword"`
   164  		ThirdPartyAccess bool `json:"thirdPartyAccess"`
   165  		CanEditTFA       bool `json:"canEditTFA"`
   166  		EditProfile      bool `json:"editProfile"`
   167  	}
   168  
   169  	// AuthGrant is user’s role assignments, per group
   170  	AuthGrant struct {
   171  		GroupID         int64       `json:"groupId"`
   172  		GroupName       string      `json:"groupName"`
   173  		IsBlocked       bool        `json:"isBlocked"`
   174  		RoleDescription string      `json:"roleDescription"`
   175  		RoleID          *int        `json:"roleId,omitempty"`
   176  		RoleName        string      `json:"roleName"`
   177  		Subgroups       []AuthGrant `json:"subGroups,omitempty"`
   178  	}
   179  
   180  	// AuthGrantRequest is user’s role assignments, per group for the create/update operation
   181  	AuthGrantRequest struct {
   182  		GroupID   int64              `json:"groupId"`
   183  		IsBlocked bool               `json:"isBlocked"`
   184  		RoleID    *int               `json:"roleId,omitempty"`
   185  		Subgroups []AuthGrantRequest `json:"subGroups,omitempty"`
   186  	}
   187  
   188  	// UserNotifications types of notification emails the user receives
   189  	UserNotifications struct {
   190  		EnableEmail bool                    `json:"enableEmailNotifications"`
   191  		Options     UserNotificationOptions `json:"options"`
   192  	}
   193  
   194  	// UserNotificationOptions types of notification emails the user receives
   195  	UserNotificationOptions struct {
   196  		NewUser        bool     `json:"newUserNotification"`
   197  		PasswordExpiry bool     `json:"passwordExpiry"`
   198  		Proactive      []string `json:"proactive"`
   199  		Upgrade        []string `json:"upgrade"`
   200  	}
   201  
   202  	// TFAActionType is a type for tfa action constants
   203  	TFAActionType string
   204  
   205  	// UpdateTFARequest contains the request parameters of the tfa user endpoint
   206  	UpdateTFARequest struct {
   207  		IdentityID string
   208  		Action     TFAActionType
   209  	}
   210  )
   211  
   212  const (
   213  	// TFAActionEnable ia an action value to use to enable tfa
   214  	TFAActionEnable TFAActionType = "enable"
   215  	// TFAActionDisable ia an action value to use to disable tfa
   216  	TFAActionDisable TFAActionType = "disable"
   217  	// TFAActionReset ia an action value to use to reset tfa
   218  	TFAActionReset TFAActionType = "reset"
   219  )
   220  
   221  var (
   222  	// ErrCreateUser is returned when CreateUser fails
   223  	ErrCreateUser = errors.New("create user")
   224  
   225  	// ErrGetUser is returned when GetUser fails
   226  	ErrGetUser = errors.New("get user")
   227  
   228  	// ErrListUsers is returned when GetUser fails
   229  	ErrListUsers = errors.New("list users")
   230  
   231  	// ErrRemoveUser is returned when RemoveUser fails
   232  	ErrRemoveUser = errors.New("remove user")
   233  
   234  	// ErrUpdateUserAuthGrants is returned when UpdateUserAuthGrants fails
   235  	ErrUpdateUserAuthGrants = errors.New("update user auth grants")
   236  
   237  	// ErrUpdateUserInfo is returned when UpdateUserInfo fails
   238  	ErrUpdateUserInfo = errors.New("update user info")
   239  
   240  	// ErrUpdateUserNotifications is returned when UpdateUserNotifications fails
   241  	ErrUpdateUserNotifications = errors.New("update user notifications")
   242  
   243  	// ErrUpdateTFA is returned when UpdateTFA fails
   244  	ErrUpdateTFA = errors.New("update user's two-factor authentication")
   245  )
   246  
   247  // Validate performs validation on AuthGrant
   248  func (r AuthGrant) Validate() error {
   249  	return validation.Errors{
   250  		"group_id": validation.Validate(r.GroupID, validation.Required),
   251  		"role_id":  validation.Validate(r.RoleID, validation.Required),
   252  	}.Filter()
   253  }
   254  
   255  // Validate validates CreateUserRequest
   256  func (r CreateUserRequest) Validate() error {
   257  	return validation.Errors{
   258  		"country":       validation.Validate(r.Country, validation.Required),
   259  		"email":         validation.Validate(r.Email, validation.Required, is.EmailFormat),
   260  		"firstName":     validation.Validate(r.FirstName, validation.Required),
   261  		"lastName":      validation.Validate(r.LastName, validation.Required),
   262  		"phone":         validation.Validate(r.Phone, validation.Required),
   263  		"authGrants":    validation.Validate(r.AuthGrants, validation.Required),
   264  		"notifications": validation.Validate(r.Notifications, validation.Required),
   265  	}.Filter()
   266  }
   267  
   268  // Validate validates GetUserRequest
   269  func (r GetUserRequest) Validate() error {
   270  	return validation.Errors{
   271  		"uiIdentity": validation.Validate(r.IdentityID, validation.Required),
   272  	}.Filter()
   273  }
   274  
   275  // Validate validates UpdateUserInfoRequest
   276  func (r UpdateUserInfoRequest) Validate() error {
   277  	return validation.Errors{
   278  		"uiIdentity":        validation.Validate(r.IdentityID, validation.Required),
   279  		"firstName":         validation.Validate(r.User.FirstName, validation.Required),
   280  		"lastName":          validation.Validate(r.User.LastName, validation.Required),
   281  		"country":           validation.Validate(r.User.Country, validation.Required),
   282  		"phone":             validation.Validate(r.User.Phone, validation.Required),
   283  		"contactType":       validation.Validate(r.User.ContactType, validation.Required),
   284  		"timeZone":          validation.Validate(r.User.TimeZone, validation.Required),
   285  		"preferredLanguage": validation.Validate(r.User.PreferredLanguage, validation.Required),
   286  		"sessionTimeOut":    validation.Validate(r.User.SessionTimeOut, validation.Required),
   287  	}.Filter()
   288  }
   289  
   290  // Validate validates UpdateUserNotificationsRequest
   291  func (r UpdateUserNotificationsRequest) Validate() error {
   292  	return validation.Errors{
   293  		"uiIdentity": validation.Validate(r.IdentityID, validation.Required),
   294  	}.Filter()
   295  }
   296  
   297  // Validate validates UpdateUserAuthGrantsRequest
   298  func (r UpdateUserAuthGrantsRequest) Validate() error {
   299  	return validation.Errors{
   300  		"uiIdentity": validation.Validate(r.IdentityID, validation.Required),
   301  		"authGrants": validation.Validate(r.AuthGrants, validation.Required),
   302  	}.Filter()
   303  }
   304  
   305  // Validate validates RemoveUserRequest
   306  func (r RemoveUserRequest) Validate() error {
   307  	return validation.Errors{
   308  		"uiIdentity": validation.Validate(r.IdentityID, validation.Required),
   309  	}.Filter()
   310  }
   311  
   312  // Validate validates UpdateTFARequest
   313  func (r UpdateTFARequest) Validate() error {
   314  	return validation.Errors{
   315  		"IdentityID": validation.Validate(r.IdentityID, validation.Required),
   316  		"Action": validation.Validate(r.Action, validation.Required, validation.In(TFAActionEnable, TFAActionDisable, TFAActionReset).
   317  			Error(fmt.Sprintf("value '%s' is invalid. Must be one of: 'enable', 'disable' or 'reset'", r.Action))),
   318  	}.Filter()
   319  }
   320  
   321  func (i *iam) CreateUser(ctx context.Context, params CreateUserRequest) (*User, error) {
   322  	if err := params.Validate(); err != nil {
   323  		return nil, fmt.Errorf("%s: %w:\n%s", ErrCreateUser, ErrStructValidation, err)
   324  	}
   325  
   326  	u, err := url.Parse(path.Join("/identity-management/v2/user-admin", "ui-identities"))
   327  	if err != nil {
   328  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrCreateUser, err)
   329  	}
   330  
   331  	q := u.Query()
   332  	q.Add("sendEmail", strconv.FormatBool(params.SendEmail))
   333  
   334  	u.RawQuery = q.Encode()
   335  
   336  	req, err := http.NewRequestWithContext(ctx, http.MethodPost, u.String(), nil)
   337  	if err != nil {
   338  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrCreateUser, err)
   339  	}
   340  
   341  	var result User
   342  	resp, err := i.Exec(req, &result, params)
   343  	if err != nil {
   344  		return nil, fmt.Errorf("%w: request failed: %s", ErrCreateUser, err)
   345  	}
   346  
   347  	if resp.StatusCode != http.StatusCreated {
   348  		return nil, fmt.Errorf("%s: %w", ErrCreateUser, i.Error(resp))
   349  	}
   350  
   351  	return &result, nil
   352  }
   353  
   354  func (i *iam) GetUser(ctx context.Context, params GetUserRequest) (*User, error) {
   355  	if err := params.Validate(); err != nil {
   356  		return nil, fmt.Errorf("%s: %w:\n%s", ErrGetUser, ErrStructValidation, err)
   357  	}
   358  
   359  	u, err := url.Parse(fmt.Sprintf("/identity-management/v2/user-admin/ui-identities/%s", params.IdentityID))
   360  	if err != nil {
   361  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrGetUser, err)
   362  	}
   363  
   364  	q := u.Query()
   365  	q.Add("actions", strconv.FormatBool(params.Actions))
   366  	q.Add("authGrants", strconv.FormatBool(params.AuthGrants))
   367  	q.Add("notifications", strconv.FormatBool(params.Notifications))
   368  
   369  	u.RawQuery = q.Encode()
   370  
   371  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
   372  	if err != nil {
   373  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrGetUser, err)
   374  	}
   375  
   376  	var rval User
   377  	resp, err := i.Exec(req, &rval)
   378  	if err != nil {
   379  		return nil, fmt.Errorf("%w: request failed: %s", ErrGetUser, err)
   380  	}
   381  
   382  	if resp.StatusCode != http.StatusOK {
   383  		return nil, fmt.Errorf("%s: %w", ErrGetUser, i.Error(resp))
   384  	}
   385  
   386  	return &rval, nil
   387  }
   388  
   389  func (i *iam) ListUsers(ctx context.Context, params ListUsersRequest) ([]UserListItem, error) {
   390  	u, err := url.Parse("/identity-management/v2/user-admin/ui-identities")
   391  	if err != nil {
   392  		return nil, fmt.Errorf("%w: failed to parse the URL:\n%s", ErrListUsers, err)
   393  	}
   394  
   395  	q := u.Query()
   396  	q.Add("actions", strconv.FormatBool(params.Actions))
   397  	q.Add("authGrants", strconv.FormatBool(params.AuthGrants))
   398  	if params.GroupID != nil {
   399  		q.Add("groupId", strconv.FormatInt(int64(*params.GroupID), 10))
   400  	}
   401  	u.RawQuery = q.Encode()
   402  
   403  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
   404  	if err != nil {
   405  		return nil, fmt.Errorf("%w: failed to create request:\n%s", ErrListUsers, err)
   406  	}
   407  
   408  	var users []UserListItem
   409  	resp, err := i.Exec(req, &users)
   410  	if err != nil {
   411  		return nil, fmt.Errorf("%w: request failed:\n%s", ErrListUsers, err)
   412  	}
   413  
   414  	if resp.StatusCode != http.StatusOK {
   415  		return nil, fmt.Errorf("%s: %w", ErrListUsers, i.Error(resp))
   416  	}
   417  
   418  	return users, nil
   419  }
   420  
   421  func (i *iam) RemoveUser(ctx context.Context, params RemoveUserRequest) error {
   422  	if err := params.Validate(); err != nil {
   423  		return fmt.Errorf("%s: %w:\n%s", ErrRemoveUser, ErrStructValidation, err)
   424  	}
   425  
   426  	u, err := url.Parse(fmt.Sprintf("/identity-management/v2/user-admin/ui-identities/%s", params.IdentityID))
   427  	if err != nil {
   428  		return fmt.Errorf("%w: failed to create request: %s", ErrRemoveUser, err)
   429  	}
   430  
   431  	req, err := http.NewRequestWithContext(ctx, http.MethodDelete, u.String(), nil)
   432  	if err != nil {
   433  		return fmt.Errorf("%w: failed to create request: %s", ErrRemoveUser, err)
   434  	}
   435  
   436  	resp, err := i.Exec(req, nil)
   437  	if err != nil {
   438  		return fmt.Errorf("%w: request failed: %s", ErrRemoveUser, err)
   439  	}
   440  
   441  	if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusNoContent {
   442  		return fmt.Errorf("%s: %w", ErrRemoveUser, i.Error(resp))
   443  	}
   444  
   445  	return nil
   446  }
   447  
   448  func (i *iam) UpdateUserAuthGrants(ctx context.Context, params UpdateUserAuthGrantsRequest) ([]AuthGrant, error) {
   449  	if err := params.Validate(); err != nil {
   450  		return nil, fmt.Errorf("%s: %w:\n%s", ErrUpdateUserAuthGrants, ErrStructValidation, err)
   451  	}
   452  
   453  	u, err := url.Parse(fmt.Sprintf("/identity-management/v2/user-admin/ui-identities/%s/auth-grants", params.IdentityID))
   454  	if err != nil {
   455  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrUpdateUserAuthGrants, err)
   456  	}
   457  
   458  	req, err := http.NewRequestWithContext(ctx, http.MethodPut, u.String(), nil)
   459  	if err != nil {
   460  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrUpdateUserAuthGrants, err)
   461  	}
   462  
   463  	rval := make([]AuthGrant, 0)
   464  
   465  	resp, err := i.Exec(req, &rval, params.AuthGrants)
   466  	if err != nil {
   467  		return nil, fmt.Errorf("%w: request failed: %s", ErrUpdateUserAuthGrants, err)
   468  	}
   469  
   470  	if resp.StatusCode != http.StatusOK {
   471  		return nil, fmt.Errorf("%s: %w", ErrUpdateUserAuthGrants, i.Error(resp))
   472  	}
   473  
   474  	return rval, nil
   475  }
   476  
   477  func (i *iam) UpdateUserInfo(ctx context.Context, params UpdateUserInfoRequest) (*UserBasicInfo, error) {
   478  	if err := params.Validate(); err != nil {
   479  		return nil, fmt.Errorf("%s: %w:\n%s", ErrUpdateUserInfo, ErrStructValidation, err)
   480  	}
   481  
   482  	u, err := url.Parse(fmt.Sprintf("/identity-management/v2/user-admin/ui-identities/%s/basic-info", params.IdentityID))
   483  	if err != nil {
   484  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrUpdateUserInfo, err)
   485  	}
   486  
   487  	req, err := http.NewRequestWithContext(ctx, http.MethodPut, u.String(), nil)
   488  	if err != nil {
   489  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrUpdateUserInfo, err)
   490  	}
   491  
   492  	var rval UserBasicInfo
   493  	resp, err := i.Exec(req, &rval, params.User)
   494  	if err != nil {
   495  		return nil, fmt.Errorf("%w: request failed: %s", ErrUpdateUserInfo, err)
   496  	}
   497  
   498  	if resp.StatusCode != http.StatusOK {
   499  		return nil, fmt.Errorf("%s: %w", ErrUpdateUserInfo, i.Error(resp))
   500  	}
   501  
   502  	return &rval, nil
   503  }
   504  
   505  func (i *iam) UpdateUserNotifications(ctx context.Context, params UpdateUserNotificationsRequest) (*UserNotifications, error) {
   506  	if err := params.Validate(); err != nil {
   507  		return nil, fmt.Errorf("%s: %w:\n%s", ErrUpdateUserNotifications, ErrStructValidation, err)
   508  	}
   509  
   510  	u, err := url.Parse(fmt.Sprintf("/identity-management/v2/user-admin/ui-identities/%s/notifications", params.IdentityID))
   511  	if err != nil {
   512  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrUpdateUserNotifications, err)
   513  	}
   514  
   515  	req, err := http.NewRequestWithContext(ctx, http.MethodPut, u.String(), nil)
   516  	if err != nil {
   517  		return nil, fmt.Errorf("%w: failed to create request: %s", ErrUpdateUserNotifications, err)
   518  	}
   519  
   520  	var rval UserNotifications
   521  	resp, err := i.Exec(req, &rval, params.Notifications)
   522  	if err != nil {
   523  		return nil, fmt.Errorf("%w: request failed: %s", ErrUpdateUserNotifications, err)
   524  	}
   525  
   526  	if resp.StatusCode != http.StatusOK {
   527  		return nil, fmt.Errorf("%s: %w", ErrUpdateUserNotifications, i.Error(resp))
   528  	}
   529  
   530  	return &rval, nil
   531  }
   532  
   533  func (i *iam) UpdateTFA(ctx context.Context, params UpdateTFARequest) error {
   534  	if err := params.Validate(); err != nil {
   535  		return fmt.Errorf("%s: %w:\n%s", ErrUpdateTFA, ErrStructValidation, err)
   536  	}
   537  
   538  	u, err := url.Parse(fmt.Sprintf("/identity-management/v2/user-admin/ui-identities/%s/tfa", params.IdentityID))
   539  	if err != nil {
   540  		return fmt.Errorf("%w: failed to create request: %s", ErrUpdateTFA, err)
   541  	}
   542  
   543  	q := u.Query()
   544  	q.Add("action", string(params.Action))
   545  	u.RawQuery = q.Encode()
   546  
   547  	req, err := http.NewRequestWithContext(ctx, http.MethodPut, u.String(), nil)
   548  	if err != nil {
   549  		return fmt.Errorf("%w: failed to create request: %s", ErrUpdateTFA, err)
   550  	}
   551  
   552  	resp, err := i.Exec(req, nil, nil)
   553  	if err != nil {
   554  		return fmt.Errorf("%w: request failed: %s", ErrUpdateTFA, err)
   555  	}
   556  
   557  	if resp.StatusCode != http.StatusNoContent {
   558  		return fmt.Errorf("%s: %w", ErrUpdateTFA, i.Error(resp))
   559  	}
   560  
   561  	return nil
   562  }