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

     1  package iam
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"errors"
     7  	"net/http"
     8  	"net/http/httptest"
     9  	"testing"
    10  
    11  	"github.com/akamai/AkamaiOPEN-edgegrid-golang/v8/pkg/tools"
    12  	"github.com/stretchr/testify/require"
    13  	"github.com/tj/assert"
    14  )
    15  
    16  func TestIAM_CreateUser(t *testing.T) {
    17  	tests := map[string]struct {
    18  		params           CreateUserRequest
    19  		requestBody      string
    20  		responseStatus   int
    21  		responseBody     string
    22  		expectedPath     string
    23  		expectedResponse *User
    24  		withError        func(*testing.T, error)
    25  	}{
    26  		"201 OK": {
    27  			params: CreateUserRequest{
    28  				UserBasicInfo: UserBasicInfo{
    29  					FirstName: "John",
    30  					LastName:  "Doe",
    31  					Email:     "john.doe@mycompany.com",
    32  					Phone:     "(123) 321-1234",
    33  					Country:   "USA",
    34  					State:     "CA",
    35  				},
    36  				AuthGrants:    []AuthGrantRequest{{GroupID: 1, RoleID: tools.IntPtr(1)}},
    37  				Notifications: UserNotifications{},
    38  			},
    39  			requestBody:    `{"firstName":"John","lastName":"Doe","email":"john.doe@mycompany.com","phone":"(123) 321-1234","jobTitle":"","tfaEnabled":false,"state":"CA","country":"USA","authGrants":[{"groupId":1,"isBlocked":false,"roleId":1}],"notifications":{"enableEmailNotifications":false,"options":{"newUserNotification":false,"passwordExpiry":false,"proactive":null,"upgrade":null}}}`,
    40  			responseStatus: http.StatusCreated,
    41  			responseBody: `
    42  {
    43  	"uiIdentityId": "A-BC-1234567",
    44  	"firstName": "John",
    45  	"lastName": "Doe",
    46  	"email": "john.doe@mycompany.com",
    47  	"phone": "(123) 321-1234",
    48  	"state": "CA",
    49  	"country": "USA"
    50  }`,
    51  			expectedPath: "/identity-management/v2/user-admin/ui-identities?sendEmail=false",
    52  			expectedResponse: &User{
    53  				IdentityID: "A-BC-1234567",
    54  				UserBasicInfo: UserBasicInfo{
    55  					FirstName: "John",
    56  					LastName:  "Doe",
    57  					Email:     "john.doe@mycompany.com",
    58  					Phone:     "(123) 321-1234",
    59  					Country:   "USA",
    60  					State:     "CA",
    61  				},
    62  			},
    63  		},
    64  		"500 internal server error": {
    65  			params: CreateUserRequest{
    66  				UserBasicInfo: UserBasicInfo{
    67  					FirstName: "John",
    68  					LastName:  "Doe",
    69  					Email:     "john.doe@mycompany.com",
    70  					Phone:     "(123) 321-1234",
    71  					Country:   "USA",
    72  					State:     "CA",
    73  				},
    74  				AuthGrants:    []AuthGrantRequest{{GroupID: 1, RoleID: tools.IntPtr(1)}},
    75  				Notifications: UserNotifications{},
    76  			},
    77  			responseStatus: http.StatusInternalServerError,
    78  			responseBody: `
    79  {
    80  	"type": "internal_error",
    81      "title": "Internal Server Error",
    82      "detail": "Error making request",
    83      "status": 500
    84  }`,
    85  			expectedPath: "/identity-management/v2/user-admin/ui-identities?sendEmail=false",
    86  			withError: func(t *testing.T, err error) {
    87  				want := &Error{
    88  					Type:       "internal_error",
    89  					Title:      "Internal Server Error",
    90  					Detail:     "Error making request",
    91  					StatusCode: http.StatusInternalServerError,
    92  				}
    93  				assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err)
    94  			},
    95  		},
    96  	}
    97  
    98  	for name, test := range tests {
    99  		t.Run(name, func(t *testing.T) {
   100  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   101  				assert.Equal(t, test.expectedPath, r.URL.String())
   102  				assert.Equal(t, http.MethodPost, r.Method)
   103  				w.WriteHeader(test.responseStatus)
   104  				if test.requestBody != "" {
   105  					buf := new(bytes.Buffer)
   106  					_, err := buf.ReadFrom(r.Body)
   107  					assert.NoError(t, err)
   108  					req := buf.String()
   109  					assert.Equal(t, test.requestBody, req)
   110  				}
   111  				_, err := w.Write([]byte(test.responseBody))
   112  				assert.NoError(t, err)
   113  			}))
   114  			client := mockAPIClient(t, mockServer)
   115  			result, err := client.CreateUser(context.Background(), test.params)
   116  			if test.withError != nil {
   117  				test.withError(t, err)
   118  				return
   119  			}
   120  			require.NoError(t, err)
   121  			assert.Equal(t, test.expectedResponse, result)
   122  		})
   123  	}
   124  }
   125  
   126  func TestIAM_GetUser(t *testing.T) {
   127  	tests := map[string]struct {
   128  		params           GetUserRequest
   129  		responseStatus   int
   130  		responseBody     string
   131  		expectedPath     string
   132  		expectedResponse *User
   133  		withError        func(*testing.T, error)
   134  	}{
   135  		"200 OK": {
   136  			params: GetUserRequest{
   137  				IdentityID: "A-BC-1234567",
   138  			},
   139  			responseStatus: http.StatusOK,
   140  			responseBody: `
   141  {
   142  	"uiIdentityId": "A-BC-1234567",
   143  	"firstName": "John",
   144  	"lastName": "Doe",
   145  	"email": "john.doe@mycompany.com",
   146  	"phone": "(123) 321-1234",
   147  	"state": "CA",
   148  	"country": "USA"
   149  }`,
   150  			expectedPath: "/identity-management/v2/user-admin/ui-identities/A-BC-1234567?actions=false&authGrants=false&notifications=false",
   151  			expectedResponse: &User{
   152  				IdentityID: "A-BC-1234567",
   153  				UserBasicInfo: UserBasicInfo{
   154  					FirstName: "John",
   155  					LastName:  "Doe",
   156  					Email:     "john.doe@mycompany.com",
   157  					Phone:     "(123) 321-1234",
   158  					Country:   "USA",
   159  					State:     "CA",
   160  				},
   161  			},
   162  		},
   163  		"500 internal server error": {
   164  			params: GetUserRequest{
   165  				IdentityID: "A-BC-1234567",
   166  			},
   167  			responseStatus: http.StatusInternalServerError,
   168  			responseBody: `
   169  {
   170  	"type": "internal_error",
   171      "title": "Internal Server Error",
   172      "detail": "Error making request",
   173      "status": 500
   174  }`,
   175  			expectedPath: "/identity-management/v2/user-admin/ui-identities/A-BC-1234567?actions=false&authGrants=false&notifications=false",
   176  			withError: func(t *testing.T, err error) {
   177  				want := &Error{
   178  					Type:       "internal_error",
   179  					Title:      "Internal Server Error",
   180  					Detail:     "Error making request",
   181  					StatusCode: http.StatusInternalServerError,
   182  				}
   183  				assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err)
   184  			},
   185  		},
   186  	}
   187  
   188  	for name, test := range tests {
   189  		t.Run(name, func(t *testing.T) {
   190  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   191  				assert.Equal(t, test.expectedPath, r.URL.String())
   192  				assert.Equal(t, http.MethodGet, r.Method)
   193  				w.WriteHeader(test.responseStatus)
   194  				_, err := w.Write([]byte(test.responseBody))
   195  				assert.NoError(t, err)
   196  			}))
   197  			client := mockAPIClient(t, mockServer)
   198  			result, err := client.GetUser(context.Background(), test.params)
   199  			if test.withError != nil {
   200  				test.withError(t, err)
   201  				return
   202  			}
   203  			require.NoError(t, err)
   204  			assert.Equal(t, test.expectedResponse, result)
   205  		})
   206  	}
   207  }
   208  
   209  func TestIam_ListUsers(t *testing.T) {
   210  	tests := map[string]struct {
   211  		params           ListUsersRequest
   212  		responseStatus   int
   213  		expectedPath     string
   214  		responseBody     string
   215  		expectedResponse []UserListItem
   216  		withError        func(*testing.T, error)
   217  	}{
   218  		"200 OK": {
   219  			params: ListUsersRequest{
   220  				GroupID:    tools.Int64Ptr(12345),
   221  				AuthGrants: true,
   222  				Actions:    true,
   223  			},
   224  			responseStatus: http.StatusOK,
   225  			expectedPath:   "/identity-management/v2/user-admin/ui-identities?actions=true&authGrants=true&groupId=12345",
   226  			responseBody: `[
   227  			  {
   228  				"uiIdentityId": "A-B-123456",
   229  				"firstName": "John",
   230  				"lastName": "Doe",
   231  				"uiUserName": "johndoe",
   232  				"email": "john.doe@mycompany.com",
   233  				"accountId": "1-123A",
   234  				"lastLoginDate": "2016-01-13T17:53:57Z",
   235  				"tfaEnabled": true,
   236  				"tfaConfigured": true,
   237  				"isLocked": false,
   238  				"actions": {
   239  				  "resetPassword": true,
   240  				  "delete": true,
   241  				  "edit": true,
   242  				  "apiClient": true,
   243  				  "thirdPartyAccess": true,
   244  				  "isCloneable": true,
   245  				  "editProfile": true,
   246  				  "canEditTFA": false
   247  				},
   248  				"authGrants": [
   249  				  {
   250  					"groupId": 12345,
   251  					"roleId": 12,
   252  					"groupName": "mygroup",
   253  					"roleName": "admin",
   254  					"roleDescription": "This is a new role that has been created to",
   255  					"isBlocked": false
   256  				  }
   257  				]
   258  			  }
   259  			]`,
   260  			expectedResponse: []UserListItem{
   261  				{
   262  					IdentityID:    "A-B-123456",
   263  					FirstName:     "John",
   264  					LastName:      "Doe",
   265  					UserName:      "johndoe",
   266  					Email:         "john.doe@mycompany.com",
   267  					AccountID:     "1-123A",
   268  					TFAEnabled:    true,
   269  					LastLoginDate: "2016-01-13T17:53:57Z",
   270  					TFAConfigured: true,
   271  					IsLocked:      false,
   272  					Actions: &UserActions{
   273  						APIClient:        true,
   274  						Delete:           true,
   275  						Edit:             true,
   276  						IsCloneable:      true,
   277  						ResetPassword:    true,
   278  						ThirdPartyAccess: true,
   279  						EditProfile:      true,
   280  					},
   281  					AuthGrants: []AuthGrant{
   282  						{
   283  							GroupID:         12345,
   284  							RoleID:          tools.IntPtr(12),
   285  							GroupName:       "mygroup",
   286  							RoleName:        "admin",
   287  							RoleDescription: "This is a new role that has been created to",
   288  						},
   289  					},
   290  				},
   291  			},
   292  		},
   293  		"200 OK, no actions nor grants": {
   294  			params: ListUsersRequest{
   295  				GroupID: tools.Int64Ptr(12345),
   296  			},
   297  			responseStatus: http.StatusOK,
   298  			expectedPath:   "/identity-management/v2/user-admin/ui-identities?actions=false&authGrants=false&groupId=12345",
   299  			responseBody: `[
   300  			  {
   301  				"uiIdentityId": "A-B-123456",
   302  				"firstName": "John",
   303  				"lastName": "Doe",
   304  				"uiUserName": "johndoe",
   305  				"email": "john.doe@mycompany.com",
   306  				"accountId": "1-123A",
   307  				"lastLoginDate": "2016-01-13T17:53:57Z",
   308  				"tfaEnabled": true,
   309  				"tfaConfigured": true,
   310  				"isLocked": false
   311  			  }
   312  			]`,
   313  			expectedResponse: []UserListItem{
   314  				{
   315  					IdentityID:    "A-B-123456",
   316  					FirstName:     "John",
   317  					LastName:      "Doe",
   318  					UserName:      "johndoe",
   319  					Email:         "john.doe@mycompany.com",
   320  					AccountID:     "1-123A",
   321  					TFAEnabled:    true,
   322  					LastLoginDate: "2016-01-13T17:53:57Z",
   323  					TFAConfigured: true,
   324  					IsLocked:      false,
   325  				},
   326  			},
   327  		},
   328  		"no group id": {
   329  			params:       ListUsersRequest{},
   330  			expectedPath: "/identity-management/v2/user-admin/ui-identities?actions=false&authGrants=false",
   331  			responseBody: `[
   332  			  {
   333  				"uiIdentityId": "A-B-123456",
   334  				"firstName": "John",
   335  				"lastName": "Doe",
   336  				"uiUserName": "johndoe",
   337  				"email": "john.doe@mycompany.com",
   338  				"accountId": "1-123A",
   339  				"lastLoginDate": "2016-01-13T17:53:57Z",
   340  				"tfaEnabled": true,
   341  				"tfaConfigured": true,
   342  				"isLocked": false
   343  			  }
   344  			]`,
   345  			expectedResponse: []UserListItem{
   346  				{
   347  					IdentityID:    "A-B-123456",
   348  					FirstName:     "John",
   349  					LastName:      "Doe",
   350  					UserName:      "johndoe",
   351  					Email:         "john.doe@mycompany.com",
   352  					AccountID:     "1-123A",
   353  					TFAEnabled:    true,
   354  					LastLoginDate: "2016-01-13T17:53:57Z",
   355  					TFAConfigured: true,
   356  					IsLocked:      false,
   357  				},
   358  			},
   359  			responseStatus: http.StatusOK,
   360  		},
   361  		"500 internal server error": {
   362  			params: ListUsersRequest{
   363  				GroupID:    tools.Int64Ptr(12345),
   364  				AuthGrants: true,
   365  				Actions:    true,
   366  			},
   367  			responseStatus: http.StatusInternalServerError,
   368  			expectedPath:   "/identity-management/v2/user-admin/ui-identities?actions=true&authGrants=true&groupId=12345",
   369  			responseBody: `
   370  			{
   371  				"type": "internal_error",
   372  				"title": "Internal Server Error",
   373  				"detail": "Error processing request",
   374  				"status": 500
   375  			}`,
   376  			withError: func(t *testing.T, err error) {
   377  				want := &Error{
   378  					Type:       "internal_error",
   379  					Title:      "Internal Server Error",
   380  					Detail:     "Error processing request",
   381  					StatusCode: http.StatusInternalServerError,
   382  				}
   383  				assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err)
   384  			},
   385  		},
   386  	}
   387  	for name, test := range tests {
   388  		t.Run(name, func(t *testing.T) {
   389  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   390  				assert.Equal(t, test.expectedPath, r.URL.String())
   391  				assert.Equal(t, http.MethodGet, r.Method)
   392  				w.WriteHeader(test.responseStatus)
   393  				_, err := w.Write([]byte(test.responseBody))
   394  				assert.NoError(t, err)
   395  			}))
   396  			client := mockAPIClient(t, mockServer)
   397  			users, err := client.ListUsers(context.Background(), test.params)
   398  			if test.withError != nil {
   399  				test.withError(t, err)
   400  				return
   401  			}
   402  			assert.NoError(t, err)
   403  			assert.Equal(t, test.expectedResponse, users)
   404  		})
   405  	}
   406  }
   407  
   408  func TestIAM_UpdateUserInfo(t *testing.T) {
   409  	tests := map[string]struct {
   410  		params           UpdateUserInfoRequest
   411  		requestBody      string
   412  		responseStatus   int
   413  		responseBody     string
   414  		expectedPath     string
   415  		expectedResponse *UserBasicInfo
   416  		withError        func(*testing.T, error)
   417  	}{
   418  		"200 OK": {
   419  			params: UpdateUserInfoRequest{
   420  				IdentityID: "1-ABCDE",
   421  				User: UserBasicInfo{
   422  					FirstName:         "John",
   423  					LastName:          "Doe",
   424  					Email:             "john.doe@mycompany.com",
   425  					Phone:             "(123) 321-1234",
   426  					Country:           "USA",
   427  					State:             "CA",
   428  					PreferredLanguage: "English",
   429  					ContactType:       "Billing",
   430  					SessionTimeOut:    tools.IntPtr(30),
   431  					TimeZone:          "GMT",
   432  				},
   433  			},
   434  			requestBody:    `{"firstName":"John","lastName":"Doe","email":"john.doe@mycompany.com","phone":"(123) 321-1234","timeZone":"GMT","jobTitle":"","tfaEnabled":false,"state":"CA","country":"USA","contactType":"Billing","preferredLanguage":"English","sessionTimeOut":30}`,
   435  			responseStatus: http.StatusOK,
   436  			responseBody: `
   437  {
   438  	"firstName": "John",
   439  	"lastName": "Doe",
   440  	"email": "john.doe@mycompany.com",
   441  	"phone": "(123) 321-1234",
   442  	"state": "CA",
   443  	"country": "USA",
   444  	"preferredLanguage": "English",
   445  	"contactType": "Billing",
   446  	"sessionTimeOut": 30,
   447  	"timeZone": "GMT"
   448  }`,
   449  			expectedPath: "/identity-management/v2/user-admin/ui-identities/1-ABCDE/basic-info",
   450  			expectedResponse: &UserBasicInfo{
   451  				FirstName:         "John",
   452  				LastName:          "Doe",
   453  				Email:             "john.doe@mycompany.com",
   454  				Phone:             "(123) 321-1234",
   455  				Country:           "USA",
   456  				State:             "CA",
   457  				PreferredLanguage: "English",
   458  				ContactType:       "Billing",
   459  				SessionTimeOut:    tools.IntPtr(30),
   460  				TimeZone:          "GMT",
   461  			},
   462  		},
   463  		"500 internal server error": {
   464  			params: UpdateUserInfoRequest{
   465  				IdentityID: "1-ABCDE",
   466  				User: UserBasicInfo{
   467  					FirstName:         "John",
   468  					LastName:          "Doe",
   469  					Email:             "john.doe@mycompany.com",
   470  					Phone:             "(123) 321-1234",
   471  					Country:           "USA",
   472  					State:             "CA",
   473  					PreferredLanguage: "English",
   474  					ContactType:       "Billing",
   475  					SessionTimeOut:    tools.IntPtr(30),
   476  					TimeZone:          "GMT",
   477  				},
   478  			},
   479  			responseStatus: http.StatusInternalServerError,
   480  			responseBody: `
   481  {
   482  	"type": "internal_error",
   483      "title": "Internal Server Error",
   484      "detail": "Error making request",
   485      "status": 500
   486  }`,
   487  			expectedPath: "/identity-management/v2/user-admin/ui-identities/1-ABCDE/basic-info",
   488  			withError: func(t *testing.T, err error) {
   489  				want := &Error{
   490  					Type:       "internal_error",
   491  					Title:      "Internal Server Error",
   492  					Detail:     "Error making request",
   493  					StatusCode: http.StatusInternalServerError,
   494  				}
   495  				assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err)
   496  			},
   497  		},
   498  	}
   499  
   500  	for name, test := range tests {
   501  		t.Run(name, func(t *testing.T) {
   502  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   503  				assert.Equal(t, test.expectedPath, r.URL.String())
   504  				assert.Equal(t, http.MethodPut, r.Method)
   505  				if test.requestBody != "" {
   506  					buf := new(bytes.Buffer)
   507  					_, err := buf.ReadFrom(r.Body)
   508  					assert.NoError(t, err)
   509  					req := buf.String()
   510  					assert.Equal(t, test.requestBody, req)
   511  				}
   512  				w.WriteHeader(test.responseStatus)
   513  				_, err := w.Write([]byte(test.responseBody))
   514  				assert.NoError(t, err)
   515  			}))
   516  			client := mockAPIClient(t, mockServer)
   517  			result, err := client.UpdateUserInfo(context.Background(), test.params)
   518  			if test.withError != nil {
   519  				test.withError(t, err)
   520  				return
   521  			}
   522  			require.NoError(t, err)
   523  			assert.Equal(t, test.expectedResponse, result)
   524  		})
   525  	}
   526  }
   527  
   528  func TestIAM_UpdateUserNotifications(t *testing.T) {
   529  	tests := map[string]struct {
   530  		params           UpdateUserNotificationsRequest
   531  		requestBody      string
   532  		responseStatus   int
   533  		responseBody     string
   534  		expectedPath     string
   535  		expectedResponse *UserNotifications
   536  		withError        func(*testing.T, error)
   537  	}{
   538  		"200 OK": {
   539  			params: UpdateUserNotificationsRequest{
   540  				IdentityID: "1-ABCDE",
   541  				Notifications: UserNotifications{
   542  					EnableEmail: true,
   543  					Options: UserNotificationOptions{
   544  						Upgrade:        []string{"NetStorage", "Other Upgrade Notifications (Planned)"},
   545  						Proactive:      []string{"EdgeScape", "EdgeSuite (HTTP Content Delivery)"},
   546  						PasswordExpiry: true,
   547  						NewUser:        true,
   548  					},
   549  				},
   550  			},
   551  			requestBody:    `{"enableEmailNotifications":true,"options":{"newUserNotification":true,"passwordExpiry":true,"proactive":["EdgeScape","EdgeSuite (HTTP Content Delivery)"],"upgrade":["NetStorage","Other Upgrade Notifications (Planned)"]}}`,
   552  			responseStatus: http.StatusOK,
   553  			responseBody: `
   554  {
   555  	"enableEmailNotifications": true,
   556  	"options": {
   557  		"upgrade": [
   558  			"NetStorage",
   559  			"Other Upgrade Notifications (Planned)"
   560  		],
   561  		"proactive": [
   562  			"EdgeScape",
   563  			"EdgeSuite (HTTP Content Delivery)"
   564  		],
   565  		"passwordExpiry": true,
   566  		"newUserNotification": true
   567  	}
   568  }`,
   569  			expectedPath: "/identity-management/v2/user-admin/ui-identities/1-ABCDE/notifications",
   570  			expectedResponse: &UserNotifications{
   571  				EnableEmail: true,
   572  				Options: UserNotificationOptions{
   573  					Upgrade:        []string{"NetStorage", "Other Upgrade Notifications (Planned)"},
   574  					Proactive:      []string{"EdgeScape", "EdgeSuite (HTTP Content Delivery)"},
   575  					PasswordExpiry: true,
   576  					NewUser:        true,
   577  				},
   578  			},
   579  		},
   580  		"500 internal server error": {
   581  			params: UpdateUserNotificationsRequest{
   582  				IdentityID: "1-ABCDE",
   583  				Notifications: UserNotifications{
   584  					EnableEmail: true,
   585  					Options: UserNotificationOptions{
   586  						Upgrade:        []string{"NetStorage", "Other Upgrade Notifications (Planned)"},
   587  						Proactive:      []string{"EdgeScape", "EdgeSuite (HTTP Content Delivery)"},
   588  						PasswordExpiry: true,
   589  						NewUser:        true,
   590  					},
   591  				},
   592  			},
   593  			responseStatus: http.StatusInternalServerError,
   594  			responseBody: `
   595  {
   596  	"type": "internal_error",
   597      "title": "Internal Server Error",
   598      "detail": "Error making request",
   599      "status": 500
   600  }`,
   601  			expectedPath: "/identity-management/v2/user-admin/ui-identities/1-ABCDE/notifications",
   602  			withError: func(t *testing.T, err error) {
   603  				want := &Error{
   604  					Type:       "internal_error",
   605  					Title:      "Internal Server Error",
   606  					Detail:     "Error making request",
   607  					StatusCode: http.StatusInternalServerError,
   608  				}
   609  				assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err)
   610  			},
   611  		},
   612  	}
   613  
   614  	for name, test := range tests {
   615  		t.Run(name, func(t *testing.T) {
   616  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   617  				assert.Equal(t, test.expectedPath, r.URL.String())
   618  				assert.Equal(t, http.MethodPut, r.Method)
   619  				if test.requestBody != "" {
   620  					buf := new(bytes.Buffer)
   621  					_, err := buf.ReadFrom(r.Body)
   622  					assert.NoError(t, err)
   623  					req := buf.String()
   624  					assert.Equal(t, test.requestBody, req)
   625  				}
   626  				w.WriteHeader(test.responseStatus)
   627  				_, err := w.Write([]byte(test.responseBody))
   628  				assert.NoError(t, err)
   629  			}))
   630  			client := mockAPIClient(t, mockServer)
   631  			result, err := client.UpdateUserNotifications(context.Background(), test.params)
   632  			if test.withError != nil {
   633  				test.withError(t, err)
   634  				return
   635  			}
   636  			require.NoError(t, err)
   637  			assert.Equal(t, test.expectedResponse, result)
   638  		})
   639  	}
   640  }
   641  
   642  func TestIAM_UpdateUserAuthGrants(t *testing.T) {
   643  	tests := map[string]struct {
   644  		params           UpdateUserAuthGrantsRequest
   645  		responseStatus   int
   646  		responseBody     string
   647  		expectedPath     string
   648  		expectedResponse []AuthGrant
   649  		withError        func(*testing.T, error)
   650  	}{
   651  		"200 OK": {
   652  			params: UpdateUserAuthGrantsRequest{
   653  				IdentityID: "1-ABCDE",
   654  				AuthGrants: []AuthGrantRequest{
   655  					{
   656  						GroupID: 12345,
   657  						RoleID:  tools.IntPtr(16),
   658  						Subgroups: []AuthGrantRequest{
   659  							{
   660  								GroupID: 54321,
   661  							},
   662  						},
   663  					},
   664  				},
   665  			},
   666  			responseStatus: http.StatusOK,
   667  			responseBody: `
   668  [
   669  	{
   670  		"groupId": 12345,
   671  		"roleId": 16,
   672  		"subGroups": [
   673  			{
   674  				"groupId": 54321
   675  			}
   676  		]
   677  	}
   678  ]`,
   679  			expectedPath: "/identity-management/v2/user-admin/ui-identities/1-ABCDE/auth-grants",
   680  			expectedResponse: []AuthGrant{
   681  				{
   682  					GroupID: 12345,
   683  					RoleID:  tools.IntPtr(16),
   684  					Subgroups: []AuthGrant{
   685  						{
   686  							GroupID: 54321,
   687  						},
   688  					},
   689  				},
   690  			},
   691  		},
   692  		"500 internal server error": {
   693  			params: UpdateUserAuthGrantsRequest{
   694  				IdentityID: "1-ABCDE",
   695  				AuthGrants: []AuthGrantRequest{
   696  					{
   697  						GroupID: 12345,
   698  						RoleID:  tools.IntPtr(16),
   699  						Subgroups: []AuthGrantRequest{
   700  							{
   701  								GroupID: 54321,
   702  							},
   703  						},
   704  					},
   705  				},
   706  			},
   707  			responseStatus: http.StatusInternalServerError,
   708  			responseBody: `
   709  {
   710  	"type": "internal_error",
   711      "title": "Internal Server Error",
   712      "detail": "Error making request",
   713      "status": 500
   714  }`,
   715  			expectedPath: "/identity-management/v2/user-admin/ui-identities/1-ABCDE/auth-grants",
   716  			withError: func(t *testing.T, err error) {
   717  				want := &Error{
   718  					Type:       "internal_error",
   719  					Title:      "Internal Server Error",
   720  					Detail:     "Error making request",
   721  					StatusCode: http.StatusInternalServerError,
   722  				}
   723  				assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err)
   724  			},
   725  		},
   726  	}
   727  
   728  	for name, test := range tests {
   729  		t.Run(name, func(t *testing.T) {
   730  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   731  				assert.Equal(t, test.expectedPath, r.URL.String())
   732  				assert.Equal(t, http.MethodPut, r.Method)
   733  				w.WriteHeader(test.responseStatus)
   734  				_, err := w.Write([]byte(test.responseBody))
   735  				assert.NoError(t, err)
   736  			}))
   737  			client := mockAPIClient(t, mockServer)
   738  			result, err := client.UpdateUserAuthGrants(context.Background(), test.params)
   739  			if test.withError != nil {
   740  				test.withError(t, err)
   741  				return
   742  			}
   743  			require.NoError(t, err)
   744  			assert.Equal(t, test.expectedResponse, result)
   745  		})
   746  	}
   747  }
   748  
   749  func TestIAM_RemoveUser(t *testing.T) {
   750  	tests := map[string]struct {
   751  		params         RemoveUserRequest
   752  		responseStatus int
   753  		responseBody   string
   754  		expectedPath   string
   755  		withError      func(*testing.T, error)
   756  	}{
   757  		"200 OK": {
   758  			params: RemoveUserRequest{
   759  				IdentityID: "1-ABCDE",
   760  			},
   761  			responseStatus: http.StatusOK,
   762  			responseBody:   "",
   763  			expectedPath:   "/identity-management/v2/user-admin/ui-identities/1-ABCDE",
   764  		},
   765  		"204 No Content": {
   766  			params: RemoveUserRequest{
   767  				IdentityID: "1-ABCDE",
   768  			},
   769  			responseStatus: http.StatusNoContent,
   770  			responseBody:   "",
   771  			expectedPath:   "/identity-management/v2/user-admin/ui-identities/1-ABCDE",
   772  		},
   773  		"500 internal server error": {
   774  			params: RemoveUserRequest{
   775  				IdentityID: "1-ABCDE",
   776  			},
   777  			responseStatus: http.StatusInternalServerError,
   778  			responseBody: `
   779  {
   780  	"type": "internal_error",
   781      "title": "Internal Server Error",
   782      "detail": "Error making request",
   783      "status": 500
   784  }`,
   785  			expectedPath: "/identity-management/v2/user-admin/ui-identities/1-ABCDE",
   786  			withError: func(t *testing.T, err error) {
   787  				want := &Error{
   788  					Type:       "internal_error",
   789  					Title:      "Internal Server Error",
   790  					Detail:     "Error making request",
   791  					StatusCode: http.StatusInternalServerError,
   792  				}
   793  				assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err)
   794  			},
   795  		},
   796  	}
   797  
   798  	for name, test := range tests {
   799  		t.Run(name, func(t *testing.T) {
   800  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   801  				assert.Equal(t, test.expectedPath, r.URL.String())
   802  				assert.Equal(t, http.MethodDelete, r.Method)
   803  				w.WriteHeader(test.responseStatus)
   804  				_, err := w.Write([]byte(test.responseBody))
   805  				assert.NoError(t, err)
   806  			}))
   807  			client := mockAPIClient(t, mockServer)
   808  			err := client.RemoveUser(context.Background(), test.params)
   809  			if test.withError != nil {
   810  				test.withError(t, err)
   811  				return
   812  			}
   813  			require.NoError(t, err)
   814  		})
   815  	}
   816  }
   817  
   818  func TestIAM_UpdateTFA(t *testing.T) {
   819  	tests := map[string]struct {
   820  		params         UpdateTFARequest
   821  		responseStatus int
   822  		responseBody   string
   823  		expectedPath   string
   824  		withError      func(*testing.T, error)
   825  	}{
   826  		"204 No Content": {
   827  			params: UpdateTFARequest{
   828  				IdentityID: "1-ABCDE",
   829  				Action:     TFAActionEnable,
   830  			},
   831  			responseStatus: http.StatusNoContent,
   832  			responseBody:   "",
   833  			expectedPath:   "/identity-management/v2/user-admin/ui-identities/1-ABCDE/tfa?action=enable",
   834  		},
   835  		"500 internal server error": {
   836  			params: UpdateTFARequest{
   837  				IdentityID: "1-ABCDE",
   838  				Action:     TFAActionDisable,
   839  			},
   840  			responseStatus: http.StatusInternalServerError,
   841  			responseBody: `
   842  {
   843  	"type": "internal_error",
   844      "title": "Internal Server Error",
   845      "detail": "Error making request",
   846      "status": 500
   847  }`,
   848  			expectedPath: "/identity-management/v2/user-admin/ui-identities/1-ABCDE/tfa?action=disable",
   849  			withError: func(t *testing.T, err error) {
   850  				want := &Error{
   851  					Type:       "internal_error",
   852  					Title:      "Internal Server Error",
   853  					Detail:     "Error making request",
   854  					StatusCode: http.StatusInternalServerError,
   855  				}
   856  				assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err)
   857  			},
   858  		},
   859  	}
   860  
   861  	for name, test := range tests {
   862  		t.Run(name, func(t *testing.T) {
   863  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   864  				assert.Equal(t, test.expectedPath, r.URL.String())
   865  				assert.Equal(t, http.MethodPut, r.Method)
   866  				w.WriteHeader(test.responseStatus)
   867  				_, err := w.Write([]byte(test.responseBody))
   868  				assert.NoError(t, err)
   869  			}))
   870  			client := mockAPIClient(t, mockServer)
   871  			err := client.UpdateTFA(context.Background(), test.params)
   872  			if test.withError != nil {
   873  				test.withError(t, err)
   874  				return
   875  			}
   876  			require.NoError(t, err)
   877  		})
   878  	}
   879  }