Adding options to user cli
User options [1] can be set by making POST and PATCH request for /v3/users API calls but cannot by openstack CLI because of no user options defined in create and update user CLI [2]. This patch adds the user options [1] in create user and update user CLI. [1] https://docs.openstack.org/keystone/latest/admin/resource-options.html#multi-factor-auth-rules [2] https://docs.openstack.org/api-ref/identity/v3/#create-user Change-Id: I4e41bae2e8cfbe92d52b14d856991bedcd44164f
This commit is contained in:
		| @@ -19,6 +19,12 @@ Create new user | ||||
|         [--password-prompt] | ||||
|         [--email <email-address>] | ||||
|         [--description <description>] | ||||
|         [--multi-factor-auth-rule <rule>] | ||||
|         [--ignore-lockout-failure-attempts| --no-ignore-lockout-failure-attempts] | ||||
|         [--ignore-password-expiry| --no-ignore-password-expiry] | ||||
|         [--ignore-change-password-upon-first-use| --no-ignore-change-password-upon-first-use] | ||||
|         [--enable-lock-password| --disable-lock-password] | ||||
|         [--enable-multi-factor-auth| --disable-multi-factor-auth] | ||||
|         [--enable | --disable] | ||||
|         [--or-show] | ||||
|         <user-name> | ||||
| @@ -56,6 +62,63 @@ Create new user | ||||
|  | ||||
|     .. versionadded:: 3 | ||||
|  | ||||
| .. option:: --ignore-lockout-failure-attempts | ||||
|  | ||||
|     Opt into ignoring the number of times a user has authenticated and | ||||
|     locking out the user as a result | ||||
|  | ||||
| .. option:: --no-ignore-lockout-failure-attempts | ||||
|  | ||||
|     Opt out of ignoring the number of times a user has authenticated | ||||
|     and locking out the user as a result | ||||
|  | ||||
| .. option:: --ignore-change-password-upon-first-use | ||||
|  | ||||
|     Control if a user should be forced to change their password immediately | ||||
|     after they log into keystone for the first time. Opt into ignoring | ||||
|     the user to change their password during first time login in keystone. | ||||
|  | ||||
| .. option:: --no-ignore-change-password-upon-first-use | ||||
|  | ||||
|     Control if a user should be forced to change their password immediately | ||||
|     after they log into keystone for the first time. Opt out of ignoring | ||||
|     the user to change their password during first time login in keystone. | ||||
|  | ||||
| .. option:: --ignore-password-expiry | ||||
|  | ||||
|     Opt into allowing user to continue using passwords that may be | ||||
|     expired | ||||
|  | ||||
| .. option:: --no-ignore-password-expiry | ||||
|  | ||||
|     Opt out of allowing user to continue using passwords that may be | ||||
|     expired | ||||
|  | ||||
| .. option:: --enable-lock-password | ||||
|  | ||||
|     Disables the ability for a user to change its password through | ||||
|     self-service APIs | ||||
|  | ||||
| .. option:: --disable-lock-password | ||||
|  | ||||
|     Enables the ability for a user to change its password through | ||||
|     self-service APIs | ||||
|  | ||||
| .. option:: --enable-multi-factor-auth | ||||
|  | ||||
|     Enables the MFA (Multi Factor Auth) | ||||
|  | ||||
| .. option:: --disable-multi-factor-auth | ||||
|  | ||||
|     Disables the MFA (Multi Factor Auth) | ||||
|  | ||||
| .. option:: --multi-factor-auth-rule <rule> | ||||
|  | ||||
|     Set multi-factor auth rules. For example, to set a rule requiring the | ||||
|     "password" and "totp" auth methods to be provided, | ||||
|     use: "--multi-factor-auth-rule password,totp". | ||||
|     May be provided multiple times to set different rule combinations. | ||||
|  | ||||
| .. option:: --enable | ||||
|  | ||||
|     Enable user (default) | ||||
| @@ -146,6 +209,12 @@ Set user properties | ||||
|         [--password-prompt] | ||||
|         [--email <email-address>] | ||||
|         [--description <description>] | ||||
|         [--multi-factor-auth-rule <rule>] | ||||
|         [--ignore-lockout-failure-attempts| --no-ignore-lockout-failure-attempts] | ||||
|         [--ignore-password-expiry| --no-ignore-password-expiry] | ||||
|         [--ignore-change-password-upon-first-use| --no-ignore-change-password-upon-first-use] | ||||
|         [--enable-lock-password| --disable-lock-password] | ||||
|         [--enable-multi-factor-auth| --disable-multi-factor-auth] | ||||
|         [--enable|--disable] | ||||
|         <user> | ||||
|  | ||||
| @@ -187,6 +256,63 @@ Set user properties | ||||
|  | ||||
|     .. versionadded:: 3 | ||||
|  | ||||
| .. option:: --ignore-lockout-failure-attempts | ||||
|  | ||||
|     Opt into ignoring the number of times a user has authenticated and | ||||
|     locking out the user as a result | ||||
|  | ||||
| .. option:: --no-ignore-lockout-failure-attempts | ||||
|  | ||||
|     Opt out of ignoring the number of times a user has authenticated | ||||
|     and locking out the user as a result | ||||
|  | ||||
| .. option:: --ignore-change-password-upon-first-use | ||||
|  | ||||
|     Control if a user should be forced to change their password immediately | ||||
|     after they log into keystone for the first time. Opt into ignoring | ||||
|     the user to change their password during first time login in keystone. | ||||
|  | ||||
| .. option:: --no-ignore-change-password-upon-first-use | ||||
|  | ||||
|     Control if a user should be forced to change their password immediately | ||||
|     after they log into keystone for the first time. Opt out of ignoring | ||||
|     the user to change their password during first time login in keystone. | ||||
|  | ||||
| .. option:: --ignore-password-expiry | ||||
|  | ||||
|     Opt into allowing user to continue using passwords that may be | ||||
|     expired | ||||
|  | ||||
| .. option:: --no-ignore-password-expiry | ||||
|  | ||||
|     Opt out of allowing user to continue using passwords that may be | ||||
|     expired | ||||
|  | ||||
| .. option:: --enable-lock-password | ||||
|  | ||||
|     Disables the ability for a user to change its password through | ||||
|     self-service APIs | ||||
|  | ||||
| .. option:: --disable-lock-password | ||||
|  | ||||
|     Enables the ability for a user to change its password through | ||||
|     self-service APIs | ||||
|  | ||||
| .. option:: --enable-multi-factor-auth | ||||
|  | ||||
|     Enables the MFA (Multi Factor Auth) | ||||
|  | ||||
| .. option:: --disable-multi-factor-auth | ||||
|  | ||||
|     Disables the MFA (Multi Factor Auth) | ||||
|  | ||||
| .. option:: --multi-factor-auth-rule <rule> | ||||
|  | ||||
|     Set multi-factor auth rules. For example, to set a rule requiring the | ||||
|     "password" and "totp" auth methods to be provided, | ||||
|     use: "--multi-factor-auth-rule password,totp". | ||||
|     May be provided multiple times to set different rule combinations. | ||||
|  | ||||
| .. option:: --enable | ||||
|  | ||||
|     Enable user (default) | ||||
|   | ||||
| @@ -30,6 +30,114 @@ from openstackclient.identity import common | ||||
| LOG = logging.getLogger(__name__) | ||||
|  | ||||
|  | ||||
| def _get_options_for_user(identity_client, parsed_args): | ||||
|     options = {} | ||||
|     if parsed_args.ignore_lockout_failure_attempts: | ||||
|         options['ignore_lockout_failure_attempts'] = True | ||||
|     if parsed_args.no_ignore_lockout_failure_attempts: | ||||
|         options['ignore_lockout_failure_attempts'] = False | ||||
|     if parsed_args.ignore_password_expiry: | ||||
|         options['ignore_password_expiry'] = True | ||||
|     if parsed_args.no_ignore_password_expiry: | ||||
|         options['ignore_password_expiry'] = False | ||||
|     if parsed_args.ignore_change_password_upon_first_use: | ||||
|         options['ignore_change_password_upon_first_use'] = True | ||||
|     if parsed_args.no_ignore_change_password_upon_first_use: | ||||
|         options['ignore_change_password_upon_first_use'] = False | ||||
|     if parsed_args.enable_lock_password: | ||||
|         options['lock_password'] = True | ||||
|     if parsed_args.disable_lock_password: | ||||
|         options['lock_password'] = False | ||||
|     if parsed_args.enable_multi_factor_auth: | ||||
|         options['multi_factor_auth_enabled'] = True | ||||
|     if parsed_args.disable_multi_factor_auth: | ||||
|         options['multi_factor_auth_enabled'] = False | ||||
|     if parsed_args.multi_factor_auth_rule: | ||||
|         auth_rules = [rule.split(",") for rule in | ||||
|                       parsed_args.multi_factor_auth_rule] | ||||
|         if auth_rules: | ||||
|             options['multi_factor_auth_rules'] = auth_rules | ||||
|     return options | ||||
|  | ||||
|  | ||||
| def _add_user_options(parser): | ||||
|     # Add additional user options | ||||
|  | ||||
|     parser.add_argument( | ||||
|         '--ignore-lockout-failure-attempts', | ||||
|         action="store_true", | ||||
|         help=_('Opt into ignoring the number of times a user has ' | ||||
|                'authenticated and locking out the user as a result'), | ||||
|     ) | ||||
|     parser.add_argument( | ||||
|         '--no-ignore-lockout-failure-attempts', | ||||
|         action="store_true", | ||||
|         help=_('Opt out of ignoring the number of times a user has ' | ||||
|                'authenticated and locking out the user as a result'), | ||||
|     ) | ||||
|     parser.add_argument( | ||||
|         '--ignore-password-expiry', | ||||
|         action="store_true", | ||||
|         help=_('Opt into allowing user to continue using passwords that ' | ||||
|                'may be expired'), | ||||
|     ) | ||||
|     parser.add_argument( | ||||
|         '--no-ignore-password-expiry', | ||||
|         action="store_true", | ||||
|         help=_('Opt out of allowing user to continue using passwords ' | ||||
|                'that may be expired'), | ||||
|     ) | ||||
|     parser.add_argument( | ||||
|         '--ignore-change-password-upon-first-use', | ||||
|         action="store_true", | ||||
|         help=_('Control if a user should be forced to change their password ' | ||||
|                'immediately after they log into keystone for the first time. ' | ||||
|                'Opt into ignoring the user to change their password during ' | ||||
|                'first time login in keystone'), | ||||
|     ) | ||||
|     parser.add_argument( | ||||
|         '--no-ignore-change-password-upon-first-use', | ||||
|         action="store_true", | ||||
|         help=_('Control if a user should be forced to change their password ' | ||||
|                'immediately after they log into keystone for the first time. ' | ||||
|                'Opt out of ignoring the user to change their password during ' | ||||
|                'first time login in keystone'), | ||||
|     ) | ||||
|     parser.add_argument( | ||||
|         '--enable-lock-password', | ||||
|         action="store_true", | ||||
|         help=_('Disables the ability for a user to change its password ' | ||||
|                'through self-service APIs'), | ||||
|     ) | ||||
|     parser.add_argument( | ||||
|         '--disable-lock-password', | ||||
|         action="store_true", | ||||
|         help=_('Enables the ability for a user to change its password ' | ||||
|                'through self-service APIs'), | ||||
|     ) | ||||
|     parser.add_argument( | ||||
|         '--enable-multi-factor-auth', | ||||
|         action="store_true", | ||||
|         help=_('Enables the MFA (Multi Factor Auth)'), | ||||
|     ) | ||||
|     parser.add_argument( | ||||
|         '--disable-multi-factor-auth', | ||||
|         action="store_true", | ||||
|         help=_('Disables the MFA (Multi Factor Auth)'), | ||||
|     ) | ||||
|     parser.add_argument( | ||||
|         '--multi-factor-auth-rule', | ||||
|         metavar='<rule>', | ||||
|         action="append", | ||||
|         default=[], | ||||
|         help=_('Set multi-factor auth rules. For example, to set a rule ' | ||||
|                'requiring the "password" and "totp" auth methods to be ' | ||||
|                'provided, use: "--multi-factor-auth-rule password,totp". ' | ||||
|                'May be provided multiple times to set different rule ' | ||||
|                'combinations.') | ||||
|     ) | ||||
|  | ||||
|  | ||||
| class CreateUser(command.ShowOne): | ||||
|     _description = _("Create new user") | ||||
|  | ||||
| @@ -72,6 +180,8 @@ class CreateUser(command.ShowOne): | ||||
|             metavar='<description>', | ||||
|             help=_('User description'), | ||||
|         ) | ||||
|         _add_user_options(parser) | ||||
|  | ||||
|         enable_group = parser.add_mutually_exclusive_group() | ||||
|         enable_group.add_argument( | ||||
|             '--enable', | ||||
| @@ -113,6 +223,7 @@ class CreateUser(command.ShowOne): | ||||
|         if not parsed_args.password: | ||||
|             LOG.warning(_("No password was supplied, authentication will fail " | ||||
|                           "when a user does not have a password.")) | ||||
|         options = _get_options_for_user(identity_client, parsed_args) | ||||
|  | ||||
|         try: | ||||
|             user = identity_client.users.create( | ||||
| @@ -122,7 +233,8 @@ class CreateUser(command.ShowOne): | ||||
|                 password=parsed_args.password, | ||||
|                 email=parsed_args.email, | ||||
|                 description=parsed_args.description, | ||||
|                 enabled=enabled | ||||
|                 enabled=enabled, | ||||
|                 options=options, | ||||
|             ) | ||||
|         except ks_exc.Conflict: | ||||
|             if parsed_args.or_show: | ||||
| @@ -333,6 +445,8 @@ class SetUser(command.Command): | ||||
|             metavar='<description>', | ||||
|             help=_('Set user description'), | ||||
|         ) | ||||
|         _add_user_options(parser) | ||||
|  | ||||
|         enable_group = parser.add_mutually_exclusive_group() | ||||
|         enable_group.add_argument( | ||||
|             '--enable', | ||||
| @@ -390,6 +504,10 @@ class SetUser(command.Command): | ||||
|         if parsed_args.disable: | ||||
|             kwargs['enabled'] = False | ||||
|  | ||||
|         options = _get_options_for_user(identity_client, parsed_args) | ||||
|         if options: | ||||
|             kwargs['options'] = options | ||||
|  | ||||
|         identity_client.users.update(user.id, **kwargs) | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -108,6 +108,9 @@ MAPPING_RESPONSE_2 = { | ||||
|     "rules": MAPPING_RULES_2 | ||||
| } | ||||
|  | ||||
| mfa_opt1 = 'password,totp' | ||||
| mfa_opt2 = 'password' | ||||
|  | ||||
| project_id = '8-9-64' | ||||
| project_name = 'beatles' | ||||
| project_description = 'Fab Four' | ||||
|   | ||||
| @@ -111,6 +111,7 @@ class TestUserCreate(TestUser): | ||||
|             'description': None, | ||||
|             'domain': None, | ||||
|             'email': None, | ||||
|             'options': {}, | ||||
|             'enabled': True, | ||||
|             'password': None, | ||||
|         } | ||||
| @@ -150,6 +151,7 @@ class TestUserCreate(TestUser): | ||||
|             'description': None, | ||||
|             'domain': None, | ||||
|             'email': None, | ||||
|             'options': {}, | ||||
|             'enabled': True, | ||||
|             'password': 'secret', | ||||
|         } | ||||
| @@ -190,6 +192,7 @@ class TestUserCreate(TestUser): | ||||
|             'description': None, | ||||
|             'domain': None, | ||||
|             'email': None, | ||||
|             'options': {}, | ||||
|             'enabled': True, | ||||
|             'password': 'abc123', | ||||
|         } | ||||
| @@ -228,6 +231,7 @@ class TestUserCreate(TestUser): | ||||
|             'domain': None, | ||||
|             'email': 'barney@example.com', | ||||
|             'enabled': True, | ||||
|             'options': {}, | ||||
|             'password': None, | ||||
|         } | ||||
|         # UserManager.create(name=, domain=, project=, password=, email=, | ||||
| @@ -265,6 +269,7 @@ class TestUserCreate(TestUser): | ||||
|             'domain': None, | ||||
|             'email': None, | ||||
|             'enabled': True, | ||||
|             'options': {}, | ||||
|             'password': None, | ||||
|         } | ||||
|         # UserManager.create(name=, domain=, project=, password=, email=, | ||||
| @@ -311,6 +316,7 @@ class TestUserCreate(TestUser): | ||||
|             'description': None, | ||||
|             'domain': None, | ||||
|             'email': None, | ||||
|             'options': {}, | ||||
|             'enabled': True, | ||||
|             'password': None, | ||||
|         } | ||||
| @@ -356,6 +362,7 @@ class TestUserCreate(TestUser): | ||||
|             'description': None, | ||||
|             'domain': self.domain.id, | ||||
|             'email': None, | ||||
|             'options': {}, | ||||
|             'enabled': True, | ||||
|             'password': None, | ||||
|         } | ||||
| @@ -392,6 +399,7 @@ class TestUserCreate(TestUser): | ||||
|             'description': None, | ||||
|             'domain': None, | ||||
|             'email': None, | ||||
|             'options': {}, | ||||
|             'enabled': True, | ||||
|             'password': None, | ||||
|         } | ||||
| @@ -428,6 +436,7 @@ class TestUserCreate(TestUser): | ||||
|             'description': None, | ||||
|             'domain': None, | ||||
|             'email': None, | ||||
|             'options': {}, | ||||
|             'enabled': False, | ||||
|             'password': None, | ||||
|         } | ||||
| @@ -438,6 +447,471 @@ class TestUserCreate(TestUser): | ||||
|         self.assertEqual(self.columns, columns) | ||||
|         self.assertEqual(self.datalist, data) | ||||
|  | ||||
|     def test_user_create_ignore_lockout_failure_attempts(self): | ||||
|         arglist = [ | ||||
|             '--ignore-lockout-failure-attempts', | ||||
|             self.user.name, | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('ignore_lockout_failure_attempts', True), | ||||
|             ('enable', False), | ||||
|             ('disable', False), | ||||
|             ('name', self.user.name), | ||||
|         ] | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         # In base command class ShowOne in cliff, abstract method take_action() | ||||
|         # returns a two-part tuple with a tuple of column names and a tuple of | ||||
|         # data to be shown. | ||||
|         columns, data = self.cmd.take_action(parsed_args) | ||||
|  | ||||
|         # Set expected values | ||||
|         kwargs = { | ||||
|             'name': self.user.name, | ||||
|             'default_project': None, | ||||
|             'description': None, | ||||
|             'domain': None, | ||||
|             'email': None, | ||||
|             'enabled': True, | ||||
|             'options': {'ignore_lockout_failure_attempts': True}, | ||||
|             'password': None, | ||||
|         } | ||||
|         # UserManager.create(name=, domain=, project=, password=, email=, | ||||
|         #   description=, enabled=, default_project=) | ||||
|         self.users_mock.create.assert_called_with( | ||||
|             **kwargs | ||||
|         ) | ||||
|  | ||||
|         self.assertEqual(self.columns, columns) | ||||
|         self.assertEqual(self.datalist, data) | ||||
|  | ||||
|     def test_user_create_no_ignore_lockout_failure_attempts(self): | ||||
|         arglist = [ | ||||
|             '--no-ignore-lockout-failure-attempts', | ||||
|             self.user.name, | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('no_ignore_lockout_failure_attempts', True), | ||||
|             ('enable', False), | ||||
|             ('disable', False), | ||||
|             ('name', self.user.name), | ||||
|         ] | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         # In base command class ShowOne in cliff, abstract method take_action() | ||||
|         # returns a two-part tuple with a tuple of column names and a tuple of | ||||
|         # data to be shown. | ||||
|         columns, data = self.cmd.take_action(parsed_args) | ||||
|  | ||||
|         # Set expected values | ||||
|         kwargs = { | ||||
|             'name': self.user.name, | ||||
|             'default_project': None, | ||||
|             'description': None, | ||||
|             'domain': None, | ||||
|             'email': None, | ||||
|             'enabled': True, | ||||
|             'options': {'ignore_lockout_failure_attempts': False}, | ||||
|             'password': None, | ||||
|         } | ||||
|         # UserManager.create(name=, domain=, project=, password=, email=, | ||||
|         #   description=, enabled=, default_project=) | ||||
|         self.users_mock.create.assert_called_with( | ||||
|             **kwargs | ||||
|         ) | ||||
|  | ||||
|         self.assertEqual(self.columns, columns) | ||||
|         self.assertEqual(self.datalist, data) | ||||
|  | ||||
|     def test_user_create_ignore_password_expiry(self): | ||||
|         arglist = [ | ||||
|             '--ignore-password-expiry', | ||||
|             self.user.name, | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('ignore_password_expiry', True), | ||||
|             ('enable', False), | ||||
|             ('disable', False), | ||||
|             ('name', self.user.name), | ||||
|         ] | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         # In base command class ShowOne in cliff, abstract method take_action() | ||||
|         # returns a two-part tuple with a tuple of column names and a tuple of | ||||
|         # data to be shown. | ||||
|         columns, data = self.cmd.take_action(parsed_args) | ||||
|  | ||||
|         # Set expected values | ||||
|         kwargs = { | ||||
|             'name': self.user.name, | ||||
|             'default_project': None, | ||||
|             'description': None, | ||||
|             'domain': None, | ||||
|             'email': None, | ||||
|             'enabled': True, | ||||
|             'options': {'ignore_password_expiry': True}, | ||||
|             'password': None, | ||||
|         } | ||||
|         # UserManager.create(name=, domain=, project=, password=, email=, | ||||
|         #   description=, enabled=, default_project=) | ||||
|         self.users_mock.create.assert_called_with( | ||||
|             **kwargs | ||||
|         ) | ||||
|  | ||||
|         self.assertEqual(self.columns, columns) | ||||
|         self.assertEqual(self.datalist, data) | ||||
|  | ||||
|     def test_user_create_no_ignore_password_expiry(self): | ||||
|         arglist = [ | ||||
|             '--no-ignore-password-expiry', | ||||
|             self.user.name, | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('no_ignore_password_expiry', True), | ||||
|             ('enable', False), | ||||
|             ('disable', False), | ||||
|             ('name', self.user.name), | ||||
|         ] | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         # In base command class ShowOne in cliff, abstract method take_action() | ||||
|         # returns a two-part tuple with a tuple of column names and a tuple of | ||||
|         # data to be shown. | ||||
|         columns, data = self.cmd.take_action(parsed_args) | ||||
|  | ||||
|         # Set expected values | ||||
|         kwargs = { | ||||
|             'name': self.user.name, | ||||
|             'default_project': None, | ||||
|             'description': None, | ||||
|             'domain': None, | ||||
|             'email': None, | ||||
|             'enabled': True, | ||||
|             'options': {'ignore_password_expiry': False}, | ||||
|             'password': None, | ||||
|         } | ||||
|         # UserManager.create(name=, domain=, project=, password=, email=, | ||||
|         #   description=, enabled=, default_project=) | ||||
|         self.users_mock.create.assert_called_with( | ||||
|             **kwargs | ||||
|         ) | ||||
|  | ||||
|         self.assertEqual(self.columns, columns) | ||||
|         self.assertEqual(self.datalist, data) | ||||
|  | ||||
|     def test_user_create_ignore_change_password_upon_first_use(self): | ||||
|         arglist = [ | ||||
|             '--ignore-change-password-upon-first-use', | ||||
|             self.user.name, | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('ignore_change_password_upon_first_use', True), | ||||
|             ('enable', False), | ||||
|             ('disable', False), | ||||
|             ('name', self.user.name), | ||||
|         ] | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         # In base command class ShowOne in cliff, abstract method take_action() | ||||
|         # returns a two-part tuple with a tuple of column names and a tuple of | ||||
|         # data to be shown. | ||||
|         columns, data = self.cmd.take_action(parsed_args) | ||||
|  | ||||
|         # Set expected values | ||||
|         kwargs = { | ||||
|             'name': self.user.name, | ||||
|             'default_project': None, | ||||
|             'description': None, | ||||
|             'domain': None, | ||||
|             'email': None, | ||||
|             'enabled': True, | ||||
|             'options': {'ignore_change_password_upon_first_use': True}, | ||||
|             'password': None, | ||||
|         } | ||||
|         # UserManager.create(name=, domain=, project=, password=, email=, | ||||
|         #   description=, enabled=, default_project=) | ||||
|         self.users_mock.create.assert_called_with( | ||||
|             **kwargs | ||||
|         ) | ||||
|  | ||||
|         self.assertEqual(self.columns, columns) | ||||
|         self.assertEqual(self.datalist, data) | ||||
|  | ||||
|     def test_user_create_no_ignore_change_password_upon_first_use(self): | ||||
|         arglist = [ | ||||
|             '--no-ignore-change-password-upon-first-use', | ||||
|             self.user.name, | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('no_ignore_change_password_upon_first_use', True), | ||||
|             ('enable', False), | ||||
|             ('disable', False), | ||||
|             ('name', self.user.name), | ||||
|         ] | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         # In base command class ShowOne in cliff, abstract method take_action() | ||||
|         # returns a two-part tuple with a tuple of column names and a tuple of | ||||
|         # data to be shown. | ||||
|         columns, data = self.cmd.take_action(parsed_args) | ||||
|  | ||||
|         # Set expected values | ||||
|         kwargs = { | ||||
|             'name': self.user.name, | ||||
|             'default_project': None, | ||||
|             'description': None, | ||||
|             'domain': None, | ||||
|             'email': None, | ||||
|             'enabled': True, | ||||
|             'options': {'ignore_change_password_upon_first_use': False}, | ||||
|             'password': None, | ||||
|         } | ||||
|         # UserManager.create(name=, domain=, project=, password=, email=, | ||||
|         #   description=, enabled=, default_project=) | ||||
|         self.users_mock.create.assert_called_with( | ||||
|             **kwargs | ||||
|         ) | ||||
|  | ||||
|         self.assertEqual(self.columns, columns) | ||||
|         self.assertEqual(self.datalist, data) | ||||
|  | ||||
|     def test_user_create_enables_lock_password(self): | ||||
|         arglist = [ | ||||
|             '--enable-lock-password', | ||||
|             self.user.name, | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('enable_lock_password', True), | ||||
|             ('enable', False), | ||||
|             ('disable', False), | ||||
|             ('name', self.user.name), | ||||
|         ] | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         # In base command class ShowOne in cliff, abstract method take_action() | ||||
|         # returns a two-part tuple with a tuple of column names and a tuple of | ||||
|         # data to be shown. | ||||
|         columns, data = self.cmd.take_action(parsed_args) | ||||
|  | ||||
|         # Set expected values | ||||
|         kwargs = { | ||||
|             'name': self.user.name, | ||||
|             'default_project': None, | ||||
|             'description': None, | ||||
|             'domain': None, | ||||
|             'email': None, | ||||
|             'enabled': True, | ||||
|             'options': {'lock_password': True}, | ||||
|             'password': None, | ||||
|         } | ||||
|         # UserManager.create(name=, domain=, project=, password=, email=, | ||||
|         #   description=, enabled=, default_project=) | ||||
|         self.users_mock.create.assert_called_with( | ||||
|             **kwargs | ||||
|         ) | ||||
|  | ||||
|         self.assertEqual(self.columns, columns) | ||||
|         self.assertEqual(self.datalist, data) | ||||
|  | ||||
|     def test_user_create_disables_lock_password(self): | ||||
|         arglist = [ | ||||
|             '--disable-lock-password', | ||||
|             self.user.name, | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('disable_lock_password', True), | ||||
|             ('enable', False), | ||||
|             ('disable', False), | ||||
|             ('name', self.user.name), | ||||
|         ] | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         # In base command class ShowOne in cliff, abstract method take_action() | ||||
|         # returns a two-part tuple with a tuple of column names and a tuple of | ||||
|         # data to be shown. | ||||
|         columns, data = self.cmd.take_action(parsed_args) | ||||
|  | ||||
|         # Set expected values | ||||
|         kwargs = { | ||||
|             'name': self.user.name, | ||||
|             'default_project': None, | ||||
|             'description': None, | ||||
|             'domain': None, | ||||
|             'email': None, | ||||
|             'enabled': True, | ||||
|             'options': {'lock_password': False}, | ||||
|             'password': None, | ||||
|         } | ||||
|         # UserManager.create(name=, domain=, project=, password=, email=, | ||||
|         #   description=, enabled=, default_project=) | ||||
|         self.users_mock.create.assert_called_with( | ||||
|             **kwargs | ||||
|         ) | ||||
|  | ||||
|         self.assertEqual(self.columns, columns) | ||||
|         self.assertEqual(self.datalist, data) | ||||
|  | ||||
|     def test_user_create_enable_multi_factor_auth(self): | ||||
|         arglist = [ | ||||
|             '--enable-multi-factor-auth', | ||||
|             self.user.name, | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('enable_multi_factor_auth', True), | ||||
|             ('enable', False), | ||||
|             ('disable', False), | ||||
|             ('name', self.user.name), | ||||
|         ] | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         # In base command class ShowOne in cliff, abstract method take_action() | ||||
|         # returns a two-part tuple with a tuple of column names and a tuple of | ||||
|         # data to be shown. | ||||
|         columns, data = self.cmd.take_action(parsed_args) | ||||
|  | ||||
|         # Set expected values | ||||
|         kwargs = { | ||||
|             'name': self.user.name, | ||||
|             'default_project': None, | ||||
|             'description': None, | ||||
|             'domain': None, | ||||
|             'email': None, | ||||
|             'enabled': True, | ||||
|             'options': {'multi_factor_auth_enabled': True}, | ||||
|             'password': None, | ||||
|         } | ||||
|         # UserManager.create(name=, domain=, project=, password=, email=, | ||||
|         #   description=, enabled=, default_project=) | ||||
|         self.users_mock.create.assert_called_with( | ||||
|             **kwargs | ||||
|         ) | ||||
|  | ||||
|         self.assertEqual(self.columns, columns) | ||||
|         self.assertEqual(self.datalist, data) | ||||
|  | ||||
|     def test_user_create_disable_multi_factor_auth(self): | ||||
|         arglist = [ | ||||
|             '--disable-multi-factor-auth', | ||||
|             self.user.name, | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('disable_multi_factor_auth', True), | ||||
|             ('enable', False), | ||||
|             ('disable', False), | ||||
|             ('name', self.user.name), | ||||
|         ] | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         # In base command class ShowOne in cliff, abstract method take_action() | ||||
|         # returns a two-part tuple with a tuple of column names and a tuple of | ||||
|         # data to be shown. | ||||
|         columns, data = self.cmd.take_action(parsed_args) | ||||
|  | ||||
|         # Set expected values | ||||
|         kwargs = { | ||||
|             'name': self.user.name, | ||||
|             'default_project': None, | ||||
|             'description': None, | ||||
|             'domain': None, | ||||
|             'email': None, | ||||
|             'enabled': True, | ||||
|             'options': {'multi_factor_auth_enabled': False}, | ||||
|             'password': None, | ||||
|         } | ||||
|         # UserManager.create(name=, domain=, project=, password=, email=, | ||||
|         #   description=, enabled=, default_project=) | ||||
|         self.users_mock.create.assert_called_with( | ||||
|             **kwargs | ||||
|         ) | ||||
|  | ||||
|         self.assertEqual(self.columns, columns) | ||||
|         self.assertEqual(self.datalist, data) | ||||
|  | ||||
|     def test_user_create_option_with_multi_factor_auth_rule(self): | ||||
|         arglist = [ | ||||
|             '--multi-factor-auth-rule', identity_fakes.mfa_opt1, | ||||
|             '--multi-factor-auth-rule', identity_fakes.mfa_opt2, | ||||
|             self.user.name, | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('multi_factor_auth_rule', [identity_fakes.mfa_opt1, | ||||
|                                         identity_fakes.mfa_opt2]), | ||||
|             ('enable', False), | ||||
|             ('disable', False), | ||||
|             ('name', self.user.name), | ||||
|         ] | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         # In base command class ShowOne in cliff, abstract method take_action() | ||||
|         # returns a two-part tuple with a tuple of column names and a tuple of | ||||
|         # data to be shown. | ||||
|         columns, data = self.cmd.take_action(parsed_args) | ||||
|  | ||||
|         # Set expected values | ||||
|         kwargs = { | ||||
|             'name': self.user.name, | ||||
|             'default_project': None, | ||||
|             'description': None, | ||||
|             'domain': None, | ||||
|             'email': None, | ||||
|             'enabled': True, | ||||
|             'options': {'multi_factor_auth_rules': [["password", "totp"], | ||||
|                                                     ["password"]]}, | ||||
|             'password': None, | ||||
|         } | ||||
|         # UserManager.create(name=, domain=, project=, password=, email=, | ||||
|         #   description=, enabled=, default_project=) | ||||
|         self.users_mock.create.assert_called_with( | ||||
|             **kwargs | ||||
|         ) | ||||
|  | ||||
|         self.assertEqual(self.columns, columns) | ||||
|         self.assertEqual(self.datalist, data) | ||||
|  | ||||
|     def test_user_create_with_multiple_options(self): | ||||
|         arglist = [ | ||||
|             '--ignore-password-expiry', | ||||
|             '--disable-multi-factor-auth', | ||||
|             '--multi-factor-auth-rule', identity_fakes.mfa_opt1, | ||||
|             self.user.name, | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('ignore_password_expiry', True), | ||||
|             ('disable_multi_factor_auth', True), | ||||
|             ('multi_factor_auth_rule', [identity_fakes.mfa_opt1]), | ||||
|             ('enable', False), | ||||
|             ('disable', False), | ||||
|             ('name', self.user.name), | ||||
|         ] | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         # In base command class ShowOne in cliff, abstract method take_action() | ||||
|         # returns a two-part tuple with a tuple of column names and a tuple of | ||||
|         # data to be shown. | ||||
|         columns, data = self.cmd.take_action(parsed_args) | ||||
|  | ||||
|         # Set expected values | ||||
|         kwargs = { | ||||
|             'name': self.user.name, | ||||
|             'default_project': None, | ||||
|             'description': None, | ||||
|             'domain': None, | ||||
|             'email': None, | ||||
|             'enabled': True, | ||||
|             'options': {'ignore_password_expiry': True, | ||||
|                         'multi_factor_auth_enabled': False, | ||||
|                         'multi_factor_auth_rules': [["password", "totp"]]}, | ||||
|             'password': None, | ||||
|         } | ||||
|         # UserManager.create(name=, domain=, project=, password=, email=, | ||||
|         #   description=, enabled=, default_project=) | ||||
|         self.users_mock.create.assert_called_with( | ||||
|             **kwargs | ||||
|         ) | ||||
|  | ||||
|         self.assertEqual(self.columns, columns) | ||||
|         self.assertEqual(self.datalist, data) | ||||
|  | ||||
|  | ||||
| class TestUserDelete(TestUser): | ||||
|  | ||||
| @@ -1007,6 +1481,384 @@ class TestUserSet(TestUser): | ||||
|         ) | ||||
|         self.assertIsNone(result) | ||||
|  | ||||
|     def test_user_set_ignore_lockout_failure_attempts(self): | ||||
|         arglist = [ | ||||
|             '--ignore-lockout-failure-attempts', | ||||
|             self.user.name, | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('name', None), | ||||
|             ('password', None), | ||||
|             ('email', None), | ||||
|             ('ignore_lockout_failure_attempts', True), | ||||
|             ('project', None), | ||||
|             ('enable', False), | ||||
|             ('disable', False), | ||||
|             ('user', self.user.name), | ||||
|         ] | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         result = self.cmd.take_action(parsed_args) | ||||
|         # Set expected values | ||||
|         kwargs = { | ||||
|             'enabled': True, | ||||
|             'options': {'ignore_lockout_failure_attempts': True}, | ||||
|         } | ||||
|         # UserManager.update(user, name=, domain=, project=, password=, | ||||
|         #     email=, description=, enabled=, default_project=) | ||||
|         self.users_mock.update.assert_called_with( | ||||
|             self.user.id, | ||||
|             **kwargs | ||||
|         ) | ||||
|         self.assertIsNone(result) | ||||
|  | ||||
|     def test_user_set_no_ignore_lockout_failure_attempts(self): | ||||
|         arglist = [ | ||||
|             '--no-ignore-lockout-failure-attempts', | ||||
|             self.user.name, | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('name', None), | ||||
|             ('password', None), | ||||
|             ('email', None), | ||||
|             ('no_ignore_lockout_failure_attempts', True), | ||||
|             ('project', None), | ||||
|             ('enable', False), | ||||
|             ('disable', False), | ||||
|             ('user', self.user.name), | ||||
|         ] | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         result = self.cmd.take_action(parsed_args) | ||||
|         # Set expected values | ||||
|         kwargs = { | ||||
|             'enabled': True, | ||||
|             'options': {'ignore_lockout_failure_attempts': False}, | ||||
|         } | ||||
|         # UserManager.update(user, name=, domain=, project=, password=, | ||||
|         #     email=, description=, enabled=, default_project=) | ||||
|         self.users_mock.update.assert_called_with( | ||||
|             self.user.id, | ||||
|             **kwargs | ||||
|         ) | ||||
|         self.assertIsNone(result) | ||||
|  | ||||
|     def test_user_set_ignore_password_expiry(self): | ||||
|         arglist = [ | ||||
|             '--ignore-password-expiry', | ||||
|             self.user.name, | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('name', None), | ||||
|             ('password', None), | ||||
|             ('email', None), | ||||
|             ('ignore_password_expiry', True), | ||||
|             ('project', None), | ||||
|             ('enable', False), | ||||
|             ('disable', False), | ||||
|             ('user', self.user.name), | ||||
|         ] | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         result = self.cmd.take_action(parsed_args) | ||||
|         # Set expected values | ||||
|         kwargs = { | ||||
|             'enabled': True, | ||||
|             'options': {'ignore_password_expiry': True}, | ||||
|         } | ||||
|         # UserManager.update(user, name=, domain=, project=, password=, | ||||
|         #     email=, description=, enabled=, default_project=) | ||||
|         self.users_mock.update.assert_called_with( | ||||
|             self.user.id, | ||||
|             **kwargs | ||||
|         ) | ||||
|         self.assertIsNone(result) | ||||
|  | ||||
|     def test_user_set_no_ignore_password_expiry(self): | ||||
|         arglist = [ | ||||
|             '--no-ignore-password-expiry', | ||||
|             self.user.name, | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('name', None), | ||||
|             ('password', None), | ||||
|             ('email', None), | ||||
|             ('no_ignore_password_expiry', True), | ||||
|             ('project', None), | ||||
|             ('enable', False), | ||||
|             ('disable', False), | ||||
|             ('user', self.user.name), | ||||
|         ] | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         result = self.cmd.take_action(parsed_args) | ||||
|         # Set expected values | ||||
|         kwargs = { | ||||
|             'enabled': True, | ||||
|             'options': {'ignore_password_expiry': False}, | ||||
|         } | ||||
|         # UserManager.update(user, name=, domain=, project=, password=, | ||||
|         #     email=, description=, enabled=, default_project=) | ||||
|         self.users_mock.update.assert_called_with( | ||||
|             self.user.id, | ||||
|             **kwargs | ||||
|         ) | ||||
|         self.assertIsNone(result) | ||||
|  | ||||
|     def test_user_set_ignore_change_password_upon_first_use(self): | ||||
|         arglist = [ | ||||
|             '--ignore-change-password-upon-first-use', | ||||
|             self.user.name, | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('name', None), | ||||
|             ('password', None), | ||||
|             ('email', None), | ||||
|             ('ignore_change_password_upon_first_use', True), | ||||
|             ('project', None), | ||||
|             ('enable', False), | ||||
|             ('disable', False), | ||||
|             ('user', self.user.name), | ||||
|         ] | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         result = self.cmd.take_action(parsed_args) | ||||
|         # Set expected values | ||||
|         kwargs = { | ||||
|             'enabled': True, | ||||
|             'options': {'ignore_change_password_upon_first_use': True}, | ||||
|         } | ||||
|         # UserManager.update(user, name=, domain=, project=, password=, | ||||
|         #     email=, description=, enabled=, default_project=) | ||||
|         self.users_mock.update.assert_called_with( | ||||
|             self.user.id, | ||||
|             **kwargs | ||||
|         ) | ||||
|         self.assertIsNone(result) | ||||
|  | ||||
|     def test_user_set_no_ignore_change_password_upon_first_use(self): | ||||
|         arglist = [ | ||||
|             '--no-ignore-change-password-upon-first-use', | ||||
|             self.user.name, | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('name', None), | ||||
|             ('password', None), | ||||
|             ('email', None), | ||||
|             ('no_ignore_change_password_upon_first_use', True), | ||||
|             ('project', None), | ||||
|             ('enable', False), | ||||
|             ('disable', False), | ||||
|             ('user', self.user.name), | ||||
|         ] | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         result = self.cmd.take_action(parsed_args) | ||||
|         # Set expected values | ||||
|         kwargs = { | ||||
|             'enabled': True, | ||||
|             'options': {'ignore_change_password_upon_first_use': False}, | ||||
|         } | ||||
|         # UserManager.update(user, name=, domain=, project=, password=, | ||||
|         #     email=, description=, enabled=, default_project=) | ||||
|         self.users_mock.update.assert_called_with( | ||||
|             self.user.id, | ||||
|             **kwargs | ||||
|         ) | ||||
|         self.assertIsNone(result) | ||||
|  | ||||
|     def test_user_set_enable_lock_password(self): | ||||
|         arglist = [ | ||||
|             '--enable-lock-password', | ||||
|             self.user.name, | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('name', None), | ||||
|             ('password', None), | ||||
|             ('email', None), | ||||
|             ('enable_lock_password', True), | ||||
|             ('project', None), | ||||
|             ('enable', False), | ||||
|             ('disable', False), | ||||
|             ('user', self.user.name), | ||||
|         ] | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         result = self.cmd.take_action(parsed_args) | ||||
|         # Set expected values | ||||
|         kwargs = { | ||||
|             'enabled': True, | ||||
|             'options': {'lock_password': True}, | ||||
|         } | ||||
|         # UserManager.update(user, name=, domain=, project=, password=, | ||||
|         #     email=, description=, enabled=, default_project=) | ||||
|         self.users_mock.update.assert_called_with( | ||||
|             self.user.id, | ||||
|             **kwargs | ||||
|         ) | ||||
|         self.assertIsNone(result) | ||||
|  | ||||
|     def test_user_set_disable_lock_password(self): | ||||
|         arglist = [ | ||||
|             '--disable-lock-password', | ||||
|             self.user.name, | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('name', None), | ||||
|             ('password', None), | ||||
|             ('email', None), | ||||
|             ('disable_lock_password', True), | ||||
|             ('project', None), | ||||
|             ('enable', False), | ||||
|             ('disable', False), | ||||
|             ('user', self.user.name), | ||||
|         ] | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         result = self.cmd.take_action(parsed_args) | ||||
|         # Set expected values | ||||
|         kwargs = { | ||||
|             'enabled': True, | ||||
|             'options': {'lock_password': False}, | ||||
|         } | ||||
|         # UserManager.update(user, name=, domain=, project=, password=, | ||||
|         #     email=, description=, enabled=, default_project=) | ||||
|         self.users_mock.update.assert_called_with( | ||||
|             self.user.id, | ||||
|             **kwargs | ||||
|         ) | ||||
|         self.assertIsNone(result) | ||||
|  | ||||
|     def test_user_set_enable_multi_factor_auth(self): | ||||
|         arglist = [ | ||||
|             '--enable-multi-factor-auth', | ||||
|             self.user.name, | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('name', None), | ||||
|             ('password', None), | ||||
|             ('email', None), | ||||
|             ('enable_multi_factor_auth', True), | ||||
|             ('project', None), | ||||
|             ('enable', False), | ||||
|             ('disable', False), | ||||
|             ('user', self.user.name), | ||||
|         ] | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         result = self.cmd.take_action(parsed_args) | ||||
|         # Set expected values | ||||
|         kwargs = { | ||||
|             'enabled': True, | ||||
|             'options': {'multi_factor_auth_enabled': True}, | ||||
|         } | ||||
|         # UserManager.update(user, name=, domain=, project=, password=, | ||||
|         #     email=, description=, enabled=, default_project=) | ||||
|         self.users_mock.update.assert_called_with( | ||||
|             self.user.id, | ||||
|             **kwargs | ||||
|         ) | ||||
|         self.assertIsNone(result) | ||||
|  | ||||
|     def test_user_set_disable_multi_factor_auth(self): | ||||
|         arglist = [ | ||||
|             '--disable-multi-factor-auth', | ||||
|             self.user.name, | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('name', None), | ||||
|             ('password', None), | ||||
|             ('email', None), | ||||
|             ('disable_multi_factor_auth', True), | ||||
|             ('project', None), | ||||
|             ('enable', False), | ||||
|             ('disable', False), | ||||
|             ('user', self.user.name), | ||||
|         ] | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         result = self.cmd.take_action(parsed_args) | ||||
|         # Set expected values | ||||
|         kwargs = { | ||||
|             'enabled': True, | ||||
|             'options': {'multi_factor_auth_enabled': False}, | ||||
|         } | ||||
|         # UserManager.update(user, name=, domain=, project=, password=, | ||||
|         #     email=, description=, enabled=, default_project=) | ||||
|         self.users_mock.update.assert_called_with( | ||||
|             self.user.id, | ||||
|             **kwargs | ||||
|         ) | ||||
|         self.assertIsNone(result) | ||||
|  | ||||
|     def test_user_set_option_multi_factor_auth_rule(self): | ||||
|         arglist = [ | ||||
|             '--multi-factor-auth-rule', identity_fakes.mfa_opt1, | ||||
|             self.user.name, | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('name', None), | ||||
|             ('password', None), | ||||
|             ('email', None), | ||||
|             ('multi_factor_auth_rule', [identity_fakes.mfa_opt1]), | ||||
|             ('project', None), | ||||
|             ('enable', False), | ||||
|             ('disable', False), | ||||
|             ('user', self.user.name), | ||||
|         ] | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         result = self.cmd.take_action(parsed_args) | ||||
|         # Set expected values | ||||
|         kwargs = { | ||||
|             'enabled': True, | ||||
|             'options': {'multi_factor_auth_rules': [["password", "totp"]]}} | ||||
|  | ||||
|         # UserManager.update(user, name=, domain=, project=, password=, | ||||
|         #     email=, description=, enabled=, default_project=) | ||||
|         self.users_mock.update.assert_called_with( | ||||
|             self.user.id, | ||||
|             **kwargs | ||||
|         ) | ||||
|         self.assertIsNone(result) | ||||
|  | ||||
|     def test_user_set_with_multiple_options(self): | ||||
|         arglist = [ | ||||
|             '--ignore-password-expiry', | ||||
|             '--enable-multi-factor-auth', | ||||
|             '--multi-factor-auth-rule', identity_fakes.mfa_opt1, | ||||
|             self.user.name, | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('name', None), | ||||
|             ('password', None), | ||||
|             ('email', None), | ||||
|             ('ignore_password_expiry', True), | ||||
|             ('enable_multi_factor_auth', True), | ||||
|             ('multi_factor_auth_rule', [identity_fakes.mfa_opt1]), | ||||
|             ('project', None), | ||||
|             ('enable', False), | ||||
|             ('disable', False), | ||||
|             ('user', self.user.name), | ||||
|         ] | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         result = self.cmd.take_action(parsed_args) | ||||
|         # Set expected values | ||||
|         kwargs = { | ||||
|             'enabled': True, | ||||
|             'options': {'ignore_password_expiry': True, | ||||
|                         'multi_factor_auth_enabled': True, | ||||
|                         'multi_factor_auth_rules': [["password", "totp"]]}} | ||||
|  | ||||
|         # UserManager.update(user, name=, domain=, project=, password=, | ||||
|         #     email=, description=, enabled=, default_project=) | ||||
|         self.users_mock.update.assert_called_with( | ||||
|             self.user.id, | ||||
|             **kwargs | ||||
|         ) | ||||
|         self.assertIsNone(result) | ||||
|  | ||||
|  | ||||
| class TestUserSetPassword(TestUser): | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,19 @@ | ||||
| --- | ||||
| features: | ||||
|   - | | ||||
|     Added the below mentioned parameters to the user create and set commands. | ||||
|  | ||||
|     * --ignore-lockout-failure-attempts | ||||
|     * --no-ignore-lockout-failure-attempts | ||||
|     * --ignore-password-expiry | ||||
|     * --no-ignore-password-expiry | ||||
|     * --ignore-change-password-upon-first-use | ||||
|     * --no-ignore-change-password-upon-first-use | ||||
|     * --enable-lock-password | ||||
|     * --disable-lock-password | ||||
|     * --enable-multi-factor-auth | ||||
|     * --disable-multi-factor-auth | ||||
|     * --multi-factor-auth-rule | ||||
|  | ||||
|     This will now allow users to set user options via CLI. | ||||
|     <https://docs.openstack.org/keystone/latest/admin/resource-options.html#user-options> | ||||
		Reference in New Issue
	
	Block a user
	 Vishakha Agarwal
					Vishakha Agarwal