From f3459e2662e86b275ac3baf01330753df4d3f092 Mon Sep 17 00:00:00 2001 From: Lingxian Kong Date: Wed, 25 Aug 2021 16:11:12 +1200 Subject: Allow regular user to get quotas The project user can query the project's own resource quota. Story: 2009140 Task: 43082 Change-Id: Iebac740e982a89fcf882a2cfc3e447ac53ee6656 --- trove/common/wsgi.py | 1 + trove/extensions/mgmt/quota/service.py | 13 +++- .../unittests/extensions/mgmt/quota/__init__.py | 0 .../extensions/mgmt/quota/test_service.py | 81 ++++++++++++++++++++++ 4 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 trove/tests/unittests/extensions/mgmt/quota/__init__.py create mode 100644 trove/tests/unittests/extensions/mgmt/quota/test_service.py (limited to 'trove') diff --git a/trove/common/wsgi.py b/trove/common/wsgi.py index 4c8673d5..66cff129 100644 --- a/trove/common/wsgi.py +++ b/trove/common/wsgi.py @@ -324,6 +324,7 @@ class Controller(object): exception.ModuleAppliedToInstance, exception.PolicyNotAuthorized, exception.LogAccessForbidden, + exception.TroveOperationAuthError, ], webob.exc.HTTPBadRequest: [ exception.InvalidModelError, diff --git a/trove/extensions/mgmt/quota/service.py b/trove/extensions/mgmt/quota/service.py index a16f8716..bb55e781 100644 --- a/trove/extensions/mgmt/quota/service.py +++ b/trove/extensions/mgmt/quota/service.py @@ -29,12 +29,21 @@ LOG = logging.getLogger(__name__) class QuotaController(wsgi.Controller): """Controller for quota functionality.""" - @admin_context def show(self, req, tenant_id, id): - """Return all quotas for this tenant.""" + """Return all quotas for this tenant. + + Regular tenant can get his own resource quota. + Admin user can get quota for any tenant. + """ LOG.info("Indexing quota info for tenant '%(id)s'\n" "req : '%(req)s'\n\n", {"id": id, "req": req}) + context = req.environ[wsgi.CONTEXT_KEY] + if id != tenant_id and not context.is_admin: + raise exception.TroveOperationAuthError( + tenant_id=tenant_id + ) + usages = quota_engine.get_all_quota_usages_by_tenant(id) limits = quota_engine.get_all_quotas_by_tenant(id) for key in usages.keys(): diff --git a/trove/tests/unittests/extensions/mgmt/quota/__init__.py b/trove/tests/unittests/extensions/mgmt/quota/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/trove/tests/unittests/extensions/mgmt/quota/test_service.py b/trove/tests/unittests/extensions/mgmt/quota/test_service.py new file mode 100644 index 00000000..5c853255 --- /dev/null +++ b/trove/tests/unittests/extensions/mgmt/quota/test_service.py @@ -0,0 +1,81 @@ +# Copyright 2021 Catalyst Cloud +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +from trove.common import exception +from trove.common import wsgi +from trove.extensions.mgmt.quota import service as quota_service +from trove.tests.unittests import trove_testtools +from trove.tests.unittests.util import util + + +class TestQuotaController(trove_testtools.TestCase): + @classmethod + def setUpClass(cls): + util.init_db() + cls.controller = quota_service.QuotaController() + cls.admin_project_id = cls.random_uuid() + super(TestQuotaController, cls).setUpClass() + + @classmethod + def tearDownClass(cls): + util.cleanup_db() + super(TestQuotaController, cls).tearDownClass() + + def test_show_admin_query(self): + user_project_id = self.random_uuid() + req_mock = mock.MagicMock( + environ={ + wsgi.CONTEXT_KEY: mock.MagicMock( + project_id=self.admin_project_id, + is_admin=True + ) + } + ) + result = self.controller.show(req_mock, self.admin_project_id, + user_project_id) + + self.assertEqual(200, result.status) + + def test_show_user_query(self): + """Show the tenant's own quota.""" + user_project_id = self.random_uuid() + req_mock = mock.MagicMock( + environ={ + wsgi.CONTEXT_KEY: mock.MagicMock( + is_admin=False + ) + } + ) + result = self.controller.show(req_mock, user_project_id, + user_project_id) + + self.assertEqual(200, result.status) + + def test_show_user_query_not_allowed(self): + """Show other tenant's quota should fail.""" + user_project_id = self.random_uuid() + req_mock = mock.MagicMock( + environ={ + wsgi.CONTEXT_KEY: mock.MagicMock( + is_admin=False + ) + } + ) + self.assertRaises( + exception.TroveOperationAuthError, + self.controller.show, + req_mock, user_project_id, + self.random_uuid() + ) -- cgit v1.2.1