From f34d620218a9a0a24be33705cdba6ac3bec09b7c Mon Sep 17 00:00:00 2001 From: dasarinaidu Date: Tue, 13 Aug 2024 06:17:34 -0700 Subject: [PATCH] Validated defaults for userretention settings --- .../auth/userretention/userretention.go | 105 +++++ .../userretention_delete_user_test.go | 297 +++++++++++++ .../userretention_disable_user_test.go | 399 ++++++++++++++++++ .../userretention_settings_test.go | 337 +++++++++++++++ 4 files changed, 1138 insertions(+) create mode 100644 tests/v2/validation/auth/userretention/userretention.go create mode 100644 tests/v2/validation/auth/userretention/userretention_delete_user_test.go create mode 100644 tests/v2/validation/auth/userretention/userretention_disable_user_test.go create mode 100644 tests/v2/validation/auth/userretention/userretention_settings_test.go diff --git a/tests/v2/validation/auth/userretention/userretention.go b/tests/v2/validation/auth/userretention/userretention.go new file mode 100644 index 00000000000..8bfdab355dd --- /dev/null +++ b/tests/v2/validation/auth/userretention/userretention.go @@ -0,0 +1,105 @@ +package userretention + +import ( + "context" + "fmt" + "time" + + "github.com/rancher/rancher/tests/v2/actions/auth" + "github.com/rancher/shepherd/clients/rancher" + "github.com/rancher/shepherd/extensions/users" + "github.com/sirupsen/logrus" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" +) + +const ( + disableInactiveUserAfter = "disable-inactive-user-after" + deleteInactiveUserAfter = "delete-inactive-user-after" + userRetentionCron = "user-retention-cron" + userRetentionDryRun = "user-retention-dry-run" + lastloginLabel = "cattle.io/last-login" + defaultWaitDuration = 70 * time.Second + pollInterval = 10 * time.Second + isActive = true + isInActive = false + webhookErrorMessage = "admission webhook \"rancher.cattle.io.settings.management.cattle.io\" denied the request: value: Invalid value:" + defaultSettingValue = "" +) + +func setupUserRetentionSettings(client *rancher.Client, disableAfterValue string, deleteAfterValue string, userRetentionCronValue string, dryRunValue string) error { + logrus.Info("Setting up userretention settings TO : ") + logrus.Infof("DisableAfterValue as %s, DeleteAfterValue as %s, UserRetentionCronValue as %s, DryRunValue as %s", disableAfterValue, deleteAfterValue, userRetentionCronValue, dryRunValue) + err := updateUserRetentionSettings(client, disableInactiveUserAfter, defaultSettingValue, disableAfterValue) + if err != nil { + return fmt.Errorf("failed to update disable-inactive-user-after setting: %w", err) + } + err = updateUserRetentionSettings(client, deleteInactiveUserAfter, defaultSettingValue, deleteAfterValue) + if err != nil { + return fmt.Errorf("failed to update delete-inactive-user-after setting: %w", err) + } + + err = updateUserRetentionSettings(client, userRetentionCron, defaultSettingValue, userRetentionCronValue) + if err != nil { + return fmt.Errorf("failed to update user-retention-cron setting: %w", err) + } + err = updateUserRetentionSettings(client, userRetentionDryRun, defaultSettingValue, dryRunValue) + if err != nil { + return fmt.Errorf("failed to update user-retention-dry-run setting: %w", err) + } + logrus.Info("userretention settings setup completed") + return nil +} + +func updateUserRetentionSettings(client *rancher.Client, settingName string, settingDefaultValue string, settingValue string) error { + logrus.Infof("Updating setting: %s, value: %s", settingName, settingValue) + setting, err := client.WranglerContext.Mgmt.Setting().Get(settingName, v1.GetOptions{}) + if err != nil { + return fmt.Errorf("failed to get setting %s: %w", settingName, err) + } + + setting.Value = settingValue + setting.Default = settingDefaultValue + _, err = client.WranglerContext.Mgmt.Setting().Update(setting) + if err != nil { + return fmt.Errorf("failed to update setting %s: %w", settingName, err) + } + return nil +} + +func pollUserStatus(rancherClient *rancher.Client, userID string, expectedStatus bool) error { + logrus.Infof("Polling user status for user %s, expected status: %v", userID, expectedStatus) + ctx, cancel := context.WithTimeout(context.Background(), defaultWaitDuration) + defer cancel() + + adminID, err := users.GetUserIDByName(rancherClient, "admin") + if err != nil { + return fmt.Errorf("failed to get admin user ID: %v", err) + } + adminUser, err := rancherClient.Management.User.ByID(adminID) + if err != nil { + return fmt.Errorf("failed to get admin user: %v", err) + } + adminUser.Password = rancherClient.RancherConfig.AdminPassword + + return wait.PollUntilContextTimeout(ctx, pollInterval, defaultWaitDuration, true, func(ctx context.Context) (bool, error) { + logrus.Info("Logging in with default admin user") + _, err := auth.GetUserAfterLogin(rancherClient, *adminUser) + if err != nil { + return false, fmt.Errorf("failed to login with admin user: %v", err) + } + + logrus.Info("Searching for the user status using the admin client") + user, err := rancherClient.Management.User.ByID(userID) + if err != nil { + return false, fmt.Errorf("failed to get user by ID: %v", err) + } + if user.Enabled == nil { + return false, fmt.Errorf("user.Enabled is nil") + } + + currentStatus := *user.Enabled + logrus.Infof("Current user status: %v, Expected status: %v", currentStatus, expectedStatus) + return currentStatus == expectedStatus, nil + }) +} diff --git a/tests/v2/validation/auth/userretention/userretention_delete_user_test.go b/tests/v2/validation/auth/userretention/userretention_delete_user_test.go new file mode 100644 index 00000000000..57a222db53d --- /dev/null +++ b/tests/v2/validation/auth/userretention/userretention_delete_user_test.go @@ -0,0 +1,297 @@ +//go:build (validation || infra.any || cluster.any || sanity) && !stress && !extended + +package userretention + +import ( + "testing" + "time" + + "github.com/rancher/norman/types" + "github.com/rancher/rancher/tests/v2/actions/auth" + "github.com/rancher/rancher/tests/v2/actions/rbac" + "github.com/rancher/shepherd/clients/rancher" + "github.com/rancher/shepherd/extensions/users" + "github.com/rancher/shepherd/pkg/session" + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + rbac1 "k8s.io/api/rbac/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type URDeleteTestSuite struct { + suite.Suite + client *rancher.Client + session *session.Session +} + +func (ur *URDeleteTestSuite) SetupSuite() { + logrus.Info("Setting up URDeleteTestSuite") + ur.session = session.NewSession() + + logrus.Info("Creating new Rancher client") + client, err := rancher.NewClient("", ur.session) + require.NoError(ur.T(), err) + ur.client = client +} + +func (ur *URDeleteTestSuite) TearDownSuite() { + logrus.Info("Tearing down URDeleteTestSuite") + ur.session.Cleanup() +} + +func (ur *URDeleteTestSuite) TestDefaultAdminUserIsNotDeleted() { + logrus.Info("Setting up userretention settings") + setupUserRetentionSettings(ur.client, "", "400h", "*/1 * * * *", "false") + + logrus.Info("Getting admin user details") + adminID, err := users.GetUserIDByName(ur.client, "admin") + require.NoError(ur.T(), err) + adminUser, err := ur.client.Management.User.ByID(adminID) + require.NoError(ur.T(), err) + adminUser.Password = ur.client.RancherConfig.AdminPassword + + logrus.Info("Updating user attributes") + userAttributes, err := ur.client.WranglerContext.Mgmt.UserAttribute().Get(adminUser.ID, v1.GetOptions{}) + require.NoError(ur.T(), err) + userAttributes.DeleteAfter = &v1.Duration{Duration: time.Second * 10} + _, err = ur.client.WranglerContext.Mgmt.UserAttribute().Update(userAttributes) + require.NoError(ur.T(), err) + + logrus.Info("Attempting initial login") + _, err = auth.GetUserAfterLogin(ur.client, *adminUser) + require.NoError(ur.T(), err) + + logrus.Info("Waiting for default duration") + time.Sleep(defaultWaitDuration) + + logrus.Info("Attempting login after wait period") + _, err = auth.GetUserAfterLogin(ur.client, *adminUser) + require.NoError(ur.T(), err) +} + +func (ur *URDeleteTestSuite) TestAdminUserGetDeleted() { + logrus.Info("Setting up userretention settings") + setupUserRetentionSettings(ur.client, "", "400h", "*/1 * * * *", "false") + + logrus.Info("Creating new admin user") + newAdminUser, err := users.CreateUserWithRole(ur.client, users.UserConfig(), "admin") + require.NoError(ur.T(), err) + userReLogin, err := auth.GetUserAfterLogin(ur.client, *newAdminUser) + require.NoError(ur.T(), err) + + logrus.Info("Updating user attributes") + userAttributes, err := ur.client.WranglerContext.Mgmt.UserAttribute().Get(newAdminUser.ID, v1.GetOptions{}) + require.NoError(ur.T(), err) + userAttributes.DeleteAfter = &v1.Duration{Duration: time.Second * 10} + _, err = ur.client.WranglerContext.Mgmt.UserAttribute().Update(userAttributes) + require.NoError(ur.T(), err) + + logrus.Info("Verifying user status") + userReLogin, err = ur.client.WranglerContext.Mgmt.User().Get(userReLogin.Name, v1.GetOptions{}) + assert.Equal(ur.T(), isActive, *(userReLogin).Enabled) + require.NoError(ur.T(), err) + + logrus.Info("Waiting for default duration") + pollUserStatus(ur.client, newAdminUser.ID, isInActive) + + logrus.Info("Attempting login after wait period") + _, err = auth.GetUserAfterLogin(ur.client, *newAdminUser) + assert.ErrorContains(ur.T(), err, "401 Unauthorized") + + logrus.Info("Checking bindings after user deletion") + bindingsAfter, err := rbac.GetBindings(ur.client, newAdminUser.ID) + require.NoError(ur.T(), err) + assert.Empty(ur.T(), bindingsAfter["RoleBindings"], "Expected no RoleBindings after user deletion") + assert.Equal(ur.T(), 0, len(bindingsAfter["RoleBindings"].([]rbac1.RoleBinding)), "RoleBindings slice should be empty after user deletion") + + logrus.Info("Checking global role bindings after user deletion") + globalRoleBindingsAfter, err := ur.client.Management.GlobalRoleBinding.List(&types.ListOpts{ + Filters: map[string]interface{}{ + "userId": newAdminUser.ID, + }, + }) + require.NoError(ur.T(), err) + assert.Empty(ur.T(), globalRoleBindingsAfter.Data, "Expected no GlobalRoleBindings after user deletion") +} + +func (ur *URDeleteTestSuite) TestStandardUserGetDeleted() { + logrus.Info("Setting up userretention settings") + setupUserRetentionSettings(ur.client, "", "400h", "*/1 * * * *", "false") + + logrus.Info("Creating new standard user") + newStdUser, err := users.CreateUserWithRole(ur.client, users.UserConfig(), "user") + require.NoError(ur.T(), err) + + logrus.Info("Logging in with new standard user") + userReLogin, err := auth.GetUserAfterLogin(ur.client, *newStdUser) + require.NoError(ur.T(), err) + + logrus.Info("Updating user attributes") + userAttributes, err := ur.client.WranglerContext.Mgmt.UserAttribute().Get(newStdUser.ID, v1.GetOptions{}) + require.NoError(ur.T(), err) + userAttributes.DeleteAfter = &v1.Duration{Duration: time.Second * 10} + _, err = ur.client.WranglerContext.Mgmt.UserAttribute().Update(userAttributes) + require.NoError(ur.T(), err) + + logrus.Info("Verifying user status") + userReLogin, err = ur.client.WranglerContext.Mgmt.User().Get(userReLogin.Name, v1.GetOptions{}) + assert.Equal(ur.T(), isActive, *(userReLogin).Enabled) + require.NoError(ur.T(), err) + + logrus.Info("Polling user status to disable") + pollUserStatus(ur.client, newStdUser.ID, isInActive) + + logrus.Info("Attempting login after wait period") + _, err = auth.GetUserAfterLogin(ur.client, *newStdUser) + assert.ErrorContains(ur.T(), err, "401 Unauthorized") + + logrus.Info("Checking bindings after user deletion") + bindingsAfter, err := rbac.GetBindings(ur.client, newStdUser.ID) + require.NoError(ur.T(), err) + assert.Empty(ur.T(), bindingsAfter["RoleBindings"], "Expected no RoleBindings after user deletion") + assert.Equal(ur.T(), 0, len(bindingsAfter["RoleBindings"].([]rbac1.RoleBinding)), "RoleBindings slice should be empty after user deletion") + + logrus.Info("Checking global role bindings after user deletion") + globalRoleBindingsAfter, err := ur.client.Management.GlobalRoleBinding.List(&types.ListOpts{ + Filters: map[string]interface{}{ + "userId": newStdUser.ID, + }, + }) + require.NoError(ur.T(), err) + assert.Empty(ur.T(), globalRoleBindingsAfter.Data, "Expected no GlobalRoleBindings after user deletion") +} + +func (ur *URDeleteTestSuite) TestUserIsNotDeletedWithBlankSettings() { + logrus.Info("Setting up userretention settings with blank values") + setupUserRetentionSettings(ur.client, "", "400h", "*/1 * * * *", "false") + + logrus.Info("Creating new standard user") + newUser, err := users.CreateUserWithRole(ur.client, users.UserConfig(), "user") + require.NoError(ur.T(), err) + + logrus.Info("Logging in with new user") + userReLogin, err := auth.GetUserAfterLogin(ur.client, *newUser) + require.NoError(ur.T(), err) + + logrus.Info("Updating user attributes") + userAttributes, err := ur.client.WranglerContext.Mgmt.UserAttribute().Get(newUser.ID, v1.GetOptions{}) + require.NoError(ur.T(), err) + userAttributes.DeleteAfter = nil + _, err = ur.client.WranglerContext.Mgmt.UserAttribute().Update(userAttributes) + require.NoError(ur.T(), err) + + logrus.Info("Verifying user status") + userReLogin, err = ur.client.WranglerContext.Mgmt.User().Get(userReLogin.Name, v1.GetOptions{}) + assert.Equal(ur.T(), isActive, *(userReLogin).Enabled) + require.NoError(ur.T(), err) + + logrus.Info("Waiting for default duration") + time.Sleep(defaultWaitDuration) + + logrus.Info("Verifying user status after wait period") + userReLogin1, err := ur.client.WranglerContext.Mgmt.User().Get(userReLogin.Name, v1.GetOptions{}) + require.NoError(ur.T(), err) + assert.Equal(ur.T(), isActive, *(userReLogin1).Enabled) +} + +func (ur *URDeleteTestSuite) TestUserIsNotGetDeletedWithDryRun() { + logrus.Info("Setting up userretention settings with dry run") + setupUserRetentionSettings(ur.client, "", "400h", "*/1 * * * *", "true") + + logrus.Info("Creating new standard user") + newUser, err := users.CreateUserWithRole(ur.client, users.UserConfig(), "user") + require.NoError(ur.T(), err) + + logrus.Info("Logging in with new user") + userReLogin, err := auth.GetUserAfterLogin(ur.client, *newUser) + require.NoError(ur.T(), err) + + logrus.Info("Updating user attributes") + userAttributes, err := ur.client.WranglerContext.Mgmt.UserAttribute().Get(newUser.ID, v1.GetOptions{}) + require.NoError(ur.T(), err) + userAttributes.DeleteAfter = &v1.Duration{Duration: time.Second * 10} + _, err = ur.client.WranglerContext.Mgmt.UserAttribute().Update(userAttributes) + require.NoError(ur.T(), err) + + logrus.Info("Verifying user status") + userReLogin, err = ur.client.WranglerContext.Mgmt.User().Get(userReLogin.Name, v1.GetOptions{}) + assert.Equal(ur.T(), isActive, *(userReLogin).Enabled) + require.NoError(ur.T(), err) + + logrus.Info("Getting initial bindings") + bindingsBefore, _ := rbac.GetBindings(ur.client, newUser.ID) + + logrus.Info("Waiting for default duration") + time.Sleep(2 * defaultWaitDuration) + + logrus.Info("Verifying user status after wait period") + userReLogin, err = ur.client.WranglerContext.Mgmt.User().Get(userReLogin.Name, v1.GetOptions{}) + require.NoError(ur.T(), err) + assert.Equal(ur.T(), isActive, *(userReLogin).Enabled) + + logrus.Info("Checking bindings after wait period") + bindingsAfter, _ := rbac.GetBindings(ur.client, newUser.ID) + assert.Equal(ur.T(), bindingsBefore, bindingsAfter, "RoleBindings") + assert.Equal(ur.T(), bindingsBefore, bindingsAfter, "ClusterRoleBindings") + assert.Equal(ur.T(), bindingsBefore, bindingsAfter, "GlobalRoleBindings") + assert.Equal(ur.T(), bindingsBefore, bindingsAfter, "ClusterRoleTemplateBindings") + require.NoError(ur.T(), err) + + logrus.Info("Resetting userretention dry run setting") + updateUserRetentionSettings(ur.client, userRetentionDryRun, defaultSettingValue, "false") +} + +func (ur *URDeleteTestSuite) TestStandardUserGetDeletedWithDefaultValue() { + logrus.Info("Setting up userretention settings") + setupUserRetentionSettings(ur.client, "400h", "", "*/1 * * * *", "false") + logrus.Info("Update deleteInactiveUserAfter settings with Default value") + updateUserRetentionSettings(ur.client, deleteInactiveUserAfter, "400h", "") + + logrus.Info("Creating new standard user") + newStdUser, err := users.CreateUserWithRole(ur.client, users.UserConfig(), "user") + require.NoError(ur.T(), err) + + logrus.Info("Logging in with new standard user") + userReLogin, err := auth.GetUserAfterLogin(ur.client, *newStdUser) + require.NoError(ur.T(), err) + + logrus.Info("Updating user attributes") + userAttributes, err := ur.client.WranglerContext.Mgmt.UserAttribute().Get(newStdUser.ID, v1.GetOptions{}) + require.NoError(ur.T(), err) + userAttributes.DeleteAfter = &v1.Duration{Duration: time.Second * 10} + _, err = ur.client.WranglerContext.Mgmt.UserAttribute().Update(userAttributes) + require.NoError(ur.T(), err) + + logrus.Info("Verifying user status") + userReLogin, err = ur.client.WranglerContext.Mgmt.User().Get(userReLogin.Name, v1.GetOptions{}) + assert.Equal(ur.T(), isActive, *(userReLogin).Enabled) + require.NoError(ur.T(), err) + + logrus.Info("Polling user status to disable") + pollUserStatus(ur.client, newStdUser.ID, isInActive) + + logrus.Info("Attempting login after wait period") + _, err = auth.GetUserAfterLogin(ur.client, *newStdUser) + assert.ErrorContains(ur.T(), err, "401 Unauthorized") + + logrus.Info("Checking bindings after user deletion") + bindingsAfter, err := rbac.GetBindings(ur.client, newStdUser.ID) + require.NoError(ur.T(), err) + assert.Empty(ur.T(), bindingsAfter["RoleBindings"], "Expected no RoleBindings after user deletion") + assert.Equal(ur.T(), 0, len(bindingsAfter["RoleBindings"].([]rbac1.RoleBinding)), "RoleBindings slice should be empty after user deletion") + + logrus.Info("Checking global role bindings after user deletion") + globalRoleBindingsAfter, err := ur.client.Management.GlobalRoleBinding.List(&types.ListOpts{ + Filters: map[string]interface{}{ + "userId": newStdUser.ID, + }, + }) + require.NoError(ur.T(), err) + assert.Empty(ur.T(), globalRoleBindingsAfter.Data, "Expected no GlobalRoleBindings after user deletion") +} + +func TestURDeleteUserSuite(t *testing.T) { + suite.Run(t, new(URDeleteTestSuite)) +} diff --git a/tests/v2/validation/auth/userretention/userretention_disable_user_test.go b/tests/v2/validation/auth/userretention/userretention_disable_user_test.go new file mode 100644 index 00000000000..66f515af071 --- /dev/null +++ b/tests/v2/validation/auth/userretention/userretention_disable_user_test.go @@ -0,0 +1,399 @@ +package userretention + +import ( + "testing" + "time" + + "github.com/rancher/rancher/tests/v2/actions/auth" + "github.com/rancher/rancher/tests/v2/actions/rbac" + "github.com/rancher/shepherd/clients/rancher" + managementv3 "github.com/rancher/shepherd/clients/rancher/generated/management/v3" + "github.com/rancher/shepherd/extensions/users" + "github.com/rancher/shepherd/pkg/session" + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type URDisableTestSuite struct { + suite.Suite + client *rancher.Client + session *session.Session + adminClient *rancher.Client + adminUser *managementv3.User +} + +func (ur *URDisableTestSuite) SetupSuite() { + logrus.Info("Setting up URDisableTestSuite") + ur.session = session.NewSession() + + logrus.Info("Creating new Rancher client") + client, err := rancher.NewClient("", ur.session) + require.NoError(ur.T(), err) + ur.client = client +} + +func (ur *URDisableTestSuite) TearDownSuite() { + logrus.Info("Tearing down URDisableTestSuite") + if ur.adminUser != nil { + logrus.Info("Deleting admin user") + err := ur.client.Management.User.Delete(ur.adminUser) + if err != nil { + logrus.Errorf("Failed to delete admin user: %v", err) + } + } + logrus.Info("Cleaning up session") + ur.session.Cleanup() +} + +func (ur *URDisableTestSuite) assertBindingsEqual(before, after map[string]interface{}) { + assert.Equal(ur.T(), before["RoleBindings"], after["RoleBindings"], "RoleBindings mismatch") + assert.Equal(ur.T(), before["ClusterRoleBindings"], after["ClusterRoleBindings"], "ClusterRoleBindings mismatch") + assert.Equal(ur.T(), before["GlobalRoleBindings"], after["GlobalRoleBindings"], "GlobalRoleBindings mismatch") + assert.Equal(ur.T(), before["ClusterRoleTemplateBindings"], after["ClusterRoleTemplateBindings"], "ClusterRoleTemplateBindings mismatch") +} + +func (ur *URDisableTestSuite) TestDefaultAdminUserIsNotDisabled() { + logrus.Info("Setting up userretention settings") + setupUserRetentionSettings(ur.client, "10s", "", "*/1 * * * *", "false") + logrus.Info("Retrieving admin user details") + adminID, err := users.GetUserIDByName(ur.client, "admin") + require.NoError(ur.T(), err) + adminUser, err := ur.client.Management.User.ByID(adminID) + require.NoError(ur.T(), err) + adminUser.Password = ur.client.RancherConfig.AdminPassword + + logrus.Info("Attempting initial login for admin user") + _, err = auth.GetUserAfterLogin(ur.client, *adminUser) + require.NoError(ur.T(), err) + + logrus.Info("Waiting for default duration") + time.Sleep(defaultWaitDuration) + + logrus.Info("Attempting login after wait period") + _, err = auth.GetUserAfterLogin(ur.client, *adminUser) + require.NoError(ur.T(), err) +} + +func (ur *URDisableTestSuite) TestAdminUserGetDisabled() { + logrus.Info("Setting up userretention settings") + setupUserRetentionSettings(ur.client, "10s", "", "*/1 * * * *", "false") + + logrus.Info("Creating new admin user") + newAdminUser, err := users.CreateUserWithRole(ur.client, users.UserConfig(), "admin") + require.NoError(ur.T(), err) + userReLogin, err := auth.GetUserAfterLogin(ur.client, *newAdminUser) + require.NoError(ur.T(), err) + assert.Equal(ur.T(), isActive, *(userReLogin).Enabled) + + bindingsBefore, err := rbac.GetBindings(ur.client, newAdminUser.ID) + require.NoError(ur.T(), err, "Failed to get initial bindings") + + logrus.Info("Polling user status") + pollUserStatus(ur.client, newAdminUser.ID, isInActive) + + logrus.Info("Verifying user status after polling") + userReLogin, err = ur.client.WranglerContext.Mgmt.User().Get(userReLogin.Name, v1.GetOptions{}) + require.NoError(ur.T(), err) + assert.Equal(ur.T(), isInActive, *(userReLogin).Enabled) + + logrus.Info("Attempting login with disabled user") + _, err = auth.GetUserAfterLogin(ur.client, *newAdminUser) + assert.ErrorContains(ur.T(), err, "403 Forbidden") + bindingsAfter, err := rbac.GetBindings(ur.client, newAdminUser.ID) + require.NoError(ur.T(), err, "Failed to get final bindings") + ur.assertBindingsEqual(bindingsBefore, bindingsAfter) + +} + +func (ur *URDisableTestSuite) TestStandardUserGetDisabled() { + logrus.Info("Setting up userretention settings") + setupUserRetentionSettings(ur.client, "10s", "", "*/1 * * * *", "false") + + logrus.Info("Creating new standard user") + newStdUser, err := users.CreateUserWithRole(ur.client, users.UserConfig(), "user") + require.NoError(ur.T(), err) + userReLogin, err := auth.GetUserAfterLogin(ur.client, *newStdUser) + require.NoError(ur.T(), err) + assert.Equal(ur.T(), isActive, *(userReLogin).Enabled) + + logrus.Info("Getting initial bindings") + bindingsBefore, err := rbac.GetBindings(ur.client, newStdUser.ID) + require.NoError(ur.T(), err, "Failed to get initial bindings") + + logrus.Info("Polling user status") + pollUserStatus(ur.client, newStdUser.ID, isInActive) + + logrus.Info("Verifying user status after polling") + userReLogin, err = ur.client.WranglerContext.Mgmt.User().Get(userReLogin.Name, v1.GetOptions{}) + require.NoError(ur.T(), err) + assert.Equal(ur.T(), isInActive, *(userReLogin).Enabled) + + logrus.Info("Attempting login with disabled user") + _, err = auth.GetUserAfterLogin(ur.client, *newStdUser) + assert.ErrorContains(ur.T(), err, "403 Forbidden") + + logrus.Info("Getting final bindings") + bindingsAfter, err := rbac.GetBindings(ur.client, newStdUser.ID) + require.NoError(ur.T(), err, "Failed to get final bindings") + ur.assertBindingsEqual(bindingsBefore, bindingsAfter) +} + +func (ur *URDisableTestSuite) TestDisabledUserGetEnabled() { + logrus.Info("Setting up userretention settings") + setupUserRetentionSettings(ur.client, "10s", "", "*/1 * * * *", "false") + + logrus.Info("Creating new standard user") + newStdUser, err := users.CreateUserWithRole(ur.client, users.UserConfig(), "user") + require.NoError(ur.T(), err) + userReLogin, err := auth.GetUserAfterLogin(ur.client, *newStdUser) + require.NoError(ur.T(), err) + assert.Equal(ur.T(), isActive, *(userReLogin).Enabled) + + logrus.Info("Getting initial bindings") + bindingsBefore, err := rbac.GetBindings(ur.client, newStdUser.ID) + require.NoError(ur.T(), err, "Failed to get initial bindings") + + logrus.Info("Polling user status to disable") + pollUserStatus(ur.client, newStdUser.ID, isInActive) + + logrus.Info("Verifying user status after polling") + userReLogin, err = ur.client.WranglerContext.Mgmt.User().Get(userReLogin.Name, v1.GetOptions{}) + require.NoError(ur.T(), err) + assert.Equal(ur.T(), isInActive, *(userReLogin).Enabled) + + logrus.Info("Attempting login with disabled user") + _, err = auth.GetUserAfterLogin(ur.client, *newStdUser) + assert.ErrorContains(ur.T(), err, "403 Forbidden") + + logrus.Info("Enabling the disabled user") + enabled := true + userReLogin.Enabled = &enabled + activateUser, err := ur.client.WranglerContext.Mgmt.User().Update(userReLogin) + require.NoError(ur.T(), err) + assert.Equal(ur.T(), isActive, *(activateUser).Enabled) + + logrus.Info("Verifying user status after enabling") + activeUserReLogin, err := ur.client.WranglerContext.Mgmt.User().Get(activateUser.Name, v1.GetOptions{}) + require.NoError(ur.T(), err) + assert.Equal(ur.T(), isActive, *(activeUserReLogin).Enabled) + + logrus.Info("Getting final bindings") + bindingsAfterEnabled, err := rbac.GetBindings(ur.client, newStdUser.ID) + require.NoError(ur.T(), err, "Failed to get final bindings") + ur.assertBindingsEqual(bindingsBefore, bindingsAfterEnabled) +} + +func (ur *URDisableTestSuite) TestStandardUserDidNotGetDisabledWithBlankSettings() { + logrus.Info("Setting up userretention settings with blank values") + setupUserRetentionSettings(ur.client, "", "", "*/1 * * * *", "false") + + logrus.Info("Creating new standard user") + newUser, err := users.CreateUserWithRole(ur.client, users.UserConfig(), "user") + require.NoError(ur.T(), err) + userReLogin, err := auth.GetUserAfterLogin(ur.client, *newUser) + require.NoError(ur.T(), err) + assert.Equal(ur.T(), isActive, *(userReLogin).Enabled) + + logrus.Info("Waiting for default duration") + time.Sleep(defaultWaitDuration) + + logrus.Info("Attempting login after wait period") + userReLogin, err = auth.GetUserAfterLogin(ur.client, *newUser) + require.NoError(ur.T(), err) + assert.Equal(ur.T(), isActive, *(userReLogin).Enabled) +} + +func (ur *URDisableTestSuite) TestUserDisableByUpdatingUserattributes() { + logrus.Info("Setting up userretention settings") + setupUserRetentionSettings(ur.client, "10s", "", "*/1 * * * *", "false") + + logrus.Info("Creating new standard user") + newStdUser, err := users.CreateUserWithRole(ur.client, users.UserConfig(), "user") + require.NoError(ur.T(), err) + userReLogin, err := auth.GetUserAfterLogin(ur.client, *newStdUser) + require.NoError(ur.T(), err) + + logrus.Info("Getting initial bindings") + bindingsBefore, err := rbac.GetBindings(ur.client, newStdUser.ID) + require.NoError(ur.T(), err, "Failed to get initial bindings") + + logrus.Info("Updating user attributes") + userAttributes, err := ur.client.WranglerContext.Mgmt.UserAttribute().Get(newStdUser.ID, v1.GetOptions{}) + require.NoError(ur.T(), err) + userAttributes.DisableAfter = &v1.Duration{Duration: time.Second * 10} + _, err = ur.client.WranglerContext.Mgmt.UserAttribute().Update(userAttributes) + require.NoError(ur.T(), err) + + logrus.Info("Verifying user status after updating attributes") + userReLogin, err = ur.client.WranglerContext.Mgmt.User().Get(userReLogin.Name, v1.GetOptions{}) + assert.Equal(ur.T(), isActive, *(userReLogin).Enabled) + require.NoError(ur.T(), err) + + logrus.Info("Polling user status") + pollUserStatus(ur.client, newStdUser.ID, isInActive) + + logrus.Info("Verifying user status after polling") + userReLogin, err = ur.client.WranglerContext.Mgmt.User().Get(userReLogin.Name, v1.GetOptions{}) + require.NoError(ur.T(), err) + assert.Equal(ur.T(), isInActive, *(userReLogin).Enabled) + + logrus.Info("Attempting login with disabled user") + _, err = auth.GetUserAfterLogin(ur.client, *newStdUser) + assert.ErrorContains(ur.T(), err, "403 Forbidden") + + logrus.Info("Getting final bindings") + bindingsAfter, err := rbac.GetBindings(ur.client, newStdUser.ID) + require.NoError(ur.T(), err, "Failed to get final bindings") + ur.assertBindingsEqual(bindingsBefore, bindingsAfter) +} + +func (ur *URDisableTestSuite) TestStandardUserIsNotDisabledWithDryRun() { + logrus.Info("Setting up userretention settings with dry run") + setupUserRetentionSettings(ur.client, "10s", "", "*/1 * * * *", "true") + + logrus.Info("Creating new standard user") + newStdUser, err := users.CreateUserWithRole(ur.client, users.UserConfig(), "user") + require.NoError(ur.T(), err) + userReLogin, err := auth.GetUserAfterLogin(ur.client, *newStdUser) + require.NoError(ur.T(), err) + + logrus.Info("Getting initial bindings") + bindingsBefore, err := rbac.GetBindings(ur.client, newStdUser.ID) + require.NoError(ur.T(), err, "Failed to get initial bindings") + + logrus.Info("Updating user attributes") + userAttributes, err := ur.client.WranglerContext.Mgmt.UserAttribute().Get(newStdUser.ID, v1.GetOptions{}) + require.NoError(ur.T(), err) + userAttributes.DisableAfter = &v1.Duration{Duration: time.Second * 10} + _, err = ur.client.WranglerContext.Mgmt.UserAttribute().Update(userAttributes) + require.NoError(ur.T(), err) + + logrus.Info("Verifying user status after updating attributes") + userReLogin, err = ur.client.WranglerContext.Mgmt.User().Get(userReLogin.Name, v1.GetOptions{}) + assert.Equal(ur.T(), isActive, *(userReLogin).Enabled) + require.NoError(ur.T(), err) + + logrus.Info("Waiting for default duration") + time.Sleep(2 * defaultWaitDuration) + + logrus.Info("Attempting login after wait period") + userReLogin, err = ur.client.WranglerContext.Mgmt.User().Get(userReLogin.Name, v1.GetOptions{}) + require.NoError(ur.T(), err) + assert.Equal(ur.T(), isActive, *(userReLogin).Enabled) + + logrus.Info("Getting final bindings") + bindingsAfter, err := rbac.GetBindings(ur.client, newStdUser.ID) + require.NoError(ur.T(), err, "Failed to get final bindings") + ur.assertBindingsEqual(bindingsBefore, bindingsAfter) + + logrus.Info("userretention settings:dry run settings back to default value") + updateUserRetentionSettings(ur.client, userRetentionDryRun, defaultSettingValue, "false") +} + +func (ur *URDisableTestSuite) TestStandardUserGetDisabledWithDefaultValue() { + logrus.Info("Setting up userretention settings") + setupUserRetentionSettings(ur.client, "", "", "*/1 * * * *", "false") + logrus.Info("Update userretention settings with Default value") + updateUserRetentionSettings(ur.client, disableInactiveUserAfter, "10s", "") + + logrus.Info("Creating new standard user") + newStdUser, err := users.CreateUserWithRole(ur.client, users.UserConfig(), "user") + require.NoError(ur.T(), err) + userReLogin, err := auth.GetUserAfterLogin(ur.client, *newStdUser) + require.NoError(ur.T(), err) + assert.Equal(ur.T(), isActive, *(userReLogin).Enabled) + + logrus.Info("Getting initial bindings") + bindingsBefore, err := rbac.GetBindings(ur.client, newStdUser.ID) + require.NoError(ur.T(), err, "Failed to get initial bindings") + + logrus.Info("Polling user status") + pollUserStatus(ur.client, newStdUser.ID, isInActive) + + logrus.Info("Verifying user status after polling") + userReLogin, err = ur.client.WranglerContext.Mgmt.User().Get(userReLogin.Name, v1.GetOptions{}) + require.NoError(ur.T(), err) + assert.Equal(ur.T(), isInActive, *(userReLogin).Enabled) + + logrus.Info("Attempting login with disabled user") + _, err = auth.GetUserAfterLogin(ur.client, *newStdUser) + assert.ErrorContains(ur.T(), err, "403 Forbidden") + + logrus.Info("Getting final bindings") + bindingsAfter, err := rbac.GetBindings(ur.client, newStdUser.ID) + require.NoError(ur.T(), err, "Failed to get final bindings") + ur.assertBindingsEqual(bindingsBefore, bindingsAfter) +} + +func (ur *URDisableTestSuite) TestStandardUserGetDisabledWithDefaultValueIgnored() { + logrus.Info("Setting up userretention settings") + setupUserRetentionSettings(ur.client, "", "", "*/1 * * * *", "false") + logrus.Info("Update userretention settings with Default value") + updateUserRetentionSettings(ur.client, disableInactiveUserAfter, "20m", "10s") + + logrus.Info("Creating new standard user") + newStdUser, err := users.CreateUserWithRole(ur.client, users.UserConfig(), "user") + require.NoError(ur.T(), err) + userReLogin, err := auth.GetUserAfterLogin(ur.client, *newStdUser) + require.NoError(ur.T(), err) + assert.Equal(ur.T(), isActive, *(userReLogin).Enabled) + + logrus.Info("Getting initial bindings") + bindingsBefore, err := rbac.GetBindings(ur.client, newStdUser.ID) + require.NoError(ur.T(), err, "Failed to get initial bindings") + + logrus.Info("Polling user status") + pollUserStatus(ur.client, newStdUser.ID, isInActive) + + logrus.Info("Verifying user status after polling") + userReLogin, err = ur.client.WranglerContext.Mgmt.User().Get(userReLogin.Name, v1.GetOptions{}) + require.NoError(ur.T(), err) + assert.Equal(ur.T(), isInActive, *(userReLogin).Enabled) + + logrus.Info("Attempting login with disabled user") + _, err = auth.GetUserAfterLogin(ur.client, *newStdUser) + assert.ErrorContains(ur.T(), err, "403 Forbidden") + + logrus.Info("Getting final bindings") + bindingsAfter, err := rbac.GetBindings(ur.client, newStdUser.ID) + require.NoError(ur.T(), err, "Failed to get final bindings") + ur.assertBindingsEqual(bindingsBefore, bindingsAfter) +} + +func (ur *URDisableTestSuite) TestStandardUserDidNotGetDisabledWithDefaultValue() { + logrus.Info("Setting up userretention settings") + setupUserRetentionSettings(ur.client, "", "", "*/1 * * * *", "false") + logrus.Info("Update userretention settings with Default value") + updateUserRetentionSettings(ur.client, disableInactiveUserAfter, "10s", "20m") + + logrus.Info("Creating new standard user") + newStdUser, err := users.CreateUserWithRole(ur.client, users.UserConfig(), "user") + require.NoError(ur.T(), err) + userReLogin, err := auth.GetUserAfterLogin(ur.client, *newStdUser) + require.NoError(ur.T(), err) + assert.Equal(ur.T(), isActive, *(userReLogin).Enabled) + + logrus.Info("Getting initial bindings") + bindingsBefore, err := rbac.GetBindings(ur.client, newStdUser.ID) + require.NoError(ur.T(), err, "Failed to get initial bindings") + + logrus.Info("Waiting for default duration") + time.Sleep(2 * defaultWaitDuration) + + logrus.Info("Attempting login after wait period") + userReLogin, err = ur.client.WranglerContext.Mgmt.User().Get(userReLogin.Name, v1.GetOptions{}) + require.NoError(ur.T(), err) + assert.Equal(ur.T(), isActive, *(userReLogin).Enabled) + + logrus.Info("Getting final bindings") + bindingsAfter, err := rbac.GetBindings(ur.client, newStdUser.ID) + require.NoError(ur.T(), err, "Failed to get final bindings") + ur.assertBindingsEqual(bindingsBefore, bindingsAfter) +} + +func TestURDisableUserSuite(t *testing.T) { + suite.Run(t, new(URDisableTestSuite)) +} diff --git a/tests/v2/validation/auth/userretention/userretention_settings_test.go b/tests/v2/validation/auth/userretention/userretention_settings_test.go new file mode 100644 index 00000000000..c8107d70715 --- /dev/null +++ b/tests/v2/validation/auth/userretention/userretention_settings_test.go @@ -0,0 +1,337 @@ +//go:build (validation || infra.any || cluster.any || sanity) && !stress && !extended + +package userretention + +import ( + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/rancher/shepherd/clients/rancher" + "github.com/rancher/shepherd/pkg/session" + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + apierrors "k8s.io/apimachinery/pkg/api/errors" +) + +type UserRetentionSettingsTestSuite struct { + suite.Suite + client *rancher.Client + session *session.Session +} + +func (ur *UserRetentionSettingsTestSuite) SetupSuite() { + ur.session = session.NewSession() + client, err := rancher.NewClient("", ur.session) + require.NoError(ur.T(), err) + ur.client = client +} + +func (ur *UserRetentionSettingsTestSuite) TearDownSuite() { + ur.session.Cleanup() +} + +func (ur *UserRetentionSettingsTestSuite) testPositiveInputValues(settingName string, tests []struct { + defaultValue string + value string + description string +}) { + logrus.Infof("Updating %s settings with positive values:", settingName) + for _, test := range tests { + ur.T().Run(test.description, func(*testing.T) { + err := updateUserRetentionSettings(ur.client, settingName, test.defaultValue, test.value) + assert.NoError(ur.T(), err, "Unexpected error updating settings") + + if err == nil { + settings, err := ur.client.Management.Setting.ByID(settingName) + assert.NoError(ur.T(), err, "Failed to retrieve settings") + + if err == nil { + assert.Equal(ur.T(), settingName, settings.Name, "Setting name should match") + + expectedValue := test.value + if expectedValue == "" { + expectedValue = test.defaultValue + } + assert.Equal(ur.T(), expectedValue, settings.Value, "Setting value should match expected") + + if test.defaultValue != "" { + assert.Equal(ur.T(), test.defaultValue, settings.Default, "Default value should match when provided") + } else { + assert.Empty(ur.T(), settings.Default, "Default value should be empty when not provided") + } + + logrus.Infof("Setting updated - Name: %s, Default: %s, Value: %s", + settings.Name, settings.Default, settings.Value) + } + } + + logrus.Infof("Test completed: %s", test.description) + }) + } +} +func (ur *UserRetentionSettingsTestSuite) testNegativeInputValues(settingName string, tests []struct { + defaultValue string + value string + description string +}) { + logrus.Infof("Updating %s settings with negative values:", settingName) + for _, test := range tests { + ur.T().Run(test.description, func(*testing.T) { + + initialSettings, getErr := ur.client.Management.Setting.ByID(settingName) + assert.NoError(ur.T(), getErr, "Failed to retrieve initial settings") + + err := updateUserRetentionSettings(ur.client, settingName, test.defaultValue, test.value) + assert.Error(ur.T(), err, "Expected an error for input '%s', but got nil", test.value) + + if err != nil { + ur.validateError(err, test.description) + + updatedSettings, getErr := ur.client.Management.Setting.ByID(settingName) + assert.NoError(ur.T(), getErr, "Failed to retrieve updated settings") + + if getErr == nil { + assert.NotEqual(ur.T(), test.value, updatedSettings.Value, "Value should not be updated for invalid input") + + if initialSettings.Default != updatedSettings.Default { + logrus.Warnf("Default value changed from %s to %s for invalid input", initialSettings.Default, updatedSettings.Default) + } + + assert.NotEqual(ur.T(), test.value, updatedSettings.Value, "Value should not be updated to invalid input") + } + + logrus.Infof("Failed to update %s settings as expected. Error: %v", settingName, err) + } + }) + } +} + +func (ur *UserRetentionSettingsTestSuite) validateError(err error, expectedDescription string) { + var statusErr *apierrors.StatusError + var found bool + + switch e := err.(type) { + case interface{ Unwrap() error }: + if innerErr := e.Unwrap(); innerErr != nil { + if innerWrapper, ok := innerErr.(interface{ Unwrap() error }); ok { + if deepestErr := innerWrapper.Unwrap(); deepestErr != nil { + statusErr, found = deepestErr.(*apierrors.StatusError) + } + } + } + } + + if found && statusErr != nil { + assert.Equal(ur.T(), int32(400), statusErr.ErrStatus.Code, "Status code should be 400") + assert.Equal(ur.T(), metav1.StatusReasonBadRequest, statusErr.ErrStatus.Reason, "Reason should be BadRequest") + assert.Contains(ur.T(), statusErr.ErrStatus.Message, expectedDescription, "Error should contain the expected description") + } else { + errMsg := err.Error() + assert.Contains(ur.T(), errMsg, "denied the request", "Error should mention denied request") + assert.Contains(ur.T(), errMsg, expectedDescription, "Error should contain the expected description") + } +} + +func (ur *UserRetentionSettingsTestSuite) validateSettingsNotUpdated(settingName, inputValue string) { + settings, err := ur.client.Management.Setting.ByID(settingName) + if assert.NoError(ur.T(), err, "Failed to retrieve settings") { + assert.Equal(ur.T(), settingName, settings.Name) + assert.NotEqual(ur.T(), defaultSettingValue, settings.Default) + assert.NotEqual(ur.T(), inputValue, settings.Value) + } +} + +func (ur *UserRetentionSettingsTestSuite) TestUpdateSettingsForDisableUserWithPositiveInputValues() { + tests := []struct { + defaultValue string + value string + description string + }{ + {"", "", "No action - users will not be deactivated"}, + {"", "0s", "Users will be deactivated after 0s"}, + {"", "0m", "Users will be deactivated after 0m"}, + {"", "0h", "Users will be deactivated after 0h"}, + {"", "10s", "Users will be deactivated after 10s"}, + {"", "10m", "Users will be deactivated after 10m"}, + {"", "20h", "Users will be deactivated after 20h"}, + {"", "10000s", "Users will be deactivated after 10000s"}, + {"", "10000m", "Users will be deactivated after 10000m"}, + {"", "10000h", "Users will be deactivated after 10000h"}, + {"", "", "No action - users will not be deactivated"}, + {"0s", "", "Users will be deactivated after 0s"}, + {"0m", "", "Users will be deactivated after 0m"}, + {"0h", "", "Users will be deactivated after 0h"}, + {"10s", "", "Users will be deactivated after 10s"}, + {"10m", "", "Users will be deactivated after 10m"}, + {"20h", "", "Users will be deactivated after 20h"}, + {"10000s", "", "Users will be deactivated after 10000s"}, + {"10000m", "", "Users will be deactivated after 10000m"}, + {"10000h", "", "Users will be deactivated after 10000h"}, + {"20h", "20m", "Users will be deactivated after 20m"}, + {"20m", "20h", "Users will be deactivated after 20h"}, + } + setupUserRetentionSettings(ur.client, "", "", "", "") + ur.testPositiveInputValues(disableInactiveUserAfter, tests) +} + +func (ur *UserRetentionSettingsTestSuite) TestUpdateSettingsForDisableInactiveUserAfterWithNegativeInputValues() { + tests := []struct { + defaultValue string + value string + description string + }{ + {"", "10", "Invalid value: \"10\": time: missing unit in duration \"10\""}, + {"", "10S", "Invalid value: \"10S\": time: unknown unit \"S\" in duration \"10S\""}, + {"", "10M", "Invalid value: \"10M\": time: unknown unit \"M\" in duration \"10M\""}, + {"", "10H", "Invalid value: \"10H\": time: unknown unit \"H\" in duration \"10H\""}, + {"", "10sec", "Invalid value: \"10sec\": time: unknown unit \"sec\" in duration \"10sec\""}, + {"", "10min", "Invalid value: \"10min\": time: unknown unit \"min\" in duration \"10min\""}, + {"", "20hour", "Invalid value: \"20hour\": time: unknown unit \"hour\" in duration \"20hour\""}, + {"", "1d", "Invalid value: \"1d\": time: unknown unit \"d\" in duration \"1d\""}, + {"", "-20m", "Invalid value: \"-20m\": negative duration"}, + {"", "tens", "Invalid value: \"tens\": time: invalid duration \"tens\""}, + // {"10", "", "Invalid value: \"10\": time: missing unit in duration \"10\""}, + // {"10S", "", "Invalid value: \"10S\": time: unknown unit \"S\" in duration \"10S\""}, + // {"10M", "", "Invalid value: \"10M\": time: unknown unit \"M\" in duration \"10M\""}, + // {"10H", "", "Invalid value: \"10H\": time: unknown unit \"H\" in duration \"10H\""}, + // {"10sec", "", "Invalid value: \"10sec\": time: unknown unit \"sec\" in duration \"10sec\""}, + // {"10min", "", "Invalid value: \"10min\": time: unknown unit \"min\" in duration \"10min\""}, + // {"20hour", "", "Invalid value: \"20hour\": time: unknown unit \"hour\" in duration \"20hour\""}, + // {"1d", "", "Invalid value: \"1d\": time: unknown unit \"d\" in duration \"1d\""}, + // {"-20m", "", "Invalid value: \"-20m\": negative duration"}, + // {"tens", "", "Invalid value: \"tens\": time: invalid duration \"tens\""}, + // {"-20m", "1d", "Invalid value: \"-20m\": negative duration"}, + // {"", "-20m", "Invalid value: \"-20m\": negative duration"}, + // {"1d", "-20m", "Invalid value: \"1d\": time: unknown unit \"d\" in duration \"1d\""}, + } + ur.testNegativeInputValues(disableInactiveUserAfter, tests) + setupUserRetentionSettings(ur.client, "", "", "", "false") +} + +func (ur *UserRetentionSettingsTestSuite) TestUpdateSettingsForDeleteInactiveUserAfterWithPositiveInputValues() { + tests := []struct { + defaultValue string + value string + description string + }{ + {"", "", "No action - users will not be deleted"}, + {"", "100000000s", "Users will delete after 100000000s"}, + {"", "200000m", "Users will delete after 200000m"}, + {"", "10000h", "Users will delete after 10000h"}, + {"100000000s", "", "Users will delete after 100000000s"}, + {"200000m", "", "Users will delete after 200000m"}, + {"10000h", "", "Users will delete after 10000h"}, + {"10000h", "200000m", "Users will delete after 200000m"}, + {"200000m", "10000h", "Users will delete after 10000h"}, + } + ur.testPositiveInputValues(deleteInactiveUserAfter, tests) + setupUserRetentionSettings(ur.client, "", "", "", "false") +} + +func (ur *UserRetentionSettingsTestSuite) TestUpdateSettingsForDeleteInactiveUserAfterWithNegativeInputValues() { + tests := []struct { + defaultValue string + value string + description string + }{ + {"", "10", "Invalid value: \"10\": time: missing unit in duration \"10\""}, + {"", "10s", "Invalid value: \"10s\": must be at least 336h0m0s"}, + {"", "10m", "Invalid value: \"10m\": must be at least 336h0m0s"}, + {"", "10h", "Invalid value: \"10h\": must be at least 336h0m0s"}, + {"", "10S", "Invalid value: \"10S\": time: unknown unit \"S\" in duration \"10S\""}, + {"", "10M", "Invalid value: \"10M\": time: unknown unit \"M\" in duration \"10M\""}, + {"", "10H", "Invalid value: \"10H\": time: unknown unit \"H\" in duration \"10H\""}, + {"", "10sec", "Invalid value: \"10sec\": time: unknown unit \"sec\" in duration \"10sec\""}, + {"", "10min", "Invalid value: \"10min\": time: unknown unit \"min\" in duration \"10min\""}, + {"", "20hour", "Invalid value: \"20hour\": time: unknown unit \"hour\" in duration \"20hour\""}, + {"", "1d", "Invalid value: \"1d\": time: unknown unit \"d\" in duration \"1d\""}, + {"", "-20m", "Invalid value: \"-20m\": negative duration"}, + // {"10", "", "Invalid value: \"10\": time: missing unit in duration \"10\""}, + // {"10s", "", "Invalid value: \"10s\": must be at least 336h0m0s"}, + // {"10m", "", "Invalid value: \"10m\": must be at least 336h0m0s"}, + // {"10h", "", "Invalid value: \"10h\": must be at least 336h0m0s"}, + // {"10S", "", "Invalid value: \"10S\": time: unknown unit \"S\" in duration \"10S\""}, + // {"10M", "", "Invalid value: \"10M\": time: unknown unit \"M\" in duration \"10M\""}, + // {"10H", "", "Invalid value: \"10H\": time: unknown unit \"H\" in duration \"10H\""}, + // {"10sec", "", "Invalid value: \"10sec\": time: unknown unit \"sec\" in duration \"10sec\""}, + // {"10min", "", "Invalid value: \"10min\": time: unknown unit \"min\" in duration \"10min\""}, + // {"20hour", "", "Invalid value: \"20hour\": time: unknown unit \"hour\" in duration \"20hour\""}, + // {"1d", "", "Invalid value: \"1d\": time: unknown unit \"d\" in duration \"1d\""}, + // {"-20m", "", "Invalid value: \"-20m\": negative duration"}, + // {"-20m", "10000h", "Invalid value: \"-20m\": negative duration"}, + // {"10000h", "-20m", "Invalid value: \"-20m\": negative duration"}, + // {"-20m", "20m", "Invalid value: \"-20m\": negative duration"}, + } + ur.testNegativeInputValues(deleteInactiveUserAfter, tests) + setupUserRetentionSettings(ur.client, "", "", "", "false") +} + +func (ur *UserRetentionSettingsTestSuite) TestUpdateSettingsForUserRetentionCronWithPositiveInputValues() { + tests := []struct { + defaultValue string + value string + description string + }{ + {"", "0 * * * *", "every 1 hour"}, + {"", "0 0 * * *", "every 1 day"}, + {"", "*/5 * * * *", "every 5 mins"}, + {"", "*/1 * * * *", "every min"}, + {"", "* * * * *", "every min"}, + {"", "30/1 * * * *", "every 30 sec"}, + {"", "0-5 14 * * *", "every minute starting at 2:00 PM and ending at 2:05 PM, every day"}, + {"", "0 0 1,2 * *", "at midnight of 1st, 2nd day of each month"}, + {"", "0 0 1,2 * 3", "at midnight of 1st, 2nd day of each month, and each Wednesday"}, + {"0 * * * *", "", "every 1 hour"}, + {"0 0 * * *", "", "every 1 day"}, + {"*/5 * * * *", "", "every 5 mins"}, + {"*/1 * * * *", "", "every min"}, + {"* * * * *", "", "every min"}, + {"30/1 * * * *", "", "every 30 sec"}, + {"0-5 14 * * *", "", "every minute starting at 2:00 PM and ending at 2:05 PM, every day"}, + {"0 0 1,2 * *", "", "at midnight of 1st, 2nd day of each month"}, + {"0 0 1,2 * 3", "", "at midnight of 1st, 2nd day of each month, and each Wednesday"}, + {"* * * * *", "30/1 * * * *", "every 30 sec"}, + {"30/1 * * * *", "* * * * *", "every min"}, + } + ur.testPositiveInputValues(userRetentionCron, tests) + setupUserRetentionSettings(ur.client, "", "", "", "false") +} + +func (ur *UserRetentionSettingsTestSuite) TestUpdateSettingsForUserRetentionCronWithNegativeInputValues() { + tests := []struct { + defaultValue string + value string + description string + }{ + {"", "* * * * * *", "Invalid value: \"* * * * * *\": Expected exactly 5 fields, found 6: * * * * * *"}, + {"", "*/-1 * * * *", "Invalid value: \"*/-1 * * * *\": Negative number (-1) not allowed: -1"}, + {"", "60/1 * * * *", "Invalid value: \"60/1 * * * *\": Beginning of range (60) beyond end of range (59): 60/1"}, + {"", "-30/1 * * * *", "Invalid value: \"-30/1 * * * *\": Failed to parse int from : strconv.Atoi: parsing \"\": invalid syntax"}, + {"", "(*/1) * * * *", "Invalid value: \"(*/1) * * * *\": Failed to parse int from (*: strconv.Atoi: parsing \"(*\": invalid syntax"}, + {"", "10min", "Invalid value: \"10min\": Expected exactly 5 fields, found 1: 10min"}, + {"", "* * * * * */2", "Invalid value: \"* * * * * */2\": Expected exactly 5 fields, found 6: * * * * * */2"}, + {"", "1d", "Invalid value: \"1d\": Expected exactly 5 fields, found 1: 1d"}, + {"", "-20m", "Invalid value: \"-20m\": Expected exactly 5 fields, found 1: -20m"}, + // {"* * * * * *", "", "Invalid value: \"* * * * * *\": Expected exactly 5 fields, found 6: * * * * * *"}, + // {"*/-1 * * * *", "", "Invalid value: \"*/-1 * * * *\": Negative number (-1) not allowed: -1"}, + // {"60/1 * * * *", "", "Invalid value: \"60/1 * * * *\": Beginning of range (60) beyond end of range (59): 60/1"}, + // {"-30/1 * * * *", "", "Invalid value: \"-30/1 * * * *\": Failed to parse int from : strconv.Atoi: parsing \"\": invalid syntax"}, + // {"(*/1) * * * *", "", "Invalid value: \"(*/1) * * * *\": Failed to parse int from (*: strconv.Atoi: parsing \"(*\": invalid syntax"}, + // {"10min", "", "Invalid value: \"10min\": Expected exactly 5 fields, found 1: 10min"}, + // {"* * * * * */2", "", "Invalid value: \"* * * * * */2\": Expected exactly 5 fields, found 6: * * * * * */2"}, + // {"1d", "", "Invalid value: \"1d\": Expected exactly 5 fields, found 1: 1d"}, + // {"-20m", "", "Invalid value: \"-20m\": Expected exactly 5 fields, found 1: -20m"}, + // {"1d", "1d", "Invalid value: \"1d\": Expected exactly 5 fields, found 1: 1d"}, + // {"0 * * * *", "", "Invalid value: \"1d\": Expected exactly 5 fields, found 1: 1d"}, + // {"", "0 * * * *", "Invalid value: \"1d\": Expected exactly 5 fields, found 1: 1d"}, + } + ur.testNegativeInputValues(userRetentionCron, tests) + setupUserRetentionSettings(ur.client, "", "", "", "false") +} + +func TestUserRetentionSettingsSuite(t *testing.T) { + suite.Run(t, new(UserRetentionSettingsTestSuite)) +}