github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.0/pkg/iam/groups_test.go (about) 1 package iam 2 3 import ( 4 "context" 5 "errors" 6 "io/ioutil" 7 "net/http" 8 "net/http/httptest" 9 "testing" 10 11 "github.com/stretchr/testify/require" 12 "github.com/tj/assert" 13 ) 14 15 func TestCreateGroup(t *testing.T) { 16 tests := map[string]struct { 17 params GroupRequest 18 responseStatus int 19 responseBody string 20 expectedPath string 21 expectedRequestBody string 22 expectedResponse *Group 23 withError error 24 }{ 25 "201 OK": { 26 params: GroupRequest{ 27 GroupID: 12345, 28 GroupName: "Test Group", 29 }, 30 responseStatus: http.StatusCreated, 31 responseBody: ` 32 { 33 "groupId": 98765, 34 "groupName": "Test Group", 35 "parentGroupId": 12345, 36 "createdDate": "2012-04-28T00:00:00.000Z", 37 "createdBy": "johndoe", 38 "modifiedDate": "2012-04-28T00:00:00.000Z", 39 "modifiedBy": "johndoe" 40 }`, 41 expectedPath: "/identity-management/v2/user-admin/groups/12345", 42 expectedRequestBody: `{"groupName":"Test Group"}`, 43 expectedResponse: &Group{ 44 GroupID: 98765, 45 GroupName: "Test Group", 46 ParentGroupID: 12345, 47 CreatedDate: "2012-04-28T00:00:00.000Z", 48 CreatedBy: "johndoe", 49 ModifiedDate: "2012-04-28T00:00:00.000Z", 50 ModifiedBy: "johndoe", 51 }, 52 }, 53 "500 internal server error": { 54 params: GroupRequest{ 55 GroupID: 12345, 56 GroupName: "Test Group", 57 }, 58 responseStatus: http.StatusInternalServerError, 59 responseBody: ` 60 { 61 "type": "internal_error", 62 "title": "Internal Server Error", 63 "detail": "Error making request", 64 "status": 500 65 }`, 66 expectedPath: "/identity-management/v2/user-admin/groups/12345", 67 withError: &Error{ 68 Type: "internal_error", 69 Title: "Internal Server Error", 70 Detail: "Error making request", 71 StatusCode: http.StatusInternalServerError, 72 }, 73 }, 74 "missing group id": { 75 params: GroupRequest{ 76 GroupName: "Test Group", 77 }, 78 withError: ErrStructValidation, 79 }, 80 "missing group name": { 81 params: GroupRequest{ 82 GroupID: 12345, 83 }, 84 withError: ErrStructValidation, 85 }, 86 } 87 88 for name, test := range tests { 89 t.Run(name, func(t *testing.T) { 90 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 91 assert.Equal(t, test.expectedPath, r.URL.String()) 92 assert.Equal(t, http.MethodPost, r.Method) 93 w.WriteHeader(test.responseStatus) 94 _, err := w.Write([]byte(test.responseBody)) 95 assert.NoError(t, err) 96 97 if len(test.expectedRequestBody) > 0 { 98 body, err := ioutil.ReadAll(r.Body) 99 require.NoError(t, err) 100 assert.Equal(t, test.expectedRequestBody, string(body)) 101 } 102 })) 103 client := mockAPIClient(t, mockServer) 104 result, err := client.CreateGroup(context.Background(), test.params) 105 if test.withError != nil { 106 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 107 return 108 } 109 require.NoError(t, err) 110 assert.Equal(t, test.expectedResponse, result) 111 }) 112 } 113 } 114 115 func TestMoveGroup(t *testing.T) { 116 tests := map[string]struct { 117 params MoveGroupRequest 118 expectedRequestBody string 119 responseStatus int 120 withError error 121 responseBody string 122 }{ 123 "204 ok": { 124 responseStatus: http.StatusNoContent, 125 expectedRequestBody: `{"sourceGroupId":1,"destinationGroupId":1}`, 126 params: MoveGroupRequest{DestinationGroupID: 1, SourceGroupID: 1}, 127 }, 128 "500 internal server error": { 129 responseStatus: http.StatusInternalServerError, 130 params: MoveGroupRequest{DestinationGroupID: 1, SourceGroupID: 1}, 131 expectedRequestBody: `{"sourceGroupId":1,"destinationGroupId":1}`, 132 withError: ErrMoveGroup, 133 }, 134 "validation error": { 135 params: MoveGroupRequest{}, 136 withError: ErrStructValidation, 137 }, 138 } 139 140 for name, test := range tests { 141 t.Run(name, func(t *testing.T) { 142 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 143 assert.Equal(t, "/identity-management/v2/user-admin/groups/move", r.URL.String()) 144 assert.Equal(t, http.MethodPost, r.Method) 145 body, err := ioutil.ReadAll(r.Body) 146 require.NoError(t, err) 147 assert.Equal(t, test.expectedRequestBody, string(body)) 148 w.WriteHeader(test.responseStatus) 149 _, err = w.Write([]byte(test.responseBody)) 150 assert.NoError(t, err) 151 })) 152 client := mockAPIClient(t, mockServer) 153 err := client.MoveGroup(context.Background(), test.params) 154 if test.withError != nil { 155 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 156 return 157 } 158 require.NoError(t, err) 159 }) 160 } 161 } 162 163 func TestGetGroup(t *testing.T) { 164 tests := map[string]struct { 165 params GetGroupRequest 166 responseStatus int 167 responseBody string 168 expectedPath string 169 expectedResponse *Group 170 withError error 171 }{ 172 "200 OK with actions": { 173 params: GetGroupRequest{ 174 GroupID: 12345, 175 Actions: true, 176 }, 177 responseStatus: http.StatusOK, 178 responseBody: ` 179 { 180 "groupId": 12345, 181 "groupName": "Top Level group", 182 "createdDate": "2012-04-28T00:00:00.000Z", 183 "createdBy": "johndoe", 184 "modifiedDate": "2012-04-28T00:00:00.000Z", 185 "modifiedBy": "johndoe", 186 "actions": { 187 "edit": true, 188 "delete": true 189 } 190 }`, 191 expectedPath: "/identity-management/v2/user-admin/groups/12345?actions=true", 192 expectedResponse: &Group{ 193 GroupID: 12345, 194 GroupName: "Top Level group", 195 CreatedDate: "2012-04-28T00:00:00.000Z", 196 CreatedBy: "johndoe", 197 ModifiedDate: "2012-04-28T00:00:00.000Z", 198 ModifiedBy: "johndoe", 199 Actions: &GroupActions{ 200 Edit: true, 201 Delete: true, 202 }, 203 }, 204 }, 205 "200 OK with no actions": { 206 params: GetGroupRequest{ 207 GroupID: 12345, 208 }, 209 responseStatus: http.StatusOK, 210 responseBody: ` 211 { 212 "groupId": 12345, 213 "groupName": "Top Level group", 214 "createdDate": "2012-04-28T00:00:00.000Z", 215 "createdBy": "johndoe", 216 "modifiedDate": "2012-04-28T00:00:00.000Z", 217 "modifiedBy": "johndoe" 218 }`, 219 expectedPath: "/identity-management/v2/user-admin/groups/12345?actions=false", 220 expectedResponse: &Group{ 221 GroupID: 12345, 222 GroupName: "Top Level group", 223 CreatedDate: "2012-04-28T00:00:00.000Z", 224 CreatedBy: "johndoe", 225 ModifiedDate: "2012-04-28T00:00:00.000Z", 226 ModifiedBy: "johndoe", 227 }, 228 }, 229 "500 internal server error": { 230 params: GetGroupRequest{ 231 GroupID: 12345, 232 }, 233 responseStatus: http.StatusInternalServerError, 234 responseBody: ` 235 { 236 "type": "internal_error", 237 "title": "Internal Server Error", 238 "detail": "Error making request", 239 "status": 500 240 }`, 241 expectedPath: "/identity-management/v2/user-admin/groups/12345?actions=false", 242 withError: &Error{ 243 Type: "internal_error", 244 Title: "Internal Server Error", 245 Detail: "Error making request", 246 StatusCode: http.StatusInternalServerError, 247 }, 248 }, 249 "missing group id": { 250 params: GetGroupRequest{ 251 Actions: true, 252 }, 253 withError: ErrStructValidation, 254 }, 255 } 256 257 for name, test := range tests { 258 t.Run(name, func(t *testing.T) { 259 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 260 assert.Equal(t, test.expectedPath, r.URL.String()) 261 assert.Equal(t, http.MethodGet, r.Method) 262 w.WriteHeader(test.responseStatus) 263 _, err := w.Write([]byte(test.responseBody)) 264 assert.NoError(t, err) 265 })) 266 client := mockAPIClient(t, mockServer) 267 result, err := client.GetGroup(context.Background(), test.params) 268 if test.withError != nil { 269 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 270 return 271 } 272 require.NoError(t, err) 273 assert.Equal(t, test.expectedResponse, result) 274 }) 275 } 276 } 277 278 func TestListAffectedUsers(t *testing.T) { 279 tests := map[string]struct { 280 params ListAffectedUsersRequest 281 responseStatus int 282 responseBody string 283 expectedPath string 284 expectedResponse []GroupUser 285 withError error 286 }{ 287 "200 OK": { 288 params: ListAffectedUsersRequest{ 289 DestinationGroupID: 12345, 290 SourceGroupID: 12344, 291 UserType: GainAccessUsers, 292 }, 293 responseStatus: http.StatusOK, 294 responseBody: ` 295 [ 296 { 297 "uiIdentityId": "test-identity", 298 "firstName": "jhon", 299 "lastName": "doe", 300 "accountId": "test-account", 301 "email": "john.doe@mycompany.com", 302 "uiUserName": "john.doe@mycompany.com", 303 "lastLoginDate": "2022-02-22T17:06:50.000Z" 304 } 305 ]`, 306 expectedPath: "/identity-management/v2/user-admin/groups/move/12344/12345/affected-users?userType=gainAccess", 307 expectedResponse: []GroupUser{ 308 { 309 IdentityID: "test-identity", 310 FirstName: "jhon", 311 LastName: "doe", 312 AccountID: "test-account", 313 Email: "john.doe@mycompany.com", 314 UserName: "john.doe@mycompany.com", 315 LastLoginDate: "2022-02-22T17:06:50.000Z", 316 }, 317 }, 318 }, 319 "500 internal server error": { 320 params: ListAffectedUsersRequest{ 321 DestinationGroupID: 12345, 322 SourceGroupID: 12344, 323 UserType: GainAccessUsers, 324 }, 325 responseStatus: http.StatusInternalServerError, 326 responseBody: ` 327 { 328 "type": "internal_error", 329 "title": "Internal Server Error", 330 "detail": "Error making request", 331 "status": 500 332 }`, 333 expectedPath: "/identity-management/v2/user-admin/groups/move/12344/12345/affected-users?userType=gainAccess", 334 withError: &Error{ 335 Type: "internal_error", 336 Title: "Internal Server Error", 337 Detail: "Error making request", 338 StatusCode: http.StatusInternalServerError, 339 }, 340 }, 341 "missing destination group id": { 342 params: ListAffectedUsersRequest{ 343 SourceGroupID: 12344, 344 UserType: GainAccessUsers, 345 }, 346 withError: ErrStructValidation, 347 }, 348 "missing source group id": { 349 params: ListAffectedUsersRequest{ 350 DestinationGroupID: 12345, 351 UserType: GainAccessUsers, 352 }, 353 withError: ErrStructValidation, 354 }, 355 "invalid user type": { 356 params: ListAffectedUsersRequest{ 357 DestinationGroupID: 12345, 358 SourceGroupID: 12344, 359 UserType: "different", 360 }, 361 withError: ErrStructValidation, 362 }, 363 } 364 365 for name, test := range tests { 366 t.Run(name, func(t *testing.T) { 367 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 368 assert.Equal(t, test.expectedPath, r.URL.String()) 369 assert.Equal(t, http.MethodGet, r.Method) 370 w.WriteHeader(test.responseStatus) 371 _, err := w.Write([]byte(test.responseBody)) 372 assert.NoError(t, err) 373 })) 374 client := mockAPIClient(t, mockServer) 375 result, err := client.ListAffectedUsers(context.Background(), test.params) 376 if test.withError != nil { 377 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 378 return 379 } 380 require.NoError(t, err) 381 assert.Equal(t, test.expectedResponse, result) 382 }) 383 } 384 } 385 386 func TestListGroups(t *testing.T) { 387 tests := map[string]struct { 388 params ListGroupsRequest 389 responseStatus int 390 responseBody string 391 expectedPath string 392 expectedResponse []Group 393 withError func(*testing.T, error) 394 }{ 395 "200 OK with actions": { 396 params: ListGroupsRequest{ 397 Actions: true, 398 }, 399 responseStatus: http.StatusOK, 400 responseBody: ` 401 [ 402 { 403 "groupId": 12345, 404 "groupName": "Top Level group", 405 "createdDate": "2012-04-28T00:00:00.000Z", 406 "createdBy": "johndoe", 407 "modifiedDate": "2012-04-28T00:00:00.000Z", 408 "modifiedBy": "johndoe", 409 "actions": { 410 "edit": true, 411 "delete": true 412 } 413 } 414 ]`, 415 expectedPath: "/identity-management/v2/user-admin/groups?actions=true", 416 expectedResponse: []Group{ 417 { 418 GroupID: 12345, 419 GroupName: "Top Level group", 420 CreatedDate: "2012-04-28T00:00:00.000Z", 421 CreatedBy: "johndoe", 422 ModifiedDate: "2012-04-28T00:00:00.000Z", 423 ModifiedBy: "johndoe", 424 Actions: &GroupActions{ 425 Edit: true, 426 Delete: true, 427 }, 428 }, 429 }, 430 }, 431 "200 OK with no actions": { 432 params: ListGroupsRequest{ 433 Actions: false, 434 }, 435 responseStatus: http.StatusOK, 436 responseBody: ` 437 [ 438 { 439 "groupId": 12345, 440 "groupName": "Top Level group", 441 "createdDate": "2012-04-28T00:00:00.000Z", 442 "createdBy": "johndoe", 443 "modifiedDate": "2012-04-28T00:00:00.000Z", 444 "modifiedBy": "johndoe" 445 } 446 ]`, 447 expectedPath: "/identity-management/v2/user-admin/groups?actions=false", 448 expectedResponse: []Group{ 449 { 450 GroupID: 12345, 451 GroupName: "Top Level group", 452 CreatedDate: "2012-04-28T00:00:00.000Z", 453 CreatedBy: "johndoe", 454 ModifiedDate: "2012-04-28T00:00:00.000Z", 455 ModifiedBy: "johndoe", 456 }, 457 }, 458 }, 459 "500 internal server error": { 460 params: ListGroupsRequest{ 461 Actions: true, 462 }, 463 responseStatus: http.StatusInternalServerError, 464 responseBody: ` 465 { 466 "type": "internal_error", 467 "title": "Internal Server Error", 468 "detail": "Error making request", 469 "status": 500 470 }`, 471 expectedPath: "/identity-management/v2/user-admin/groups?actions=true", 472 withError: func(t *testing.T, err error) { 473 want := &Error{ 474 Type: "internal_error", 475 Title: "Internal Server Error", 476 Detail: "Error making request", 477 StatusCode: http.StatusInternalServerError, 478 } 479 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 480 }, 481 }, 482 } 483 484 for name, test := range tests { 485 t.Run(name, func(t *testing.T) { 486 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 487 assert.Equal(t, test.expectedPath, r.URL.String()) 488 assert.Equal(t, http.MethodGet, r.Method) 489 w.WriteHeader(test.responseStatus) 490 _, err := w.Write([]byte(test.responseBody)) 491 assert.NoError(t, err) 492 })) 493 client := mockAPIClient(t, mockServer) 494 result, err := client.ListGroups(context.Background(), test.params) 495 if test.withError != nil { 496 test.withError(t, err) 497 return 498 } 499 require.NoError(t, err) 500 assert.Equal(t, test.expectedResponse, result) 501 }) 502 } 503 } 504 505 func TestRemoveGroup(t *testing.T) { 506 tests := map[string]struct { 507 params RemoveGroupRequest 508 responseStatus int 509 responseBody string 510 expectedPath string 511 withError error 512 }{ 513 "204 deleted": { 514 params: RemoveGroupRequest{ 515 GroupID: 12345, 516 }, 517 responseStatus: http.StatusNoContent, 518 expectedPath: "/identity-management/v2/user-admin/groups/12345", 519 }, 520 "500 internal server error": { 521 params: RemoveGroupRequest{ 522 GroupID: 12345, 523 }, 524 responseStatus: http.StatusInternalServerError, 525 responseBody: ` 526 { 527 "type": "internal_error", 528 "title": "Internal Server Error", 529 "detail": "Error making request", 530 "status": 500 531 }`, 532 expectedPath: "/identity-management/v2/user-admin/groups/12345", 533 withError: &Error{ 534 Type: "internal_error", 535 Title: "Internal Server Error", 536 Detail: "Error making request", 537 StatusCode: http.StatusInternalServerError, 538 }, 539 }, 540 "403 not authorised": { 541 params: RemoveGroupRequest{ 542 GroupID: 12345, 543 }, 544 responseStatus: http.StatusForbidden, 545 responseBody: ` 546 { 547 "instance": "", 548 "httpStatus": 403, 549 "detail": "Not Authorized to perform this action", 550 "title": "Forbidden", 551 "type": "/useradmin-api/error-types/1001" 552 }`, 553 expectedPath: "/identity-management/v2/user-admin/groups/12345", 554 withError: &Error{ 555 Instance: "", 556 StatusCode: http.StatusForbidden, 557 Detail: "Not Authorized to perform this action", 558 Title: "Forbidden", 559 Type: "/useradmin-api/error-types/1001", 560 HTTPStatus: http.StatusForbidden, 561 }, 562 }, 563 "missing group id": { 564 params: RemoveGroupRequest{}, 565 withError: ErrStructValidation, 566 }, 567 } 568 569 for name, test := range tests { 570 t.Run(name, func(t *testing.T) { 571 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 572 assert.Equal(t, test.expectedPath, r.URL.String()) 573 assert.Equal(t, http.MethodDelete, r.Method) 574 w.WriteHeader(test.responseStatus) 575 _, err := w.Write([]byte(test.responseBody)) 576 assert.NoError(t, err) 577 })) 578 client := mockAPIClient(t, mockServer) 579 err := client.RemoveGroup(context.Background(), test.params) 580 if test.withError != nil { 581 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 582 return 583 } 584 require.NoError(t, err) 585 }) 586 } 587 } 588 589 func TestUpdateGroupName(t *testing.T) { 590 tests := map[string]struct { 591 params GroupRequest 592 responseStatus int 593 responseBody string 594 expectedPath string 595 expectedRequestBody string 596 expectedResponse *Group 597 withError error 598 }{ 599 "200 updated": { 600 params: GroupRequest{ 601 GroupID: 12345, 602 GroupName: "New Group Name", 603 }, 604 responseStatus: http.StatusOK, 605 responseBody: ` 606 { 607 "groupId": 12345, 608 "groupName": "New Group Name", 609 "parentGroupId": 12344, 610 "createdDate": "2012-04-28T00:00:00.000Z", 611 "createdBy": "johndoe", 612 "modifiedDate": "2012-04-28T00:00:00.000Z", 613 "modifiedBy": "johndoe" 614 }`, 615 expectedPath: "/identity-management/v2/user-admin/groups/12345", 616 expectedRequestBody: `{"groupName":"New Group Name"}`, 617 expectedResponse: &Group{ 618 GroupID: 12345, 619 GroupName: "New Group Name", 620 ParentGroupID: 12344, 621 CreatedDate: "2012-04-28T00:00:00.000Z", 622 CreatedBy: "johndoe", 623 ModifiedDate: "2012-04-28T00:00:00.000Z", 624 ModifiedBy: "johndoe", 625 }, 626 }, 627 "500 internal server error": { 628 params: GroupRequest{ 629 GroupID: 12345, 630 GroupName: "New Group Name", 631 }, 632 responseStatus: http.StatusInternalServerError, 633 responseBody: ` 634 { 635 "type": "internal_error", 636 "title": "Internal Server Error", 637 "detail": "Error making request", 638 "status": 500 639 }`, 640 expectedPath: "/identity-management/v2/user-admin/groups/12345", 641 withError: &Error{ 642 Type: "internal_error", 643 Title: "Internal Server Error", 644 Detail: "Error making request", 645 StatusCode: http.StatusInternalServerError, 646 }, 647 }, 648 "missing group id": { 649 params: GroupRequest{ 650 GroupName: "New Group Name", 651 }, 652 withError: ErrStructValidation, 653 }, 654 "missing group name": { 655 params: GroupRequest{ 656 GroupID: 12345, 657 }, 658 withError: ErrStructValidation, 659 }, 660 } 661 662 for name, test := range tests { 663 t.Run(name, func(t *testing.T) { 664 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 665 assert.Equal(t, test.expectedPath, r.URL.String()) 666 assert.Equal(t, http.MethodPut, r.Method) 667 w.WriteHeader(test.responseStatus) 668 _, err := w.Write([]byte(test.responseBody)) 669 assert.NoError(t, err) 670 671 if len(test.expectedRequestBody) > 0 { 672 body, err := ioutil.ReadAll(r.Body) 673 require.NoError(t, err) 674 assert.Equal(t, test.expectedRequestBody, string(body)) 675 } 676 })) 677 client := mockAPIClient(t, mockServer) 678 result, err := client.UpdateGroupName(context.Background(), test.params) 679 if test.withError != nil { 680 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 681 return 682 } 683 require.NoError(t, err) 684 assert.Equal(t, test.expectedResponse, result) 685 }) 686 } 687 }