...

Source file src/github.com/okta/okta-sdk-golang/v2/tests/integration/group_test.go

Documentation: github.com/okta/okta-sdk-golang/v2/tests/integration

     1  /*
     2   * Copyright 2018 - Present Okta, Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *      http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package integration
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"fmt"
    23  	"net/http"
    24  	"testing"
    25  	"time"
    26  
    27  	"github.com/cenkalti/backoff/v4"
    28  	"github.com/okta/okta-sdk-golang/v2/okta"
    29  	"github.com/okta/okta-sdk-golang/v2/okta/query"
    30  	"github.com/okta/okta-sdk-golang/v2/tests"
    31  	"github.com/stretchr/testify/assert"
    32  	"github.com/stretchr/testify/require"
    33  )
    34  
    35  func TestCanGetAGroup(t *testing.T) {
    36  	ctx, client, err := tests.NewClient(context.TODO(), okta.WithCache(false))
    37  	require.NoError(t, err)
    38  	// Create a new group → POST /api/v1/groups
    39  	gp := &okta.GroupProfile{
    40  		Name: testName("SDK_TEST Get Test Group"),
    41  	}
    42  	g := &okta.Group{
    43  		Profile: gp,
    44  	}
    45  	group, _, err := client.Group.CreateGroup(ctx, *g)
    46  	require.NoError(t, err, "Should not error when creating a group")
    47  	assert.IsType(t, &okta.Group{}, group)
    48  
    49  	// Get the group by ID → GET /api/v1/groups/{{groupId}}
    50  	foundGroup, _, err := client.Group.GetGroup(ctx, group.Id)
    51  	require.NoError(t, err, "Should not error when finding a group")
    52  	assert.Equal(t, group.Id, foundGroup.Id, "Group that was found was not correct")
    53  
    54  	// Delete the group → DELETE /api/v1/groups/{{groupId}}
    55  	_, err = client.Group.DeleteGroup(ctx, group.Id)
    56  	require.NoError(t, err, "Should not error when deleting a group")
    57  
    58  	// Verify that the group is deleted by calling get on group (Exception thrown with 404 error message) → GET /api/v1/groups/{{groupId}}
    59  	_, resp, err := client.Group.GetGroup(ctx, group.Id)
    60  	assert.Error(t, err, "Finding a group by id should have reported an error")
    61  	assert.Equal(t, http.StatusNotFound, resp.StatusCode,
    62  		"Should have resulted in a 404 when finding a deleted group")
    63  }
    64  
    65  func TestCanListGroups(t *testing.T) {
    66  	ctx, client, err := tests.NewClient(context.TODO(), okta.WithCache(false))
    67  	require.NoError(t, err)
    68  	// Create a new group → POST /api/v1/groups
    69  	gp := &okta.GroupProfile{
    70  		Name: testName("SDK_TEST List Test Group"),
    71  	}
    72  	g := &okta.Group{
    73  		Profile: gp,
    74  	}
    75  	group, _, err := client.Group.CreateGroup(ctx, *g)
    76  	require.NoError(t, err, "Should not error when creating a group")
    77  	assert.IsType(t, &okta.Group{}, group)
    78  
    79  	// List all groups and find the group created → GET /api/v1/groups
    80  	groupList, _, err := client.Group.ListGroups(ctx, nil)
    81  	require.NoError(t, err, "Listing groups should not error")
    82  	found := false
    83  	for _, grp := range groupList {
    84  		if grp.Id == group.Id {
    85  			found = true
    86  		}
    87  	}
    88  	assert.True(t, found, "Could not find group from list")
    89  
    90  	// Delete the group → DELETE /api/v1/groups/{{groupId}}
    91  	_, err = client.Group.DeleteGroup(ctx, group.Id)
    92  	require.NoError(t, err, "Should not error when deleting a group")
    93  }
    94  
    95  func TestCanSearchForAGroup(t *testing.T) {
    96  	ctx, client, err := tests.NewClient(context.TODO(), okta.WithCache(false))
    97  	require.NoError(t, err)
    98  	// Create a new group → POST /api/v1/groups
    99  	groupName := testName("SDK_TEST Search Test Group")
   100  	gp := &okta.GroupProfile{
   101  		Name: groupName,
   102  	}
   103  	g := &okta.Group{
   104  		Profile: gp,
   105  	}
   106  	group, _, err := client.Group.CreateGroup(ctx, *g)
   107  	require.NoError(t, err, "Should not error when creating a group")
   108  	assert.IsType(t, &okta.Group{}, group)
   109  
   110  	// Search the group by name with query parameter → GET /api/v1/groups?q=Search
   111  	groupList, _, err := client.Group.ListGroups(ctx, query.NewQueryParams(query.WithQ(groupName)))
   112  	assert.Len(t, groupList, 1, "Did not find correct amount of groups")
   113  	require.NoError(t, err, "Listing groups should not error")
   114  	found := false
   115  	for _, grp := range groupList {
   116  		if grp.Id == group.Id {
   117  			found = true
   118  		}
   119  	}
   120  	assert.True(t, found, "Could not find group from list")
   121  
   122  	// Delete the group → DELETE /api/v1/groups/{{groupId}}
   123  	_, err = client.Group.DeleteGroup(ctx, group.Id)
   124  	require.NoError(t, err, "Should not error when deleting a group")
   125  }
   126  
   127  func TestCanUpdateAGroup(t *testing.T) {
   128  	ctx, client, err := tests.NewClient(context.TODO(), okta.WithCache(false))
   129  	require.NoError(t, err)
   130  	// Create a new group → POST /api/v1/groups
   131  	groupName := testName("SDK_TEST Update Test Group")
   132  	gp := &okta.GroupProfile{
   133  		Name: groupName,
   134  	}
   135  	g := &okta.Group{
   136  		Profile: gp,
   137  	}
   138  	group, _, err := client.Group.CreateGroup(ctx, *g)
   139  	require.NoError(t, err, "Should not error when creating a group")
   140  	assert.IsType(t, &okta.Group{}, group)
   141  
   142  	// Update the group name and description → PUT /api/v1/groups/{{groupId}}
   143  	newGroupName := testName("SDK_TEST Updated Name")
   144  	ngp := &okta.GroupProfile{
   145  		Name: newGroupName,
   146  	}
   147  	client.Group.UpdateGroup(ctx, group.Id, okta.Group{Profile: ngp})
   148  
   149  	// Verify that group profile is updated by calling get on the group and verifying the profile → GET /api/v1/groups/{{groupId}}
   150  	updatedGroup, _, err := client.Group.GetGroup(ctx, group.Id)
   151  	require.NoError(t, err, "Should not error when getting updated group")
   152  	assert.Equal(t, newGroupName, updatedGroup.Profile.Name, "The group was not updated")
   153  
   154  	// Delete the group → DELETE /api/v1/groups/{{groupId}}
   155  	_, err = client.Group.DeleteGroup(ctx, group.Id)
   156  	require.NoError(t, err, "Should not error when deleting a group")
   157  }
   158  
   159  func TestGroupUserOperations(t *testing.T) {
   160  	ctx, client, err := tests.NewClient(context.TODO(), okta.WithCache(false))
   161  	require.NoError(t, err)
   162  	// Create a user with credentials → POST /api/v1/users?activate=false
   163  	p := &okta.PasswordCredential{
   164  		Value: "Abcd1234",
   165  	}
   166  	uc := &okta.UserCredentials{
   167  		Password: p,
   168  	}
   169  	profile := okta.UserProfile{}
   170  	profile["firstName"] = "John"
   171  	profile["lastName"] = "With-Group"
   172  	profile["email"] = randomEmail()
   173  	profile["login"] = profile["email"]
   174  	u := &okta.CreateUserRequest{
   175  		Credentials: uc,
   176  		Profile:     &profile,
   177  	}
   178  	qp := query.NewQueryParams(query.WithActivate(false))
   179  
   180  	user, _, err := client.User.CreateUser(ctx, *u, qp)
   181  	require.NoError(t, err, "Creating a new user should not error")
   182  	assert.IsType(t, &okta.User{}, user)
   183  
   184  	// Create a new group → POST /api/v1/groups
   185  	gp := &okta.GroupProfile{
   186  		Name: testName("SDK_TEST Group-Member API Test Group"),
   187  	}
   188  	g := &okta.Group{
   189  		Profile: gp,
   190  	}
   191  
   192  	group, _, err := client.Group.CreateGroup(ctx, *g)
   193  	require.NoError(t, err, "Should not error when creating a group")
   194  	assert.IsType(t, &okta.Group{}, group)
   195  
   196  	// Add user to the group  → POST /api/v1/groups/{{groupId}}/users/{{userId}}
   197  	_, err = client.Group.AddUserToGroup(ctx, group.Id, user.Id)
   198  	require.NoError(t, err, "Should not error when adding user to group")
   199  
   200  	// Validate user present in group → GET /api/v1/groups/{{groupId}}/users
   201  	users, _, err := client.Group.ListGroupUsers(ctx, group.Id, nil)
   202  	require.NoError(t, err)
   203  	found := false
   204  	for _, tmpuser := range users {
   205  		if tmpuser.Id == user.Id {
   206  			found = true
   207  		}
   208  	}
   209  	assert.True(t, found, "Could not find user in group")
   210  
   211  	// Deactivate the user → POST /api/v1/users/{{userId}}/lifecycle/deactivate
   212  	_, err = client.User.DeactivateUser(ctx, user.Id, nil)
   213  	require.NoError(t, err, "Should not error when deactivating")
   214  
   215  	// Delete the user → DELETE /api/v1/users/{{userId}}
   216  	_, err = client.User.DeactivateOrDeleteUser(ctx, user.Id, nil)
   217  	require.NoError(t, err, "Should not error when deleting")
   218  
   219  	// Delete the group →  DELETE /api/v1/groups/{{groupId}}
   220  	_, err = client.Group.DeleteGroup(ctx, group.Id)
   221  	require.NoError(t, err, "Should not error when deleting a group")
   222  }
   223  
   224  func TestGroupRuleOperations(t *testing.T) {
   225  	ctx, client, err := tests.NewClient(context.TODO(), okta.WithCache(false))
   226  	require.NoError(t, err)
   227  	// Create a user with credentials, activated by default → POST /api/v1/users?activate=true
   228  	p := &okta.PasswordCredential{
   229  		Value: testPassword(10),
   230  	}
   231  	uc := &okta.UserCredentials{
   232  		Password: p,
   233  	}
   234  	profile := okta.UserProfile{}
   235  	profile["firstName"] = "John"
   236  	profile["lastName"] = "With-Group-Rule"
   237  	profile["email"] = randomEmail()
   238  	profile["login"] = profile["email"]
   239  	u := &okta.CreateUserRequest{
   240  		Credentials: uc,
   241  		Profile:     &profile,
   242  	}
   243  	qp := query.NewQueryParams(query.WithActivate(true))
   244  
   245  	user, _, err := client.User.CreateUser(ctx, *u, qp)
   246  	require.NoError(t, err, "Creating a new user should not error")
   247  	assert.IsType(t, &okta.User{}, user)
   248  
   249  	// Create a new group → POST /api/v1/groups
   250  	gp := &okta.GroupProfile{
   251  		Name: testName("SDK_TEST Group-Member-Rule API Test Group"),
   252  	}
   253  	g := &okta.Group{
   254  		Profile: gp,
   255  	}
   256  	group, _, err := client.Group.CreateGroup(ctx, *g)
   257  	require.NoError(t, err, "Should not error when creating a group")
   258  	assert.IsType(t, &okta.Group{}, group)
   259  
   260  	// Create a group rule and verify rule executes → POST /api/v1/groups/rules
   261  	// The rule below adds the user created in step 1 to the group created in step 2 upon rule execution/activation
   262  	lastName := profile["lastName"].(string)
   263  	grce := &okta.GroupRuleExpression{
   264  		Type:  "urn:okta:expression:1.0",
   265  		Value: "user.lastName==\"" + lastName + "\"",
   266  	}
   267  	grc := &okta.GroupRuleConditions{
   268  		Expression: grce,
   269  	}
   270  	grga := &okta.GroupRuleGroupAssignment{
   271  		GroupIds: []string{group.Id},
   272  	}
   273  	gra := &okta.GroupRuleAction{
   274  		AssignUserToGroups: grga,
   275  	}
   276  	gr := &okta.GroupRule{
   277  		Actions:    gra,
   278  		Conditions: grc,
   279  		Type:       "group_rule",
   280  		Name:       testName("SDK_TEST group rule"),
   281  	}
   282  	groupRule, _, err := client.Group.CreateGroupRule(ctx, *gr)
   283  	require.NoError(t, err, "Should not error when creating a group Rule")
   284  	assert.IsType(t, &okta.GroupRule{}, groupRule)
   285  
   286  	// Activate the above rule and verify that user is added to the group → POST /api/v1/groups/rules/{{ruleId}}/lifecycle/activate
   287  	_, err = client.Group.ActivateGroupRule(ctx, groupRule.Id)
   288  	require.NoError(t, err, "Should not error when activating rule")
   289  
   290  	users := []*okta.User{}
   291  
   292  	// Use a backoff to check the user is in the group as there can be eventual
   293  	// consistency issues in adding users to groups.
   294  	operation := func() error {
   295  		users, _, err = client.Group.ListGroupUsers(ctx, group.Id, nil)
   296  		if err != nil {
   297  			return err
   298  		}
   299  		for _, tmpuser := range users {
   300  			if tmpuser.Id == user.Id {
   301  				return nil
   302  			}
   303  		}
   304  		return fmt.Errorf("returning error so backoff continues to looking for user being added")
   305  	}
   306  	bOff := backoff.NewExponentialBackOff()
   307  	bOff.MaxElapsedTime = 30 * time.Second
   308  	err = backoff.Retry(operation, bOff)
   309  	require.NoError(t, err, "Inspecting group for user addition had an issue.")
   310  
   311  	// List the group rules and validate the above rule is present → POST /api/v1/groups/rules
   312  	groupRules, _, err := client.Group.ListGroupRules(ctx, nil)
   313  	require.NoError(t, err, "Error should not happen when listing rules")
   314  	found := false
   315  	for _, tmpRules := range groupRules {
   316  		if tmpRules.Id == groupRule.Id {
   317  			found = true
   318  		}
   319  	}
   320  	assert.True(t, found, "Group rule execution did not happen")
   321  
   322  	// Deactivate the rule  → POST /api/v1/groups/rules/{{ruleId}}/lifecycle/deactivate
   323  	_, err = client.Group.DeactivateGroupRule(ctx, groupRule.Id)
   324  	require.NoError(t, err, "Error should not happen when deactivating rule")
   325  
   326  	// Update the rule (Rule can only be updated when it's deactivated) → POST /api/v1/groups/rules/{{ruleId}}
   327  	grce = &okta.GroupRuleExpression{
   328  		Type:  "urn:okta:expression:1.0",
   329  		Value: "user.lastName==\"Incorrect\"",
   330  	}
   331  	grc = &okta.GroupRuleConditions{
   332  		Expression: grce,
   333  	}
   334  	grga = &okta.GroupRuleGroupAssignment{
   335  		GroupIds: []string{group.Id},
   336  	}
   337  	gra = &okta.GroupRuleAction{
   338  		AssignUserToGroups: grga,
   339  	}
   340  	gr = &okta.GroupRule{
   341  		Actions:    gra,
   342  		Conditions: grc,
   343  		Type:       "group_rule",
   344  		Name:       testName("SDK_TEST group rule Updated"),
   345  	}
   346  	newGroupRule, _, err := client.Group.UpdateGroupRule(ctx, groupRule.Id, *gr)
   347  	require.NoError(t, err, "Should not error when updating rule")
   348  
   349  	// Activate the updated rule and verify that the user is removed from the group →  POST /api/v1/groups/rules/{{ruleId}}/lifecycle/activate
   350  	_, err = client.Group.ActivateGroupRule(ctx, newGroupRule.Id)
   351  	require.NoError(t, err, "Should not error when activating the group rule")
   352  
   353  	bOff.Reset()
   354  	// Use a backoff to check the user has been removed from the group as there
   355  	// can be eventual consistency issues in removing users from groups.
   356  	operation = func() error {
   357  		users, _, err = client.Group.ListGroupUsers(ctx, group.Id, nil)
   358  		if err != nil {
   359  			return err
   360  		}
   361  		for _, tmpuser := range users {
   362  			if tmpuser.Id == user.Id {
   363  				return fmt.Errorf("returning error so backoff continues user still listed in group")
   364  			}
   365  		}
   366  		return nil
   367  	}
   368  	err = backoff.Retry(operation, bOff)
   369  	require.NoError(t, err, "Inspecting group for user removal had an issue.")
   370  
   371  	// Deactivate the user, group and group rule → POST /api/v1/users/{{userId}}/lifecycle/deactivate
   372  	_, err = client.Group.DeactivateGroupRule(ctx, newGroupRule.Id)
   373  	require.NoError(t, err, "should not error when deactivating rule")
   374  
   375  	_, err = client.User.DeactivateUser(ctx, user.Id, nil)
   376  	require.NoError(t, err, "should not error when deactivating user")
   377  
   378  	// Delete the user → DELETE /api/v1/users/{{userId}}
   379  	_, err = client.User.DeactivateOrDeleteUser(ctx, user.Id, nil)
   380  	require.NoError(t, err, "Should not error when deleting user")
   381  
   382  	// Delete the group → DELETE /api/v1/groups/{{groupId}}
   383  	_, err = client.Group.DeleteGroup(ctx, group.Id)
   384  	require.NoError(t, err, "Should not error when deleting Group")
   385  
   386  	// Delete the group rule → DELETE /api/v1/groups/rules/{{ruleId}}
   387  	_, err = client.Group.DeleteGroupRule(ctx, groupRule.Id, &query.Params{})
   388  	require.NoError(t, err, "Should not error when deleting Rule")
   389  }
   390  
   391  func TestGroupProfileSerialization(t *testing.T) {
   392  	gp := okta.GroupProfile{
   393  		Name:        "test",
   394  		Description: "tester",
   395  		GroupProfileMap: okta.GroupProfileMap{
   396  			"custom": "value",
   397  		},
   398  	}
   399  
   400  	gpExpected := okta.GroupProfile{
   401  		Name:        "test",
   402  		Description: "tester",
   403  		GroupProfileMap: okta.GroupProfileMap{
   404  			"custom": "value",
   405  		},
   406  	}
   407  
   408  	b, err := json.Marshal(&gp)
   409  	require.NoError(t, err)
   410  
   411  	var gpCopy okta.GroupProfile
   412  	err = json.Unmarshal(b, &gpCopy)
   413  	require.NoError(t, err)
   414  
   415  	assert.Equal(t, gpExpected, gpCopy, "expected marshal to unmarshal to produce exact copy of group profile")
   416  }
   417  
   418  func TestListAssignedApplicationsForGroup(t *testing.T) {
   419  	ctx, client, err := tests.NewClient(context.TODO(), okta.WithCache(false))
   420  	require.NoError(t, err)
   421  
   422  	gp := &okta.GroupProfile{
   423  		Name: testName("SDK_TEST Get Test Group"),
   424  	}
   425  	g := &okta.Group{
   426  		Profile: gp,
   427  	}
   428  	group, _, err := client.Group.CreateGroup(ctx, *g)
   429  	require.NoError(t, err, "Should not error when creating a group")
   430  	assert.IsType(t, &okta.Group{}, group)
   431  
   432  	apps, _, err := client.Group.ListAssignedApplicationsForGroup(ctx, group.Id, nil)
   433  	require.NoError(t, err, "Should not error when listing assigned apps for group")
   434  	assert.Equal(t, 0, len(apps), "there shouldn't be any apps assigned to group")
   435  
   436  	app := okta.NewBookmarkApplication()
   437  	app.Settings = &okta.BookmarkApplicationSettings{
   438  		App: &okta.BookmarkApplicationSettingsApplication{
   439  			RequestIntegration: new(bool),
   440  			Url:                "https://example.com/bookmark.htm",
   441  		},
   442  	}
   443  	_, _, err = client.Application.CreateApplication(ctx, app, nil)
   444  	require.NoError(t, err, "Creating an application should not error")
   445  
   446  	_, _, err = client.Application.CreateApplicationGroupAssignment(ctx, app.Id, group.Id, okta.ApplicationGroupAssignment{})
   447  	require.NoError(t, err, "Assigning application to group should not error")
   448  
   449  	apps, _, err = client.Group.ListAssignedApplicationsForGroup(ctx, group.Id, nil)
   450  	require.NoError(t, err, "Should not error when listing assigned apps for group")
   451  	assert.Equal(t, 1, len(apps), "there should be one app assigned to group")
   452  
   453  	// teardown
   454  	client.Application.DeactivateApplication(ctx, app.Id)
   455  	client.Application.DeleteApplication(ctx, app.Id)
   456  	client.Group.DeleteGroup(ctx, group.Id)
   457  }
   458  

View as plain text