diff --git a/openstack_dashboard/dashboards/identity/groups/tests.py b/openstack_dashboard/dashboards/identity/groups/tests.py
index 48d58931bc..f542681a55 100644
--- a/openstack_dashboard/dashboards/identity/groups/tests.py
+++ b/openstack_dashboard/dashboards/identity/groups/tests.py
@@ -308,3 +308,10 @@ class GroupsViewTests(test.BaseAdminViewTests):
self.assertRedirectsNoFollow(res, GROUP_MANAGE_URL)
self.assertMessageCount(success=1)
+
+ @test.update_settings(FILTER_DATA_FIRST={'identity.groups': True})
+ def test_index_with_filter_first(self):
+ res = self.client.get(GROUPS_INDEX_URL)
+ self.assertTemplateUsed(res, constants.GROUPS_INDEX_VIEW_TEMPLATE)
+ groups = res.context['table'].data
+ self.assertItemsEqual(groups, [])
diff --git a/openstack_dashboard/dashboards/identity/groups/views.py b/openstack_dashboard/dashboards/identity/groups/views.py
index c8069de025..13332f4c62 100644
--- a/openstack_dashboard/dashboards/identity/groups/views.py
+++ b/openstack_dashboard/dashboards/identity/groups/views.py
@@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+from django.conf import settings
from django.core.urlresolvers import reverse
from django.core.urlresolvers import reverse_lazy
from django.utils.translation import ugettext_lazy as _
@@ -37,12 +38,28 @@ class IndexView(tables.DataTableView):
template_name = constants.GROUPS_INDEX_VIEW_TEMPLATE
page_title = _("Groups")
+ def needs_filter_first(self, table):
+ return self._needs_filter_first
+
def get_data(self):
groups = []
- domain_id = api.keystone.get_effective_domain_id(self.request)
filters = self.get_filters()
+ self._needs_filter_first = False
+
if policy.check((("identity", "identity:list_groups"),),
self.request):
+
+ # If filter_first is set and if there are not other filters
+ # selected, then search criteria must be provided and
+ # return an empty list
+ filter_first = getattr(settings, 'FILTER_DATA_FIRST', {})
+ if filter_first.get('identity.groups', False) \
+ and len(filters) == 0:
+ self._needs_filter_first = True
+ return groups
+
+ domain_id = api.keystone.get_effective_domain_id(self.request)
+
try:
groups = api.keystone.group_list(self.request,
domain=domain_id,
diff --git a/openstack_dashboard/dashboards/identity/projects/tests.py b/openstack_dashboard/dashboards/identity/projects/tests.py
index f47ca3476e..08c476ef09 100644
--- a/openstack_dashboard/dashboards/identity/projects/tests.py
+++ b/openstack_dashboard/dashboards/identity/projects/tests.py
@@ -97,6 +97,13 @@ class TenantsViewTests(test.BaseAdminViewTests):
self.assertItemsEqual(res.context['table'].data, domain_tenants)
self.assertContains(res, "test_domain:")
+ @test.update_settings(FILTER_DATA_FIRST={'identity.projects': True})
+ def test_index_with_filter_first(self):
+ res = self.client.get(INDEX_URL)
+ self.assertTemplateUsed(res, 'identity/projects/index.html')
+ projects = res.context['table'].data
+ self.assertItemsEqual(projects, [])
+
class ProjectsViewNonAdminTests(test.TestCase):
@override_settings(POLICY_CHECK_FUNCTION='openstack_auth.policy.check')
diff --git a/openstack_dashboard/dashboards/identity/projects/views.py b/openstack_dashboard/dashboards/identity/projects/views.py
index a0a3589c7d..405c546e46 100644
--- a/openstack_dashboard/dashboards/identity/projects/views.py
+++ b/openstack_dashboard/dashboards/identity/projects/views.py
@@ -71,6 +71,9 @@ class IndexView(tables.DataTableView):
template_name = 'identity/projects/index.html'
page_title = _("Projects")
+ def needs_filter_first(self, table):
+ return self._needs_filter_first
+
def has_more_data(self, table):
return self._more
@@ -80,8 +83,22 @@ class IndexView(tables.DataTableView):
project_tables.TenantsTable._meta.pagination_param, None)
self._more = False
filters = self.get_filters()
+
+ self._needs_filter_first = False
+
if policy.check((("identity", "identity:list_projects"),),
self.request):
+
+ # If filter_first is set and if there are not other filters
+ # selected, then search criteria must be provided and
+ # return an empty list
+ filter_first = getattr(settings, 'FILTER_DATA_FIRST', {})
+ if filter_first.get('identity.projects', False) and len(
+ filters) == 0:
+ self._needs_filter_first = True
+ self._more = False
+ return tenants
+
domain_context = api.keystone.get_effective_domain_id(self.request)
try:
tenants, self._more = api.keystone.tenant_list(
diff --git a/openstack_dashboard/dashboards/identity/roles/tests.py b/openstack_dashboard/dashboards/identity/roles/tests.py
index 5fa2112256..d5766f35c7 100644
--- a/openstack_dashboard/dashboards/identity/roles/tests.py
+++ b/openstack_dashboard/dashboards/identity/roles/tests.py
@@ -120,3 +120,10 @@ class RolesViewTests(test.BaseAdminViewTests):
res = self.client.post(ROLES_INDEX_URL, formData)
self.assertNoFormErrors(res)
+
+ @test.update_settings(FILTER_DATA_FIRST={'identity.roles': True})
+ def test_index_with_filter_first(self):
+ res = self.client.get(ROLES_INDEX_URL)
+ self.assertTemplateUsed(res, INDEX_TEMPLATE)
+ roles = res.context['table'].data
+ self.assertItemsEqual(roles, [])
diff --git a/openstack_dashboard/dashboards/identity/roles/views.py b/openstack_dashboard/dashboards/identity/roles/views.py
index 26c8d80380..d5b86e28d7 100644
--- a/openstack_dashboard/dashboards/identity/roles/views.py
+++ b/openstack_dashboard/dashboards/identity/roles/views.py
@@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+from django.conf import settings
from django.core.urlresolvers import reverse
from django.core.urlresolvers import reverse_lazy
from django.utils.translation import ugettext_lazy as _
@@ -35,11 +36,26 @@ class IndexView(tables.DataTableView):
table_class = project_tables.RolesTable
page_title = _("Roles")
+ def needs_filter_first(self, table):
+ return self._needs_filter_first
+
def get_data(self):
roles = []
filters = self.get_filters()
+
+ self._needs_filter_first = False
+
if policy.check((("identity", "identity:list_roles"),),
self.request):
+
+ # If filter_first is set and if there are not other filters
+ # selected, then search criteria must be provided
+ # and return an empty list
+ filter_first = getattr(settings, 'FILTER_DATA_FIRST', {})
+ if filter_first.get('identity.roles', False) and len(filters) == 0:
+ self._needs_filter_first = True
+ return roles
+
try:
roles = api.keystone.role_list(self.request,
filters=filters)
diff --git a/openstack_dashboard/dashboards/identity/users/tests.py b/openstack_dashboard/dashboards/identity/users/tests.py
index 99ae894a08..1d5ecd1bea 100644
--- a/openstack_dashboard/dashboards/identity/users/tests.py
+++ b/openstack_dashboard/dashboards/identity/users/tests.py
@@ -963,6 +963,13 @@ class UsersViewTests(test.BaseAdminViewTests):
self.assertNoFormErrors(res)
+ @test.update_settings(FILTER_DATA_FIRST={'identity.users': True})
+ def test_index_with_filter_first(self):
+ res = self.client.get(USERS_INDEX_URL)
+ self.assertTemplateUsed(res, 'identity/users/index.html')
+ users = res.context['table'].data
+ self.assertItemsEqual(users, [])
+
class SeleniumTests(test.SeleniumAdminTestCase):
def _get_default_domain(self):
diff --git a/openstack_dashboard/dashboards/identity/users/views.py b/openstack_dashboard/dashboards/identity/users/views.py
index b48599a87b..ea7af63c39 100644
--- a/openstack_dashboard/dashboards/identity/users/views.py
+++ b/openstack_dashboard/dashboards/identity/users/views.py
@@ -49,11 +49,26 @@ class IndexView(tables.DataTableView):
template_name = 'identity/users/index.html'
page_title = _("Users")
+ def needs_filter_first(self, table):
+ return self._needs_filter_first
+
def get_data(self):
users = []
filters = self.get_filters()
+
+ self._needs_filter_first = False
+
if policy.check((("identity", "identity:list_users"),),
self.request):
+
+ # If filter_first is set and if there are not other filters
+ # selected, then search criteria must be provided
+ # and return an empty list
+ filter_first = getattr(settings, 'FILTER_DATA_FIRST', {})
+ if filter_first.get('identity.users', False) and len(filters) == 0:
+ self._needs_filter_first = True
+ return users
+
domain_context = api.keystone.get_effective_domain_id(self.request)
try:
users = api.keystone.user_list(self.request,
diff --git a/openstack_dashboard/local/local_settings.py.example b/openstack_dashboard/local/local_settings.py.example
index 5c4a147e84..72483975c5 100644
--- a/openstack_dashboard/local/local_settings.py.example
+++ b/openstack_dashboard/local/local_settings.py.example
@@ -800,7 +800,11 @@ REST_API_REQUIRED_SETTINGS = ['OPENSTACK_HYPERVISOR_FEATURES',
# 'admin.images': False,
# 'admin.networks': False,
# 'admin.routers': False,
-# 'admin.volumes': False
+# 'admin.volumes': False,
+# 'identity.users': False,
+# 'identity.projects': False,
+# 'identity.groups': False,
+# 'identity.roles': False
#}
# Dict used to restrict user private subnet cidr range.
diff --git a/releasenotes/notes/filter-first-identity-panels-139c4a5b7a696707.yaml b/releasenotes/notes/filter-first-identity-panels-139c4a5b7a696707.yaml
new file mode 100644
index 0000000000..2e093014ec
--- /dev/null
+++ b/releasenotes/notes/filter-first-identity-panels-139c4a5b7a696707.yaml
@@ -0,0 +1,5 @@
+---
+features:
+ - Implements the "filter first" functionality for identity panels
+ such as projects, users, groups and roles. The filter first
+ functionality is described in `