mirror of
https://github.com/ceph/ceph
synced 2025-01-29 22:43:40 +00:00
mgr/dashboard: Replace RGW proxy controller
Fixes: http://tracker.ceph.com/issues/24436 To fully support the role based authentication/authorization system it is necessary to replace the RGW proxy controller by separate controllers for RGW user and bucket. Signed-off-by: Volker Theile <vtheile@suse.com>
This commit is contained in:
parent
80a51c9714
commit
a98bca6a2f
@ -7,51 +7,90 @@ logger = logging.getLogger(__name__)
|
||||
from .helper import DashboardTestCase, authenticate
|
||||
|
||||
|
||||
class RgwControllerTest(DashboardTestCase):
|
||||
@authenticate
|
||||
def test_rgw_daemon_list(self):
|
||||
data = self._get('/api/rgw/daemon')
|
||||
self.assertStatus(200)
|
||||
class RgwTestCase(DashboardTestCase):
|
||||
|
||||
self.assertEqual(len(data), 1)
|
||||
data = data[0]
|
||||
self.assertIn('id', data)
|
||||
self.assertIn('version', data)
|
||||
self.assertIn('server_hostname', data)
|
||||
maxDiff = None
|
||||
create_test_user = False
|
||||
|
||||
@authenticate
|
||||
def test_rgw_daemon_get(self):
|
||||
data = self._get('/api/rgw/daemon')
|
||||
self.assertStatus(200)
|
||||
data = self._get('/api/rgw/daemon/{}'.format(data[0]['id']))
|
||||
self.assertStatus(200)
|
||||
|
||||
self.assertIn('rgw_metadata', data)
|
||||
self.assertIn('rgw_id', data)
|
||||
self.assertIn('rgw_status', data)
|
||||
self.assertTrue(data['rgw_metadata'])
|
||||
|
||||
|
||||
class RgwApiUserTest(DashboardTestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(RgwApiUserTest, cls).setUpClass()
|
||||
super(RgwTestCase, cls).setUpClass()
|
||||
# Create the administrator account.
|
||||
cls._radosgw_admin_cmd([
|
||||
'user', 'create', '--uid=admin', '--display-name=admin',
|
||||
'--system', '--access-key=admin', '--secret=admin'
|
||||
'user', 'create', '--uid', 'admin', '--display-name', 'admin',
|
||||
'--system', '--access-key', 'admin', '--secret', 'admin'
|
||||
])
|
||||
# Update the dashboard configuration.
|
||||
cls._ceph_cmd(['dashboard', 'set-rgw-api-secret-key', 'admin'])
|
||||
cls._ceph_cmd(['dashboard', 'set-rgw-api-access-key', 'admin'])
|
||||
# Create a test user?
|
||||
if cls.create_test_user:
|
||||
cls._radosgw_admin_cmd([
|
||||
'user', 'create', '--uid', 'teuth-test-user',
|
||||
'--display-name', 'teuth-test-user'
|
||||
])
|
||||
cls._radosgw_admin_cmd([
|
||||
'caps', 'add', '--uid', 'teuth-test-user',
|
||||
'--caps', 'metadata=write'
|
||||
])
|
||||
cls._radosgw_admin_cmd([
|
||||
'subuser', 'create', '--uid', 'teuth-test-user',
|
||||
'--subuser', 'teuth-test-subuser', '--access',
|
||||
'full', '--key-type', 's3', '--access-key',
|
||||
'xyz123'
|
||||
])
|
||||
cls._radosgw_admin_cmd([
|
||||
'subuser', 'create', '--uid', 'teuth-test-user',
|
||||
'--subuser', 'teuth-test-subuser2', '--access',
|
||||
'full', '--key-type', 'swift'
|
||||
])
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
if cls.create_test_user:
|
||||
cls._radosgw_admin_cmd(['user', 'rm', '--uid=teuth-test-user'])
|
||||
super(DashboardTestCase, cls).tearDownClass()
|
||||
|
||||
def get_rgw_user(self, uid):
|
||||
return self._get('/api/rgw/user/{}'.format(uid))
|
||||
|
||||
def find_in_list(self, key, value, data):
|
||||
"""
|
||||
Helper function to find an object with the specified key/value
|
||||
in a list.
|
||||
:param key: The name of the key.
|
||||
:param value: The value to search for.
|
||||
:param data: The list to process.
|
||||
:return: Returns the found object or None.
|
||||
"""
|
||||
return next(iter(filter(lambda x: x[key] == value, data)), None)
|
||||
|
||||
|
||||
class RgwApiCredentialsTest(RgwTestCase):
|
||||
|
||||
def setUp(self):
|
||||
# Restart the Dashboard module to ensure that the connection to the
|
||||
# RGW Admin Ops API is re-established with the new credentials.
|
||||
self._ceph_cmd(['mgr', 'module', 'disable', 'dashboard'])
|
||||
self._ceph_cmd(['mgr', 'module', 'enable', 'dashboard', '--force'])
|
||||
# Set the default credentials.
|
||||
self._ceph_cmd(['dashboard', 'set-rgw-api-user-id', ''])
|
||||
self._ceph_cmd(['dashboard', 'set-rgw-api-secret-key', 'admin'])
|
||||
self._ceph_cmd(['dashboard', 'set-rgw-api-access-key', 'admin'])
|
||||
|
||||
@authenticate
|
||||
def test_no_access_secret_key(self):
|
||||
self._ceph_cmd(['dashboard', 'set-rgw-api-secret-key', ''])
|
||||
self._ceph_cmd(['dashboard', 'set-rgw-api-access-key', ''])
|
||||
resp = self._get('/api/rgw/user')
|
||||
self.assertStatus(500)
|
||||
self.assertIn('detail', resp)
|
||||
self.assertIn('component', resp)
|
||||
self.assertIn('No RGW credentials found', resp['detail'])
|
||||
self.assertEquals(resp['component'], 'rgw')
|
||||
|
||||
@authenticate
|
||||
def test_success(self):
|
||||
self._ceph_cmd(['dashboard', 'set-rgw-api-user-id', ''])
|
||||
data = self._get('/api/rgw/status')
|
||||
self.assertStatus(200)
|
||||
self.assertIn('available', data)
|
||||
@ -59,7 +98,7 @@ class RgwApiUserTest(DashboardTestCase):
|
||||
self.assertTrue(data['available'])
|
||||
|
||||
@authenticate
|
||||
def test_failure(self):
|
||||
def test_invalid_user_id(self):
|
||||
self._ceph_cmd(['dashboard', 'set-rgw-api-user-id', 'xyz'])
|
||||
data = self._get('/api/rgw/status')
|
||||
self.assertStatus(200)
|
||||
@ -70,32 +109,115 @@ class RgwApiUserTest(DashboardTestCase):
|
||||
data['message'])
|
||||
|
||||
|
||||
class RgwProxyExceptionsTest(DashboardTestCase):
|
||||
class RgwBucketTest(RgwTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(RgwProxyExceptionsTest, cls).setUpClass()
|
||||
|
||||
cls._ceph_cmd(['dashboard', 'set-rgw-api-secret-key', ''])
|
||||
cls._ceph_cmd(['dashboard', 'set-rgw-api-access-key', ''])
|
||||
cls.create_test_user = True
|
||||
super(RgwBucketTest, cls).setUpClass()
|
||||
|
||||
@authenticate
|
||||
def test_no_credentials_exception(self):
|
||||
resp = self._get('/api/rgw/proxy/status')
|
||||
self.assertStatus(500)
|
||||
self.assertIn('detail', resp)
|
||||
def test_all(self):
|
||||
# Create a new bucket.
|
||||
self._post(
|
||||
'/api/rgw/bucket',
|
||||
params={
|
||||
'bucket': 'teuth-test-bucket',
|
||||
'uid': 'admin'
|
||||
})
|
||||
self.assertStatus(201)
|
||||
data = self.jsonBody()
|
||||
self.assertIn('bucket_info', data)
|
||||
data = data['bucket_info']
|
||||
self.assertIn('bucket', data)
|
||||
self.assertIn('quota', data)
|
||||
self.assertIn('creation_time', data)
|
||||
self.assertIn('name', data['bucket'])
|
||||
self.assertIn('bucket_id', data['bucket'])
|
||||
self.assertEquals(data['bucket']['name'], 'teuth-test-bucket')
|
||||
|
||||
# List all buckets.
|
||||
data = self._get('/api/rgw/bucket')
|
||||
self.assertStatus(200)
|
||||
self.assertEqual(len(data), 1)
|
||||
self.assertIn('teuth-test-bucket', data)
|
||||
|
||||
# Get the bucket.
|
||||
data = self._get('/api/rgw/bucket/teuth-test-bucket')
|
||||
self.assertStatus(200)
|
||||
self.assertIn('id', data)
|
||||
self.assertIn('bucket', data)
|
||||
self.assertIn('bucket_quota', data)
|
||||
self.assertIn('owner', data)
|
||||
self.assertEquals(data['bucket'], 'teuth-test-bucket')
|
||||
self.assertEquals(data['owner'], 'admin')
|
||||
|
||||
# Update the bucket.
|
||||
self._put(
|
||||
'/api/rgw/bucket/teuth-test-bucket',
|
||||
params={
|
||||
'bucket_id': data['id'],
|
||||
'uid': 'teuth-test-user'
|
||||
})
|
||||
self.assertStatus(200)
|
||||
data = self._get('/api/rgw/bucket/teuth-test-bucket')
|
||||
self.assertStatus(200)
|
||||
self.assertEquals(data['owner'], 'teuth-test-user')
|
||||
|
||||
# Delete the bucket.
|
||||
self._delete('/api/rgw/bucket/teuth-test-bucket')
|
||||
self.assertStatus(204)
|
||||
data = self._get('/api/rgw/bucket')
|
||||
self.assertStatus(200)
|
||||
self.assertEqual(len(data), 0)
|
||||
|
||||
|
||||
class RgwProxyTest(DashboardTestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(RgwProxyTest, cls).setUpClass()
|
||||
cls._radosgw_admin_cmd([
|
||||
class RgwDaemonTest(DashboardTestCase):
|
||||
|
||||
@authenticate
|
||||
def test_list(self):
|
||||
data = self._get('/api/rgw/daemon')
|
||||
self.assertStatus(200)
|
||||
self.assertEqual(len(data), 1)
|
||||
data = data[0]
|
||||
self.assertIn('id', data)
|
||||
self.assertIn('version', data)
|
||||
self.assertIn('server_hostname', data)
|
||||
|
||||
@authenticate
|
||||
def test_get(self):
|
||||
data = self._get('/api/rgw/daemon')
|
||||
self.assertStatus(200)
|
||||
|
||||
data = self._get('/api/rgw/daemon/{}'.format(data[0]['id']))
|
||||
self.assertStatus(200)
|
||||
self.assertIn('rgw_metadata', data)
|
||||
self.assertIn('rgw_id', data)
|
||||
self.assertIn('rgw_status', data)
|
||||
self.assertTrue(data['rgw_metadata'])
|
||||
|
||||
@authenticate
|
||||
def test_status(self):
|
||||
self._radosgw_admin_cmd([
|
||||
'user', 'create', '--uid=admin', '--display-name=admin',
|
||||
'--system', '--access-key=admin', '--secret=admin'
|
||||
])
|
||||
cls._ceph_cmd(['dashboard', 'set-rgw-api-secret-key', 'admin'])
|
||||
cls._ceph_cmd(['dashboard', 'set-rgw-api-access-key', 'admin'])
|
||||
self._ceph_cmd(['dashboard', 'set-rgw-api-user-id', 'admin'])
|
||||
self._ceph_cmd(['dashboard', 'set-rgw-api-secret-key', 'admin'])
|
||||
self._ceph_cmd(['dashboard', 'set-rgw-api-access-key', 'admin'])
|
||||
|
||||
data = self._get('/api/rgw/status')
|
||||
self.assertStatus(200)
|
||||
self.assertIn('available', data)
|
||||
self.assertIn('message', data)
|
||||
self.assertTrue(data['available'])
|
||||
|
||||
|
||||
class RgwUserTest(RgwTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(RgwUserTest, cls).setUpClass()
|
||||
|
||||
def _assert_user_data(self, data):
|
||||
self.assertIn('caps', data)
|
||||
@ -110,71 +232,308 @@ class RgwProxyTest(DashboardTestCase):
|
||||
self.assertIn('tenant', data)
|
||||
self.assertIn('user_id', data)
|
||||
|
||||
def _test_put(self):
|
||||
self._put(
|
||||
'/api/rgw/proxy/user',
|
||||
params={
|
||||
'uid': 'teuth-test-user',
|
||||
'display-name': 'display name',
|
||||
})
|
||||
data = self._resp.json()
|
||||
|
||||
@authenticate
|
||||
def test_get(self):
|
||||
data = self.get_rgw_user('admin')
|
||||
self.assertStatus(200)
|
||||
self._assert_user_data(data)
|
||||
self.assertEquals(data['user_id'], 'admin')
|
||||
|
||||
@authenticate
|
||||
def test_list(self):
|
||||
data = self._get('/api/rgw/user')
|
||||
self.assertStatus(200)
|
||||
self.assertGreaterEqual(len(data), 1)
|
||||
self.assertIn('admin', data)
|
||||
|
||||
data = self._get(
|
||||
'/api/rgw/proxy/user', params={'uid': 'teuth-test-user'})
|
||||
|
||||
self.assertStatus(200)
|
||||
self.assertEqual(data['user_id'], 'teuth-test-user')
|
||||
|
||||
def _test_get(self):
|
||||
data = self._get(
|
||||
'/api/rgw/proxy/user', params={'uid': 'teuth-test-user'})
|
||||
|
||||
@authenticate
|
||||
def test_create_update_delete(self):
|
||||
# Create a new user.
|
||||
self._post('/api/rgw/user', params={
|
||||
'uid': 'teuth-test-user',
|
||||
'display_name': 'display name'
|
||||
})
|
||||
self.assertStatus(201)
|
||||
data = self.jsonBody()
|
||||
self._assert_user_data(data)
|
||||
self.assertEquals(data['user_id'], 'teuth-test-user')
|
||||
self.assertEquals(data['display_name'], 'display name')
|
||||
|
||||
# Get the user.
|
||||
data = self.get_rgw_user('teuth-test-user')
|
||||
self.assertStatus(200)
|
||||
self._assert_user_data(data)
|
||||
self.assertEquals(data['user_id'], 'teuth-test-user')
|
||||
|
||||
def _test_post(self):
|
||||
"""Updates the user"""
|
||||
self._post(
|
||||
'/api/rgw/proxy/user',
|
||||
# Update the user.
|
||||
self._put(
|
||||
'/api/rgw/user/teuth-test-user',
|
||||
params={
|
||||
'uid': 'teuth-test-user',
|
||||
'display-name': 'new name'
|
||||
'display_name': 'new name'
|
||||
})
|
||||
|
||||
self.assertStatus(200)
|
||||
self._assert_user_data(self._resp.json())
|
||||
self.assertEqual(self._resp.json()['display_name'], 'new name')
|
||||
data = self.jsonBody()
|
||||
self._assert_user_data(data)
|
||||
self.assertEqual(data['display_name'], 'new name')
|
||||
|
||||
def _test_delete(self):
|
||||
self._delete('/api/rgw/proxy/user', params={'uid': 'teuth-test-user'})
|
||||
self.assertStatus(200)
|
||||
|
||||
self._delete('/api/rgw/proxy/user', params={'uid': 'teuth-test-user'})
|
||||
# Delete the user.
|
||||
self._delete('/api/rgw/user/teuth-test-user')
|
||||
self.assertStatus(204)
|
||||
self.get_rgw_user('teuth-test-user')
|
||||
self.assertStatus(500)
|
||||
resp = self._resp.json()
|
||||
resp = self.jsonBody()
|
||||
self.assertIn('detail', resp)
|
||||
self.assertIn('failed request with status code 404', resp['detail'])
|
||||
self.assertIn('"Code":"NoSuchUser"', resp['detail'])
|
||||
self.assertIn('"HostId"', resp['detail'])
|
||||
self.assertIn('"RequestId"', resp['detail'])
|
||||
|
||||
|
||||
class RgwUserCapabilityTest(RgwTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.create_test_user = True
|
||||
super(RgwUserCapabilityTest, cls).setUpClass()
|
||||
|
||||
@authenticate
|
||||
def test_rgw_proxy(self):
|
||||
"""Test basic request types"""
|
||||
self.maxDiff = None
|
||||
def test_set(self):
|
||||
self._post(
|
||||
'/api/rgw/user/teuth-test-user/capability',
|
||||
params={
|
||||
'type': 'usage',
|
||||
'perm': 'read'
|
||||
})
|
||||
self.assertStatus(201)
|
||||
data = self.jsonBody()
|
||||
self.assertEqual(len(data), 1)
|
||||
data = data[0]
|
||||
self.assertEqual(data['type'], 'usage')
|
||||
self.assertEqual(data['perm'], 'read')
|
||||
|
||||
# PUT - Create a user
|
||||
self._test_put()
|
||||
# Get the user data to validate the capabilities.
|
||||
data = self.get_rgw_user('teuth-test-user')
|
||||
self.assertStatus(200)
|
||||
self.assertGreaterEqual(len(data['caps']), 1)
|
||||
self.assertEqual(data['caps'][0]['type'], 'usage')
|
||||
self.assertEqual(data['caps'][0]['perm'], 'read')
|
||||
|
||||
# GET - Get the user details
|
||||
self._test_get()
|
||||
@authenticate
|
||||
def test_delete(self):
|
||||
self._delete(
|
||||
'/api/rgw/user/teuth-test-user/capability',
|
||||
params={
|
||||
'type': 'metadata',
|
||||
'perm': 'write'
|
||||
})
|
||||
self.assertStatus(204)
|
||||
|
||||
# POST - Update the user details
|
||||
self._test_post()
|
||||
# Get the user data to validate the capabilities.
|
||||
data = self.get_rgw_user('teuth-test-user')
|
||||
self.assertStatus(200)
|
||||
self.assertEqual(len(data['caps']), 0)
|
||||
|
||||
# DELETE - Delete the user
|
||||
self._test_delete()
|
||||
|
||||
class RgwUserKeyTest(RgwTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.create_test_user = True
|
||||
super(RgwUserKeyTest, cls).setUpClass()
|
||||
|
||||
@authenticate
|
||||
def test_create_s3(self):
|
||||
self._post(
|
||||
'/api/rgw/user/teuth-test-user/key',
|
||||
params={
|
||||
'key_type': 's3',
|
||||
'generate_key': 'false',
|
||||
'access_key': 'abc987',
|
||||
'secret_key': 'aaabbbccc'
|
||||
})
|
||||
data = self.jsonBody()
|
||||
self.assertStatus(201)
|
||||
self.assertGreaterEqual(len(data), 3)
|
||||
key = self.find_in_list('access_key', 'abc987', data)
|
||||
self.assertIsInstance(key, object)
|
||||
self.assertEqual(key['secret_key'], 'aaabbbccc')
|
||||
|
||||
@authenticate
|
||||
def test_create_swift(self):
|
||||
self._post(
|
||||
'/api/rgw/user/teuth-test-user/key',
|
||||
params={
|
||||
'key_type': 'swift',
|
||||
'subuser': 'teuth-test-subuser',
|
||||
'generate_key': 'false',
|
||||
'secret_key': 'xxxyyyzzz'
|
||||
})
|
||||
data = self.jsonBody()
|
||||
self.assertStatus(201)
|
||||
self.assertGreaterEqual(len(data), 2)
|
||||
key = self.find_in_list('secret_key', 'xxxyyyzzz', data)
|
||||
self.assertIsInstance(key, object)
|
||||
|
||||
@authenticate
|
||||
def test_delete_s3(self):
|
||||
self._delete(
|
||||
'/api/rgw/user/teuth-test-user/key',
|
||||
params={
|
||||
'key_type': 's3',
|
||||
'access_key': 'xyz123'
|
||||
})
|
||||
self.assertStatus(204)
|
||||
|
||||
@authenticate
|
||||
def test_delete_swift(self):
|
||||
self._delete(
|
||||
'/api/rgw/user/teuth-test-user/key',
|
||||
params={
|
||||
'key_type': 'swift',
|
||||
'subuser': 'teuth-test-user:teuth-test-subuser2'
|
||||
})
|
||||
self.assertStatus(204)
|
||||
|
||||
|
||||
class RgwUserQuotaTest(RgwTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.create_test_user = True
|
||||
super(RgwUserQuotaTest, cls).setUpClass()
|
||||
|
||||
def _assert_quota(self, data):
|
||||
self.assertIn('user_quota', data)
|
||||
self.assertIn('max_objects', data['user_quota'])
|
||||
self.assertIn('enabled', data['user_quota'])
|
||||
self.assertIn('max_size_kb', data['user_quota'])
|
||||
self.assertIn('max_size', data['user_quota'])
|
||||
self.assertIn('bucket_quota', data)
|
||||
self.assertIn('max_objects', data['bucket_quota'])
|
||||
self.assertIn('enabled', data['bucket_quota'])
|
||||
self.assertIn('max_size_kb', data['bucket_quota'])
|
||||
self.assertIn('max_size', data['bucket_quota'])
|
||||
|
||||
@authenticate
|
||||
def test_get_quota(self):
|
||||
data = self._get('/api/rgw/user/teuth-test-user/quota')
|
||||
self.assertStatus(200)
|
||||
self._assert_quota(data)
|
||||
|
||||
@authenticate
|
||||
def test_set_user_quota(self):
|
||||
self._put(
|
||||
'/api/rgw/user/teuth-test-user/quota',
|
||||
params={
|
||||
'quota_type': 'user',
|
||||
'enabled': 'true',
|
||||
'max_size_kb': 2048,
|
||||
'max_objects': 101
|
||||
})
|
||||
self.assertStatus(200)
|
||||
|
||||
data = self._get('/api/rgw/user/teuth-test-user/quota')
|
||||
self.assertStatus(200)
|
||||
self._assert_quota(data)
|
||||
self.assertEqual(data['user_quota']['max_objects'], 101)
|
||||
self.assertTrue(data['user_quota']['enabled'])
|
||||
self.assertEqual(data['user_quota']['max_size_kb'], 2048)
|
||||
|
||||
@authenticate
|
||||
def test_set_bucket_quota(self):
|
||||
self._put(
|
||||
'/api/rgw/user/teuth-test-user/quota',
|
||||
params={
|
||||
'quota_type': 'bucket',
|
||||
'enabled': 'false',
|
||||
'max_size_kb': 4096,
|
||||
'max_objects': 2000
|
||||
})
|
||||
self.assertStatus(200)
|
||||
|
||||
data = self._get('/api/rgw/user/teuth-test-user/quota')
|
||||
self.assertStatus(200)
|
||||
self._assert_quota(data)
|
||||
self.assertEqual(data['bucket_quota']['max_objects'], 2000)
|
||||
self.assertFalse(data['bucket_quota']['enabled'])
|
||||
self.assertEqual(data['bucket_quota']['max_size_kb'], 4096)
|
||||
|
||||
|
||||
class RgwUserSubuserTest(RgwTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.create_test_user = True
|
||||
super(RgwUserSubuserTest, cls).setUpClass()
|
||||
|
||||
@authenticate
|
||||
def test_create_swift(self):
|
||||
self._post(
|
||||
'/api/rgw/user/teuth-test-user/subuser',
|
||||
params={
|
||||
'subuser': 'tux',
|
||||
'access': 'readwrite',
|
||||
'key_type': 'swift'
|
||||
})
|
||||
self.assertStatus(201)
|
||||
data = self.jsonBody()
|
||||
subuser = self.find_in_list('id', 'teuth-test-user:tux', data)
|
||||
self.assertIsInstance(subuser, object)
|
||||
self.assertEqual(subuser['permissions'], 'read-write')
|
||||
|
||||
# Get the user data to validate the keys.
|
||||
data = self.get_rgw_user('teuth-test-user')
|
||||
self.assertStatus(200)
|
||||
key = self.find_in_list('user', 'teuth-test-user:tux', data['swift_keys'])
|
||||
self.assertIsInstance(key, object)
|
||||
|
||||
@authenticate
|
||||
def test_create_s3(self):
|
||||
self._post(
|
||||
'/api/rgw/user/teuth-test-user/subuser',
|
||||
params={
|
||||
'subuser': 'hugo',
|
||||
'access': 'write',
|
||||
'generate_secret': 'false',
|
||||
'access_key': 'yyy',
|
||||
'secret_key': 'xxx'
|
||||
})
|
||||
self.assertStatus(201)
|
||||
data = self.jsonBody()
|
||||
subuser = self.find_in_list('id', 'teuth-test-user:hugo', data)
|
||||
self.assertIsInstance(subuser, object)
|
||||
self.assertEqual(subuser['permissions'], 'write')
|
||||
|
||||
# Get the user data to validate the keys.
|
||||
data = self.get_rgw_user('teuth-test-user')
|
||||
self.assertStatus(200)
|
||||
key = self.find_in_list('user', 'teuth-test-user:hugo', data['keys'])
|
||||
self.assertIsInstance(key, object)
|
||||
self.assertEqual(key['secret_key'], 'xxx')
|
||||
|
||||
@authenticate
|
||||
def test_delete_w_purge(self):
|
||||
self._delete(
|
||||
'/api/rgw/user/teuth-test-user/subuser/teuth-test-subuser2')
|
||||
self.assertStatus(204)
|
||||
|
||||
# Get the user data to check that the keys don't exist anymore.
|
||||
data = self.get_rgw_user('teuth-test-user')
|
||||
self.assertStatus(200)
|
||||
key = self.find_in_list('user', 'teuth-test-user:teuth-test-subuser2',
|
||||
data['swift_keys'])
|
||||
self.assertIsNone(key)
|
||||
|
||||
@authenticate
|
||||
def test_delete_wo_purge(self):
|
||||
self._delete(
|
||||
'/api/rgw/user/teuth-test-user/subuser/teuth-test-subuser',
|
||||
params={'purge_keys': 'false'})
|
||||
self.assertStatus(204)
|
||||
|
||||
# Get the user data to check whether they keys still exist.
|
||||
data = self.get_rgw_user('teuth-test-user')
|
||||
self.assertStatus(200)
|
||||
key = self.find_in_list('user', 'teuth-test-user:teuth-test-subuser',
|
||||
data['keys'])
|
||||
self.assertIsInstance(key, object)
|
||||
|
@ -509,19 +509,19 @@ class BaseController(object):
|
||||
content_length = int(cherrypy.request.headers['Content-Length'])
|
||||
body = cherrypy.request.body.read(content_length)
|
||||
if not body:
|
||||
return func(*args, **kwargs)
|
||||
|
||||
try:
|
||||
data = json.loads(body.decode('utf-8'))
|
||||
except Exception as e:
|
||||
raise cherrypy.HTTPError(400, 'Failed to decode JSON: {}'
|
||||
.format(str(e)))
|
||||
kwargs.update(data.items())
|
||||
ret = func(*args, **kwargs)
|
||||
ret = func(*args, **kwargs)
|
||||
else:
|
||||
try:
|
||||
data = json.loads(body.decode('utf-8'))
|
||||
except Exception as e:
|
||||
raise cherrypy.HTTPError(400, 'Failed to decode JSON: {}'
|
||||
.format(str(e)))
|
||||
kwargs.update(data.items())
|
||||
ret = func(*args, **kwargs)
|
||||
|
||||
if json_response:
|
||||
cherrypy.response.headers['Content-Type'] = 'application/json'
|
||||
return json.dumps(ret).encode('utf8')
|
||||
ret = json.dumps(ret).encode('utf8')
|
||||
return ret
|
||||
return inner
|
||||
|
||||
|
@ -4,12 +4,12 @@ from __future__ import absolute_import
|
||||
import json
|
||||
import cherrypy
|
||||
|
||||
from . import ApiController, BaseController, RESTController, AuthRequired, \
|
||||
Endpoint, Proxy
|
||||
from . import ApiController, BaseController, RESTController, AuthRequired, Endpoint
|
||||
from .. import logger
|
||||
from ..services.ceph_service import CephService
|
||||
from ..services.rgw_client import RgwClient
|
||||
from ..rest_client import RequestException
|
||||
from ..exceptions import DashboardException
|
||||
|
||||
|
||||
@ApiController('/rgw')
|
||||
@ -73,7 +73,7 @@ class RgwDaemon(RESTController):
|
||||
try:
|
||||
status = json.loads(status['json'])
|
||||
except ValueError:
|
||||
logger.warning("%s had invalid status json", service['id'])
|
||||
logger.warning('%s had invalid status json', service['id'])
|
||||
status = {}
|
||||
else:
|
||||
logger.warning('%s has no key "json" in status', service['id'])
|
||||
@ -83,40 +83,179 @@ class RgwDaemon(RESTController):
|
||||
return daemon
|
||||
|
||||
|
||||
@ApiController('/rgw/proxy')
|
||||
@AuthRequired()
|
||||
class RgwProxy(BaseController):
|
||||
class RgwRESTController(RESTController):
|
||||
|
||||
@Proxy()
|
||||
def __call__(self, path, **params):
|
||||
def proxy(self, method, path, params=None, json_response=True):
|
||||
try:
|
||||
rgw_client = RgwClient.admin_instance()
|
||||
|
||||
method = cherrypy.request.method
|
||||
data = None
|
||||
|
||||
if cherrypy.request.body.length:
|
||||
data = cherrypy.request.body.read()
|
||||
|
||||
return rgw_client.proxy(method, path, params, data)
|
||||
except RequestException as e:
|
||||
# Always use status code 500 and NOT the status that may delivered
|
||||
# by the exception. That's because we do not want to forward e.g.
|
||||
# 401 or 404 that may trigger unwanted actions in the UI.
|
||||
cherrypy.response.headers['Content-Type'] = 'application/json'
|
||||
cherrypy.response.status = 500
|
||||
return json.dumps({'detail': str(e)}).encode('utf-8')
|
||||
instance = RgwClient.admin_instance()
|
||||
result = instance.proxy(method, path, params, None)
|
||||
if json_response and result != '':
|
||||
result = json.loads(result.decode('utf-8'))
|
||||
return result
|
||||
except (DashboardException, RequestException) as e:
|
||||
raise DashboardException(e, http_status_code=500, component='rgw')
|
||||
|
||||
|
||||
@ApiController('/rgw/bucket')
|
||||
@AuthRequired()
|
||||
class RgwBucket(RESTController):
|
||||
class RgwBucket(RgwRESTController):
|
||||
|
||||
def list(self):
|
||||
return self.proxy('GET', 'bucket')
|
||||
|
||||
def get(self, bucket):
|
||||
return self.proxy('GET', 'bucket', {'bucket': bucket})
|
||||
|
||||
def create(self, bucket, uid):
|
||||
try:
|
||||
rgw_client = RgwClient.instance(uid)
|
||||
return rgw_client.create_bucket(bucket)
|
||||
except RequestException as e:
|
||||
cherrypy.response.headers['Content-Type'] = 'application/json'
|
||||
cherrypy.response.status = 500
|
||||
return {'detail': str(e)}
|
||||
raise DashboardException(e, http_status_code=500, component='rgw')
|
||||
|
||||
def set(self, bucket, bucket_id, uid):
|
||||
return self.proxy('PUT', 'bucket', {
|
||||
'bucket': bucket,
|
||||
'bucket-id': bucket_id,
|
||||
'uid': uid
|
||||
}, json_response=False)
|
||||
|
||||
def delete(self, bucket, purge_objects='true'):
|
||||
return self.proxy('DELETE', 'bucket', {
|
||||
'bucket': bucket,
|
||||
'purge-objects': purge_objects
|
||||
}, json_response=False)
|
||||
|
||||
|
||||
@ApiController('/rgw/user')
|
||||
@AuthRequired()
|
||||
class RgwUser(RgwRESTController):
|
||||
|
||||
def list(self):
|
||||
return self.proxy('GET', 'metadata/user')
|
||||
|
||||
def get(self, uid):
|
||||
return self.proxy('GET', 'user', {'uid': uid})
|
||||
|
||||
def create(self, uid, display_name, email=None, max_buckets=None,
|
||||
suspended=None, generate_key=None, access_key=None,
|
||||
secret_key=None):
|
||||
params = {'uid': uid}
|
||||
if display_name is not None:
|
||||
params['display-name'] = display_name
|
||||
if email is not None:
|
||||
params['email'] = email
|
||||
if max_buckets is not None:
|
||||
params['max-buckets'] = max_buckets
|
||||
if suspended is not None:
|
||||
params['suspended'] = suspended
|
||||
if generate_key is not None:
|
||||
params['generate-key'] = generate_key
|
||||
if access_key is not None:
|
||||
params['access-key'] = access_key
|
||||
if secret_key is not None:
|
||||
params['secret-key'] = secret_key
|
||||
return self.proxy('PUT', 'user', params)
|
||||
|
||||
def set(self, uid, display_name=None, email=None, max_buckets=None,
|
||||
suspended=None):
|
||||
params = {'uid': uid}
|
||||
if display_name is not None:
|
||||
params['display-name'] = display_name
|
||||
if email is not None:
|
||||
params['email'] = email
|
||||
if max_buckets is not None:
|
||||
params['max-buckets'] = max_buckets
|
||||
if suspended is not None:
|
||||
params['suspended'] = suspended
|
||||
return self.proxy('POST', 'user', params)
|
||||
|
||||
def delete(self, uid):
|
||||
try:
|
||||
instance = RgwClient.admin_instance()
|
||||
# Ensure the user is not configured to access the RGW Object Gateway.
|
||||
if instance.userid == uid:
|
||||
raise DashboardException(msg='Unable to delete "{}" - this user '
|
||||
'account is required for managing the '
|
||||
'Object Gateway'.format(uid))
|
||||
# Finally redirect request to the RGW proxy.
|
||||
return self.proxy('DELETE', 'user', {'uid': uid}, json_response=False)
|
||||
except (DashboardException, RequestException) as e:
|
||||
raise DashboardException(e, component='rgw')
|
||||
|
||||
# pylint: disable=redefined-builtin
|
||||
@RESTController.Resource(method='POST', path='/capability', status=201)
|
||||
def create_cap(self, uid, type, perm):
|
||||
return self.proxy('PUT', 'user?caps', {
|
||||
'uid': uid,
|
||||
'user-caps': '{}={}'.format(type, perm)
|
||||
})
|
||||
|
||||
# pylint: disable=redefined-builtin
|
||||
@RESTController.Resource(method='DELETE', path='/capability', status=204)
|
||||
def delete_cap(self, uid, type, perm):
|
||||
return self.proxy('DELETE', 'user?caps', {
|
||||
'uid': uid,
|
||||
'user-caps': '{}={}'.format(type, perm)
|
||||
})
|
||||
|
||||
@RESTController.Resource(method='POST', path='/key', status=201)
|
||||
def create_key(self, uid, key_type='s3', subuser=None, generate_key='true',
|
||||
access_key=None, secret_key=None):
|
||||
params = {'uid': uid, 'key-type': key_type, 'generate-key': generate_key}
|
||||
if subuser is not None:
|
||||
params['subuser'] = subuser
|
||||
if access_key is not None:
|
||||
params['access-key'] = access_key
|
||||
if secret_key is not None:
|
||||
params['secret-key'] = secret_key
|
||||
return self.proxy('PUT', 'user?key', params)
|
||||
|
||||
@RESTController.Resource(method='DELETE', path='/key', status=204)
|
||||
def delete_key(self, uid, key_type='s3', subuser=None, access_key=None):
|
||||
params = {'uid': uid, 'key-type': key_type}
|
||||
if subuser is not None:
|
||||
params['subuser'] = subuser
|
||||
if access_key is not None:
|
||||
params['access-key'] = access_key
|
||||
return self.proxy('DELETE', 'user?key', params, json_response=False)
|
||||
|
||||
@RESTController.Resource(method='GET', path='/quota')
|
||||
def get_quota(self, uid):
|
||||
return self.proxy('GET', 'user?quota', {'uid': uid})
|
||||
|
||||
@RESTController.Resource(method='PUT', path='/quota')
|
||||
def set_quota(self, uid, quota_type, enabled, max_size_kb, max_objects):
|
||||
return self.proxy('PUT', 'user?quota', {
|
||||
'uid': uid,
|
||||
'quota-type': quota_type,
|
||||
'enabled': enabled,
|
||||
'max-size-kb': max_size_kb,
|
||||
'max-objects': max_objects
|
||||
}, json_response=False)
|
||||
|
||||
@RESTController.Resource(method='POST', path='/subuser', status=201)
|
||||
def create_subuser(self, uid, subuser, access, key_type='s3',
|
||||
generate_secret='true', access_key=None,
|
||||
secret_key=None):
|
||||
return self.proxy('PUT', 'user', {
|
||||
'uid': uid,
|
||||
'subuser': subuser,
|
||||
'key-type': key_type,
|
||||
'access': access,
|
||||
'generate-secret': generate_secret,
|
||||
'access-key': access_key,
|
||||
'secret-key': secret_key
|
||||
})
|
||||
|
||||
@RESTController.Resource(method='DELETE', path='/subuser/{subuser}', status=204)
|
||||
def delete_subuser(self, uid, subuser, purge_keys='true'):
|
||||
"""
|
||||
:param purge_keys: Set to False to do not purge the keys.
|
||||
Note, this only works for s3 subusers.
|
||||
"""
|
||||
return self.proxy('DELETE', 'user', {
|
||||
'uid': uid,
|
||||
'subuser': subuser,
|
||||
'purge-keys': purge_keys
|
||||
}, json_response=False)
|
||||
|
@ -91,7 +91,7 @@ export class RgwBucketFormComponent implements OnInit {
|
||||
if (this.editing) {
|
||||
// Edit
|
||||
const idCtl = this.bucketForm.get('id');
|
||||
this.rgwBucketService.update(idCtl.value, bucketCtl.value, ownerCtl.value).subscribe(
|
||||
this.rgwBucketService.update(bucketCtl.value, idCtl.value, ownerCtl.value).subscribe(
|
||||
() => {
|
||||
this.goToListView();
|
||||
},
|
||||
|
@ -117,12 +117,18 @@
|
||||
<label class="control-label col-sm-3"
|
||||
for="max_buckets"
|
||||
i18n>Max. buckets
|
||||
<span class="required"></span>
|
||||
</label>
|
||||
<div class="col-sm-9">
|
||||
<input id="max_buckets"
|
||||
class="form-control"
|
||||
type="number"
|
||||
formControlName="max_buckets">
|
||||
<span class="help-block"
|
||||
*ngIf="(frm.submitted || userForm.controls.max_buckets.dirty) && userForm.controls.max_buckets.hasError('required')"
|
||||
i18n>
|
||||
This field is required.
|
||||
</span>
|
||||
<span class="help-block"
|
||||
*ngIf="(frm.submitted || userForm.controls.max_buckets.dirty) && userForm.controls.max_buckets.hasError('min')"
|
||||
i18n>
|
||||
|
@ -9,6 +9,7 @@ import { of as observableOf } from 'rxjs';
|
||||
import { RgwUserService } from '../../../shared/api/rgw-user.service';
|
||||
import { SharedModule } from '../../../shared/shared.module';
|
||||
import { configureTestBed } from '../../../shared/unit-test-helper';
|
||||
import { RgwUserS3Key } from '../models/rgw-user-s3-key';
|
||||
import { RgwUserFormComponent } from './rgw-user-form.component';
|
||||
|
||||
describe('RgwUserFormComponent', () => {
|
||||
@ -46,6 +47,53 @@ describe('RgwUserFormComponent', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('s3 key management', () => {
|
||||
let rgwUserService: RgwUserService;
|
||||
|
||||
beforeEach(() => {
|
||||
rgwUserService = TestBed.get(RgwUserService);
|
||||
spyOn(rgwUserService, 'addS3Key').and.stub();
|
||||
});
|
||||
|
||||
it('should not update key', () => {
|
||||
component.setS3Key(new RgwUserS3Key(), 3);
|
||||
expect(component.s3Keys.length).toBe(0);
|
||||
expect(rgwUserService.addS3Key).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should set key', () => {
|
||||
const key = new RgwUserS3Key();
|
||||
key.user = 'test1:subuser2';
|
||||
component.setS3Key(key);
|
||||
expect(component.s3Keys.length).toBe(1);
|
||||
expect(component.s3Keys[0].user).toBe('test1:subuser2');
|
||||
expect(rgwUserService.addS3Key).toHaveBeenCalledWith(
|
||||
'test1', {
|
||||
subuser: 'subuser2',
|
||||
generate_key: 'false',
|
||||
access_key: undefined,
|
||||
secret_key: undefined
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should set key w/o subuser', () => {
|
||||
const key = new RgwUserS3Key();
|
||||
key.user = 'test1';
|
||||
component.setS3Key(key);
|
||||
expect(component.s3Keys.length).toBe(1);
|
||||
expect(component.s3Keys[0].user).toBe('test1');
|
||||
expect(rgwUserService.addS3Key).toHaveBeenCalledWith(
|
||||
'test1', {
|
||||
subuser: '',
|
||||
generate_key: 'false',
|
||||
access_key: undefined,
|
||||
secret_key: undefined
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('quotaMaxSizeValidator', () => {
|
||||
it('should validate max size (1/7)', () => {
|
||||
const resp = component.quotaMaxSizeValidator(new FormControl(''));
|
||||
|
@ -59,7 +59,7 @@ export class RgwUserFormComponent implements OnInit {
|
||||
user_id: [null, [Validators.required], [this.userIdValidator()]],
|
||||
display_name: [null, [Validators.required]],
|
||||
email: [null, [CdValidators.email]],
|
||||
max_buckets: [null, [Validators.min(0)]],
|
||||
max_buckets: [1000, [Validators.required, Validators.min(0)]],
|
||||
suspended: [false],
|
||||
// S3 key
|
||||
generate_key: [true],
|
||||
@ -181,8 +181,8 @@ export class RgwUserFormComponent implements OnInit {
|
||||
value[type + '_quota_max_size'] = quota.max_size;
|
||||
}
|
||||
if (quota.max_objects < 0) {
|
||||
value[type + '_quota_max_size_unlimited'] = true;
|
||||
value[type + '_quota_max_size'] = null;
|
||||
value[type + '_quota_max_objects_unlimited'] = true;
|
||||
value[type + '_quota_max_objects'] = null;
|
||||
} else {
|
||||
value[type + '_quota_max_objects_unlimited'] = false;
|
||||
value[type + '_quota_max_objects'] = quota.max_objects;
|
||||
@ -225,26 +225,27 @@ export class RgwUserFormComponent implements OnInit {
|
||||
if (this.userForm.pristine) {
|
||||
this.goToListView();
|
||||
}
|
||||
const uid = this.userForm.get('user_id').value;
|
||||
if (this.editing) {
|
||||
// Edit
|
||||
if (this._isGeneralDirty()) {
|
||||
const args = this._getApiPostArgs();
|
||||
this.submitObservables.push(this.rgwUserService.post(args));
|
||||
const args = this._getUpdateArgs();
|
||||
this.submitObservables.push(this.rgwUserService.update(uid, args));
|
||||
}
|
||||
} else {
|
||||
// Add
|
||||
const args = this._getApiPutArgs();
|
||||
this.submitObservables.push(this.rgwUserService.put(args));
|
||||
const args = this._getCreateArgs();
|
||||
this.submitObservables.push(this.rgwUserService.create(args));
|
||||
}
|
||||
// Check if user quota has been modified.
|
||||
if (this._isUserQuotaDirty()) {
|
||||
const userQuotaArgs = this._getApiUserQuotaArgs();
|
||||
this.submitObservables.push(this.rgwUserService.putQuota(userQuotaArgs));
|
||||
const userQuotaArgs = this._getUserQuotaArgs();
|
||||
this.submitObservables.push(this.rgwUserService.updateQuota(uid, userQuotaArgs));
|
||||
}
|
||||
// Check if bucket quota has been modified.
|
||||
if (this._isBucketQuotaDirty()) {
|
||||
const bucketQuotaArgs = this._getApiBucketQuotaArgs();
|
||||
this.submitObservables.push(this.rgwUserService.putQuota(bucketQuotaArgs));
|
||||
const bucketQuotaArgs = this._getBucketQuotaArgs();
|
||||
this.submitObservables.push(this.rgwUserService.updateQuota(uid, bucketQuotaArgs));
|
||||
}
|
||||
// Finally execute all observables.
|
||||
observableForkJoin(this.submitObservables).subscribe(
|
||||
@ -304,31 +305,29 @@ export class RgwUserFormComponent implements OnInit {
|
||||
* Add/Update a subuser.
|
||||
*/
|
||||
setSubuser(subuser: RgwUserSubuser, index?: number) {
|
||||
const mapPermissions = {
|
||||
'full-control': 'full',
|
||||
'read-write': 'readwrite'
|
||||
};
|
||||
const uid = this.userForm.get('user_id').value;
|
||||
const args = {
|
||||
subuser: subuser.id,
|
||||
access:
|
||||
subuser.permissions in mapPermissions
|
||||
? mapPermissions[subuser.permissions]
|
||||
: subuser.permissions,
|
||||
key_type: 'swift',
|
||||
secret_key: subuser.secret_key,
|
||||
generate_secret: subuser.generate_secret ? 'true' : 'false'
|
||||
};
|
||||
this.submitObservables.push(this.rgwUserService.createSubuser(uid, args));
|
||||
if (_.isNumber(index)) {
|
||||
// Modify
|
||||
// Create an observable to modify the subuser when the form is submitted.
|
||||
this.submitObservables.push(
|
||||
this.rgwUserService.addSubuser(
|
||||
this.userForm.get('user_id').value,
|
||||
subuser.id,
|
||||
subuser.permissions,
|
||||
subuser.secret_key,
|
||||
subuser.generate_secret
|
||||
)
|
||||
);
|
||||
this.subusers[index] = subuser;
|
||||
} else {
|
||||
// Add
|
||||
// Create an observable to add the subuser when the form is submitted.
|
||||
this.submitObservables.push(
|
||||
this.rgwUserService.addSubuser(
|
||||
this.userForm.get('user_id').value,
|
||||
subuser.id,
|
||||
subuser.permissions,
|
||||
subuser.secret_key,
|
||||
subuser.generate_secret
|
||||
)
|
||||
);
|
||||
this.subusers.push(subuser);
|
||||
// Add a Swift key. If the secret key is auto-generated, then visualize
|
||||
// this to the user by displaying a notification instead of the key.
|
||||
@ -418,16 +417,17 @@ export class RgwUserFormComponent implements OnInit {
|
||||
// Nothing to do here at the moment.
|
||||
} else {
|
||||
// Add
|
||||
// Split the key's user name into its user and subuser parts.
|
||||
const userMatches = key.user.match(/([^:]+)(:(.+))?/);
|
||||
// Create an observable to add the S3 key when the form is submitted.
|
||||
this.submitObservables.push(
|
||||
this.rgwUserService.addS3Key(
|
||||
this.userForm.get('user_id').value,
|
||||
key.user,
|
||||
key.access_key,
|
||||
key.secret_key,
|
||||
key.generate_key
|
||||
)
|
||||
);
|
||||
const uid = userMatches[1];
|
||||
const args = {
|
||||
subuser: userMatches[2] ? userMatches[3] : '',
|
||||
generate_key: key.generate_key ? 'true' : 'false',
|
||||
access_key: key.access_key,
|
||||
secret_key: key.secret_key
|
||||
};
|
||||
this.submitObservables.push(this.rgwUserService.addS3Key(uid, args));
|
||||
// If the access and the secret key are auto-generated, then visualize
|
||||
// this to the user by displaying a notification instead of the key.
|
||||
this.s3Keys.push({
|
||||
@ -578,31 +578,28 @@ export class RgwUserFormComponent implements OnInit {
|
||||
* Helper function to get the arguments of the API request when a new
|
||||
* user is created.
|
||||
*/
|
||||
private _getApiPutArgs() {
|
||||
private _getCreateArgs() {
|
||||
const result = {
|
||||
uid: this.userForm.get('user_id').value,
|
||||
'display-name': this.userForm.get('display_name').value
|
||||
display_name: this.userForm.get('display_name').value,
|
||||
suspended: this.userForm.get('suspended').value,
|
||||
email: '',
|
||||
max_buckets: this.userForm.get('max_buckets').value,
|
||||
generate_key: this.userForm.get('generate_key').value,
|
||||
access_key: '',
|
||||
secret_key: ''
|
||||
};
|
||||
const suspendedCtl = this.userForm.get('suspended');
|
||||
if (suspendedCtl.value) {
|
||||
_.extend(result, { suspended: suspendedCtl.value });
|
||||
}
|
||||
const emailCtl = this.userForm.get('email');
|
||||
if (_.isString(emailCtl.value) && emailCtl.value.length > 0) {
|
||||
_.extend(result, { email: emailCtl.value });
|
||||
}
|
||||
const maxBucketsCtl = this.userForm.get('max_buckets');
|
||||
if (maxBucketsCtl.value > 0) {
|
||||
_.extend(result, { 'max-buckets': maxBucketsCtl.value });
|
||||
_.merge(result, { email: emailCtl.value });
|
||||
}
|
||||
const generateKeyCtl = this.userForm.get('generate_key');
|
||||
if (!generateKeyCtl.value) {
|
||||
_.extend(result, {
|
||||
'access-key': this.userForm.get('access_key').value,
|
||||
'secret-key': this.userForm.get('secret_key').value
|
||||
_.merge(result, {
|
||||
generate_key: false,
|
||||
access_key: this.userForm.get('access_key').value,
|
||||
secret_key: this.userForm.get('secret_key').value
|
||||
});
|
||||
} else {
|
||||
_.extend(result, { 'generate-key': true });
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -611,21 +608,12 @@ export class RgwUserFormComponent implements OnInit {
|
||||
* Helper function to get the arguments for the API request when the user
|
||||
* configuration has been modified.
|
||||
*/
|
||||
private _getApiPostArgs() {
|
||||
const result = {
|
||||
uid: this.userForm.get('user_id').value
|
||||
};
|
||||
const argsMap = {
|
||||
'display-name': 'display_name',
|
||||
email: 'email',
|
||||
'max-buckets': 'max_buckets',
|
||||
suspended: 'suspended'
|
||||
};
|
||||
for (const key of Object.keys(argsMap)) {
|
||||
const ctl = this.userForm.get(argsMap[key]);
|
||||
if (ctl.dirty) {
|
||||
result[key] = ctl.value;
|
||||
}
|
||||
private _getUpdateArgs() {
|
||||
const result = {};
|
||||
const keys = ['display_name', 'email', 'max_buckets', 'suspended'];
|
||||
for (const key of keys) {
|
||||
const ctl = this.userForm.get(key);
|
||||
result[key] = ctl.value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -634,22 +622,21 @@ export class RgwUserFormComponent implements OnInit {
|
||||
* Helper function to get the arguments for the API request when the user
|
||||
* quota configuration has been modified.
|
||||
*/
|
||||
private _getApiUserQuotaArgs(): object {
|
||||
private _getUserQuotaArgs(): object {
|
||||
const result = {
|
||||
uid: this.userForm.get('user_id').value,
|
||||
'quota-type': 'user',
|
||||
quota_type: 'user',
|
||||
enabled: this.userForm.get('user_quota_enabled').value,
|
||||
'max-size-kb': -1,
|
||||
'max-objects': -1
|
||||
max_size_kb: -1,
|
||||
max_objects: -1
|
||||
};
|
||||
if (!this.userForm.get('user_quota_max_size_unlimited').value) {
|
||||
// Convert the given value to bytes.
|
||||
const bytes = new FormatterService().toBytes(this.userForm.get('user_quota_max_size').value);
|
||||
// Finally convert the value to KiB.
|
||||
result['max-size-kb'] = (bytes / 1024).toFixed(0) as any;
|
||||
result['max_size_kb'] = (bytes / 1024).toFixed(0) as any;
|
||||
}
|
||||
if (!this.userForm.get('user_quota_max_objects_unlimited').value) {
|
||||
result['max-objects'] = this.userForm.get('user_quota_max_objects').value;
|
||||
result['max_objects'] = this.userForm.get('user_quota_max_objects').value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -658,13 +645,12 @@ export class RgwUserFormComponent implements OnInit {
|
||||
* Helper function to get the arguments for the API request when the bucket
|
||||
* quota configuration has been modified.
|
||||
*/
|
||||
private _getApiBucketQuotaArgs(): object {
|
||||
private _getBucketQuotaArgs(): object {
|
||||
const result = {
|
||||
uid: this.userForm.get('user_id').value,
|
||||
'quota-type': 'bucket',
|
||||
quota_type: 'bucket',
|
||||
enabled: this.userForm.get('bucket_quota_enabled').value,
|
||||
'max-size-kb': -1,
|
||||
'max-objects': -1
|
||||
max_size_kb: -1,
|
||||
max_objects: -1
|
||||
};
|
||||
if (!this.userForm.get('bucket_quota_max_size_unlimited').value) {
|
||||
// Convert the given value to bytes.
|
||||
@ -672,10 +658,10 @@ export class RgwUserFormComponent implements OnInit {
|
||||
this.userForm.get('bucket_quota_max_size').value
|
||||
);
|
||||
// Finally convert the value to KiB.
|
||||
result['max-size-kb'] = (bytes / 1024).toFixed(0) as any;
|
||||
result['max_size_kb'] = (bytes / 1024).toFixed(0) as any;
|
||||
}
|
||||
if (!this.userForm.get('bucket_quota_max_objects_unlimited').value) {
|
||||
result['max-objects'] = this.userForm.get('bucket_quota_max_objects').value;
|
||||
result['max_objects'] = this.userForm.get('bucket_quota_max_objects').value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ describe('RgwBucketService', () => {
|
||||
service.list().subscribe((resp) => {
|
||||
result = resp;
|
||||
});
|
||||
const req = httpTesting.expectOne('/api/rgw/proxy/bucket');
|
||||
const req = httpTesting.expectOne('/api/rgw/bucket');
|
||||
req.flush([]);
|
||||
expect(req.request.method).toBe('GET');
|
||||
expect(result).toEqual([]);
|
||||
@ -42,13 +42,13 @@ describe('RgwBucketService', () => {
|
||||
service.list().subscribe((resp) => {
|
||||
result = resp;
|
||||
});
|
||||
let req = httpTesting.expectOne('/api/rgw/proxy/bucket');
|
||||
let req = httpTesting.expectOne('/api/rgw/bucket');
|
||||
req.flush(['foo', 'bar']);
|
||||
|
||||
req = httpTesting.expectOne('/api/rgw/proxy/bucket?bucket=foo');
|
||||
req = httpTesting.expectOne('/api/rgw/bucket/foo');
|
||||
req.flush({ name: 'foo' });
|
||||
|
||||
req = httpTesting.expectOne('/api/rgw/proxy/bucket?bucket=bar');
|
||||
req = httpTesting.expectOne('/api/rgw/bucket/bar');
|
||||
req.flush({ name: 'bar' });
|
||||
|
||||
expect(req.request.method).toBe('GET');
|
||||
@ -57,35 +57,31 @@ describe('RgwBucketService', () => {
|
||||
|
||||
it('should call get', () => {
|
||||
service.get('foo').subscribe();
|
||||
const req = httpTesting.expectOne('/api/rgw/proxy/bucket?bucket=foo');
|
||||
const req = httpTesting.expectOne('/api/rgw/bucket/foo');
|
||||
expect(req.request.method).toBe('GET');
|
||||
});
|
||||
|
||||
it('should call create', () => {
|
||||
service.create('foo', 'bar').subscribe();
|
||||
const req = httpTesting.expectOne('/api/rgw/bucket');
|
||||
const req = httpTesting.expectOne('/api/rgw/bucket?bucket=foo&uid=bar');
|
||||
expect(req.request.method).toBe('POST');
|
||||
expect(req.request.body).toEqual({
|
||||
bucket: 'foo',
|
||||
uid: 'bar'
|
||||
});
|
||||
});
|
||||
|
||||
it('should call update', () => {
|
||||
service.update('foo', 'bar', 'baz').subscribe();
|
||||
const req = httpTesting.expectOne('/api/rgw/proxy/bucket?bucket=bar&bucket-id=foo&uid=baz');
|
||||
const req = httpTesting.expectOne('/api/rgw/bucket/foo?bucket_id=bar&uid=baz');
|
||||
expect(req.request.method).toBe('PUT');
|
||||
});
|
||||
|
||||
it('should call delete, with purgeObjects = true', () => {
|
||||
service.delete('foo').subscribe();
|
||||
const req = httpTesting.expectOne('/api/rgw/proxy/bucket?bucket=foo&purge-objects=true');
|
||||
const req = httpTesting.expectOne('/api/rgw/bucket/foo?purge_objects=true');
|
||||
expect(req.request.method).toBe('DELETE');
|
||||
});
|
||||
|
||||
it('should call delete, with purgeObjects = false', () => {
|
||||
service.delete('foo', false).subscribe();
|
||||
const req = httpTesting.expectOne('/api/rgw/proxy/bucket?bucket=foo&purge-objects=false');
|
||||
const req = httpTesting.expectOne('/api/rgw/bucket/foo?purge_objects=false');
|
||||
expect(req.request.method).toBe('DELETE');
|
||||
});
|
||||
|
||||
@ -94,7 +90,7 @@ describe('RgwBucketService', () => {
|
||||
service.exists('foo').subscribe((resp) => {
|
||||
result = resp;
|
||||
});
|
||||
const req = httpTesting.expectOne('/api/rgw/proxy/bucket');
|
||||
const req = httpTesting.expectOne('/api/rgw/bucket');
|
||||
expect(req.request.method).toBe('GET');
|
||||
req.flush(['foo', 'bar']);
|
||||
expect(result).toBe(true);
|
||||
|
@ -11,7 +11,7 @@ import { ApiModule } from './api.module';
|
||||
providedIn: ApiModule
|
||||
})
|
||||
export class RgwBucketService {
|
||||
private url = '/api/rgw/proxy/bucket';
|
||||
private url = '/api/rgw/bucket';
|
||||
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
@ -26,10 +26,12 @@ export class RgwBucketService {
|
||||
return observableForkJoin(
|
||||
buckets.map((bucket: string) => {
|
||||
return this.get(bucket);
|
||||
}));
|
||||
})
|
||||
);
|
||||
}
|
||||
return observableOf([]);
|
||||
}));
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -41,32 +43,27 @@ export class RgwBucketService {
|
||||
}
|
||||
|
||||
get(bucket: string) {
|
||||
let params = new HttpParams();
|
||||
params = params.append('bucket', bucket);
|
||||
return this.http.get(this.url, { params: params });
|
||||
return this.http.get(`${this.url}/${bucket}`);
|
||||
}
|
||||
|
||||
create(bucket: string, uid: string) {
|
||||
const body = {
|
||||
bucket: bucket,
|
||||
uid: uid
|
||||
};
|
||||
return this.http.post('/api/rgw/bucket', body);
|
||||
}
|
||||
|
||||
update(bucketId: string, bucket: string, uid: string) {
|
||||
let params = new HttpParams();
|
||||
params = params.append('bucket', bucket);
|
||||
params = params.append('bucket-id', bucketId as string);
|
||||
params = params.append('uid', uid);
|
||||
return this.http.put(this.url, null, { params: params });
|
||||
return this.http.post(this.url, null, { params: params });
|
||||
}
|
||||
|
||||
update(bucket: string, bucketId: string, uid: string) {
|
||||
let params = new HttpParams();
|
||||
params = params.append('bucket_id', bucketId);
|
||||
params = params.append('uid', uid);
|
||||
return this.http.put(`${this.url}/${bucket}`, null, { params: params});
|
||||
}
|
||||
|
||||
delete(bucket: string, purgeObjects = true) {
|
||||
let params = new HttpParams();
|
||||
params = params.append('bucket', bucket);
|
||||
params = params.append('purge-objects', purgeObjects ? 'true' : 'false');
|
||||
return this.http.delete(this.url, { params: params });
|
||||
params = params.append('purge_objects', purgeObjects ? 'true' : 'false');
|
||||
return this.http.delete(`${this.url}/${bucket}`, { params: params });
|
||||
}
|
||||
|
||||
/**
|
||||
@ -79,6 +76,7 @@ export class RgwBucketService {
|
||||
mergeMap((resp: string[]) => {
|
||||
const index = _.indexOf(resp, bucket);
|
||||
return observableOf(-1 !== index);
|
||||
}));
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ describe('RgwUserService', () => {
|
||||
service.list().subscribe((resp) => {
|
||||
result = resp;
|
||||
});
|
||||
const req = httpTesting.expectOne('/api/rgw/proxy/metadata/user');
|
||||
const req = httpTesting.expectOne('/api/rgw/user');
|
||||
expect(req.request.method).toBe('GET');
|
||||
req.flush([]);
|
||||
expect(result).toEqual([]);
|
||||
@ -45,15 +45,15 @@ describe('RgwUserService', () => {
|
||||
result = resp;
|
||||
});
|
||||
|
||||
let req = httpTesting.expectOne('/api/rgw/proxy/metadata/user');
|
||||
let req = httpTesting.expectOne('/api/rgw/user');
|
||||
expect(req.request.method).toBe('GET');
|
||||
req.flush(['foo', 'bar']);
|
||||
|
||||
req = httpTesting.expectOne('/api/rgw/proxy/user?uid=foo');
|
||||
req = httpTesting.expectOne('/api/rgw/user/foo');
|
||||
expect(req.request.method).toBe('GET');
|
||||
req.flush({ name: 'foo' });
|
||||
|
||||
req = httpTesting.expectOne('/api/rgw/proxy/user?uid=bar');
|
||||
req = httpTesting.expectOne('/api/rgw/user/bar');
|
||||
expect(req.request.method).toBe('GET');
|
||||
req.flush({ name: 'bar' });
|
||||
|
||||
@ -62,100 +62,79 @@ describe('RgwUserService', () => {
|
||||
|
||||
it('should call enumerate', () => {
|
||||
service.enumerate().subscribe();
|
||||
const req = httpTesting.expectOne('/api/rgw/proxy/metadata/user');
|
||||
const req = httpTesting.expectOne('/api/rgw/user');
|
||||
expect(req.request.method).toBe('GET');
|
||||
});
|
||||
|
||||
it('should call get', () => {
|
||||
service.get('foo').subscribe();
|
||||
const req = httpTesting.expectOne('/api/rgw/proxy/user?uid=foo');
|
||||
const req = httpTesting.expectOne('/api/rgw/user/foo');
|
||||
expect(req.request.method).toBe('GET');
|
||||
});
|
||||
|
||||
it('should call getQuota', () => {
|
||||
service.getQuota('foo').subscribe();
|
||||
const req = httpTesting.expectOne('/api/rgw/proxy/user?quota&uid=foo');
|
||||
const req = httpTesting.expectOne('/api/rgw/user/foo/quota');
|
||||
expect(req.request.method).toBe('GET');
|
||||
});
|
||||
|
||||
it('should call put', () => {
|
||||
service.put({ foo: 'bar' }).subscribe();
|
||||
const req = httpTesting.expectOne('/api/rgw/proxy/user?foo=bar');
|
||||
it('should call update', () => {
|
||||
service.update('foo', { xxx: 'yyy' }).subscribe();
|
||||
const req = httpTesting.expectOne('/api/rgw/user/foo?xxx=yyy');
|
||||
expect(req.request.method).toBe('PUT');
|
||||
});
|
||||
|
||||
it('should call putQuota', () => {
|
||||
service.putQuota({ foo: 'bar' }).subscribe();
|
||||
const req = httpTesting.expectOne('/api/rgw/proxy/user?quota&foo=bar');
|
||||
it('should call updateQuota', () => {
|
||||
service.updateQuota('foo', { xxx: 'yyy' }).subscribe();
|
||||
const req = httpTesting.expectOne('/api/rgw/user/foo/quota?xxx=yyy');
|
||||
expect(req.request.method).toBe('PUT');
|
||||
});
|
||||
|
||||
it('should call post', () => {
|
||||
service.post({ foo: 'bar' }).subscribe();
|
||||
const req = httpTesting.expectOne('/api/rgw/proxy/user?foo=bar');
|
||||
it('should call create', () => {
|
||||
service.create({ foo: 'bar' }).subscribe();
|
||||
const req = httpTesting.expectOne('/api/rgw/user?foo=bar');
|
||||
expect(req.request.method).toBe('POST');
|
||||
});
|
||||
|
||||
it('should call delete', () => {
|
||||
service.delete('foo').subscribe();
|
||||
const req = httpTesting.expectOne('/api/rgw/proxy/user?uid=foo');
|
||||
const req = httpTesting.expectOne('/api/rgw/user/foo');
|
||||
expect(req.request.method).toBe('DELETE');
|
||||
});
|
||||
|
||||
it('should call addSubuser with unrecognized permission', () => {
|
||||
service.addSubuser('foo', 'bar', 'baz', null, true).subscribe();
|
||||
const req = httpTesting.expectOne(
|
||||
'/api/rgw/proxy/user?uid=foo&subuser=bar&key-type=swift&access=baz&generate-secret=true'
|
||||
);
|
||||
expect(req.request.method).toBe('PUT');
|
||||
});
|
||||
|
||||
it('should call addSubuser with mapped permission', () => {
|
||||
service.addSubuser('foo', 'bar', 'full-control', 'baz', false).subscribe();
|
||||
const req = httpTesting.expectOne(
|
||||
'/api/rgw/proxy/user?uid=foo&subuser=bar&key-type=swift&access=full&secret-key=baz'
|
||||
);
|
||||
expect(req.request.method).toBe('PUT');
|
||||
it('should call createSubuser', () => {
|
||||
service.createSubuser('foo', { xxx: 'yyy' }).subscribe();
|
||||
const req = httpTesting.expectOne('/api/rgw/user/foo/subuser?xxx=yyy');
|
||||
expect(req.request.method).toBe('POST');
|
||||
});
|
||||
|
||||
it('should call deleteSubuser', () => {
|
||||
service.deleteSubuser('foo', 'bar').subscribe();
|
||||
const req = httpTesting.expectOne('/api/rgw/proxy/user?uid=foo&subuser=bar&purge-keys=true');
|
||||
const req = httpTesting.expectOne('/api/rgw/user/foo/subuser/bar');
|
||||
expect(req.request.method).toBe('DELETE');
|
||||
});
|
||||
|
||||
it('should call addCapability', () => {
|
||||
service.addCapability('foo', 'bar', 'baz').subscribe();
|
||||
const req = httpTesting.expectOne('/api/rgw/proxy/user?caps&uid=foo&user-caps=bar=baz');
|
||||
expect(req.request.method).toBe('PUT');
|
||||
const req = httpTesting.expectOne('/api/rgw/user/foo/capability?type=bar&perm=baz');
|
||||
expect(req.request.method).toBe('POST');
|
||||
});
|
||||
|
||||
it('should call deleteCapability', () => {
|
||||
service.deleteCapability('foo', 'bar', 'baz').subscribe();
|
||||
const req = httpTesting.expectOne('/api/rgw/proxy/user?caps&uid=foo&user-caps=bar=baz');
|
||||
const req = httpTesting.expectOne('/api/rgw/user/foo/capability?type=bar&perm=baz');
|
||||
expect(req.request.method).toBe('DELETE');
|
||||
});
|
||||
|
||||
it('should call addS3Key, with generateKey true', () => {
|
||||
service.addS3Key('1', 'foo', 'bar', 'baz', true).subscribe();
|
||||
const req = httpTesting.expectOne(
|
||||
'/api/rgw/proxy/user?key&uid=1&key-type=s3&generate-key=true&subuser=foo'
|
||||
);
|
||||
expect(req.request.method).toBe('PUT');
|
||||
});
|
||||
|
||||
it('should call addS3Key, with generateKey false', () => {
|
||||
service.addS3Key('1', 'foo', 'bar', 'baz', false).subscribe();
|
||||
const req = httpTesting.expectOne(
|
||||
'/api/rgw/proxy/user?key' +
|
||||
'&uid=1&key-type=s3&generate-key=false&access-key=bar&secret-key=baz&subuser=foo'
|
||||
);
|
||||
expect(req.request.method).toBe('PUT');
|
||||
it('should call addS3Key', () => {
|
||||
service.addS3Key('foo', { xxx: 'yyy' }).subscribe();
|
||||
const req = httpTesting.expectOne('/api/rgw/user/foo/key?key_type=s3&xxx=yyy');
|
||||
expect(req.request.method).toBe('POST');
|
||||
});
|
||||
|
||||
it('should call deleteS3Key', () => {
|
||||
service.deleteS3Key('foo', 'bar').subscribe();
|
||||
const req = httpTesting.expectOne('/api/rgw/proxy/user?key&uid=foo&key-type=s3&access-key=bar');
|
||||
const req = httpTesting.expectOne('/api/rgw/user/foo/key?key_type=s3&access_key=bar');
|
||||
expect(req.request.method).toBe('DELETE');
|
||||
});
|
||||
|
||||
|
@ -2,7 +2,7 @@ import { HttpClient, HttpParams } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
import * as _ from 'lodash';
|
||||
import {forkJoin as observableForkJoin, of as observableOf } from 'rxjs';
|
||||
import { forkJoin as observableForkJoin, of as observableOf } from 'rxjs';
|
||||
import { mergeMap } from 'rxjs/operators';
|
||||
|
||||
import { ApiModule } from './api.module';
|
||||
@ -11,7 +11,7 @@ import { ApiModule } from './api.module';
|
||||
providedIn: ApiModule
|
||||
})
|
||||
export class RgwUserService {
|
||||
private url = '/api/rgw/proxy/user';
|
||||
private url = '/api/rgw/user';
|
||||
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
@ -26,10 +26,12 @@ export class RgwUserService {
|
||||
return observableForkJoin(
|
||||
uids.map((uid: string) => {
|
||||
return this.get(uid);
|
||||
}));
|
||||
})
|
||||
);
|
||||
}
|
||||
return observableOf([]);
|
||||
}));
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -37,38 +39,18 @@ export class RgwUserService {
|
||||
* @return {Observable<string[]>}
|
||||
*/
|
||||
enumerate() {
|
||||
return this.http.get('/api/rgw/proxy/metadata/user');
|
||||
return this.http.get(this.url);
|
||||
}
|
||||
|
||||
get(uid: string) {
|
||||
let params = new HttpParams();
|
||||
params = params.append('uid', uid);
|
||||
return this.http.get(this.url, { params: params });
|
||||
return this.http.get(`${this.url}/${uid}`);
|
||||
}
|
||||
|
||||
getQuota(uid: string) {
|
||||
let params = new HttpParams();
|
||||
params = params.append('uid', uid);
|
||||
return this.http.get(`${this.url}?quota`, { params: params });
|
||||
return this.http.get(`${this.url}/${uid}/quota`);
|
||||
}
|
||||
|
||||
put(args: object) {
|
||||
let params = new HttpParams();
|
||||
_.keys(args).forEach((key) => {
|
||||
params = params.append(key, args[key]);
|
||||
});
|
||||
return this.http.put(this.url, null, { params: params });
|
||||
}
|
||||
|
||||
putQuota(args: object) {
|
||||
let params = new HttpParams();
|
||||
_.keys(args).forEach((key) => {
|
||||
params = params.append(key, args[key]);
|
||||
});
|
||||
return this.http.put(`${this.url}?quota`, null, { params: params });
|
||||
}
|
||||
|
||||
post(args: object) {
|
||||
create(args: object) {
|
||||
let params = new HttpParams();
|
||||
_.keys(args).forEach((key) => {
|
||||
params = params.append(key, args[key]);
|
||||
@ -76,86 +58,66 @@ export class RgwUserService {
|
||||
return this.http.post(this.url, null, { params: params });
|
||||
}
|
||||
|
||||
delete(uid: string) {
|
||||
update(uid: string, args: object) {
|
||||
let params = new HttpParams();
|
||||
params = params.append('uid', uid);
|
||||
return this.http.delete(this.url, { params: params });
|
||||
_.keys(args).forEach((key) => {
|
||||
params = params.append(key, args[key]);
|
||||
});
|
||||
return this.http.put(`${this.url}/${uid}`, null, { params: params });
|
||||
}
|
||||
|
||||
addSubuser(
|
||||
uid: string,
|
||||
subuser: string,
|
||||
permissions: string,
|
||||
secretKey: string,
|
||||
generateSecret: boolean
|
||||
) {
|
||||
const mapPermissions = {
|
||||
'full-control': 'full',
|
||||
'read-write': 'readwrite'
|
||||
};
|
||||
updateQuota(uid: string, args: object) {
|
||||
let params = new HttpParams();
|
||||
params = params.append('uid', uid);
|
||||
params = params.append('subuser', subuser);
|
||||
params = params.append('key-type', 'swift');
|
||||
params = params.append(
|
||||
'access',
|
||||
permissions in mapPermissions ? mapPermissions[permissions] : permissions
|
||||
);
|
||||
if (generateSecret) {
|
||||
params = params.append('generate-secret', 'true');
|
||||
} else {
|
||||
params = params.append('secret-key', secretKey);
|
||||
}
|
||||
return this.http.put(this.url, null, { params: params });
|
||||
_.keys(args).forEach((key) => {
|
||||
params = params.append(key, args[key]);
|
||||
});
|
||||
return this.http.put(`${this.url}/${uid}/quota`, null, { params: params });
|
||||
}
|
||||
|
||||
delete(uid: string) {
|
||||
return this.http.delete(`${this.url}/${uid}`);
|
||||
}
|
||||
|
||||
createSubuser(uid: string, args: object) {
|
||||
let params = new HttpParams();
|
||||
_.keys(args).forEach((key) => {
|
||||
params = params.append(key, args[key]);
|
||||
});
|
||||
return this.http.post(`${this.url}/${uid}/subuser`, null, { params: params });
|
||||
}
|
||||
|
||||
deleteSubuser(uid: string, subuser: string) {
|
||||
let params = new HttpParams();
|
||||
params = params.append('uid', uid);
|
||||
params = params.append('subuser', subuser);
|
||||
params = params.append('purge-keys', 'true');
|
||||
return this.http.delete(this.url, { params: params });
|
||||
return this.http.delete(`${this.url}/${uid}/subuser/${subuser}`);
|
||||
}
|
||||
|
||||
addCapability(uid: string, type: string, perm: string) {
|
||||
let params = new HttpParams();
|
||||
params = params.append('uid', uid);
|
||||
params = params.append('user-caps', `${type}=${perm}`);
|
||||
return this.http.put(`${this.url}?caps`, null, { params: params });
|
||||
params = params.append('type', type);
|
||||
params = params.append('perm', perm);
|
||||
return this.http.post(`${this.url}/${uid}/capability`, null, { params: params });
|
||||
}
|
||||
|
||||
deleteCapability(uid: string, type: string, perm: string) {
|
||||
let params = new HttpParams();
|
||||
params = params.append('uid', uid);
|
||||
params = params.append('user-caps', `${type}=${perm}`);
|
||||
return this.http.delete(`${this.url}?caps`, { params: params });
|
||||
params = params.append('type', type);
|
||||
params = params.append('perm', perm);
|
||||
return this.http.delete(`${this.url}/${uid}/capability`, { params: params });
|
||||
}
|
||||
|
||||
addS3Key(
|
||||
uid: string,
|
||||
subuser: string,
|
||||
accessKey: string,
|
||||
secretKey: string,
|
||||
generateKey: boolean
|
||||
) {
|
||||
addS3Key(uid: string, args: object) {
|
||||
let params = new HttpParams();
|
||||
params = params.append('uid', uid);
|
||||
params = params.append('key-type', 's3');
|
||||
params = params.append('generate-key', generateKey ? 'true' : 'false');
|
||||
if (!generateKey) {
|
||||
params = params.append('access-key', accessKey);
|
||||
params = params.append('secret-key', secretKey);
|
||||
}
|
||||
params = params.append('subuser', subuser);
|
||||
return this.http.put(`${this.url}?key`, null, { params: params });
|
||||
params = params.append('key_type', 's3');
|
||||
_.keys(args).forEach((key) => {
|
||||
params = params.append(key, args[key]);
|
||||
});
|
||||
return this.http.post(`${this.url}/${uid}/key`, null, { params: params });
|
||||
}
|
||||
|
||||
deleteS3Key(uid: string, accessKey: string) {
|
||||
let params = new HttpParams();
|
||||
params = params.append('uid', uid);
|
||||
params = params.append('key-type', 's3');
|
||||
params = params.append('access-key', accessKey);
|
||||
return this.http.delete(`${this.url}?key`, { params: params });
|
||||
params = params.append('key_type', 's3');
|
||||
params = params.append('access_key', accessKey);
|
||||
return this.http.delete(`${this.url}/${uid}/key`, { params: params });
|
||||
}
|
||||
|
||||
/**
|
||||
@ -168,6 +130,7 @@ export class RgwUserService {
|
||||
mergeMap((resp: string[]) => {
|
||||
const index = _.indexOf(resp, uid);
|
||||
return observableOf(-1 !== index);
|
||||
}));
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user