Refactor 404's into managers & drivers (bug 968519)

The goal is to move the responsibility of reference checks away from
controllers and into the underlying managers & drivers, which can
handle the task with equal or greater efficiency.

- Tenant references from create_user/update_user are NOT tested
  due to inconsistencies between backends
- Additional test coverage improvements

Also fixes bug 999209, bug 999608, bug 1006029, bug 1006055, bug 1006287,
bug 1006334, and bug 1006344.

Change-Id: I7de592e7dd4518038436b9a9fdaab559b00a0537
This commit is contained in:
Dolph Mathews 2012-03-28 10:37:16 -07:00
parent 94f45dac51
commit 23ca656927
20 changed files with 1014 additions and 395 deletions

View File

@ -16,7 +16,6 @@
from keystone import catalog from keystone import catalog
from keystone import exception
from keystone.common import kvs from keystone.common import kvs
@ -26,10 +25,7 @@ class Catalog(kvs.Base, catalog.Driver):
return self.db.get('catalog-%s-%s' % (tenant_id, user_id)) return self.db.get('catalog-%s-%s' % (tenant_id, user_id))
def get_service(self, service_id): def get_service(self, service_id):
res = self.db.get('service-%s' % service_id) return self.db.get('service-%s' % service_id)
if not res:
raise exception.ServiceNotFound(service_id=service_id)
return res
def list_services(self): def list_services(self):
return self.db.get('service_list', []) return self.db.get('service_list', [])
@ -46,14 +42,10 @@ class Catalog(kvs.Base, catalog.Driver):
return service return service
def delete_service(self, service_id): def delete_service(self, service_id):
if not self.db.get('service-%s' % service_id):
raise exception.ServiceNotFound(service_id=service_id)
self.db.delete('service-%s' % service_id) self.db.delete('service-%s' % service_id)
service_list = set(self.db.get('service_list', [])) service_list = set(self.db.get('service_list', []))
service_list.remove(service_id) service_list.remove(service_id)
self.db.set('service_list', list(service_list)) self.db.set('service_list', list(service_list))
return None
# Private interface # Private interface
def _create_catalog(self, user_id, tenant_id, data): def _create_catalog(self, user_id, tenant_id, data):

View File

@ -93,11 +93,9 @@ class Catalog(sql.Base, catalog.Driver):
def delete_service(self, service_id): def delete_service(self, service_id):
session = self.get_session() session = self.get_session()
service_ref = session.query(Service).filter_by(id=service_id).first()
if not service_ref:
raise exception.ServiceNotFound(service_id=service_id)
with session.begin(): with session.begin():
session.delete(service_ref) if not session.query(Service).filter_by(id=service_id).delete():
raise exception.ServiceNotFound(service_id=service_id)
session.flush() session.flush()
def create_service(self, service_id, service_ref): def create_service(self, service_id, service_ref):
@ -111,6 +109,7 @@ class Catalog(sql.Base, catalog.Driver):
# Endpoints # Endpoints
def create_endpoint(self, endpoint_id, endpoint_ref): def create_endpoint(self, endpoint_id, endpoint_ref):
session = self.get_session() session = self.get_session()
self.get_service(endpoint_ref['service_id'])
new_endpoint = Endpoint.from_dict(endpoint_ref) new_endpoint = Endpoint.from_dict(endpoint_ref)
with session.begin(): with session.begin():
session.add(new_endpoint) session.add(new_endpoint)
@ -119,12 +118,9 @@ class Catalog(sql.Base, catalog.Driver):
def delete_endpoint(self, endpoint_id): def delete_endpoint(self, endpoint_id):
session = self.get_session() session = self.get_session()
endpoint_ref = session.query(Endpoint)
endpoint_ref = endpoint_ref.filter_by(id=endpoint_id).first()
if not endpoint_ref:
raise exception.EndpointNotFound(endpoint_id=endpoint_id)
with session.begin(): with session.begin():
session.delete(endpoint_ref) if not session.query(Endpoint).filter_by(id=endpoint_id).delete():
raise exception.EndpointNotFound(endpoint_id=endpoint_id)
session.flush() session.flush()
def get_endpoint(self, endpoint_id): def get_endpoint(self, endpoint_id):

View File

@ -42,13 +42,50 @@ class Manager(manager.Manager):
def __init__(self): def __init__(self):
super(Manager, self).__init__(CONF.catalog.driver) super(Manager, self).__init__(CONF.catalog.driver)
def get_service(self, context, service_id):
try:
return self.driver.get_service(service_id)
except exception.NotFound:
raise exception.ServiceNotFound(service_id=service_id)
def delete_service(self, context, service_id):
try:
return self.driver.delete_service(service_id)
except exception.NotFound:
raise exception.ServiceNotFound(service_id=service_id)
def create_endpoint(self, context, endpoint_id, endpoint_ref):
try:
return self.driver.create_endpoint(endpoint_id, endpoint_ref)
except exception.NotFound:
service_id = endpoint_ref.get('service_id')
raise exception.ServiceNotFound(service_id=service_id)
def delete_endpoint(self, context, endpoint_id):
try:
return self.driver.delete_endpoint(endpoint_id)
except exception.NotFound:
raise exception.EndpointNotFound(endpoint_id=endpoint_id)
def get_endpoint(self, context, endpoint_id):
try:
return self.driver.get_endpoint(endpoint_id)
except exception.NotFound:
raise exception.EndpointNotFound(endpoint_id=endpoint_id)
def get_catalog(self, context, user_id, tenant_id, metadata=None):
try:
return self.driver.get_catalog(user_id, tenant_id, metadata)
except exception.NotFound:
raise exception.NotFound('Catalog not found for user and tenant')
class Driver(object): class Driver(object):
"""Interface description for an Catalog driver.""" """Interface description for an Catalog driver."""
def list_services(self): def list_services(self):
"""List all service ids in catalog. """List all service ids in catalog.
Returns: list of service_ids or an empty list. :returns: list of service_ids or an empty list.
""" """
raise exception.NotImplemented() raise exception.NotImplemented()
@ -56,27 +93,50 @@ class Driver(object):
def get_service(self, service_id): def get_service(self, service_id):
"""Get service by id. """Get service by id.
Returns: service_ref dict or None. :returns: service_ref dict
:raises: keystone.exception.ServiceNotFound
""" """
raise exception.NotImplemented() raise exception.NotImplemented()
def delete_service(self, service_id): def delete_service(self, service_id):
"""Deletes an existing service.
:raises: keystone.exception.ServiceNotFound
"""
raise exception.NotImplemented() raise exception.NotImplemented()
def create_service(self, service_id, service_ref): def create_service(self, service_id, service_ref):
"""Creates a new service.
:raises: keystone.exception.Conflict
"""
raise exception.NotImplemented() raise exception.NotImplemented()
def create_endpoint(self, endpoint_id, endpoint_ref): def create_endpoint(self, endpoint_id, endpoint_ref):
"""Creates a new endpoint for a service.
:raises: keystone.exception.Conflict,
keystone.exception.ServiceNotFound
"""
raise exception.NotImplemented() raise exception.NotImplemented()
def delete_endpoint(self, endpoint_id): def delete_endpoint(self, endpoint_id):
"""Deletes an endpoint for a service.
:raises: keystone.exception.EndpointNotFound
"""
raise exception.NotImplemented() raise exception.NotImplemented()
def get_endpoint(self, endpoint_id): def get_endpoint(self, endpoint_id):
"""Get endpoint by id. """Get endpoint by id.
Returns: endpoint_ref dict or None. :returns: endpoint_ref dict
:raises: keystone.exception.EndpointNotFound
""" """
raise exception.NotImplemented() raise exception.NotImplemented()
@ -84,7 +144,7 @@ class Driver(object):
def list_endpoints(self): def list_endpoints(self):
"""List all endpoint ids in catalog. """List all endpoint ids in catalog.
Returns: list of endpoint_ids or an empty list. :returns: list of endpoint_ids or an empty list.
""" """
raise exception.NotImplemented() raise exception.NotImplemented()
@ -92,10 +152,7 @@ class Driver(object):
def get_catalog(self, user_id, tenant_id, metadata=None): def get_catalog(self, user_id, tenant_id, metadata=None):
"""Retreive and format the current service catalog. """Retreive and format the current service catalog.
Returns: A nested dict representing the service catalog or an Example::
empty dict.
Example:
{ 'RegionOne': { 'RegionOne':
{'compute': { {'compute': {
@ -109,6 +166,10 @@ class Driver(object):
'name': 'EC2 Service', 'name': 'EC2 Service',
'publicURL': 'http://host:8773/services/Cloud'}} 'publicURL': 'http://host:8773/services/Cloud'}}
:returns: A nested dict representing the service catalog or an
empty dict.
:raises: keystone.exception.NotFound
""" """
raise exception.NotImplemented() raise exception.NotImplemented()
@ -133,15 +194,10 @@ class ServiceController(wsgi.Application):
def get_service(self, context, service_id): def get_service(self, context, service_id):
self.assert_admin(context) self.assert_admin(context)
service_ref = self.catalog_api.get_service(context, service_id) service_ref = self.catalog_api.get_service(context, service_id)
if not service_ref:
raise exception.ServiceNotFound(service_id=service_id)
return {'OS-KSADM:service': service_ref} return {'OS-KSADM:service': service_ref}
def delete_service(self, context, service_id): def delete_service(self, context, service_id):
self.assert_admin(context) self.assert_admin(context)
service_ref = self.catalog_api.get_service(context, service_id)
if not service_ref:
raise exception.ServiceNotFound(service_id=service_id)
self.catalog_api.delete_service(context, service_id) self.catalog_api.delete_service(context, service_id)
def create_service(self, context, OS_KSADM_service): def create_service(self, context, OS_KSADM_service):
@ -174,11 +230,6 @@ class EndpointController(wsgi.Application):
endpoint_id = uuid.uuid4().hex endpoint_id = uuid.uuid4().hex
endpoint_ref = endpoint.copy() endpoint_ref = endpoint.copy()
endpoint_ref['id'] = endpoint_id endpoint_ref['id'] = endpoint_id
service_id = endpoint_ref['service_id']
if not self.catalog_api.get_service(context, service_id):
raise exception.ServiceNotFound(service_id=service_id)
new_endpoint_ref = self.catalog_api.create_endpoint( new_endpoint_ref = self.catalog_api.create_endpoint(
context, endpoint_id, endpoint_ref) context, endpoint_id, endpoint_ref)
return {'endpoint': new_endpoint_ref} return {'endpoint': new_endpoint_ref}

View File

@ -14,8 +14,18 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from keystone import exception
class DictKvs(dict): class DictKvs(dict):
def get(self, key, default=None):
try:
return self[key]
except KeyError:
if default is not None:
return default
raise exception.NotFound(target=key)
def set(self, key, value): def set(self, key, value):
if isinstance(value, dict): if isinstance(value, dict):
self[key] = value.copy() self[key] = value.copy()
@ -23,7 +33,11 @@ class DictKvs(dict):
self[key] = value[:] self[key] = value[:]
def delete(self, key): def delete(self, key):
del self[key] """Deletes an item, returning True on success, False otherwise."""
try:
del self[key]
except KeyError:
raise exception.NotFound(target=key)
INMEMDB = DictKvs() INMEMDB = DictKvs()

View File

@ -138,16 +138,22 @@ class BaseLdap(object):
return obj return obj
def affirm_unique(self, values): def affirm_unique(self, values):
if values['name'] is not None: if values.get('name') is not None:
entity = self.get_by_name(values['name']) try:
if entity is not None: self.get_by_name(values['name'])
except exception.NotFound:
pass
else:
raise exception.Conflict(type=self.options_name, raise exception.Conflict(type=self.options_name,
details='Duplicate name, %s.' % details='Duplicate name, %s.' %
values['name']) values['name'])
if values['id'] is not None: if values.get('id') is not None:
entity = self.get(values['id']) try:
if entity is not None: self.get(values['id'])
except exception.NotFound:
pass
else:
raise exception.Conflict(type=self.options_name, raise exception.Conflict(type=self.options_name,
details='Duplicate ID, %s.' % details='Duplicate ID, %s.' %
values['id']) values['id'])
@ -198,7 +204,7 @@ class BaseLdap(object):
def get(self, id, filter=None): def get(self, id, filter=None):
res = self._ldap_get(id, filter) res = self._ldap_get(id, filter)
if res is None: if res is None:
return None raise exception.NotFound(target=id)
else: else:
return self._ldap_res_to_model(res) return self._ldap_res_to_model(res)

View File

@ -77,6 +77,12 @@ class EndpointNotFound(NotFound):
"""Could not find endpoint: %(endpoint_id)s""" """Could not find endpoint: %(endpoint_id)s"""
class MetadataNotFound(NotFound):
"""An unhandled exception has occurred: Could not find metadata."""
# (dolph): metadata is not a user-facing concept,
# so this exception should not be exposed
class RoleNotFound(NotFound): class RoleNotFound(NotFound):
"""Could not find role: %(role_id)s""" """Could not find role: %(role_id)s"""

View File

@ -45,49 +45,66 @@ class Identity(kvs.Base, identity.Driver):
in the list of tenants on the user. in the list of tenants on the user.
""" """
user_ref = self._get_user(user_id) user_ref = None
tenant_ref = None tenant_ref = None
metadata_ref = None metadata_ref = {}
if (not user_ref
or not utils.check_password(password, try:
user_ref.get('password'))): user_ref = self._get_user(user_id)
except exception.UserNotFound:
raise AssertionError('Invalid user / password') raise AssertionError('Invalid user / password')
tenants = self.get_tenants_for_user(user_id) if not utils.check_password(password, user_ref.get('password')):
if tenant_id and tenant_id not in tenants: raise AssertionError('Invalid user / password')
raise AssertionError('Invalid tenant')
if tenant_id is not None:
if tenant_id not in self.get_tenants_for_user(user_id):
raise AssertionError('Invalid tenant')
try:
tenant_ref = self.get_tenant(tenant_id)
metadata_ref = self.get_metadata(user_id, tenant_id)
except exception.TenantNotFound:
tenant_ref = None
metadata_ref = {}
except exception.MetadataNotFound:
metadata_ref = {}
tenant_ref = self.get_tenant(tenant_id)
if tenant_ref:
metadata_ref = self.get_metadata(user_id, tenant_id)
else:
metadata_ref = {}
return (_filter_user(user_ref), tenant_ref, metadata_ref) return (_filter_user(user_ref), tenant_ref, metadata_ref)
def get_tenant(self, tenant_id): def get_tenant(self, tenant_id):
tenant_ref = self.db.get('tenant-%s' % tenant_id) try:
return tenant_ref return self.db.get('tenant-%s' % tenant_id)
except exception.NotFound:
raise exception.TenantNotFound(tenant_id=tenant_id)
def get_tenants(self): def get_tenants(self):
tenant_keys = filter(lambda x: x.startswith("tenant-"), self.db.keys()) tenant_keys = filter(lambda x: x.startswith("tenant-"), self.db.keys())
return [self.db.get(key) for key in tenant_keys] return [self.db.get(key) for key in tenant_keys]
def get_tenant_by_name(self, tenant_name): def get_tenant_by_name(self, tenant_name):
tenant_ref = self.db.get('tenant_name-%s' % tenant_name) try:
return tenant_ref return self.db.get('tenant_name-%s' % tenant_name)
except exception.NotFound:
raise exception.TenantNotFound(tenant_id=tenant_name)
def get_tenant_users(self, tenant_id): def get_tenant_users(self, tenant_id):
self.get_tenant(tenant_id)
user_keys = filter(lambda x: x.startswith("user-"), self.db.keys()) user_keys = filter(lambda x: x.startswith("user-"), self.db.keys())
user_refs = [self.db.get(key) for key in user_keys] user_refs = [self.db.get(key) for key in user_keys]
return filter(lambda x: tenant_id in x['tenants'], user_refs) return filter(lambda x: tenant_id in x['tenants'], user_refs)
def _get_user(self, user_id): def _get_user(self, user_id):
user_ref = self.db.get('user-%s' % user_id) try:
return user_ref return self.db.get('user-%s' % user_id)
except exception.NotFound:
raise exception.UserNotFound(user_id=user_id)
def _get_user_by_name(self, user_name): def _get_user_by_name(self, user_name):
user_ref = self.db.get('user_name-%s' % user_name) try:
return user_ref return self.db.get('user_name-%s' % user_name)
except exception.NotFound:
raise exception.UserNotFound(user_id=user_name)
def get_user(self, user_id): def get_user(self, user_id):
return _filter_user(self._get_user(user_id)) return _filter_user(self._get_user(user_id))
@ -96,10 +113,16 @@ class Identity(kvs.Base, identity.Driver):
return _filter_user(self._get_user_by_name(user_name)) return _filter_user(self._get_user_by_name(user_name))
def get_metadata(self, user_id, tenant_id): def get_metadata(self, user_id, tenant_id):
return self.db.get('metadata-%s-%s' % (tenant_id, user_id)) or {} try:
return self.db.get('metadata-%s-%s' % (tenant_id, user_id))
except exception.NotFound:
raise exception.MetadataNotFound()
def get_role(self, role_id): def get_role(self, role_id):
return self.db.get('role-%s' % role_id) try:
return self.db.get('role-%s' % role_id)
except exception.NotFound:
raise exception.RoleNotFound(role_id=role_id)
def list_users(self): def list_users(self):
user_ids = self.db.get('user_list', []) user_ids = self.db.get('user_list', [])
@ -111,15 +134,20 @@ class Identity(kvs.Base, identity.Driver):
# These should probably be part of the high-level API # These should probably be part of the high-level API
def add_user_to_tenant(self, tenant_id, user_id): def add_user_to_tenant(self, tenant_id, user_id):
self.get_tenant(tenant_id)
user_ref = self._get_user(user_id) user_ref = self._get_user(user_id)
tenants = set(user_ref.get('tenants', [])) tenants = set(user_ref.get('tenants', []))
tenants.add(tenant_id) tenants.add(tenant_id)
self.update_user(user_id, {'tenants': list(tenants)}) self.update_user(user_id, {'tenants': list(tenants)})
def remove_user_from_tenant(self, tenant_id, user_id): def remove_user_from_tenant(self, tenant_id, user_id):
self.get_tenant(tenant_id)
user_ref = self._get_user(user_id) user_ref = self._get_user(user_id)
tenants = set(user_ref.get('tenants', [])) tenants = set(user_ref.get('tenants', []))
tenants.remove(tenant_id) try:
tenants.remove(tenant_id)
except KeyError:
raise exception.NotFound('User not found in tenant')
self.update_user(user_id, {'tenants': list(tenants)}) self.update_user(user_id, {'tenants': list(tenants)})
def get_tenants_for_user(self, user_id): def get_tenants_for_user(self, user_id):
@ -127,14 +155,21 @@ class Identity(kvs.Base, identity.Driver):
return user_ref.get('tenants', []) return user_ref.get('tenants', [])
def get_roles_for_user_and_tenant(self, user_id, tenant_id): def get_roles_for_user_and_tenant(self, user_id, tenant_id):
metadata_ref = self.get_metadata(user_id, tenant_id) self.get_user(user_id)
if not metadata_ref: self.get_tenant(tenant_id)
try:
metadata_ref = self.get_metadata(user_id, tenant_id)
except exception.MetadataNotFound:
metadata_ref = {} metadata_ref = {}
return metadata_ref.get('roles', []) return metadata_ref.get('roles', [])
def add_role_to_user_and_tenant(self, user_id, tenant_id, role_id): def add_role_to_user_and_tenant(self, user_id, tenant_id, role_id):
metadata_ref = self.get_metadata(user_id, tenant_id) self.get_user(user_id)
if not metadata_ref: self.get_tenant(tenant_id)
self.get_role(role_id)
try:
metadata_ref = self.get_metadata(user_id, tenant_id)
except exception.MetadataNotFound:
metadata_ref = {} metadata_ref = {}
roles = set(metadata_ref.get('roles', [])) roles = set(metadata_ref.get('roles', []))
roles.add(role_id) roles.add(role_id)
@ -142,8 +177,9 @@ class Identity(kvs.Base, identity.Driver):
self.update_metadata(user_id, tenant_id, metadata_ref) self.update_metadata(user_id, tenant_id, metadata_ref)
def remove_role_from_user_and_tenant(self, user_id, tenant_id, role_id): def remove_role_from_user_and_tenant(self, user_id, tenant_id, role_id):
metadata_ref = self.get_metadata(user_id, tenant_id) try:
if not metadata_ref: metadata_ref = self.get_metadata(user_id, tenant_id)
except exception.MetadataNotFound:
metadata_ref = {} metadata_ref = {}
roles = set(metadata_ref.get('roles', [])) roles = set(metadata_ref.get('roles', []))
if role_id not in roles: if role_id not in roles:
@ -156,12 +192,22 @@ class Identity(kvs.Base, identity.Driver):
# CRUD # CRUD
def create_user(self, user_id, user): def create_user(self, user_id, user):
if self.get_user(user_id): try:
self.get_user(user_id)
except exception.UserNotFound:
pass
else:
msg = 'Duplicate ID, %s.' % user_id msg = 'Duplicate ID, %s.' % user_id
raise exception.Conflict(type='user', details=msg) raise exception.Conflict(type='user', details=msg)
if self.get_user_by_name(user['name']):
try:
self.get_user_by_name(user['name'])
except exception.UserNotFound:
pass
else:
msg = 'Duplicate name, %s.' % user['name'] msg = 'Duplicate name, %s.' % user['name']
raise exception.Conflict(type='user', details=msg) raise exception.Conflict(type='user', details=msg)
user = _ensure_hashed_password(user) user = _ensure_hashed_password(user)
self.db.set('user-%s' % user_id, user) self.db.set('user-%s' % user_id, user)
self.db.set('user_name-%s' % user['name'], user) self.db.set('user_name-%s' % user['name'], user)
@ -177,33 +223,49 @@ class Identity(kvs.Base, identity.Driver):
msg = 'Duplicate name, %s.' % user['name'] msg = 'Duplicate name, %s.' % user['name']
raise exception.Conflict(type='user', details=msg) raise exception.Conflict(type='user', details=msg)
# get the old name and delete it too # get the old name and delete it too
old_user = self.db.get('user-%s' % user_id) try:
old_user = self.db.get('user-%s' % user_id)
except exception.NotFound:
raise exception.UserNotFound(user_id=user_id)
new_user = old_user.copy() new_user = old_user.copy()
user = _ensure_hashed_password(user) user = _ensure_hashed_password(user)
new_user.update(user) new_user.update(user)
new_user['id'] = user_id if new_user['id'] != user_id:
raise exception.ValidationError('Cannot change user ID')
self.db.delete('user_name-%s' % old_user['name']) self.db.delete('user_name-%s' % old_user['name'])
self.db.set('user-%s' % user_id, new_user) self.db.set('user-%s' % user_id, new_user)
self.db.set('user_name-%s' % new_user['name'], new_user) self.db.set('user_name-%s' % new_user['name'], new_user)
return new_user return new_user
def delete_user(self, user_id): def delete_user(self, user_id):
old_user = self.db.get('user-%s' % user_id) try:
old_user = self.db.get('user-%s' % user_id)
except exception.NotFound:
raise exception.UserNotFound(user_id=user_id)
self.db.delete('user_name-%s' % old_user['name']) self.db.delete('user_name-%s' % old_user['name'])
self.db.delete('user-%s' % user_id) self.db.delete('user-%s' % user_id)
user_list = set(self.db.get('user_list', [])) user_list = set(self.db.get('user_list', []))
user_list.remove(user_id) user_list.remove(user_id)
self.db.set('user_list', list(user_list)) self.db.set('user_list', list(user_list))
return None
def create_tenant(self, tenant_id, tenant): def create_tenant(self, tenant_id, tenant):
tenant['name'] = clean.tenant_name(tenant['name']) tenant['name'] = clean.tenant_name(tenant['name'])
if self.get_tenant(tenant_id): try:
self.get_tenant(tenant_id)
except exception.TenantNotFound:
pass
else:
msg = 'Duplicate ID, %s.' % tenant_id msg = 'Duplicate ID, %s.' % tenant_id
raise exception.Conflict(type='tenant', details=msg) raise exception.Conflict(type='tenant', details=msg)
if self.get_tenant_by_name(tenant['name']):
try:
self.get_tenant_by_name(tenant['name'])
except exception.TenantNotFound:
pass
else:
msg = 'Duplicate name, %s.' % tenant['name'] msg = 'Duplicate name, %s.' % tenant['name']
raise exception.Conflict(type='tenant', details=msg) raise exception.Conflict(type='tenant', details=msg)
self.db.set('tenant-%s' % tenant_id, tenant) self.db.set('tenant-%s' % tenant_id, tenant)
self.db.set('tenant_name-%s' % tenant['name'], tenant) self.db.set('tenant_name-%s' % tenant['name'], tenant)
return tenant return tenant
@ -211,12 +273,18 @@ class Identity(kvs.Base, identity.Driver):
def update_tenant(self, tenant_id, tenant): def update_tenant(self, tenant_id, tenant):
if 'name' in tenant: if 'name' in tenant:
tenant['name'] = clean.tenant_name(tenant['name']) tenant['name'] = clean.tenant_name(tenant['name'])
existing = self.db.get('tenant_name-%s' % tenant['name']) try:
if existing and tenant_id != existing['id']: existing = self.db.get('tenant_name-%s' % tenant['name'])
msg = 'Duplicate name, %s.' % tenant['name'] if existing and tenant_id != existing['id']:
raise exception.Conflict(type='tenant', details=msg) msg = 'Duplicate name, %s.' % tenant['name']
raise exception.Conflict(type='tenant', details=msg)
except exception.NotFound:
pass
# get the old name and delete it too # get the old name and delete it too
old_tenant = self.db.get('tenant-%s' % tenant_id) try:
old_tenant = self.db.get('tenant-%s' % tenant_id)
except exception.NotFound:
raise exception.TenantNotFound(tenant_id=tenant_id)
new_tenant = old_tenant.copy() new_tenant = old_tenant.copy()
new_tenant.update(tenant) new_tenant.update(tenant)
new_tenant['id'] = tenant_id new_tenant['id'] = tenant_id
@ -226,10 +294,12 @@ class Identity(kvs.Base, identity.Driver):
return new_tenant return new_tenant
def delete_tenant(self, tenant_id): def delete_tenant(self, tenant_id):
old_tenant = self.db.get('tenant-%s' % tenant_id) try:
old_tenant = self.db.get('tenant-%s' % tenant_id)
except exception.NotFound:
raise exception.TenantNotFound(tenant_id=tenant_id)
self.db.delete('tenant_name-%s' % old_tenant['name']) self.db.delete('tenant_name-%s' % old_tenant['name'])
self.db.delete('tenant-%s' % tenant_id) self.db.delete('tenant-%s' % tenant_id)
return None
def create_metadata(self, user_id, tenant_id, metadata): def create_metadata(self, user_id, tenant_id, metadata):
self.db.set('metadata-%s-%s' % (tenant_id, user_id), metadata) self.db.set('metadata-%s-%s' % (tenant_id, user_id), metadata)
@ -241,15 +311,17 @@ class Identity(kvs.Base, identity.Driver):
def delete_metadata(self, user_id, tenant_id): def delete_metadata(self, user_id, tenant_id):
self.db.delete('metadata-%s-%s' % (tenant_id, user_id)) self.db.delete('metadata-%s-%s' % (tenant_id, user_id))
return None
def create_role(self, role_id, role): def create_role(self, role_id, role):
role_ref = self.get_role(role_id) try:
if role_ref: self.get_role(role_id)
except exception.RoleNotFound:
pass
else:
msg = 'Duplicate ID, %s.' % role_id msg = 'Duplicate ID, %s.' % role_id
raise exception.Conflict(type='role', details=msg) raise exception.Conflict(type='role', details=msg)
role_refs = self.list_roles()
for role_ref in role_refs: for role_ref in self.list_roles():
if role['name'] == role_ref['name']: if role['name'] == role_ref['name']:
msg = 'Duplicate name, %s.' % role['name'] msg = 'Duplicate name, %s.' % role['name']
raise exception.Conflict(type='role', details=msg) raise exception.Conflict(type='role', details=msg)
@ -260,24 +332,26 @@ class Identity(kvs.Base, identity.Driver):
return role return role
def update_role(self, role_id, role): def update_role(self, role_id, role):
role_refs = self.list_roles()
old_role_ref = None old_role_ref = None
for role_ref in role_refs: for role_ref in self.list_roles():
if role['name'] == role_ref['name'] and role_id != role_ref['id']: if role['name'] == role_ref['name'] and role_id != role_ref['id']:
msg = 'Duplicate name, %s.' % role['name'] msg = 'Duplicate name, %s.' % role['name']
raise exception.Conflict(type='role', details=msg) raise exception.Conflict(type='role', details=msg)
if role_id == role_ref['id']: if role_id == role_ref['id']:
old_role_ref = role_ref old_role_ref = role_ref
if old_role_ref: if old_role_ref is None:
role['id'] = role_id
self.db.set('role-%s' % role_id, role)
else:
raise exception.RoleNotFound(role_id=role_id) raise exception.RoleNotFound(role_id=role_id)
new_role = old_role_ref.copy()
new_role.update(role)
new_role['id'] = role_id
self.db.set('role-%s' % role_id, new_role)
return role return role
def delete_role(self, role_id): def delete_role(self, role_id):
self.db.delete('role-%s' % role_id) try:
self.db.delete('role-%s' % role_id)
except exception.NotFound:
raise exception.RoleNotFound(role_id=role_id)
role_list = set(self.db.get('role_list', [])) role_list = set(self.db.get('role_list', []))
role_list.remove(role_id) role_list.remove(role_id)
self.db.set('role_list', list(role_list)) self.db.set('role_list', list(role_list))
return None

View File

@ -77,8 +77,12 @@ class Identity(identity.Driver):
Expects the user object to have a password field and the tenant to be Expects the user object to have a password field and the tenant to be
in the list of tenants on the user. in the list of tenants on the user.
""" """
user_ref = self._get_user(user_id) tenant_ref = None
if user_ref is None: metadata_ref = None
try:
user_ref = self._get_user(user_id)
except exception.UserNotFound:
raise AssertionError('Invalid user / password') raise AssertionError('Invalid user / password')
try: try:
@ -89,42 +93,49 @@ class Identity(identity.Driver):
except Exception: except Exception:
raise AssertionError('Invalid user / password') raise AssertionError('Invalid user / password')
tenants = self.get_tenants_for_user(user_id) if tenant_id is not None:
if tenant_id and tenant_id not in tenants: if tenant_id not in self.get_tenants_for_user(user_id):
raise AssertionError('Invalid tenant') raise AssertionError('Invalid tenant')
tenant_ref = self.get_tenant(tenant_id) try:
# TODO(termie): this should probably be made into a get roles call tenant_ref = self.get_tenant(tenant_id)
if tenant_ref: # TODO(termie): this should probably be made into a
metadata_ref = self.get_metadata(user_id, tenant_id) # get roles call
else: metadata_ref = self.get_metadata(user_id, tenant_id)
metadata_ref = {} except exception.TenantNotFound:
tenant_ref = None
metadata_ref = {}
except exception.MetadataNotFound:
metadata_ref = {}
return (_filter_user(user_ref), tenant_ref, metadata_ref) return (_filter_user(user_ref), tenant_ref, metadata_ref)
def get_tenant(self, tenant_id): def get_tenant(self, tenant_id):
return self.tenant.get(tenant_id) try:
return self.tenant.get(tenant_id)
except exception.NotFound:
raise exception.TenantNotFound(tenant_id=tenant_id)
def get_tenant_by_name(self, tenant_name): def get_tenant_by_name(self, tenant_name):
return self.tenant.get_by_name(tenant_name) try:
return self.tenant.get_by_name(tenant_name)
except exception.NotFound:
raise exception.TenantNotFound(tenant_id=tenant_name)
def _get_user(self, user_id): def _get_user(self, user_id):
user_ref = self.user.get(user_id) try:
if not user_ref: return self.user.get(user_id)
return None except exception.NotFound:
return user_ref raise exception.UserNotFound(user_id=user_id)
def get_user(self, user_id): def get_user(self, user_id):
user_ref = self._get_user(user_id) return _filter_user(self._get_user(user_id))
if (not user_ref):
return None
return _filter_user(user_ref)
def get_user_by_name(self, user_name): def get_user_by_name(self, user_name):
user_ref = self.user.get_by_name(user_name) try:
if not user_ref: return _filter_user(self.user.get_by_name(user_name))
return None except exception.NotFound:
return _filter_user(user_ref) raise exception.UserNotFound(user_id=user_name)
def get_metadata(self, user_id, tenant_id): def get_metadata(self, user_id, tenant_id):
if not self.get_tenant(tenant_id) or not self.get_user(user_id): if not self.get_tenant(tenant_id) or not self.get_user(user_id):
@ -136,19 +147,27 @@ class Identity(identity.Driver):
return {'roles': metadata_ref} return {'roles': metadata_ref}
def get_role(self, role_id): def get_role(self, role_id):
return self.role.get(role_id) try:
return self.role.get(role_id)
except exception.NotFound:
raise exception.RoleNotFound(role_id=role_id)
# These should probably be part of the high-level API # These should probably be part of the high-level API
def add_user_to_tenant(self, tenant_id, user_id): def add_user_to_tenant(self, tenant_id, user_id):
self.get_tenant(tenant_id)
self.get_user(user_id)
return self.tenant.add_user(tenant_id, user_id) return self.tenant.add_user(tenant_id, user_id)
def get_tenants_for_user(self, user_id): def get_tenants_for_user(self, user_id):
self.get_user(user_id)
tenant_list = [] tenant_list = []
for tenant in self.tenant.get_user_tenants(user_id): for tenant in self.tenant.get_user_tenants(user_id):
tenant_list.append(tenant['id']) tenant_list.append(tenant['id'])
return tenant_list return tenant_list
def get_roles_for_user_and_tenant(self, user_id, tenant_id): def get_roles_for_user_and_tenant(self, user_id, tenant_id):
self.get_user(user_id)
self.get_tenant(tenant_id)
assignments = self.role.get_role_assignments(tenant_id) assignments = self.role.get_role_assignments(tenant_id)
roles = [] roles = []
for assignment in assignments: for assignment in assignments:
@ -157,6 +176,9 @@ class Identity(identity.Driver):
return roles return roles
def add_role_to_user_and_tenant(self, user_id, tenant_id, role_id): def add_role_to_user_and_tenant(self, user_id, tenant_id, role_id):
self.get_user(user_id)
self.get_tenant(tenant_id)
self.get_role(role_id)
self.role.add_user(role_id, user_id, tenant_id) self.role.add_user(role_id, user_id, tenant_id)
# CRUD # CRUD
@ -182,16 +204,29 @@ class Identity(identity.Driver):
return {} return {}
def create_role(self, role_id, role): def create_role(self, role_id, role):
if self.get_role(role_id): try:
self.get_role(role_id)
except exception.NotFound:
pass
else:
msg = 'Duplicate ID, %s.' % role_id msg = 'Duplicate ID, %s.' % role_id
raise exception.Conflict(type='role', details=msg) raise exception.Conflict(type='role', details=msg)
if self.role.get_by_name(role['name']):
try:
self.role.get_by_name(role['name'])
except exception.NotFound:
pass
else:
msg = 'Duplicate name, %s.' % role['name'] msg = 'Duplicate name, %s.' % role['name']
raise exception.Conflict(type='role', details=msg) raise exception.Conflict(type='role', details=msg)
return self.role.create(role) return self.role.create(role)
def delete_role(self, role_id): def delete_role(self, role_id):
return self.role.delete(role_id) try:
return self.role.delete(role_id)
except ldap.NO_SUCH_OBJECT:
raise exception.RoleNotFound(role_id=role_id)
# TODO(termie): remove this and move cross-api calls into driver # TODO(termie): remove this and move cross-api calls into driver
@ -268,6 +303,13 @@ class UserApi(common_ldap.BaseLdap, ApiShimMixin):
super(UserApi, self).__init__(conf) super(UserApi, self).__init__(conf)
self.api = ApiShim(conf) self.api = ApiShim(conf)
def get(self, id, filter=None):
"""Replaces exception.NotFound with exception.UserNotFound."""
try:
return super(UserApi, self).get(id, filter)
except exception.NotFound:
raise exception.UserNotFound(user_id=id)
def get_by_name(self, name, filter=None): def get_by_name(self, name, filter=None):
users = self.get_all('(%s=%s)' % users = self.get_all('(%s=%s)' %
(self.attribute_mapping['name'], (self.attribute_mapping['name'],
@ -275,7 +317,7 @@ class UserApi(common_ldap.BaseLdap, ApiShimMixin):
try: try:
return users[0] return users[0]
except IndexError: except IndexError:
return None raise exception.UserNotFound(user_id=name)
def create(self, values): def create(self, values):
self.affirm_unique(values) self.affirm_unique(values)
@ -288,10 +330,13 @@ class UserApi(common_ldap.BaseLdap, ApiShimMixin):
def update(self, id, values): def update(self, id, values):
if values['id'] != id: if values['id'] != id:
return None raise exception.ValidationError('Cannot change user ID')
old_obj = self.get(id) try:
old_obj = self.get(id)
except exception.NotFound:
raise exception.UserNotFound(user_id=id)
if old_obj.get('name') != values['name']: if old_obj.get('name') != values['name']:
raise exception.Error('Changing Name not permitted') raise exception.ValidationError('Cannot change user name')
try: try:
new_tenant = values['tenant_id'] new_tenant = values['tenant_id']
@ -385,6 +430,13 @@ class TenantApi(common_ldap.BaseLdap, ApiShimMixin):
self.member_attribute = (getattr(conf.ldap, 'tenant_member_attribute') self.member_attribute = (getattr(conf.ldap, 'tenant_member_attribute')
or self.DEFAULT_MEMBER_ATTRIBUTE) or self.DEFAULT_MEMBER_ATTRIBUTE)
def get(self, id, filter=None):
"""Replaces exception.NotFound with exception.TenantNotFound."""
try:
return super(TenantApi, self).get(id, filter)
except exception.NotFound:
raise exception.TenantNotFound(tenant_id=id)
def get_by_name(self, name, filter=None): # pylint: disable=W0221,W0613 def get_by_name(self, name, filter=None): # pylint: disable=W0221,W0613
search_filter = ('(%s=%s)' search_filter = ('(%s=%s)'
% (self.attribute_mapping['name'], % (self.attribute_mapping['name'],
@ -393,13 +445,12 @@ class TenantApi(common_ldap.BaseLdap, ApiShimMixin):
try: try:
return tenants[0] return tenants[0]
except IndexError: except IndexError:
return None raise exception.TenantNotFound(tenant_id=name)
def create(self, values): def create(self, values):
self.affirm_unique(values) self.affirm_unique(values)
data = values.copy() data = values.copy()
if 'id' not in data or data['id'] is None: if data.get('id') is None:
data['id'] = uuid.uuid4().hex data['id'] = uuid.uuid4().hex
return super(TenantApi, self).create(data) return super(TenantApi, self).create(data)
@ -434,10 +485,11 @@ class TenantApi(common_ldap.BaseLdap, ApiShimMixin):
def add_user(self, tenant_id, user_id): def add_user(self, tenant_id, user_id):
conn = self.get_connection() conn = self.get_connection()
conn.modify_s(self._id_to_dn(tenant_id), conn.modify_s(
[(ldap.MOD_ADD, self._id_to_dn(tenant_id),
self.member_attribute, [(ldap.MOD_ADD,
self.user_api._id_to_dn(user_id))]) self.member_attribute,
self.user_api._id_to_dn(user_id))])
def remove_user(self, tenant_id, user_id): def remove_user(self, tenant_id, user_id):
conn = self.get_connection() conn = self.get_connection()
@ -467,9 +519,13 @@ class TenantApi(common_ldap.BaseLdap, ApiShimMixin):
super(TenantApi, self).delete(id) super(TenantApi, self).delete(id)
def update(self, id, values): def update(self, id, values):
old_obj = self.get(id) try:
old_obj = self.get(id)
except exception.NotFound:
raise exception.TenantNotFound(tenant_id=id)
if old_obj['name'] != values['name']: if old_obj['name'] != values['name']:
raise exception.Error('Changing Name not permitted') msg = 'Changing Name not supported by LDAP'
raise exception.NotImplemented(message=msg)
super(TenantApi, self).update(id, values, old_obj) super(TenantApi, self).update(id, values, old_obj)
@ -558,12 +614,9 @@ class RoleApi(common_ldap.BaseLdap, ApiShimMixin):
try: try:
return roles[0] return roles[0]
except IndexError: except IndexError:
return None raise exception.RoleNotFound(role_id=name)
def add_user(self, role_id, user_id, tenant_id=None): def add_user(self, role_id, user_id, tenant_id=None):
user = self.user_api.get(user_id)
if user is None:
raise exception.UserNotFound(user_id=user_id)
role_dn = self._subrole_id_to_dn(role_id, tenant_id) role_dn = self._subrole_id_to_dn(role_id, tenant_id)
conn = self.get_connection() conn = self.get_connection()
user_dn = self.user_api._id_to_dn(user_id) user_dn = self.user_api._id_to_dn(user_id)

View File

@ -157,38 +157,50 @@ class Identity(sql.Base, identity.Driver):
in the list of tenants on the user. in the list of tenants on the user.
""" """
user_ref = self._get_user(user_id) user_ref = None
if (not user_ref tenant_ref = None
or not self._check_password(password, user_ref)): metadata_ref = {}
try:
user_ref = self._get_user(user_id)
except exception.UserNotFound:
raise AssertionError('Invalid user / password') raise AssertionError('Invalid user / password')
tenants = self.get_tenants_for_user(user_id) if not utils.check_password(password, user_ref.get('password')):
if tenant_id and tenant_id not in tenants: raise AssertionError('Invalid user / password')
raise AssertionError('Invalid tenant')
if tenant_id is not None:
if tenant_id not in self.get_tenants_for_user(user_id):
raise AssertionError('Invalid tenant')
try:
tenant_ref = self.get_tenant(tenant_id)
metadata_ref = self.get_metadata(user_id, tenant_id)
except exception.TenantNotFound:
tenant_ref = None
metadata_ref = {}
except exception.MetadataNotFound:
metadata_ref = {}
tenant_ref = self.get_tenant(tenant_id)
if tenant_ref:
metadata_ref = self.get_metadata(user_id, tenant_id)
else:
metadata_ref = {}
return (_filter_user(user_ref), tenant_ref, metadata_ref) return (_filter_user(user_ref), tenant_ref, metadata_ref)
def get_tenant(self, tenant_id): def get_tenant(self, tenant_id):
session = self.get_session() session = self.get_session()
tenant_ref = session.query(Tenant).filter_by(id=tenant_id).first() tenant_ref = session.query(Tenant).filter_by(id=tenant_id).first()
if not tenant_ref: if tenant_ref is None:
return raise exception.TenantNotFound(tenant_id=tenant_id)
return tenant_ref.to_dict() return tenant_ref.to_dict()
def get_tenant_by_name(self, tenant_name): def get_tenant_by_name(self, tenant_name):
session = self.get_session() session = self.get_session()
tenant_ref = session.query(Tenant).filter_by(name=tenant_name).first() tenant_ref = session.query(Tenant).filter_by(name=tenant_name).first()
if not tenant_ref: if not tenant_ref:
return raise exception.TenantNotFound(tenant_id=tenant_name)
return tenant_ref.to_dict() return tenant_ref.to_dict()
def get_tenant_users(self, tenant_id): def get_tenant_users(self, tenant_id):
session = self.get_session() session = self.get_session()
self.get_tenant(tenant_id)
user_refs = session.query(User)\ user_refs = session.query(User)\
.join(UserTenantMembership)\ .join(UserTenantMembership)\
.filter(UserTenantMembership.tenant_id == .filter(UserTenantMembership.tenant_id ==
@ -200,14 +212,14 @@ class Identity(sql.Base, identity.Driver):
session = self.get_session() session = self.get_session()
user_ref = session.query(User).filter_by(id=user_id).first() user_ref = session.query(User).filter_by(id=user_id).first()
if not user_ref: if not user_ref:
return raise exception.UserNotFound(user_id=user_id)
return user_ref.to_dict() return user_ref.to_dict()
def _get_user_by_name(self, user_name): def _get_user_by_name(self, user_name):
session = self.get_session() session = self.get_session()
user_ref = session.query(User).filter_by(name=user_name).first() user_ref = session.query(User).filter_by(name=user_name).first()
if not user_ref: if not user_ref:
return raise exception.UserNotFound(user_id=user_name)
return user_ref.to_dict() return user_ref.to_dict()
def get_user(self, user_id): def get_user(self, user_id):
@ -222,11 +234,16 @@ class Identity(sql.Base, identity.Driver):
.filter_by(user_id=user_id)\ .filter_by(user_id=user_id)\
.filter_by(tenant_id=tenant_id)\ .filter_by(tenant_id=tenant_id)\
.first() .first()
return getattr(metadata_ref, 'data', {}) if metadata_ref is None:
raise exception.MetadataNotFound()
return metadata_ref.data
def get_role(self, role_id): def get_role(self, role_id):
session = self.get_session() session = self.get_session()
return session.query(Role).filter_by(id=role_id).first() role_ref = session.query(Role).filter_by(id=role_id).first()
if role_ref is None:
raise exception.RoleNotFound(role_id=role_id)
return role_ref
def list_users(self): def list_users(self):
session = self.get_session() session = self.get_session()
@ -241,6 +258,8 @@ class Identity(sql.Base, identity.Driver):
# These should probably be part of the high-level API # These should probably be part of the high-level API
def add_user_to_tenant(self, tenant_id, user_id): def add_user_to_tenant(self, tenant_id, user_id):
session = self.get_session() session = self.get_session()
self.get_tenant(tenant_id)
self.get_user(user_id)
q = session.query(UserTenantMembership)\ q = session.query(UserTenantMembership)\
.filter_by(user_id=user_id)\ .filter_by(user_id=user_id)\
.filter_by(tenant_id=tenant_id) .filter_by(tenant_id=tenant_id)
@ -255,10 +274,14 @@ class Identity(sql.Base, identity.Driver):
def remove_user_from_tenant(self, tenant_id, user_id): def remove_user_from_tenant(self, tenant_id, user_id):
session = self.get_session() session = self.get_session()
self.get_tenant(tenant_id)
self.get_user(user_id)
membership_ref = session.query(UserTenantMembership)\ membership_ref = session.query(UserTenantMembership)\
.filter_by(user_id=user_id)\ .filter_by(user_id=user_id)\
.filter_by(tenant_id=tenant_id)\ .filter_by(tenant_id=tenant_id)\
.first() .first()
if membership_ref is None:
raise exception.NotFound('User not found in tenant')
with session.begin(): with session.begin():
session.delete(membership_ref) session.delete(membership_ref)
session.flush() session.flush()
@ -270,37 +293,46 @@ class Identity(sql.Base, identity.Driver):
def get_tenants_for_user(self, user_id): def get_tenants_for_user(self, user_id):
session = self.get_session() session = self.get_session()
self.get_user(user_id)
membership_refs = session.query(UserTenantMembership)\ membership_refs = session.query(UserTenantMembership)\
.filter_by(user_id=user_id)\ .filter_by(user_id=user_id)\
.all() .all()
return [x.tenant_id for x in membership_refs] return [x.tenant_id for x in membership_refs]
def get_roles_for_user_and_tenant(self, user_id, tenant_id): def get_roles_for_user_and_tenant(self, user_id, tenant_id):
metadata_ref = self.get_metadata(user_id, tenant_id) self.get_user(user_id)
if not metadata_ref: self.get_tenant(tenant_id)
try:
metadata_ref = self.get_metadata(user_id, tenant_id)
except exception.MetadataNotFound:
metadata_ref = {} metadata_ref = {}
return metadata_ref.get('roles', []) return metadata_ref.get('roles', [])
def add_role_to_user_and_tenant(self, user_id, tenant_id, role_id): def add_role_to_user_and_tenant(self, user_id, tenant_id, role_id):
metadata_ref = self.get_metadata(user_id, tenant_id) self.get_user(user_id)
is_new = False self.get_tenant(tenant_id)
if not metadata_ref: self.get_role(role_id)
is_new = True try:
metadata_ref = self.get_metadata(user_id, tenant_id)
is_new = False
except exception.MetadataNotFound:
metadata_ref = {} metadata_ref = {}
is_new = True
roles = set(metadata_ref.get('roles', [])) roles = set(metadata_ref.get('roles', []))
roles.add(role_id) roles.add(role_id)
metadata_ref['roles'] = list(roles) metadata_ref['roles'] = list(roles)
if not is_new: if is_new:
self.update_metadata(user_id, tenant_id, metadata_ref)
else:
self.create_metadata(user_id, tenant_id, metadata_ref) self.create_metadata(user_id, tenant_id, metadata_ref)
else:
self.update_metadata(user_id, tenant_id, metadata_ref)
def remove_role_from_user_and_tenant(self, user_id, tenant_id, role_id): def remove_role_from_user_and_tenant(self, user_id, tenant_id, role_id):
metadata_ref = self.get_metadata(user_id, tenant_id) try:
is_new = False metadata_ref = self.get_metadata(user_id, tenant_id)
if not metadata_ref: is_new = False
is_new = True except exception.MetadataNotFound:
metadata_ref = {} metadata_ref = {}
is_new = True
roles = set(metadata_ref.get('roles', [])) roles = set(metadata_ref.get('roles', []))
if role_id not in roles: if role_id not in roles:
msg = 'Cannot remove role that has not been granted, %s' % role_id msg = 'Cannot remove role that has not been granted, %s' % role_id
@ -308,10 +340,10 @@ class Identity(sql.Base, identity.Driver):
roles.remove(role_id) roles.remove(role_id)
metadata_ref['roles'] = list(roles) metadata_ref['roles'] = list(roles)
if not is_new: if is_new:
self.update_metadata(user_id, tenant_id, metadata_ref)
else:
self.create_metadata(user_id, tenant_id, metadata_ref) self.create_metadata(user_id, tenant_id, metadata_ref)
else:
self.update_metadata(user_id, tenant_id, metadata_ref)
# CRUD # CRUD
@handle_conflicts(type='user') @handle_conflicts(type='user')
@ -327,8 +359,12 @@ class Identity(sql.Base, identity.Driver):
@handle_conflicts(type='user') @handle_conflicts(type='user')
def update_user(self, user_id, user): def update_user(self, user_id, user):
session = self.get_session() session = self.get_session()
if user_id != user['id']:
raise exception.ValidationError('Cannot change user ID')
with session.begin(): with session.begin():
user_ref = session.query(User).filter_by(id=user_id).first() user_ref = session.query(User).filter_by(id=user_id).first()
if user_ref is None:
raise exception.UserNotFound(user_id=user_id)
old_user_dict = user_ref.to_dict() old_user_dict = user_ref.to_dict()
user = _ensure_hashed_password(user) user = _ensure_hashed_password(user)
for k in user: for k in user:
@ -343,6 +379,8 @@ class Identity(sql.Base, identity.Driver):
def delete_user(self, user_id): def delete_user(self, user_id):
session = self.get_session() session = self.get_session()
user_ref = session.query(User).filter_by(id=user_id).first() user_ref = session.query(User).filter_by(id=user_id).first()
if not user_ref:
raise exception.UserNotFound(user_id=user_id)
membership_refs = session.query(UserTenantMembership)\ membership_refs = session.query(UserTenantMembership)\
.filter_by(user_id=user_id)\ .filter_by(user_id=user_id)\
.all() .all()
@ -379,6 +417,8 @@ class Identity(sql.Base, identity.Driver):
session = self.get_session() session = self.get_session()
with session.begin(): with session.begin():
tenant_ref = session.query(Tenant).filter_by(id=tenant_id).first() tenant_ref = session.query(Tenant).filter_by(id=tenant_id).first()
if tenant_ref is None:
raise exception.TenantNotFound(tenant_id=tenant_id)
old_tenant_dict = tenant_ref.to_dict() old_tenant_dict = tenant_ref.to_dict()
for k in tenant: for k in tenant:
old_tenant_dict[k] = tenant[k] old_tenant_dict[k] = tenant[k]
@ -392,6 +432,8 @@ class Identity(sql.Base, identity.Driver):
def delete_tenant(self, tenant_id): def delete_tenant(self, tenant_id):
session = self.get_session() session = self.get_session()
tenant_ref = session.query(Tenant).filter_by(id=tenant_id).first() tenant_ref = session.query(Tenant).filter_by(id=tenant_id).first()
if not tenant_ref:
raise exception.TenantNotFound(tenant_id=tenant_id)
membership_refs = session.query(UserTenantMembership)\ membership_refs = session.query(UserTenantMembership)\
.filter_by(tenant_id=tenant_id)\ .filter_by(tenant_id=tenant_id)\
.all() .all()
@ -452,6 +494,8 @@ class Identity(sql.Base, identity.Driver):
session = self.get_session() session = self.get_session()
with session.begin(): with session.begin():
role_ref = session.query(Role).filter_by(id=role_id).first() role_ref = session.query(Role).filter_by(id=role_id).first()
if role_ref is None:
raise exception.RoleNotFound(role_id=role_id)
for k in role: for k in role:
role_ref[k] = role[k] role_ref[k] = role[k]
session.flush() session.flush()
@ -459,6 +503,7 @@ class Identity(sql.Base, identity.Driver):
def delete_role(self, role_id): def delete_role(self, role_id):
session = self.get_session() session = self.get_session()
role_ref = session.query(Role).filter_by(id=role_id).first()
with session.begin(): with session.begin():
session.delete(role_ref) if not session.query(Role).filter_by(id=role_id).delete():
raise exception.RoleNotFound(role_id=role_id)
session.flush()

View File

@ -52,7 +52,8 @@ class Driver(object):
def authenticate(self, user_id=None, tenant_id=None, password=None): def authenticate(self, user_id=None, tenant_id=None, password=None):
"""Authenticate a given user, tenant and password. """Authenticate a given user, tenant and password.
Returns: (user, tenant, metadata). :returns: (user_ref, tenant_ref, metadata_ref)
:raises: AssertionError
""" """
raise exception.NotImplemented() raise exception.NotImplemented()
@ -60,7 +61,8 @@ class Driver(object):
def get_tenant(self, tenant_id): def get_tenant(self, tenant_id):
"""Get a tenant by id. """Get a tenant by id.
Returns: tenant_ref or None. :returns: tenant_ref
:raises: keystone.exception.TenantNotFound
""" """
raise exception.NotImplemented() raise exception.NotImplemented()
@ -68,7 +70,8 @@ class Driver(object):
def get_tenant_by_name(self, tenant_name): def get_tenant_by_name(self, tenant_name):
"""Get a tenant by name. """Get a tenant by name.
Returns: tenant_ref or None. :returns: tenant_ref
:raises: keystone.exception.TenantNotFound
""" """
raise exception.NotImplemented() raise exception.NotImplemented()
@ -76,7 +79,8 @@ class Driver(object):
def get_user(self, user_id): def get_user(self, user_id):
"""Get a user by id. """Get a user by id.
Returns: user_ref or None. :returns: user_ref
:raises: keystone.exception.UserNotFound
""" """
raise exception.NotImplemented() raise exception.NotImplemented()
@ -84,7 +88,8 @@ class Driver(object):
def get_user_by_name(self, user_name): def get_user_by_name(self, user_name):
"""Get a user by name. """Get a user by name.
Returns: user_ref or None. :returns: user_ref
:raises: keystone.exception.UserNotFound
""" """
raise exception.NotImplemented() raise exception.NotImplemented()
@ -92,7 +97,8 @@ class Driver(object):
def get_role(self, role_id): def get_role(self, role_id):
"""Get a role by id. """Get a role by id.
Returns: role_ref or None. :returns: role_ref
:raises: keystone.exception.RoleNotFound
""" """
raise exception.NotImplemented() raise exception.NotImplemented()
@ -103,7 +109,7 @@ class Driver(object):
NOTE(termie): I'd prefer if this listed only the users for a given NOTE(termie): I'd prefer if this listed only the users for a given
tenant. tenant.
Returns: a list of user_refs or an empty list. :returns: a list of user_refs or an empty list
""" """
raise exception.NotImplemented() raise exception.NotImplemented()
@ -111,7 +117,7 @@ class Driver(object):
def list_roles(self): def list_roles(self):
"""List all roles in the system. """List all roles in the system.
Returns: a list of role_refs or an empty list. :returns: a list of role_refs or an empty list.
""" """
raise exception.NotImplemented() raise exception.NotImplemented()
@ -119,18 +125,50 @@ class Driver(object):
# NOTE(termie): seven calls below should probably be exposed by the api # NOTE(termie): seven calls below should probably be exposed by the api
# more clearly when the api redesign happens # more clearly when the api redesign happens
def add_user_to_tenant(self, tenant_id, user_id): def add_user_to_tenant(self, tenant_id, user_id):
"""Add user to a tenant without an explicit role relationship.
:raises: keystone.exception.TenantNotFound,
keystone.exception.UserNotFound
"""
raise exception.NotImplemented() raise exception.NotImplemented()
def remove_user_from_tenant(self, tenant_id, user_id): def remove_user_from_tenant(self, tenant_id, user_id):
"""Remove user from a tenant without an explicit role relationship.
:raises: keystone.exception.TenantNotFound,
keystone.exception.UserNotFound
"""
raise exception.NotImplemented() raise exception.NotImplemented()
def get_all_tenants(self): def get_all_tenants(self):
"""FIXME(dolph): Lists all tenants in the system? I'm not sure how this
is different from get_tenants, why get_tenants isn't
documented as part of the driver, or why it's called
get_tenants instead of list_tenants (i.e. list_roles
and list_users)...
:returns: a list of ... FIXME(dolph): tenant_refs or tenant_id's?
"""
raise exception.NotImplemented()
def get_tenant_users(self, tenant_id):
"""FIXME(dolph): Lists all users with a relationship to the specified
tenant?
:returns: a list of ... FIXME(dolph): user_refs or user_id's?
:raises: keystone.exception.UserNotFound
"""
raise exception.NotImplemented() raise exception.NotImplemented()
def get_tenants_for_user(self, user_id): def get_tenants_for_user(self, user_id):
"""Get the tenants associated with a given user. """Get the tenants associated with a given user.
Returns: a list of tenant ids. :returns: a list of tenant_id's.
:raises: keystone.exception.UserNotFound
""" """
raise exception.NotImplemented() raise exception.NotImplemented()
@ -138,41 +176,83 @@ class Driver(object):
def get_roles_for_user_and_tenant(self, user_id, tenant_id): def get_roles_for_user_and_tenant(self, user_id, tenant_id):
"""Get the roles associated with a user within given tenant. """Get the roles associated with a user within given tenant.
Returns: a list of role ids. :returns: a list of role ids.
:raises: keystone.exception.UserNotFound,
keystone.exception.TenantNotFound
""" """
raise exception.NotImplemented() raise exception.NotImplemented()
def add_role_to_user_and_tenant(self, user_id, tenant_id, role_id): def add_role_to_user_and_tenant(self, user_id, tenant_id, role_id):
"""Add a role to a user within given tenant.""" """Add a role to a user within given tenant.
:raises: keystone.exception.UserNotFound,
keystone.exception.TenantNotFound,
keystone.exception.RoleNotFound
"""
raise exception.NotImplemented() raise exception.NotImplemented()
def remove_role_from_user_and_tenant(self, user_id, tenant_id, role_id): def remove_role_from_user_and_tenant(self, user_id, tenant_id, role_id):
"""Remove a role from a user within given tenant.""" """Remove a role from a user within given tenant.
:raises: keystone.exception.UserNotFound,
keystone.exception.TenantNotFound,
keystone.exception.RoleNotFound
"""
raise exception.NotImplemented() raise exception.NotImplemented()
# user crud # user crud
def create_user(self, user_id, user): def create_user(self, user_id, user):
"""Creates a new user.
:raises: keystone.exception.Conflict
"""
raise exception.NotImplemented() raise exception.NotImplemented()
def update_user(self, user_id, user): def update_user(self, user_id, user):
"""Updates an existing user.
:raises: keystone.exception.UserNotFound, keystone.exception.Conflict
"""
raise exception.NotImplemented() raise exception.NotImplemented()
def delete_user(self, user_id): def delete_user(self, user_id):
"""Deletes an existing user.
:raises: keystone.exception.UserNotFound
"""
raise exception.NotImplemented() raise exception.NotImplemented()
# tenant crud # tenant crud
def create_tenant(self, tenant_id, tenant): def create_tenant(self, tenant_id, tenant):
"""Creates a new tenant.
:raises: keystone.exception.Conflict
"""
raise exception.NotImplemented() raise exception.NotImplemented()
def update_tenant(self, tenant_id, tenant): def update_tenant(self, tenant_id, tenant):
"""Updates an existing tenant.
:raises: keystone.exception.TenantNotFound, keystone.exception.Conflict
"""
raise exception.NotImplemented() raise exception.NotImplemented()
def delete_tenant(self, tenant_id, tenant): def delete_tenant(self, tenant_id):
"""Deletes an existing tenant.
:raises: keystone.exception.TenantNotFound
"""
raise exception.NotImplemented() raise exception.NotImplemented()
# metadata crud # metadata crud
def get_metadata(self, user_id, tenant_id): def get_metadata(self, user_id, tenant_id):
raise exception.NotImplemented() raise exception.NotImplemented()
@ -182,17 +262,32 @@ class Driver(object):
def update_metadata(self, user_id, tenant_id, metadata): def update_metadata(self, user_id, tenant_id, metadata):
raise exception.NotImplemented() raise exception.NotImplemented()
def delete_metadata(self, user_id, tenant_id, metadata): def delete_metadata(self, user_id, tenant_id):
raise exception.NotImplemented() raise exception.NotImplemented()
# role crud # role crud
def create_role(self, role_id, role): def create_role(self, role_id, role):
"""Creates a new role.
:raises: keystone.exception.Conflict
"""
raise exception.NotImplemented() raise exception.NotImplemented()
def update_role(self, role_id, role): def update_role(self, role_id, role):
"""Updates an existing role.
:raises: keystone.exception.RoleNotFound, keystone.exception.Conflict
"""
raise exception.NotImplemented() raise exception.NotImplemented()
def delete_role(self, role_id): def delete_role(self, role_id):
"""Deletes an existing role.
:raises: keystone.exception.RoleNotFound
"""
raise exception.NotImplemented() raise exception.NotImplemented()
@ -286,11 +381,7 @@ class TenantController(wsgi.Application):
def get_tenant(self, context, tenant_id): def get_tenant(self, context, tenant_id):
# TODO(termie): this stuff should probably be moved to middleware # TODO(termie): this stuff should probably be moved to middleware
self.assert_admin(context) self.assert_admin(context)
tenant = self.identity_api.get_tenant(context, tenant_id) return {'tenant': self.identity_api.get_tenant(context, tenant_id)}
if tenant is None:
raise exception.TenantNotFound(tenant_id=tenant_id)
return {'tenant': tenant}
# CRUD Extension # CRUD Extension
def create_tenant(self, context, tenant): def create_tenant(self, context, tenant):
@ -301,36 +392,23 @@ class TenantController(wsgi.Application):
raise exception.ValidationError(message=msg) raise exception.ValidationError(message=msg)
self.assert_admin(context) self.assert_admin(context)
tenant_id = (tenant_ref.get('id') tenant_ref['id'] = tenant_ref.get('id', uuid.uuid4().hex)
and tenant_ref.get('id')
or uuid.uuid4().hex)
tenant_ref['id'] = tenant_id
tenant = self.identity_api.create_tenant( tenant = self.identity_api.create_tenant(
context, tenant_id, tenant_ref) context, tenant_ref['id'], tenant_ref)
return {'tenant': tenant} return {'tenant': tenant}
def update_tenant(self, context, tenant_id, tenant): def update_tenant(self, context, tenant_id, tenant):
self.assert_admin(context) self.assert_admin(context)
if self.identity_api.get_tenant(context, tenant_id) is None:
raise exception.TenantNotFound(tenant_id=tenant_id)
tenant_ref = self.identity_api.update_tenant( tenant_ref = self.identity_api.update_tenant(
context, tenant_id, tenant) context, tenant_id, tenant)
return {'tenant': tenant_ref} return {'tenant': tenant_ref}
def delete_tenant(self, context, tenant_id, **kw): def delete_tenant(self, context, tenant_id):
self.assert_admin(context) self.assert_admin(context)
if self.identity_api.get_tenant(context, tenant_id) is None:
raise exception.TenantNotFound(tenant_id=tenant_id)
self.identity_api.delete_tenant(context, tenant_id) self.identity_api.delete_tenant(context, tenant_id)
def get_tenant_users(self, context, tenant_id, **kw): def get_tenant_users(self, context, tenant_id, **kw):
self.assert_admin(context) self.assert_admin(context)
if self.identity_api.get_tenant(context, tenant_id) is None:
raise exception.TenantNotFound(tenant_id=tenant_id)
user_refs = self.identity_api.get_tenant_users(context, tenant_id) user_refs = self.identity_api.get_tenant_users(context, tenant_id)
return {'users': user_refs} return {'users': user_refs}
@ -376,18 +454,13 @@ class UserController(wsgi.Application):
def get_user(self, context, user_id): def get_user(self, context, user_id):
self.assert_admin(context) self.assert_admin(context)
user_ref = self.identity_api.get_user(context, user_id) return {'user': self.identity_api.get_user(context, user_id)}
if not user_ref:
raise exception.UserNotFound(user_id=user_id)
return {'user': user_ref}
def get_users(self, context): def get_users(self, context):
# NOTE(termie): i can't imagine that this really wants all the data # NOTE(termie): i can't imagine that this really wants all the data
# about every single user in the system... # about every single user in the system...
self.assert_admin(context) self.assert_admin(context)
user_refs = self.identity_api.list_users(context) return {'users': self.identity_api.list_users(context)}
return {'users': user_refs}
# CRUD extension # CRUD extension
def create_user(self, context, user): def create_user(self, context, user):
@ -414,9 +487,6 @@ class UserController(wsgi.Application):
def update_user(self, context, user_id, user): def update_user(self, context, user_id, user):
# NOTE(termie): this is really more of a patch than a put # NOTE(termie): this is really more of a patch than a put
self.assert_admin(context) self.assert_admin(context)
if self.identity_api.get_user(context, user_id) is None:
raise exception.UserNotFound(user_id=user_id)
user_ref = self.identity_api.update_user(context, user_id, user) user_ref = self.identity_api.update_user(context, user_id, user)
# If the password was changed or the user was disabled we clear tokens # If the password was changed or the user was disabled we clear tokens
@ -433,9 +503,6 @@ class UserController(wsgi.Application):
def delete_user(self, context, user_id): def delete_user(self, context, user_id):
self.assert_admin(context) self.assert_admin(context)
if self.identity_api.get_user(context, user_id) is None:
raise exception.UserNotFound(user_id=user_id)
self.identity_api.delete_user(context, user_id) self.identity_api.delete_user(context, user_id)
def set_user_enabled(self, context, user_id, user): def set_user_enabled(self, context, user_id, user):
@ -472,13 +539,6 @@ class RoleController(wsgi.Application):
raise exception.NotImplemented(message='User roles not supported: ' raise exception.NotImplemented(message='User roles not supported: '
'tenant ID required') 'tenant ID required')
user = self.identity_api.get_user(context, user_id)
if user is None:
raise exception.UserNotFound(user_id=user_id)
tenant = self.identity_api.get_tenant(context, tenant_id)
if tenant is None:
raise exception.TenantNotFound(tenant_id=tenant_id)
roles = self.identity_api.get_roles_for_user_and_tenant( roles = self.identity_api.get_roles_for_user_and_tenant(
context, user_id, tenant_id) context, user_id, tenant_id)
return {'roles': [self.identity_api.get_role(context, x) return {'roles': [self.identity_api.get_role(context, x)
@ -487,10 +547,7 @@ class RoleController(wsgi.Application):
# CRUD extension # CRUD extension
def get_role(self, context, role_id): def get_role(self, context, role_id):
self.assert_admin(context) self.assert_admin(context)
role_ref = self.identity_api.get_role(context, role_id) return {'role': self.identity_api.get_role(context, role_id)}
if not role_ref:
raise exception.RoleNotFound(role_id=role_id)
return {'role': role_ref}
def create_role(self, context, role): def create_role(self, context, role):
role = self._normalize_dict(role) role = self._normalize_dict(role)
@ -507,14 +564,11 @@ class RoleController(wsgi.Application):
def delete_role(self, context, role_id): def delete_role(self, context, role_id):
self.assert_admin(context) self.assert_admin(context)
self.get_role(context, role_id)
self.identity_api.delete_role(context, role_id) self.identity_api.delete_role(context, role_id)
def get_roles(self, context): def get_roles(self, context):
self.assert_admin(context) self.assert_admin(context)
roles = self.identity_api.list_roles(context) return {'roles': self.identity_api.list_roles(context)}
# TODO(termie): probably inefficient at some point
return {'roles': roles}
def add_role_to_user(self, context, user_id, role_id, tenant_id=None): def add_role_to_user(self, context, user_id, role_id, tenant_id=None):
"""Add a role to a user and tenant pair. """Add a role to a user and tenant pair.
@ -527,12 +581,6 @@ class RoleController(wsgi.Application):
if tenant_id is None: if tenant_id is None:
raise exception.NotImplemented(message='User roles not supported: ' raise exception.NotImplemented(message='User roles not supported: '
'tenant_id required') 'tenant_id required')
if self.identity_api.get_user(context, user_id) is None:
raise exception.UserNotFound(user_id=user_id)
if self.identity_api.get_tenant(context, tenant_id) is None:
raise exception.TenantNotFound(tenant_id=tenant_id)
if self.identity_api.get_role(context, role_id) is None:
raise exception.RoleNotFound(role_id=role_id)
# This still has the weird legacy semantics that adding a role to # This still has the weird legacy semantics that adding a role to
# a user also adds them to a tenant # a user also adds them to a tenant
@ -553,12 +601,6 @@ class RoleController(wsgi.Application):
if tenant_id is None: if tenant_id is None:
raise exception.NotImplemented(message='User roles not supported: ' raise exception.NotImplemented(message='User roles not supported: '
'tenant_id required') 'tenant_id required')
if self.identity_api.get_user(context, user_id) is None:
raise exception.UserNotFound(user_id=user_id)
if self.identity_api.get_tenant(context, tenant_id) is None:
raise exception.TenantNotFound(tenant_id=tenant_id)
if self.identity_api.get_role(context, role_id) is None:
raise exception.RoleNotFound(role_id=role_id)
# This still has the weird legacy semantics that adding a role to # This still has the weird legacy semantics that adding a role to
# a user also adds them to a tenant, so we must follow up on that # a user also adds them to a tenant, so we must follow up on that

View File

@ -249,25 +249,28 @@ class TokenController(wsgi.Application):
token_id = uuid.uuid4().hex token_id = uuid.uuid4().hex
if 'passwordCredentials' in auth: if 'passwordCredentials' in auth:
user_id = auth['passwordCredentials'].get('userId', None)
username = auth['passwordCredentials'].get('username', '') username = auth['passwordCredentials'].get('username', '')
password = auth['passwordCredentials'].get('password', '') password = auth['passwordCredentials'].get('password', '')
tenant_name = auth.get('tenantName', None) tenant_name = auth.get('tenantName', None)
user_id = auth['passwordCredentials'].get('userId', None)
if username: if username:
user_ref = self.identity_api.get_user_by_name( try:
context=context, user_ref = self.identity_api.get_user_by_name(
user_name=username) context=context, user_name=username)
if user_ref:
user_id = user_ref['id'] user_id = user_ref['id']
except exception.UserNotFound:
raise exception.Unauthorized()
# more compat # more compat
tenant_id = auth.get('tenantId', None) tenant_id = auth.get('tenantId', None)
if tenant_name: if tenant_name:
tenant_ref = self.identity_api.get_tenant_by_name( try:
context=context, tenant_name=tenant_name) tenant_ref = self.identity_api.get_tenant_by_name(
if tenant_ref: context=context, tenant_name=tenant_name)
tenant_id = tenant_ref['id'] tenant_id = tenant_ref['id']
except exception.TenantNotFound:
raise exception.Unauthorized()
try: try:
auth_info = self.identity_api.authenticate(context=context, auth_info = self.identity_api.authenticate(context=context,
@ -330,12 +333,13 @@ class TokenController(wsgi.Application):
tenants = self.identity_api.get_tenants_for_user(context, tenants = self.identity_api.get_tenants_for_user(context,
user_ref['id']) user_ref['id'])
if tenant_id: if tenant_id and tenant_id not in tenants:
assert tenant_id in tenants raise exception.Unauthorized()
tenant_ref = self.identity_api.get_tenant(context=context, try:
tenant_id=tenant_id) tenant_ref = self.identity_api.get_tenant(
if tenant_ref: context=context,
tenant_id=tenant_id)
metadata_ref = self.identity_api.get_metadata( metadata_ref = self.identity_api.get_metadata(
context=context, context=context,
user_id=user_ref['id'], user_id=user_ref['id'],
@ -345,7 +349,8 @@ class TokenController(wsgi.Application):
user_id=user_ref['id'], user_id=user_ref['id'],
tenant_id=tenant_ref['id'], tenant_id=tenant_ref['id'],
metadata=metadata_ref) metadata=metadata_ref)
else: except exception.TenantNotFound:
tenant_ref = None
metadata_ref = {} metadata_ref = {}
catalog_ref = {} catalog_ref = {}

View File

@ -25,9 +25,12 @@ from keystone import token
class Token(kvs.Base, token.Driver): class Token(kvs.Base, token.Driver):
# Public interface # Public interface
def get_token(self, token_id): def get_token(self, token_id):
token = self.db.get('token-%s' % token_id) try:
if (token and (token['expires'] is None token = self.db.get('token-%s' % token_id)
or token['expires'] > datetime.datetime.utcnow())): except exception.NotFound:
raise exception.TokenNotFound(token_id=token_id)
if (token['expires'] is None
or token['expires'] > datetime.datetime.utcnow()):
return token return token
else: else:
raise exception.TokenNotFound(token_id=token_id) raise exception.TokenNotFound(token_id=token_id)
@ -41,8 +44,8 @@ class Token(kvs.Base, token.Driver):
def delete_token(self, token_id): def delete_token(self, token_id):
try: try:
return self.db.delete('token-%s' % token_id) self.db.delete('token-%s' % token_id)
except KeyError: except exception.NotFound:
raise exception.TokenNotFound(token_id=token_id) raise exception.TokenNotFound(token_id=token_id)
def list_tokens(self, user_id): def list_tokens(self, user_id):

View File

@ -72,14 +72,9 @@ class Token(sql.Base, token.Driver):
def delete_token(self, token_id): def delete_token(self, token_id):
session = self.get_session() session = self.get_session()
token_ref = session.query(TokenModel)\
.filter_by(id=token_id)\
.first()
if not token_ref:
raise exception.TokenNotFound(token_id=token_id)
with session.begin(): with session.begin():
session.delete(token_ref) if not session.query(TokenModel).filter_by(id=token_id).delete():
raise exception.TokenNotFound(token_id=token_id)
session.flush() session.flush()
def list_tokens(self, user_id): def list_tokens(self, user_id):

View File

@ -24,7 +24,7 @@ class IdentityTests(object):
def test_authenticate_bad_user(self): def test_authenticate_bad_user(self):
self.assertRaises(AssertionError, self.assertRaises(AssertionError,
self.identity_api.authenticate, self.identity_api.authenticate,
user_id=self.user_foo['id'] + 'WRONG', user_id=uuid.uuid4().hex,
tenant_id=self.tenant_bar['id'], tenant_id=self.tenant_bar['id'],
password=self.user_foo['password']) password=self.user_foo['password'])
@ -33,13 +33,13 @@ class IdentityTests(object):
self.identity_api.authenticate, self.identity_api.authenticate,
user_id=self.user_foo['id'], user_id=self.user_foo['id'],
tenant_id=self.tenant_bar['id'], tenant_id=self.tenant_bar['id'],
password=self.user_foo['password'] + 'WRONG') password=uuid.uuid4().hex)
def test_authenticate_invalid_tenant(self): def test_authenticate_bad_tenant(self):
self.assertRaises(AssertionError, self.assertRaises(AssertionError,
self.identity_api.authenticate, self.identity_api.authenticate,
user_id=self.user_foo['id'], user_id=self.user_foo['id'],
tenant_id=self.tenant_bar['id'] + 'WRONG', tenant_id=uuid.uuid4().hex,
password=self.user_foo['password']) password=self.user_foo['password'])
def test_authenticate_no_tenant(self): def test_authenticate_no_tenant(self):
@ -86,30 +86,30 @@ class IdentityTests(object):
user_ref = self.identity_api._get_user(self.user_foo['id']) user_ref = self.identity_api._get_user(self.user_foo['id'])
self.assertNotEqual(user_ref['password'], self.user_foo['password']) self.assertNotEqual(user_ref['password'], self.user_foo['password'])
def test_get_tenant_bad_tenant(self):
tenant_ref = self.identity_api.get_tenant(
tenant_id=self.tenant_bar['id'] + 'WRONG')
self.assert_(tenant_ref is None)
def test_get_tenant(self): def test_get_tenant(self):
tenant_ref = self.identity_api.get_tenant( tenant_ref = self.identity_api.get_tenant(
tenant_id=self.tenant_bar['id']) tenant_id=self.tenant_bar['id'])
self.assertDictEqual(tenant_ref, self.tenant_bar) self.assertDictEqual(tenant_ref, self.tenant_bar)
def test_get_tenant_by_name_bad_tenant(self): def test_get_tenant_404(self):
tenant_ref = self.identity_api.get_tenant( self.assertRaises(exception.TenantNotFound,
tenant_id=self.tenant_bar['name'] + 'WRONG') self.identity_api.get_tenant,
self.assert_(tenant_ref is None) tenant_id=uuid.uuid4().hex)
def test_get_tenant_by_name(self): def test_get_tenant_by_name(self):
tenant_ref = self.identity_api.get_tenant_by_name( tenant_ref = self.identity_api.get_tenant_by_name(
tenant_name=self.tenant_bar['name']) tenant_name=self.tenant_bar['name'])
self.assertDictEqual(tenant_ref, self.tenant_bar) self.assertDictEqual(tenant_ref, self.tenant_bar)
def test_get_user_bad_user(self): def test_get_tenant_by_name_404(self):
user_ref = self.identity_api.get_user( self.assertRaises(exception.TenantNotFound,
user_id=self.user_foo['id'] + 'WRONG') self.identity_api.get_tenant,
self.assert_(user_ref is None) tenant_id=uuid.uuid4().hex)
def test_get_tenant_users_404(self):
self.assertRaises(exception.TenantNotFound,
self.identity_api.get_tenant_users,
tenant_id=uuid.uuid4().hex)
def test_get_user(self): def test_get_user(self):
user_ref = self.identity_api.get_user(user_id=self.user_foo['id']) user_ref = self.identity_api.get_user(user_id=self.user_foo['id'])
@ -119,6 +119,11 @@ class IdentityTests(object):
self.user_foo.pop('password') self.user_foo.pop('password')
self.assertDictEqual(user_ref, self.user_foo) self.assertDictEqual(user_ref, self.user_foo)
def test_get_user_404(self):
self.assertRaises(exception.UserNotFound,
self.identity_api.get_user,
user_id=uuid.uuid4().hex)
def test_get_user_by_name(self): def test_get_user_by_name(self):
user_ref = self.identity_api.get_user_by_name( user_ref = self.identity_api.get_user_by_name(
user_name=self.user_foo['name']) user_name=self.user_foo['name'])
@ -128,17 +133,10 @@ class IdentityTests(object):
self.user_foo.pop('password') self.user_foo.pop('password')
self.assertDictEqual(user_ref, self.user_foo) self.assertDictEqual(user_ref, self.user_foo)
def test_get_metadata_bad_user(self): def test_get_user_by_name_404(self):
metadata_ref = self.identity_api.get_metadata( self.assertRaises(exception.UserNotFound,
user_id=self.user_foo['id'] + 'WRONG', self.identity_api.get_user_by_name,
tenant_id=self.tenant_bar['id']) user_name=uuid.uuid4().hex)
self.assert_(metadata_ref == {})
def test_get_metadata_bad_tenant(self):
metadata_ref = self.identity_api.get_metadata(
user_id=self.user_foo['id'],
tenant_id=self.tenant_bar['id'] + 'WRONG')
self.assert_(metadata_ref == {})
def test_get_metadata(self): def test_get_metadata(self):
metadata_ref = self.identity_api.get_metadata( metadata_ref = self.identity_api.get_metadata(
@ -146,12 +144,29 @@ class IdentityTests(object):
tenant_id=self.tenant_bar['id']) tenant_id=self.tenant_bar['id'])
self.assertDictEqual(metadata_ref, self.metadata_foobar) self.assertDictEqual(metadata_ref, self.metadata_foobar)
def test_get_metadata_404(self):
# FIXME(dolph): these exceptions could be more specific
self.assertRaises(exception.NotFound,
self.identity_api.get_metadata,
user_id=uuid.uuid4().hex,
tenant_id=self.tenant_bar['id'])
self.assertRaises(exception.NotFound,
self.identity_api.get_metadata,
user_id=self.user_foo['id'],
tenant_id=uuid.uuid4().hex)
def test_get_role(self): def test_get_role(self):
role_ref = self.identity_api.get_role( role_ref = self.identity_api.get_role(
role_id=self.role_keystone_admin['id']) role_id=self.role_keystone_admin['id'])
role_ref_dict = dict((x, role_ref[x]) for x in role_ref) role_ref_dict = dict((x, role_ref[x]) for x in role_ref)
self.assertDictEqual(role_ref_dict, self.role_keystone_admin) self.assertDictEqual(role_ref_dict, self.role_keystone_admin)
def test_get_role_404(self):
self.assertRaises(exception.RoleNotFound,
self.identity_api.get_role,
role_id=uuid.uuid4().hex)
def test_create_duplicate_role_name_fails(self): def test_create_duplicate_role_name_fails(self):
role = {'id': 'fake1', role = {'id': 'fake1',
'name': 'fake1name'} 'name': 'fake1name'}
@ -170,7 +185,7 @@ class IdentityTests(object):
self.identity_api.create_role('fake1', role1) self.identity_api.create_role('fake1', role1)
self.identity_api.create_role('fake2', role2) self.identity_api.create_role('fake2', role2)
role1['name'] = 'fake2name' role1['name'] = 'fake2name'
self.assertRaises(exception.Error, self.assertRaises(exception.Conflict,
self.identity_api.update_role, self.identity_api.update_role,
'fake1', 'fake1',
role1) role1)
@ -211,23 +226,27 @@ class IdentityTests(object):
self.identity_api.create_user('fake1', user1) self.identity_api.create_user('fake1', user1)
self.identity_api.create_user('fake2', user2) self.identity_api.create_user('fake2', user2)
user2['name'] = 'fake1' user2['name'] = 'fake1'
self.assertRaises(exception.Error, self.assertRaises(exception.Conflict,
self.identity_api.update_user, self.identity_api.update_user,
'fake2', 'fake2',
user2) user2)
def test_update_user_id_does_nothing(self): def test_update_user_id_fails(self):
user = {'id': 'fake1', user = {'id': 'fake1',
'name': 'fake1', 'name': 'fake1',
'password': 'fakepass', 'password': 'fakepass',
'tenants': ['bar']} 'tenants': ['bar']}
self.identity_api.create_user('fake1', user) self.identity_api.create_user('fake1', user)
user['id'] = 'fake2' user['id'] = 'fake2'
self.identity_api.update_user('fake1', user) self.assertRaises(exception.ValidationError,
self.identity_api.update_user,
'fake1',
user)
user_ref = self.identity_api.get_user('fake1') user_ref = self.identity_api.get_user('fake1')
self.assertEqual(user_ref['id'], 'fake1') self.assertEqual(user_ref['id'], 'fake1')
user_ref = self.identity_api.get_user('fake2') self.assertRaises(exception.UserNotFound,
self.assert_(user_ref is None) self.identity_api.get_user,
'fake2')
def test_create_duplicate_tenant_id_fails(self): def test_create_duplicate_tenant_id_fails(self):
tenant = {'id': 'fake1', 'name': 'fake1'} tenant = {'id': 'fake1', 'name': 'fake1'}
@ -265,8 +284,9 @@ class IdentityTests(object):
self.identity_api.update_tenant('fake1', tenant) self.identity_api.update_tenant('fake1', tenant)
tenant_ref = self.identity_api.get_tenant('fake1') tenant_ref = self.identity_api.get_tenant('fake1')
self.assertEqual(tenant_ref['id'], 'fake1') self.assertEqual(tenant_ref['id'], 'fake1')
tenant_ref = self.identity_api.get_tenant('fake2') self.assertRaises(exception.TenantNotFound,
self.assert_(tenant_ref is None) self.identity_api.get_tenant,
'fake2')
def test_get_role_by_user_and_tenant(self): def test_get_role_by_user_and_tenant(self):
roles_ref = self.identity_api.get_roles_for_user_and_tenant( roles_ref = self.identity_api.get_roles_for_user_and_tenant(
@ -286,22 +306,160 @@ class IdentityTests(object):
self.assertIn('keystone_admin', roles_ref) self.assertIn('keystone_admin', roles_ref)
self.assertIn('useless', roles_ref) self.assertIn('useless', roles_ref)
def test_delete_role(self): def test_get_roles_for_user_and_tenant_404(self):
role_id = 'test_role_delete' self.assertRaises(exception.UserNotFound,
new_role = {'id': role_id, 'name': 'Role to Delete'} self.identity_api.get_roles_for_user_and_tenant,
self.identity_api.create_role(role_id, new_role) uuid.uuid4().hex,
role_ref = self.identity_api.get_role(role_id) self.tenant_bar['id'])
self.assertRaises(exception.TenantNotFound,
self.identity_api.get_roles_for_user_and_tenant,
self.user_foo['id'],
uuid.uuid4().hex)
def test_add_role_to_user_and_tenant_404(self):
self.assertRaises(exception.UserNotFound,
self.identity_api.add_role_to_user_and_tenant,
uuid.uuid4().hex,
self.tenant_bar['id'],
'keystone_admin')
self.assertRaises(exception.TenantNotFound,
self.identity_api.add_role_to_user_and_tenant,
self.user_foo['id'],
uuid.uuid4().hex,
'keystone_admin')
self.assertRaises(exception.RoleNotFound,
self.identity_api.add_role_to_user_and_tenant,
self.user_foo['id'],
self.tenant_bar['id'],
uuid.uuid4().hex)
def test_remove_role_from_user_and_tenant(self):
self.identity_api.add_role_to_user_and_tenant(
self.user_foo['id'], self.tenant_bar['id'], 'useless')
self.identity_api.remove_role_from_user_and_tenant(
self.user_foo['id'], self.tenant_bar['id'], 'useless')
roles_ref = self.identity_api.get_roles_for_user_and_tenant(
self.user_foo['id'], self.tenant_bar['id'])
self.assertNotIn('useless', roles_ref)
self.assertRaises(exception.NotFound,
self.identity_api.remove_role_from_user_and_tenant,
self.user_foo['id'],
self.tenant_bar['id'],
'useless')
def test_role_crud(self):
role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex}
self.identity_api.create_role(role['id'], role)
role_ref = self.identity_api.get_role(role['id'])
role_ref_dict = dict((x, role_ref[x]) for x in role_ref) role_ref_dict = dict((x, role_ref[x]) for x in role_ref)
self.assertDictEqual(role_ref_dict, new_role) self.assertDictEqual(role_ref_dict, role)
self.identity_api.delete_role(role_id)
role_ref = self.identity_api.get_role(role_id) role['name'] = uuid.uuid4().hex
self.assertIsNone(role_ref) self.identity_api.update_role(role['id'], role)
role_ref = self.identity_api.get_role(role['id'])
role_ref_dict = dict((x, role_ref[x]) for x in role_ref)
self.assertDictEqual(role_ref_dict, role)
self.identity_api.delete_role(role['id'])
self.assertRaises(exception.RoleNotFound,
self.identity_api.get_role,
role['id'])
def test_update_role_404(self):
role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex}
self.assertRaises(exception.RoleNotFound,
self.identity_api.update_role,
role['id'],
role)
def test_add_user_to_tenant(self): def test_add_user_to_tenant(self):
tenant_id = 'tenent4add' self.identity_api.add_user_to_tenant(self.tenant_bar['id'],
self.identity_api.add_user_to_tenant(tenant_id, 'foo') self.user_foo['id'])
tenants = self.identity_api.get_tenants_for_user('foo') tenants = self.identity_api.get_tenants_for_user(self.user_foo['id'])
self.assertIn(tenant_id, tenants) self.assertIn(self.tenant_bar['id'], tenants)
def test_add_user_to_tenant_404(self):
self.assertRaises(exception.TenantNotFound,
self.identity_api.add_user_to_tenant,
uuid.uuid4().hex,
self.user_foo['id'])
self.assertRaises(exception.UserNotFound,
self.identity_api.add_user_to_tenant,
self.tenant_bar['id'],
uuid.uuid4().hex)
def test_remove_user_from_tenant(self):
self.identity_api.add_user_to_tenant(self.tenant_bar['id'],
self.user_foo['id'])
self.identity_api.remove_user_from_tenant(self.tenant_bar['id'],
self.user_foo['id'])
tenants = self.identity_api.get_tenants_for_user(self.user_foo['id'])
self.assertNotIn(self.tenant_bar['id'], tenants)
def test_remove_user_from_tenant_404(self):
self.assertRaises(exception.TenantNotFound,
self.identity_api.remove_user_from_tenant,
uuid.uuid4().hex,
self.user_foo['id'])
self.assertRaises(exception.UserNotFound,
self.identity_api.remove_user_from_tenant,
self.tenant_bar['id'],
uuid.uuid4().hex)
self.assertRaises(exception.NotFound,
self.identity_api.remove_user_from_tenant,
self.tenant_baz['id'],
self.user_foo['id'])
def test_get_tenants_for_user_404(self):
self.assertRaises(exception.UserNotFound,
self.identity_api.get_tenants_for_user,
uuid.uuid4().hex)
def test_update_tenant_404(self):
self.assertRaises(exception.TenantNotFound,
self.identity_api.update_tenant,
uuid.uuid4().hex,
dict())
def test_delete_tenant_404(self):
self.assertRaises(exception.TenantNotFound,
self.identity_api.delete_tenant,
uuid.uuid4().hex)
def test_update_user_404(self):
user_id = uuid.uuid4().hex
self.assertRaises(exception.UserNotFound,
self.identity_api.update_user,
user_id,
{'id': user_id})
def test_delete_user_with_tenant_association(self):
user = {'id': uuid.uuid4().hex,
'name': uuid.uuid4().hex,
'password': uuid.uuid4().hex}
self.identity_api.create_user(user['id'], user)
self.identity_api.add_user_to_tenant(self.tenant_bar['id'],
user['id'])
self.identity_api.delete_user(user['id'])
self.assertRaises(exception.UserNotFound,
self.identity_api.get_tenants_for_user,
user['id'])
def test_delete_user_404(self):
self.assertRaises(exception.UserNotFound,
self.identity_api.delete_user,
uuid.uuid4().hex)
def test_delete_role_404(self):
self.assertRaises(exception.RoleNotFound,
self.identity_api.delete_role,
uuid.uuid4().hex)
def test_create_tenant_long_name_fails(self): def test_create_tenant_long_name_fails(self):
tenant = {'id': 'fake1', 'name': 'a' * 65} tenant = {'id': 'fake1', 'name': 'a' * 65}
@ -378,10 +536,20 @@ class TokenTests(object):
self.assertEquals(new_data_ref, data) self.assertEquals(new_data_ref, data)
self.token_api.delete_token(token_id) self.token_api.delete_token(token_id)
self.assertRaises(exception.TokenNotFound,
self.token_api.delete_token, token_id)
self.assertRaises(exception.TokenNotFound, self.assertRaises(exception.TokenNotFound,
self.token_api.get_token, token_id) self.token_api.get_token, token_id)
self.assertRaises(exception.TokenNotFound,
self.token_api.delete_token, token_id)
def test_get_token_404(self):
self.assertRaises(exception.TokenNotFound,
self.token_api.get_token,
uuid.uuid4().hex)
def test_delete_token_404(self):
self.assertRaises(exception.TokenNotFound,
self.token_api.delete_token,
uuid.uuid4().hex)
def test_expired_token(self): def test_expired_token(self):
token_id = uuid.uuid4().hex token_id = uuid.uuid4().hex
@ -403,7 +571,6 @@ class TokenTests(object):
class CatalogTests(object): class CatalogTests(object):
def test_service_crud(self): def test_service_crud(self):
new_service = {'id': 'MY_SERVICE', 'type': 'myservice', new_service = {'id': 'MY_SERVICE', 'type': 'myservice',
'name': 'My Service', 'description': 'My description'} 'name': 'My Service', 'description': 'My description'}
@ -413,9 +580,41 @@ class CatalogTests(object):
service_id = new_service['id'] service_id = new_service['id']
self.catalog_api.delete_service(service_id) self.catalog_api.delete_service(service_id)
self.assertRaises(exception.ServiceNotFound, self.assertRaises(exception.ServiceNotFound,
self.catalog_api.delete_service, service_id) self.catalog_man.delete_service, {}, service_id)
self.assertRaises(exception.ServiceNotFound, self.assertRaises(exception.ServiceNotFound,
self.catalog_api.get_service, service_id) self.catalog_man.get_service, {}, service_id)
def test_get_service_404(self):
self.assertRaises(exception.ServiceNotFound,
self.catalog_man.get_service,
{},
uuid.uuid4().hex)
def test_delete_service_404(self):
self.assertRaises(exception.ServiceNotFound,
self.catalog_man.delete_service,
{},
uuid.uuid4().hex)
def test_create_endpoint_404(self):
endpoint = {
'id': uuid.uuid4().hex,
'service_id': uuid.uuid4().hex,
}
self.assertRaises(exception.ServiceNotFound,
self.catalog_api.create_endpoint,
endpoint['id'],
endpoint)
def test_get_endpoint_404(self):
self.assertRaises(exception.EndpointNotFound,
self.catalog_api.get_endpoint,
uuid.uuid4().hex)
def test_delete_endpoint_404(self):
self.assertRaises(exception.EndpointNotFound,
self.catalog_api.delete_endpoint,
uuid.uuid4().hex)
def test_service_list(self): def test_service_list(self):
services = self.catalog_api.list_services() services = self.catalog_api.list_services()

View File

@ -13,11 +13,14 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import uuid
from keystone import exception
from keystone import test from keystone import test
from keystone.identity.backends import kvs as identity_kvs from keystone.identity.backends import kvs as identity_kvs
from keystone.token.backends import kvs as token_kvs from keystone.token.backends import kvs as token_kvs
from keystone.catalog.backends import kvs as catalog_kvs from keystone.catalog.backends import kvs as catalog_kvs
from keystone import catalog
import test_backend import test_backend
import default_fixtures import default_fixtures
@ -40,6 +43,7 @@ class KvsCatalog(test.TestCase, test_backend.CatalogTests):
def setUp(self): def setUp(self):
super(KvsCatalog, self).setUp() super(KvsCatalog, self).setUp()
self.catalog_api = catalog_kvs.Catalog(db={}) self.catalog_api = catalog_kvs.Catalog(db={})
self.catalog_man = catalog.Manager()
self.load_fixtures(default_fixtures) self.load_fixtures(default_fixtures)
self._load_fake_catalog() self._load_fake_catalog()
@ -48,14 +52,35 @@ class KvsCatalog(test.TestCase, test_backend.CatalogTests):
'foo', 'bar', 'foo', 'bar',
{'RegionFoo': {'service_bar': {'foo': 'bar'}}}) {'RegionFoo': {'service_bar': {'foo': 'bar'}}})
def test_get_catalog_bad_user(self): def test_get_catalog_404(self):
catalog_ref = self.catalog_api.get_catalog('foo' + 'WRONG', 'bar') # FIXME(dolph): this test should be moved up to test_backend
self.assert_(catalog_ref is None) # FIXME(dolph): exceptions should be UserNotFound and TenantNotFound
self.assertRaises(exception.NotFound,
self.catalog_api.get_catalog,
uuid.uuid4().hex,
'bar')
def test_get_catalog_bad_tenant(self): self.assertRaises(exception.NotFound,
catalog_ref = self.catalog_api.get_catalog('foo', 'bar' + 'WRONG') self.catalog_api.get_catalog,
self.assert_(catalog_ref is None) 'foo',
uuid.uuid4().hex)
def test_get_catalog(self): def test_get_catalog(self):
catalog_ref = self.catalog_api.get_catalog('foo', 'bar') catalog_ref = self.catalog_api.get_catalog('foo', 'bar')
self.assertDictEqual(catalog_ref, self.catalog_foobar) self.assertDictEqual(catalog_ref, self.catalog_foobar)
def test_create_endpoint_404(self):
self.assertRaises(exception.NotImplemented,
self.catalog_api.create_endpoint,
uuid.uuid4().hex,
{})
def test_get_endpoint_404(self):
self.assertRaises(exception.NotImplemented,
self.catalog_api.get_endpoint,
uuid.uuid4().hex)
def test_delete_endpoint_404(self):
self.assertRaises(exception.NotImplemented,
self.catalog_api.delete_endpoint,
uuid.uuid4().hex)

View File

@ -14,7 +14,10 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import uuid
from keystone import config from keystone import config
from keystone import exception
from keystone import test from keystone import test
from keystone.common.ldap import fakeldap from keystone.common.ldap import fakeldap
from keystone.identity.backends import ldap as identity_ldap from keystone.identity.backends import ldap as identity_ldap
@ -41,5 +44,94 @@ class LDAPIdentity(test.TestCase, test_backend.IdentityTests):
self.identity_api = identity_ldap.Identity() self.identity_api = identity_ldap.Identity()
self.load_fixtures(default_fixtures) self.load_fixtures(default_fixtures)
def tearDown(self): def test_delete_tenant_404(self):
test.TestCase.tearDown(self) self.assertRaises(exception.NotImplemented,
self.identity_api.delete_tenant,
uuid.uuid4().hex)
def test_delete_user_404(self):
self.assertRaises(exception.NotImplemented,
self.identity_api.delete_user,
uuid.uuid4().hex)
def test_rename_duplicate_role_name_fails(self):
role1 = {'id': 'fake1',
'name': 'fake1name'}
role2 = {'id': 'fake2',
'name': 'fake2name'}
self.identity_api.create_role('fake1', role1)
self.identity_api.create_role('fake2', role2)
role1['name'] = 'fake2name'
self.assertRaises(exception.NotImplemented,
self.identity_api.update_role,
'fake1',
role1)
def test_rename_duplicate_user_name_fails(self):
user1 = {'id': 'fake1',
'name': 'fake1',
'password': 'fakepass',
'tenants': ['bar']}
user2 = {'id': 'fake2',
'name': 'fake2',
'password': 'fakepass',
'tenants': ['bar']}
self.identity_api.create_user('fake1', user1)
self.identity_api.create_user('fake2', user2)
user2['name'] = 'fake1'
self.assertRaises(exception.ValidationError,
self.identity_api.update_user,
'fake2',
user2)
def test_delete_user_with_tenant_association(self):
self.assertRaises(exception.NotImplemented,
self.identity_api.delete_user,
uuid.uuid4().hex)
def test_remove_user_from_tenant(self):
self.assertRaises(exception.NotImplemented,
self.identity_api.remove_user_from_tenant,
self.tenant_bar['id'],
self.user_foo['id'])
def test_remove_user_from_tenant_404(self):
self.assertRaises(exception.NotImplemented,
self.identity_api.remove_user_from_tenant,
self.tenant_bar['id'],
self.user_foo['id'])
def test_remove_role_from_user_and_tenant(self):
self.assertRaises(exception.NotImplemented,
self.identity_api.remove_role_from_user_and_tenant,
self.tenant_bar['id'],
self.user_foo['id'],
'useless')
def test_role_crud(self):
role = {'id': uuid.uuid4().hex, 'name': uuid.uuid4().hex}
self.identity_api.create_role(role['id'], role)
role_ref = self.identity_api.get_role(role['id'])
role_ref_dict = dict((x, role_ref[x]) for x in role_ref)
self.assertDictEqual(role_ref_dict, role)
self.assertRaises(exception.NotImplemented,
self.identity_api.update_role,
role['id'],
role)
self.identity_api.delete_role(role['id'])
self.assertRaises(exception.RoleNotFound,
self.identity_api.get_role,
role['id'])
def test_update_role_404(self):
self.assertRaises(exception.NotImplemented,
self.identity_api.update_role,
uuid.uuid4().hex,
{})
def test_get_tenant_users_404(self):
self.assertRaises(exception.NotImplemented,
self.identity_api.get_tenant_users,
tenant_id=uuid.uuid4().hex)

View File

@ -41,15 +41,16 @@ class SqlIdentity(test.TestCase, test_backend.IdentityTests):
self.load_fixtures(default_fixtures) self.load_fixtures(default_fixtures)
def test_delete_user_with_tenant_association(self): def test_delete_user_with_tenant_association(self):
user = {'id': 'fake', user = {'id': uuid.uuid4().hex,
'name': 'fakeuser', 'name': uuid.uuid4().hex,
'password': 'passwd'} 'password': uuid.uuid4().hex}
self.identity_api.create_user('fake', user) self.identity_api.create_user(user['id'], user)
self.identity_api.add_user_to_tenant(self.tenant_bar['id'], self.identity_api.add_user_to_tenant(self.tenant_bar['id'],
user['id']) user['id'])
self.identity_api.delete_user(user['id']) self.identity_api.delete_user(user['id'])
tenants = self.identity_api.get_tenants_for_user(user['id']) self.assertRaises(exception.UserNotFound,
self.assertEquals(tenants, []) self.identity_api.get_tenants_for_user,
user['id'])
def test_create_null_user_name(self): def test_create_null_user_name(self):
user = {'id': uuid.uuid4().hex, user = {'id': uuid.uuid4().hex,
@ -59,13 +60,12 @@ class SqlIdentity(test.TestCase, test_backend.IdentityTests):
self.identity_api.create_user, self.identity_api.create_user,
user['id'], user['id'],
user) user)
# TODO(dolph): can be uncommented pending bug 968519 self.assertRaises(exception.UserNotFound,
#self.assertRaises(exception.UserNotFound, self.identity_api.get_user,
# self.identity_api.get_user, user['id'])
# user['id']) self.assertRaises(exception.UserNotFound,
#self.assertRaises(exception.UserNotFound, self.identity_api.get_user_by_name,
# self.identity_api.get_user_by_name, user['name'])
# user['name'])
def test_create_null_tenant_name(self): def test_create_null_tenant_name(self):
tenant = {'id': uuid.uuid4().hex, tenant = {'id': uuid.uuid4().hex,
@ -74,13 +74,12 @@ class SqlIdentity(test.TestCase, test_backend.IdentityTests):
self.identity_api.create_tenant, self.identity_api.create_tenant,
tenant['id'], tenant['id'],
tenant) tenant)
# TODO(dolph): can be uncommented pending bug 968519 self.assertRaises(exception.TenantNotFound,
#self.assertRaises(exception.TenantNotFound, self.identity_api.get_tenant,
# self.identity_api.get_tenant, tenant['id'])
# tenant['id']) self.assertRaises(exception.TenantNotFound,
#self.assertRaises(exception.TenantNotFound, self.identity_api.get_tenant_by_name,
# self.identity_api.get_tenant_by_name, tenant['name'])
# tenant['name'])
def test_create_null_role_name(self): def test_create_null_role_name(self):
role = {'id': uuid.uuid4().hex, role = {'id': uuid.uuid4().hex,
@ -89,10 +88,9 @@ class SqlIdentity(test.TestCase, test_backend.IdentityTests):
self.identity_api.create_role, self.identity_api.create_role,
role['id'], role['id'],
role) role)
# TODO(dolph): can be uncommented pending bug 968519 self.assertRaises(exception.RoleNotFound,
#self.assertRaises(exception.RoleNotFound, self.identity_api.get_role,
# self.identity_api.get_role, role['id'])
# role['id'])
def test_delete_tenant_with_user_association(self): def test_delete_tenant_with_user_association(self):
user = {'id': 'fake', user = {'id': 'fake',
@ -114,9 +112,10 @@ class SqlIdentity(test.TestCase, test_backend.IdentityTests):
self.tenant_bar['id'], self.tenant_bar['id'],
{'extra': 'extra'}) {'extra': 'extra'})
self.identity_api.delete_user(user['id']) self.identity_api.delete_user(user['id'])
metadata = self.identity_api.get_metadata(user['id'], self.assertRaises(exception.MetadataNotFound,
self.tenant_bar['id']) self.identity_api.get_metadata,
self.assertEquals(metadata, {}) user['id'],
self.tenant_bar['id'])
def test_delete_tenant_with_metadata(self): def test_delete_tenant_with_metadata(self):
user = {'id': 'fake', user = {'id': 'fake',
@ -127,9 +126,10 @@ class SqlIdentity(test.TestCase, test_backend.IdentityTests):
self.tenant_bar['id'], self.tenant_bar['id'],
{'extra': 'extra'}) {'extra': 'extra'})
self.identity_api.delete_tenant(self.tenant_bar['id']) self.identity_api.delete_tenant(self.tenant_bar['id'])
metadata = self.identity_api.get_metadata(user['id'], self.assertRaises(exception.MetadataNotFound,
self.tenant_bar['id']) self.identity_api.get_metadata,
self.assertEquals(metadata, {}) user['id'],
self.tenant_bar['id'])
class SqlToken(test.TestCase, test_backend.TokenTests): class SqlToken(test.TestCase, test_backend.TokenTests):

View File

@ -15,9 +15,12 @@
# under the License. # under the License.
import os import os
import uuid
from keystone import exception
from keystone import test from keystone import test
from keystone.catalog.backends import templated as catalog_templated from keystone.catalog.backends import templated as catalog_templated
from keystone import catalog
import test_backend import test_backend
import default_fixtures import default_fixtures
@ -50,8 +53,25 @@ class TestTemplatedCatalog(test.TestCase, test_backend.CatalogTests):
super(TestTemplatedCatalog, self).setUp() super(TestTemplatedCatalog, self).setUp()
self.opt_in_group('catalog', template_file=DEFAULT_CATALOG_TEMPLATES) self.opt_in_group('catalog', template_file=DEFAULT_CATALOG_TEMPLATES)
self.catalog_api = catalog_templated.TemplatedCatalog() self.catalog_api = catalog_templated.TemplatedCatalog()
self.catalog_man = catalog.Manager()
self.load_fixtures(default_fixtures) self.load_fixtures(default_fixtures)
def test_get_catalog(self): def test_get_catalog(self):
catalog_ref = self.catalog_api.get_catalog('foo', 'bar') catalog_ref = self.catalog_api.get_catalog('foo', 'bar')
self.assertDictEqual(catalog_ref, self.DEFAULT_FIXTURE) self.assertDictEqual(catalog_ref, self.DEFAULT_FIXTURE)
def test_create_endpoint_404(self):
self.assertRaises(exception.NotImplemented,
self.catalog_api.create_endpoint,
uuid.uuid4().hex,
{})
def test_get_endpoint_404(self):
self.assertRaises(exception.NotImplemented,
self.catalog_api.get_endpoint,
uuid.uuid4().hex)
def test_delete_endpoint_404(self):
self.assertRaises(exception.NotImplemented,
self.catalog_api.delete_endpoint,
uuid.uuid4().hex)

View File

@ -133,8 +133,9 @@ class KeystoneClientTests(object):
from keystoneclient import exceptions as client_exceptions from keystoneclient import exceptions as client_exceptions
client = self.get_client() client = self.get_client()
token = client.auth_token token = client.auth_token
self.assertRaises(client_exceptions.AuthorizationFailure, self.assertRaises(client_exceptions.Unauthorized,
self._client, token=token, tenant_id='baz') self._client, token=token,
tenant_id=uuid.uuid4().hex)
def test_authenticate_token_tenant_name(self): def test_authenticate_token_tenant_name(self):
client = self.get_client() client = self.get_client()
@ -284,15 +285,15 @@ class KeystoneClientTests(object):
self.assertRaises(client_exceptions.Unauthorized, self.assertRaises(client_exceptions.Unauthorized,
self._client, self._client,
username=self.user_foo['name'], username=self.user_foo['name'],
password='invalid') password=uuid.uuid4().hex)
def test_invalid_user_password(self): def test_invalid_user_and_password(self):
from keystoneclient import exceptions as client_exceptions from keystoneclient import exceptions as client_exceptions
self.assertRaises(client_exceptions.Unauthorized, self.assertRaises(client_exceptions.Unauthorized,
self._client, self._client,
username='blah', username=uuid.uuid4().hex,
password='blah') password=uuid.uuid4().hex)
def test_change_password_invalidates_token(self): def test_change_password_invalidates_token(self):
from keystoneclient import exceptions as client_exceptions from keystoneclient import exceptions as client_exceptions
@ -674,17 +675,6 @@ class KeystoneClientTests(object):
client.services.get, client.services.get,
id=uuid.uuid4().hex) id=uuid.uuid4().hex)
def test_endpoint_create_404(self):
from keystoneclient import exceptions as client_exceptions
client = self.get_client(admin=True)
self.assertRaises(client_exceptions.NotFound,
client.endpoints.create,
region=uuid.uuid4().hex,
service_id=uuid.uuid4().hex,
publicurl=uuid.uuid4().hex,
adminurl=uuid.uuid4().hex,
internalurl=uuid.uuid4().hex)
def test_endpoint_delete_404(self): def test_endpoint_delete_404(self):
# the catalog backend is expected to return Not Implemented # the catalog backend is expected to return Not Implemented
from keystoneclient import exceptions as client_exceptions from keystoneclient import exceptions as client_exceptions

View File

@ -74,6 +74,17 @@ class KcMasterSqlTestCase(test_keystoneclient.KcMasterTestCase):
self.assertRaises(client_exceptions.NotFound, client.endpoints.delete, self.assertRaises(client_exceptions.NotFound, client.endpoints.delete,
id=endpoint.id) id=endpoint.id)
def test_endpoint_create_404(self):
from keystoneclient import exceptions as client_exceptions
client = self.get_client(admin=True)
self.assertRaises(client_exceptions.NotFound,
client.endpoints.create,
region=uuid.uuid4().hex,
service_id=uuid.uuid4().hex,
publicurl=uuid.uuid4().hex,
adminurl=uuid.uuid4().hex,
internalurl=uuid.uuid4().hex)
def test_endpoint_delete_404(self): def test_endpoint_delete_404(self):
from keystoneclient import exceptions as client_exceptions from keystoneclient import exceptions as client_exceptions
client = self.get_client(admin=True) client = self.get_client(admin=True)