Non-Admin can't list own projects

Due to a default Keystone policy until Newtown,
and the use of resource_find, non-admins are unable
to list their own projects.

This patch bypasses this problem while also introducing better
UX for non-admins wishing to get their project list.

'openstack project list' retains the default of 'list all projects'
but on a forbidden error will default instead to 'list my projects'.
This way for non-admins 'list my projects' feels like the default
without breaking the expected admin default.

Adding the '--my-projects' option allows admins to easily list their
own projects or allows non-admins to be explicit and bypass the
forbidden error fallback.

Change-Id: I1021276f69fbbf28e13e17c4e567d932fce7ed8b
Closes-Bug: #1627555
This commit is contained in:
adrian-turjak 2016-09-26 13:06:42 +13:00
parent ad5b57fd19
commit 49f6032b69
4 changed files with 69 additions and 1 deletions

View File

@ -95,6 +95,7 @@ List projects
openstack project list
[--domain <domain>]
[--user <user>]
[--my-projects]
[--long]
[--sort <key>[:<direction>,<key>:<direction>,..]]
@ -110,6 +111,12 @@ List projects
.. versionadded:: 3
.. option:: --my-projects
List projects for the authenticated user. Supersedes other filters.
.. versionadded:: 3
.. option:: --long
List additional fields in output

View File

@ -188,6 +188,12 @@ class ListProject(command.Lister):
metavar='<user>',
help=_('Filter projects by <user> (name or ID)'),
)
parser.add_argument(
'--my-projects',
action='store_true',
help=_('List projects for the authenticated user. '
'Supersedes other filters.'),
)
parser.add_argument(
'--long',
action='store_true',
@ -228,9 +234,25 @@ class ListProject(command.Lister):
kwargs['user'] = user_id
if parsed_args.my_projects:
# NOTE(adriant): my-projects supersedes all the other filters.
kwargs = {'user': self.app.client_manager.auth_ref.user_id}
try:
data = identity_client.projects.list(**kwargs)
except ks_exc.Forbidden:
# NOTE(adriant): if no filters, assume a forbidden is non-admin
# wanting their own project list.
if not kwargs:
user = self.app.client_manager.auth_ref.user_id
data = identity_client.projects.list(
user=user)
else:
raise
if parsed_args.sort:
data = utils.sort_items(data, parsed_args.sort)
return (columns,
(utils.get_item_properties(
s, columns,

View File

@ -617,6 +617,36 @@ class TestProjectList(TestProject):
self.assertEqual(datalists, tuple(data))
def test_project_list_my_projects(self):
auth_ref = identity_fakes.fake_auth_ref(
identity_fakes.TOKEN_WITH_PROJECT_ID,
)
ar_mock = mock.PropertyMock(return_value=auth_ref)
type(self.app.client_manager).auth_ref = ar_mock
arglist = [
'--my-projects',
]
verifylist = [
('my_projects', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
# In base command class Lister in cliff, abstract method take_action()
# returns a tuple containing the column names and an iterable
# containing the data to be listed.
columns, data = self.cmd.take_action(parsed_args)
self.projects_mock.list.assert_called_with(
user=self.app.client_manager.auth_ref.user_id)
collist = ('ID', 'Name')
self.assertEqual(collist, columns)
datalist = ((
self.project.id,
self.project.name,
), )
self.assertEqual(datalist, tuple(data))
class TestProjectSet(TestProject):

View File

@ -0,0 +1,9 @@
---
features:
- |
The ``project list`` command lists all projects when called by an
admin user. For non-admin users it will now list projects for the
authenticated user instead of exiting with an authorization failure.
The ``--my-projects`` option has also been added to the ``project list``
command to allow admin users to list their own projects.
[Bug `1627555 <https://bugs.launchpad.net/bugs/1627555>`_]