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 exception
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))
def get_service(self, service_id):
res = self.db.get('service-%s' % service_id)
if not res:
raise exception.ServiceNotFound(service_id=service_id)
return res
return self.db.get('service-%s' % service_id)
def list_services(self):
return self.db.get('service_list', [])
@ -46,14 +42,10 @@ class Catalog(kvs.Base, catalog.Driver):
return service
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)
service_list = set(self.db.get('service_list', []))
service_list.remove(service_id)
self.db.set('service_list', list(service_list))
return None
# Private interface
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):
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():
session.delete(service_ref)
if not session.query(Service).filter_by(id=service_id).delete():
raise exception.ServiceNotFound(service_id=service_id)
session.flush()
def create_service(self, service_id, service_ref):
@ -111,6 +109,7 @@ class Catalog(sql.Base, catalog.Driver):
# Endpoints
def create_endpoint(self, endpoint_id, endpoint_ref):
session = self.get_session()
self.get_service(endpoint_ref['service_id'])
new_endpoint = Endpoint.from_dict(endpoint_ref)
with session.begin():
session.add(new_endpoint)
@ -119,12 +118,9 @@ class Catalog(sql.Base, catalog.Driver):
def delete_endpoint(self, endpoint_id):
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():
session.delete(endpoint_ref)
if not session.query(Endpoint).filter_by(id=endpoint_id).delete():
raise exception.EndpointNotFound(endpoint_id=endpoint_id)
session.flush()
def get_endpoint(self, endpoint_id):

View File

@ -42,13 +42,50 @@ class Manager(manager.Manager):
def __init__(self):
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):
"""Interface description for an Catalog driver."""
def list_services(self):
"""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()
@ -56,27 +93,50 @@ class Driver(object):
def get_service(self, service_id):
"""Get service by id.
Returns: service_ref dict or None.
:returns: service_ref dict
:raises: keystone.exception.ServiceNotFound
"""
raise exception.NotImplemented()
def delete_service(self, service_id):
"""Deletes an existing service.
:raises: keystone.exception.ServiceNotFound
"""
raise exception.NotImplemented()
def create_service(self, service_id, service_ref):
"""Creates a new service.
:raises: keystone.exception.Conflict
"""
raise exception.NotImplemented()
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()
def delete_endpoint(self, endpoint_id):
"""Deletes an endpoint for a service.
:raises: keystone.exception.EndpointNotFound
"""
raise exception.NotImplemented()
def get_endpoint(self, endpoint_id):
"""Get endpoint by id.
Returns: endpoint_ref dict or None.
:returns: endpoint_ref dict
:raises: keystone.exception.EndpointNotFound
"""
raise exception.NotImplemented()
@ -84,7 +144,7 @@ class Driver(object):
def list_endpoints(self):
"""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()
@ -92,10 +152,7 @@ class Driver(object):
def get_catalog(self, user_id, tenant_id, metadata=None):
"""Retreive and format the current service catalog.
Returns: A nested dict representing the service catalog or an
empty dict.
Example:
Example::
{ 'RegionOne':
{'compute': {
@ -109,6 +166,10 @@ class Driver(object):
'name': 'EC2 Service',
'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()
@ -133,15 +194,10 @@ class ServiceController(wsgi.Application):
def get_service(self, context, service_id):
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)
return {'OS-KSADM:service': service_ref}
def delete_service(self, context, service_id):
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)
def create_service(self, context, OS_KSADM_service):
@ -174,11 +230,6 @@ class EndpointController(wsgi.Application):
endpoint_id = uuid.uuid4().hex
endpoint_ref = endpoint.copy()
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(
context, endpoint_id, endpoint_ref)
return {'endpoint': new_endpoint_ref}

View File

@ -14,8 +14,18 @@
# License for the specific language governing permissions and limitations
# under the License.
from keystone import exception
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):
if isinstance(value, dict):
self[key] = value.copy()
@ -23,7 +33,11 @@ class DictKvs(dict):
self[key] = value[:]
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()

View File

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

View File

@ -77,6 +77,12 @@ class EndpointNotFound(NotFound):
"""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):
"""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.
"""
user_ref = self._get_user(user_id)
user_ref = None
tenant_ref = None
metadata_ref = None
if (not user_ref
or not utils.check_password(password,
user_ref.get('password'))):
metadata_ref = {}
try:
user_ref = self._get_user(user_id)
except exception.UserNotFound:
raise AssertionError('Invalid user / password')
tenants = self.get_tenants_for_user(user_id)
if tenant_id and tenant_id not in tenants:
raise AssertionError('Invalid tenant')
if not utils.check_password(password, user_ref.get('password')):
raise AssertionError('Invalid user / password')
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)
def get_tenant(self, tenant_id):
tenant_ref = self.db.get('tenant-%s' % tenant_id)
return tenant_ref
try:
return self.db.get('tenant-%s' % tenant_id)
except exception.NotFound:
raise exception.TenantNotFound(tenant_id=tenant_id)
def get_tenants(self):
tenant_keys = filter(lambda x: x.startswith("tenant-"), self.db.keys())
return [self.db.get(key) for key in tenant_keys]
def get_tenant_by_name(self, tenant_name):
tenant_ref = self.db.get('tenant_name-%s' % tenant_name)
return tenant_ref
try:
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):
self.get_tenant(tenant_id)
user_keys = filter(lambda x: x.startswith("user-"), self.db.keys())
user_refs = [self.db.get(key) for key in user_keys]
return filter(lambda x: tenant_id in x['tenants'], user_refs)
def _get_user(self, user_id):
user_ref = self.db.get('user-%s' % user_id)
return user_ref
try:
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):
user_ref = self.db.get('user_name-%s' % user_name)
return user_ref
try:
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):
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))
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):
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):
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
def add_user_to_tenant(self, tenant_id, user_id):
self.get_tenant(tenant_id)
user_ref = self._get_user(user_id)
tenants = set(user_ref.get('tenants', []))
tenants.add(tenant_id)
self.update_user(user_id, {'tenants': list(tenants)})
def remove_user_from_tenant(self, tenant_id, user_id):
self.get_tenant(tenant_id)
user_ref = self._get_user(user_id)
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)})
def get_tenants_for_user(self, user_id):
@ -127,14 +155,21 @@ class Identity(kvs.Base, identity.Driver):
return user_ref.get('tenants', [])
def get_roles_for_user_and_tenant(self, user_id, tenant_id):
metadata_ref = self.get_metadata(user_id, tenant_id)
if not metadata_ref:
self.get_user(user_id)
self.get_tenant(tenant_id)
try:
metadata_ref = self.get_metadata(user_id, tenant_id)
except exception.MetadataNotFound:
metadata_ref = {}
return metadata_ref.get('roles', [])
def add_role_to_user_and_tenant(self, user_id, tenant_id, role_id):
metadata_ref = self.get_metadata(user_id, tenant_id)
if not metadata_ref:
self.get_user(user_id)
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 = {}
roles = set(metadata_ref.get('roles', []))
roles.add(role_id)
@ -142,8 +177,9 @@ class Identity(kvs.Base, identity.Driver):
self.update_metadata(user_id, tenant_id, metadata_ref)
def remove_role_from_user_and_tenant(self, user_id, tenant_id, role_id):
metadata_ref = self.get_metadata(user_id, tenant_id)
if not metadata_ref:
try:
metadata_ref = self.get_metadata(user_id, tenant_id)
except exception.MetadataNotFound:
metadata_ref = {}
roles = set(metadata_ref.get('roles', []))
if role_id not in roles:
@ -156,12 +192,22 @@ class Identity(kvs.Base, identity.Driver):
# CRUD
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
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']
raise exception.Conflict(type='user', details=msg)
user = _ensure_hashed_password(user)
self.db.set('user-%s' % user_id, 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']
raise exception.Conflict(type='user', details=msg)
# 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()
user = _ensure_hashed_password(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.set('user-%s' % user_id, new_user)
self.db.set('user_name-%s' % new_user['name'], new_user)
return new_user
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-%s' % user_id)
user_list = set(self.db.get('user_list', []))
user_list.remove(user_id)
self.db.set('user_list', list(user_list))
return None
def create_tenant(self, tenant_id, tenant):
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
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']
raise exception.Conflict(type='tenant', details=msg)
self.db.set('tenant-%s' % tenant_id, tenant)
self.db.set('tenant_name-%s' % tenant['name'], tenant)
return tenant
@ -211,12 +273,18 @@ class Identity(kvs.Base, identity.Driver):
def update_tenant(self, tenant_id, tenant):
if 'name' in tenant:
tenant['name'] = clean.tenant_name(tenant['name'])
existing = self.db.get('tenant_name-%s' % tenant['name'])
if existing and tenant_id != existing['id']:
msg = 'Duplicate name, %s.' % tenant['name']
raise exception.Conflict(type='tenant', details=msg)
try:
existing = self.db.get('tenant_name-%s' % tenant['name'])
if existing and tenant_id != existing['id']:
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
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.update(tenant)
new_tenant['id'] = tenant_id
@ -226,10 +294,12 @@ class Identity(kvs.Base, identity.Driver):
return new_tenant
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-%s' % tenant_id)
return None
def create_metadata(self, user_id, tenant_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):
self.db.delete('metadata-%s-%s' % (tenant_id, user_id))
return None
def create_role(self, role_id, role):
role_ref = self.get_role(role_id)
if role_ref:
try:
self.get_role(role_id)
except exception.RoleNotFound:
pass
else:
msg = 'Duplicate ID, %s.' % role_id
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']:
msg = 'Duplicate name, %s.' % role['name']
raise exception.Conflict(type='role', details=msg)
@ -260,24 +332,26 @@ class Identity(kvs.Base, identity.Driver):
return role
def update_role(self, role_id, role):
role_refs = self.list_roles()
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']:
msg = 'Duplicate name, %s.' % role['name']
raise exception.Conflict(type='role', details=msg)
if role_id == role_ref['id']:
old_role_ref = role_ref
if old_role_ref:
role['id'] = role_id
self.db.set('role-%s' % role_id, role)
else:
if old_role_ref is None:
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
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.remove(role_id)
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
in the list of tenants on the user.
"""
user_ref = self._get_user(user_id)
if user_ref is None:
tenant_ref = None
metadata_ref = None
try:
user_ref = self._get_user(user_id)
except exception.UserNotFound:
raise AssertionError('Invalid user / password')
try:
@ -89,42 +93,49 @@ class Identity(identity.Driver):
except Exception:
raise AssertionError('Invalid user / password')
tenants = self.get_tenants_for_user(user_id)
if tenant_id and tenant_id not in tenants:
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')
tenant_ref = self.get_tenant(tenant_id)
# TODO(termie): this should probably be made into a get roles call
if tenant_ref:
metadata_ref = self.get_metadata(user_id, tenant_id)
else:
metadata_ref = {}
try:
tenant_ref = self.get_tenant(tenant_id)
# TODO(termie): this should probably be made into a
# get roles call
metadata_ref = self.get_metadata(user_id, tenant_id)
except exception.TenantNotFound:
tenant_ref = None
metadata_ref = {}
except exception.MetadataNotFound:
metadata_ref = {}
return (_filter_user(user_ref), tenant_ref, metadata_ref)
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):
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):
user_ref = self.user.get(user_id)
if not user_ref:
return None
return user_ref
try:
return self.user.get(user_id)
except exception.NotFound:
raise exception.UserNotFound(user_id=user_id)
def get_user(self, user_id):
user_ref = self._get_user(user_id)
if (not user_ref):
return None
return _filter_user(user_ref)
return _filter_user(self._get_user(user_id))
def get_user_by_name(self, user_name):
user_ref = self.user.get_by_name(user_name)
if not user_ref:
return None
return _filter_user(user_ref)
try:
return _filter_user(self.user.get_by_name(user_name))
except exception.NotFound:
raise exception.UserNotFound(user_id=user_name)
def get_metadata(self, user_id, tenant_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}
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
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)
def get_tenants_for_user(self, user_id):
self.get_user(user_id)
tenant_list = []
for tenant in self.tenant.get_user_tenants(user_id):
tenant_list.append(tenant['id'])
return tenant_list
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)
roles = []
for assignment in assignments:
@ -157,6 +176,9 @@ class Identity(identity.Driver):
return roles
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)
# CRUD
@ -182,16 +204,29 @@ class Identity(identity.Driver):
return {}
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
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']
raise exception.Conflict(type='role', details=msg)
return self.role.create(role)
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
@ -268,6 +303,13 @@ class UserApi(common_ldap.BaseLdap, ApiShimMixin):
super(UserApi, self).__init__(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):
users = self.get_all('(%s=%s)' %
(self.attribute_mapping['name'],
@ -275,7 +317,7 @@ class UserApi(common_ldap.BaseLdap, ApiShimMixin):
try:
return users[0]
except IndexError:
return None
raise exception.UserNotFound(user_id=name)
def create(self, values):
self.affirm_unique(values)
@ -288,10 +330,13 @@ class UserApi(common_ldap.BaseLdap, ApiShimMixin):
def update(self, id, values):
if values['id'] != id:
return None
old_obj = self.get(id)
raise exception.ValidationError('Cannot change user ID')
try:
old_obj = self.get(id)
except exception.NotFound:
raise exception.UserNotFound(user_id=id)
if old_obj.get('name') != values['name']:
raise exception.Error('Changing Name not permitted')
raise exception.ValidationError('Cannot change user name')
try:
new_tenant = values['tenant_id']
@ -385,6 +430,13 @@ class TenantApi(common_ldap.BaseLdap, ApiShimMixin):
self.member_attribute = (getattr(conf.ldap, 'tenant_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
search_filter = ('(%s=%s)'
% (self.attribute_mapping['name'],
@ -393,13 +445,12 @@ class TenantApi(common_ldap.BaseLdap, ApiShimMixin):
try:
return tenants[0]
except IndexError:
return None
raise exception.TenantNotFound(tenant_id=name)
def create(self, values):
self.affirm_unique(values)
data = values.copy()
if 'id' not in data or data['id'] is None:
if data.get('id') is None:
data['id'] = uuid.uuid4().hex
return super(TenantApi, self).create(data)
@ -434,10 +485,11 @@ class TenantApi(common_ldap.BaseLdap, ApiShimMixin):
def add_user(self, tenant_id, user_id):
conn = self.get_connection()
conn.modify_s(self._id_to_dn(tenant_id),
[(ldap.MOD_ADD,
self.member_attribute,
self.user_api._id_to_dn(user_id))])
conn.modify_s(
self._id_to_dn(tenant_id),
[(ldap.MOD_ADD,
self.member_attribute,
self.user_api._id_to_dn(user_id))])
def remove_user(self, tenant_id, user_id):
conn = self.get_connection()
@ -467,9 +519,13 @@ class TenantApi(common_ldap.BaseLdap, ApiShimMixin):
super(TenantApi, self).delete(id)
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']:
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)
@ -558,12 +614,9 @@ class RoleApi(common_ldap.BaseLdap, ApiShimMixin):
try:
return roles[0]
except IndexError:
return None
raise exception.RoleNotFound(role_id=name)
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)
conn = self.get_connection()
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.
"""
user_ref = self._get_user(user_id)
if (not user_ref
or not self._check_password(password, user_ref)):
user_ref = None
tenant_ref = None
metadata_ref = {}
try:
user_ref = self._get_user(user_id)
except exception.UserNotFound:
raise AssertionError('Invalid user / password')
tenants = self.get_tenants_for_user(user_id)
if tenant_id and tenant_id not in tenants:
raise AssertionError('Invalid tenant')
if not utils.check_password(password, user_ref.get('password')):
raise AssertionError('Invalid user / password')
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)
def get_tenant(self, tenant_id):
session = self.get_session()
tenant_ref = session.query(Tenant).filter_by(id=tenant_id).first()
if not tenant_ref:
return
if tenant_ref is None:
raise exception.TenantNotFound(tenant_id=tenant_id)
return tenant_ref.to_dict()
def get_tenant_by_name(self, tenant_name):
session = self.get_session()
tenant_ref = session.query(Tenant).filter_by(name=tenant_name).first()
if not tenant_ref:
return
raise exception.TenantNotFound(tenant_id=tenant_name)
return tenant_ref.to_dict()
def get_tenant_users(self, tenant_id):
session = self.get_session()
self.get_tenant(tenant_id)
user_refs = session.query(User)\
.join(UserTenantMembership)\
.filter(UserTenantMembership.tenant_id ==
@ -200,14 +212,14 @@ class Identity(sql.Base, identity.Driver):
session = self.get_session()
user_ref = session.query(User).filter_by(id=user_id).first()
if not user_ref:
return
raise exception.UserNotFound(user_id=user_id)
return user_ref.to_dict()
def _get_user_by_name(self, user_name):
session = self.get_session()
user_ref = session.query(User).filter_by(name=user_name).first()
if not user_ref:
return
raise exception.UserNotFound(user_id=user_name)
return user_ref.to_dict()
def get_user(self, user_id):
@ -222,11 +234,16 @@ class Identity(sql.Base, identity.Driver):
.filter_by(user_id=user_id)\
.filter_by(tenant_id=tenant_id)\
.first()
return getattr(metadata_ref, 'data', {})
if metadata_ref is None:
raise exception.MetadataNotFound()
return metadata_ref.data
def get_role(self, role_id):
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):
session = self.get_session()
@ -241,6 +258,8 @@ class Identity(sql.Base, identity.Driver):
# These should probably be part of the high-level API
def add_user_to_tenant(self, tenant_id, user_id):
session = self.get_session()
self.get_tenant(tenant_id)
self.get_user(user_id)
q = session.query(UserTenantMembership)\
.filter_by(user_id=user_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):
session = self.get_session()
self.get_tenant(tenant_id)
self.get_user(user_id)
membership_ref = session.query(UserTenantMembership)\
.filter_by(user_id=user_id)\
.filter_by(tenant_id=tenant_id)\
.first()
if membership_ref is None:
raise exception.NotFound('User not found in tenant')
with session.begin():
session.delete(membership_ref)
session.flush()
@ -270,37 +293,46 @@ class Identity(sql.Base, identity.Driver):
def get_tenants_for_user(self, user_id):
session = self.get_session()
self.get_user(user_id)
membership_refs = session.query(UserTenantMembership)\
.filter_by(user_id=user_id)\
.all()
return [x.tenant_id for x in membership_refs]
def get_roles_for_user_and_tenant(self, user_id, tenant_id):
metadata_ref = self.get_metadata(user_id, tenant_id)
if not metadata_ref:
self.get_user(user_id)
self.get_tenant(tenant_id)
try:
metadata_ref = self.get_metadata(user_id, tenant_id)
except exception.MetadataNotFound:
metadata_ref = {}
return metadata_ref.get('roles', [])
def add_role_to_user_and_tenant(self, user_id, tenant_id, role_id):
metadata_ref = self.get_metadata(user_id, tenant_id)
is_new = False
if not metadata_ref:
is_new = True
self.get_user(user_id)
self.get_tenant(tenant_id)
self.get_role(role_id)
try:
metadata_ref = self.get_metadata(user_id, tenant_id)
is_new = False
except exception.MetadataNotFound:
metadata_ref = {}
is_new = True
roles = set(metadata_ref.get('roles', []))
roles.add(role_id)
metadata_ref['roles'] = list(roles)
if not is_new:
self.update_metadata(user_id, tenant_id, metadata_ref)
else:
if is_new:
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):
metadata_ref = self.get_metadata(user_id, tenant_id)
is_new = False
if not metadata_ref:
is_new = True
try:
metadata_ref = self.get_metadata(user_id, tenant_id)
is_new = False
except exception.MetadataNotFound:
metadata_ref = {}
is_new = True
roles = set(metadata_ref.get('roles', []))
if role_id not in roles:
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)
metadata_ref['roles'] = list(roles)
if not is_new:
self.update_metadata(user_id, tenant_id, metadata_ref)
else:
if is_new:
self.create_metadata(user_id, tenant_id, metadata_ref)
else:
self.update_metadata(user_id, tenant_id, metadata_ref)
# CRUD
@handle_conflicts(type='user')
@ -327,8 +359,12 @@ class Identity(sql.Base, identity.Driver):
@handle_conflicts(type='user')
def update_user(self, user_id, user):
session = self.get_session()
if user_id != user['id']:
raise exception.ValidationError('Cannot change user ID')
with session.begin():
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()
user = _ensure_hashed_password(user)
for k in user:
@ -343,6 +379,8 @@ class Identity(sql.Base, identity.Driver):
def delete_user(self, user_id):
session = self.get_session()
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)\
.filter_by(user_id=user_id)\
.all()
@ -379,6 +417,8 @@ class Identity(sql.Base, identity.Driver):
session = self.get_session()
with session.begin():
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()
for k in tenant:
old_tenant_dict[k] = tenant[k]
@ -392,6 +432,8 @@ class Identity(sql.Base, identity.Driver):
def delete_tenant(self, tenant_id):
session = self.get_session()
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)\
.filter_by(tenant_id=tenant_id)\
.all()
@ -452,6 +494,8 @@ class Identity(sql.Base, identity.Driver):
session = self.get_session()
with session.begin():
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:
role_ref[k] = role[k]
session.flush()
@ -459,6 +503,7 @@ class Identity(sql.Base, identity.Driver):
def delete_role(self, role_id):
session = self.get_session()
role_ref = session.query(Role).filter_by(id=role_id).first()
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):
"""Authenticate a given user, tenant and password.
Returns: (user, tenant, metadata).
:returns: (user_ref, tenant_ref, metadata_ref)
:raises: AssertionError
"""
raise exception.NotImplemented()
@ -60,7 +61,8 @@ class Driver(object):
def get_tenant(self, tenant_id):
"""Get a tenant by id.
Returns: tenant_ref or None.
:returns: tenant_ref
:raises: keystone.exception.TenantNotFound
"""
raise exception.NotImplemented()
@ -68,7 +70,8 @@ class Driver(object):
def get_tenant_by_name(self, tenant_name):
"""Get a tenant by name.
Returns: tenant_ref or None.
:returns: tenant_ref
:raises: keystone.exception.TenantNotFound
"""
raise exception.NotImplemented()
@ -76,7 +79,8 @@ class Driver(object):
def get_user(self, user_id):
"""Get a user by id.
Returns: user_ref or None.
:returns: user_ref
:raises: keystone.exception.UserNotFound
"""
raise exception.NotImplemented()
@ -84,7 +88,8 @@ class Driver(object):
def get_user_by_name(self, user_name):
"""Get a user by name.
Returns: user_ref or None.
:returns: user_ref
:raises: keystone.exception.UserNotFound
"""
raise exception.NotImplemented()
@ -92,7 +97,8 @@ class Driver(object):
def get_role(self, role_id):
"""Get a role by id.
Returns: role_ref or None.
:returns: role_ref
:raises: keystone.exception.RoleNotFound
"""
raise exception.NotImplemented()
@ -103,7 +109,7 @@ class Driver(object):
NOTE(termie): I'd prefer if this listed only the users for a given
tenant.
Returns: a list of user_refs or an empty list.
:returns: a list of user_refs or an empty list
"""
raise exception.NotImplemented()
@ -111,7 +117,7 @@ class Driver(object):
def list_roles(self):
"""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()
@ -119,18 +125,50 @@ class Driver(object):
# NOTE(termie): seven calls below should probably be exposed by the api
# more clearly when the api redesign happens
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()
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()
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()
def get_tenants_for_user(self, user_id):
"""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()
@ -138,41 +176,83 @@ class Driver(object):
def get_roles_for_user_and_tenant(self, user_id, tenant_id):
"""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()
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()
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()
# user crud
def create_user(self, user_id, user):
"""Creates a new user.
:raises: keystone.exception.Conflict
"""
raise exception.NotImplemented()
def update_user(self, user_id, user):
"""Updates an existing user.
:raises: keystone.exception.UserNotFound, keystone.exception.Conflict
"""
raise exception.NotImplemented()
def delete_user(self, user_id):
"""Deletes an existing user.
:raises: keystone.exception.UserNotFound
"""
raise exception.NotImplemented()
# tenant crud
def create_tenant(self, tenant_id, tenant):
"""Creates a new tenant.
:raises: keystone.exception.Conflict
"""
raise exception.NotImplemented()
def update_tenant(self, tenant_id, tenant):
"""Updates an existing tenant.
:raises: keystone.exception.TenantNotFound, keystone.exception.Conflict
"""
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()
# metadata crud
def get_metadata(self, user_id, tenant_id):
raise exception.NotImplemented()
@ -182,17 +262,32 @@ class Driver(object):
def update_metadata(self, user_id, tenant_id, metadata):
raise exception.NotImplemented()
def delete_metadata(self, user_id, tenant_id, metadata):
def delete_metadata(self, user_id, tenant_id):
raise exception.NotImplemented()
# role crud
def create_role(self, role_id, role):
"""Creates a new role.
:raises: keystone.exception.Conflict
"""
raise exception.NotImplemented()
def update_role(self, role_id, role):
"""Updates an existing role.
:raises: keystone.exception.RoleNotFound, keystone.exception.Conflict
"""
raise exception.NotImplemented()
def delete_role(self, role_id):
"""Deletes an existing role.
:raises: keystone.exception.RoleNotFound
"""
raise exception.NotImplemented()
@ -286,11 +381,7 @@ class TenantController(wsgi.Application):
def get_tenant(self, context, tenant_id):
# TODO(termie): this stuff should probably be moved to middleware
self.assert_admin(context)
tenant = self.identity_api.get_tenant(context, tenant_id)
if tenant is None:
raise exception.TenantNotFound(tenant_id=tenant_id)
return {'tenant': tenant}
return {'tenant': self.identity_api.get_tenant(context, tenant_id)}
# CRUD Extension
def create_tenant(self, context, tenant):
@ -301,36 +392,23 @@ class TenantController(wsgi.Application):
raise exception.ValidationError(message=msg)
self.assert_admin(context)
tenant_id = (tenant_ref.get('id')
and tenant_ref.get('id')
or uuid.uuid4().hex)
tenant_ref['id'] = tenant_id
tenant_ref['id'] = tenant_ref.get('id', uuid.uuid4().hex)
tenant = self.identity_api.create_tenant(
context, tenant_id, tenant_ref)
context, tenant_ref['id'], tenant_ref)
return {'tenant': tenant}
def update_tenant(self, context, tenant_id, tenant):
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(
context, tenant_id, tenant)
return {'tenant': tenant_ref}
def delete_tenant(self, context, tenant_id, **kw):
def delete_tenant(self, context, tenant_id):
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)
def get_tenant_users(self, context, tenant_id, **kw):
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)
return {'users': user_refs}
@ -376,18 +454,13 @@ class UserController(wsgi.Application):
def get_user(self, context, user_id):
self.assert_admin(context)
user_ref = self.identity_api.get_user(context, user_id)
if not user_ref:
raise exception.UserNotFound(user_id=user_id)
return {'user': user_ref}
return {'user': self.identity_api.get_user(context, user_id)}
def get_users(self, context):
# NOTE(termie): i can't imagine that this really wants all the data
# about every single user in the system...
self.assert_admin(context)
user_refs = self.identity_api.list_users(context)
return {'users': user_refs}
return {'users': self.identity_api.list_users(context)}
# CRUD extension
def create_user(self, context, user):
@ -414,9 +487,6 @@ class UserController(wsgi.Application):
def update_user(self, context, user_id, user):
# NOTE(termie): this is really more of a patch than a put
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)
# 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):
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)
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: '
'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(
context, user_id, tenant_id)
return {'roles': [self.identity_api.get_role(context, x)
@ -487,10 +547,7 @@ class RoleController(wsgi.Application):
# CRUD extension
def get_role(self, context, role_id):
self.assert_admin(context)
role_ref = self.identity_api.get_role(context, role_id)
if not role_ref:
raise exception.RoleNotFound(role_id=role_id)
return {'role': role_ref}
return {'role': self.identity_api.get_role(context, role_id)}
def create_role(self, context, role):
role = self._normalize_dict(role)
@ -507,14 +564,11 @@ class RoleController(wsgi.Application):
def delete_role(self, context, role_id):
self.assert_admin(context)
self.get_role(context, role_id)
self.identity_api.delete_role(context, role_id)
def get_roles(self, context):
self.assert_admin(context)
roles = self.identity_api.list_roles(context)
# TODO(termie): probably inefficient at some point
return {'roles': roles}
return {'roles': self.identity_api.list_roles(context)}
def add_role_to_user(self, context, user_id, role_id, tenant_id=None):
"""Add a role to a user and tenant pair.
@ -527,12 +581,6 @@ class RoleController(wsgi.Application):
if tenant_id is None:
raise exception.NotImplemented(message='User roles not supported: '
'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
# a user also adds them to a tenant
@ -553,12 +601,6 @@ class RoleController(wsgi.Application):
if tenant_id is None:
raise exception.NotImplemented(message='User roles not supported: '
'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
# 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
if 'passwordCredentials' in auth:
user_id = auth['passwordCredentials'].get('userId', None)
username = auth['passwordCredentials'].get('username', '')
password = auth['passwordCredentials'].get('password', '')
tenant_name = auth.get('tenantName', None)
user_id = auth['passwordCredentials'].get('userId', None)
if username:
user_ref = self.identity_api.get_user_by_name(
context=context,
user_name=username)
if user_ref:
try:
user_ref = self.identity_api.get_user_by_name(
context=context, user_name=username)
user_id = user_ref['id']
except exception.UserNotFound:
raise exception.Unauthorized()
# more compat
tenant_id = auth.get('tenantId', None)
if tenant_name:
tenant_ref = self.identity_api.get_tenant_by_name(
context=context, tenant_name=tenant_name)
if tenant_ref:
try:
tenant_ref = self.identity_api.get_tenant_by_name(
context=context, tenant_name=tenant_name)
tenant_id = tenant_ref['id']
except exception.TenantNotFound:
raise exception.Unauthorized()
try:
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,
user_ref['id'])
if tenant_id:
assert tenant_id in tenants
if tenant_id and tenant_id not in tenants:
raise exception.Unauthorized()
tenant_ref = self.identity_api.get_tenant(context=context,
tenant_id=tenant_id)
if tenant_ref:
try:
tenant_ref = self.identity_api.get_tenant(
context=context,
tenant_id=tenant_id)
metadata_ref = self.identity_api.get_metadata(
context=context,
user_id=user_ref['id'],
@ -345,7 +349,8 @@ class TokenController(wsgi.Application):
user_id=user_ref['id'],
tenant_id=tenant_ref['id'],
metadata=metadata_ref)
else:
except exception.TenantNotFound:
tenant_ref = None
metadata_ref = {}
catalog_ref = {}

View File

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

View File

@ -24,7 +24,7 @@ class IdentityTests(object):
def test_authenticate_bad_user(self):
self.assertRaises(AssertionError,
self.identity_api.authenticate,
user_id=self.user_foo['id'] + 'WRONG',
user_id=uuid.uuid4().hex,
tenant_id=self.tenant_bar['id'],
password=self.user_foo['password'])
@ -33,13 +33,13 @@ class IdentityTests(object):
self.identity_api.authenticate,
user_id=self.user_foo['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.identity_api.authenticate,
user_id=self.user_foo['id'],
tenant_id=self.tenant_bar['id'] + 'WRONG',
tenant_id=uuid.uuid4().hex,
password=self.user_foo['password'])
def test_authenticate_no_tenant(self):
@ -86,30 +86,30 @@ class IdentityTests(object):
user_ref = self.identity_api._get_user(self.user_foo['id'])
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):
tenant_ref = self.identity_api.get_tenant(
tenant_id=self.tenant_bar['id'])
self.assertDictEqual(tenant_ref, self.tenant_bar)
def test_get_tenant_by_name_bad_tenant(self):
tenant_ref = self.identity_api.get_tenant(
tenant_id=self.tenant_bar['name'] + 'WRONG')
self.assert_(tenant_ref is None)
def test_get_tenant_404(self):
self.assertRaises(exception.TenantNotFound,
self.identity_api.get_tenant,
tenant_id=uuid.uuid4().hex)
def test_get_tenant_by_name(self):
tenant_ref = self.identity_api.get_tenant_by_name(
tenant_name=self.tenant_bar['name'])
self.assertDictEqual(tenant_ref, self.tenant_bar)
def test_get_user_bad_user(self):
user_ref = self.identity_api.get_user(
user_id=self.user_foo['id'] + 'WRONG')
self.assert_(user_ref is None)
def test_get_tenant_by_name_404(self):
self.assertRaises(exception.TenantNotFound,
self.identity_api.get_tenant,
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):
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.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):
user_ref = self.identity_api.get_user_by_name(
user_name=self.user_foo['name'])
@ -128,17 +133,10 @@ class IdentityTests(object):
self.user_foo.pop('password')
self.assertDictEqual(user_ref, self.user_foo)
def test_get_metadata_bad_user(self):
metadata_ref = self.identity_api.get_metadata(
user_id=self.user_foo['id'] + 'WRONG',
tenant_id=self.tenant_bar['id'])
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_user_by_name_404(self):
self.assertRaises(exception.UserNotFound,
self.identity_api.get_user_by_name,
user_name=uuid.uuid4().hex)
def test_get_metadata(self):
metadata_ref = self.identity_api.get_metadata(
@ -146,12 +144,29 @@ class IdentityTests(object):
tenant_id=self.tenant_bar['id'])
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):
role_ref = self.identity_api.get_role(
role_id=self.role_keystone_admin['id'])
role_ref_dict = dict((x, role_ref[x]) for x in role_ref)
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):
role = {'id': 'fake1',
'name': 'fake1name'}
@ -170,7 +185,7 @@ class IdentityTests(object):
self.identity_api.create_role('fake1', role1)
self.identity_api.create_role('fake2', role2)
role1['name'] = 'fake2name'
self.assertRaises(exception.Error,
self.assertRaises(exception.Conflict,
self.identity_api.update_role,
'fake1',
role1)
@ -211,23 +226,27 @@ class IdentityTests(object):
self.identity_api.create_user('fake1', user1)
self.identity_api.create_user('fake2', user2)
user2['name'] = 'fake1'
self.assertRaises(exception.Error,
self.assertRaises(exception.Conflict,
self.identity_api.update_user,
'fake2',
user2)
def test_update_user_id_does_nothing(self):
def test_update_user_id_fails(self):
user = {'id': 'fake1',
'name': 'fake1',
'password': 'fakepass',
'tenants': ['bar']}
self.identity_api.create_user('fake1', user)
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')
self.assertEqual(user_ref['id'], 'fake1')
user_ref = self.identity_api.get_user('fake2')
self.assert_(user_ref is None)
self.assertRaises(exception.UserNotFound,
self.identity_api.get_user,
'fake2')
def test_create_duplicate_tenant_id_fails(self):
tenant = {'id': 'fake1', 'name': 'fake1'}
@ -265,8 +284,9 @@ class IdentityTests(object):
self.identity_api.update_tenant('fake1', tenant)
tenant_ref = self.identity_api.get_tenant('fake1')
self.assertEqual(tenant_ref['id'], 'fake1')
tenant_ref = self.identity_api.get_tenant('fake2')
self.assert_(tenant_ref is None)
self.assertRaises(exception.TenantNotFound,
self.identity_api.get_tenant,
'fake2')
def test_get_role_by_user_and_tenant(self):
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('useless', roles_ref)
def test_delete_role(self):
role_id = 'test_role_delete'
new_role = {'id': role_id, 'name': 'Role to Delete'}
self.identity_api.create_role(role_id, new_role)
role_ref = self.identity_api.get_role(role_id)
def test_get_roles_for_user_and_tenant_404(self):
self.assertRaises(exception.UserNotFound,
self.identity_api.get_roles_for_user_and_tenant,
uuid.uuid4().hex,
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)
self.assertDictEqual(role_ref_dict, new_role)
self.identity_api.delete_role(role_id)
role_ref = self.identity_api.get_role(role_id)
self.assertIsNone(role_ref)
self.assertDictEqual(role_ref_dict, role)
role['name'] = uuid.uuid4().hex
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):
tenant_id = 'tenent4add'
self.identity_api.add_user_to_tenant(tenant_id, 'foo')
tenants = self.identity_api.get_tenants_for_user('foo')
self.assertIn(tenant_id, tenants)
self.identity_api.add_user_to_tenant(self.tenant_bar['id'],
self.user_foo['id'])
tenants = self.identity_api.get_tenants_for_user(self.user_foo['id'])
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):
tenant = {'id': 'fake1', 'name': 'a' * 65}
@ -378,10 +536,20 @@ class TokenTests(object):
self.assertEquals(new_data_ref, data)
self.token_api.delete_token(token_id)
self.assertRaises(exception.TokenNotFound,
self.token_api.delete_token, token_id)
self.assertRaises(exception.TokenNotFound,
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):
token_id = uuid.uuid4().hex
@ -403,7 +571,6 @@ class TokenTests(object):
class CatalogTests(object):
def test_service_crud(self):
new_service = {'id': 'MY_SERVICE', 'type': 'myservice',
'name': 'My Service', 'description': 'My description'}
@ -413,9 +580,41 @@ class CatalogTests(object):
service_id = new_service['id']
self.catalog_api.delete_service(service_id)
self.assertRaises(exception.ServiceNotFound,
self.catalog_api.delete_service, service_id)
self.catalog_man.delete_service, {}, service_id)
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):
services = self.catalog_api.list_services()

View File

@ -13,11 +13,14 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import uuid
from keystone import exception
from keystone import test
from keystone.identity.backends import kvs as identity_kvs
from keystone.token.backends import kvs as token_kvs
from keystone.catalog.backends import kvs as catalog_kvs
from keystone import catalog
import test_backend
import default_fixtures
@ -40,6 +43,7 @@ class KvsCatalog(test.TestCase, test_backend.CatalogTests):
def setUp(self):
super(KvsCatalog, self).setUp()
self.catalog_api = catalog_kvs.Catalog(db={})
self.catalog_man = catalog.Manager()
self.load_fixtures(default_fixtures)
self._load_fake_catalog()
@ -48,14 +52,35 @@ class KvsCatalog(test.TestCase, test_backend.CatalogTests):
'foo', 'bar',
{'RegionFoo': {'service_bar': {'foo': 'bar'}}})
def test_get_catalog_bad_user(self):
catalog_ref = self.catalog_api.get_catalog('foo' + 'WRONG', 'bar')
self.assert_(catalog_ref is None)
def test_get_catalog_404(self):
# FIXME(dolph): this test should be moved up to test_backend
# 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):
catalog_ref = self.catalog_api.get_catalog('foo', 'bar' + 'WRONG')
self.assert_(catalog_ref is None)
self.assertRaises(exception.NotFound,
self.catalog_api.get_catalog,
'foo',
uuid.uuid4().hex)
def test_get_catalog(self):
catalog_ref = self.catalog_api.get_catalog('foo', 'bar')
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
# under the License.
import uuid
from keystone import config
from keystone import exception
from keystone import test
from keystone.common.ldap import fakeldap
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.load_fixtures(default_fixtures)
def tearDown(self):
test.TestCase.tearDown(self)
def test_delete_tenant_404(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)
def test_delete_user_with_tenant_association(self):
user = {'id': 'fake',
'name': 'fakeuser',
'password': 'passwd'}
self.identity_api.create_user('fake', user)
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'])
tenants = self.identity_api.get_tenants_for_user(user['id'])
self.assertEquals(tenants, [])
self.assertRaises(exception.UserNotFound,
self.identity_api.get_tenants_for_user,
user['id'])
def test_create_null_user_name(self):
user = {'id': uuid.uuid4().hex,
@ -59,13 +60,12 @@ class SqlIdentity(test.TestCase, test_backend.IdentityTests):
self.identity_api.create_user,
user['id'],
user)
# TODO(dolph): can be uncommented pending bug 968519
#self.assertRaises(exception.UserNotFound,
# self.identity_api.get_user,
# user['id'])
#self.assertRaises(exception.UserNotFound,
# self.identity_api.get_user_by_name,
# user['name'])
self.assertRaises(exception.UserNotFound,
self.identity_api.get_user,
user['id'])
self.assertRaises(exception.UserNotFound,
self.identity_api.get_user_by_name,
user['name'])
def test_create_null_tenant_name(self):
tenant = {'id': uuid.uuid4().hex,
@ -74,13 +74,12 @@ class SqlIdentity(test.TestCase, test_backend.IdentityTests):
self.identity_api.create_tenant,
tenant['id'],
tenant)
# TODO(dolph): can be uncommented pending bug 968519
#self.assertRaises(exception.TenantNotFound,
# self.identity_api.get_tenant,
# tenant['id'])
#self.assertRaises(exception.TenantNotFound,
# self.identity_api.get_tenant_by_name,
# tenant['name'])
self.assertRaises(exception.TenantNotFound,
self.identity_api.get_tenant,
tenant['id'])
self.assertRaises(exception.TenantNotFound,
self.identity_api.get_tenant_by_name,
tenant['name'])
def test_create_null_role_name(self):
role = {'id': uuid.uuid4().hex,
@ -89,10 +88,9 @@ class SqlIdentity(test.TestCase, test_backend.IdentityTests):
self.identity_api.create_role,
role['id'],
role)
# TODO(dolph): can be uncommented pending bug 968519
#self.assertRaises(exception.RoleNotFound,
# self.identity_api.get_role,
# role['id'])
self.assertRaises(exception.RoleNotFound,
self.identity_api.get_role,
role['id'])
def test_delete_tenant_with_user_association(self):
user = {'id': 'fake',
@ -114,9 +112,10 @@ class SqlIdentity(test.TestCase, test_backend.IdentityTests):
self.tenant_bar['id'],
{'extra': 'extra'})
self.identity_api.delete_user(user['id'])
metadata = self.identity_api.get_metadata(user['id'],
self.tenant_bar['id'])
self.assertEquals(metadata, {})
self.assertRaises(exception.MetadataNotFound,
self.identity_api.get_metadata,
user['id'],
self.tenant_bar['id'])
def test_delete_tenant_with_metadata(self):
user = {'id': 'fake',
@ -127,9 +126,10 @@ class SqlIdentity(test.TestCase, test_backend.IdentityTests):
self.tenant_bar['id'],
{'extra': 'extra'})
self.identity_api.delete_tenant(self.tenant_bar['id'])
metadata = self.identity_api.get_metadata(user['id'],
self.tenant_bar['id'])
self.assertEquals(metadata, {})
self.assertRaises(exception.MetadataNotFound,
self.identity_api.get_metadata,
user['id'],
self.tenant_bar['id'])
class SqlToken(test.TestCase, test_backend.TokenTests):

View File

@ -15,9 +15,12 @@
# under the License.
import os
import uuid
from keystone import exception
from keystone import test
from keystone.catalog.backends import templated as catalog_templated
from keystone import catalog
import test_backend
import default_fixtures
@ -50,8 +53,25 @@ class TestTemplatedCatalog(test.TestCase, test_backend.CatalogTests):
super(TestTemplatedCatalog, self).setUp()
self.opt_in_group('catalog', template_file=DEFAULT_CATALOG_TEMPLATES)
self.catalog_api = catalog_templated.TemplatedCatalog()
self.catalog_man = catalog.Manager()
self.load_fixtures(default_fixtures)
def test_get_catalog(self):
catalog_ref = self.catalog_api.get_catalog('foo', 'bar')
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
client = self.get_client()
token = client.auth_token
self.assertRaises(client_exceptions.AuthorizationFailure,
self._client, token=token, tenant_id='baz')
self.assertRaises(client_exceptions.Unauthorized,
self._client, token=token,
tenant_id=uuid.uuid4().hex)
def test_authenticate_token_tenant_name(self):
client = self.get_client()
@ -284,15 +285,15 @@ class KeystoneClientTests(object):
self.assertRaises(client_exceptions.Unauthorized,
self._client,
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
self.assertRaises(client_exceptions.Unauthorized,
self._client,
username='blah',
password='blah')
username=uuid.uuid4().hex,
password=uuid.uuid4().hex)
def test_change_password_invalidates_token(self):
from keystoneclient import exceptions as client_exceptions
@ -674,17 +675,6 @@ class KeystoneClientTests(object):
client.services.get,
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):
# the catalog backend is expected to return Not Implemented
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,
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):
from keystoneclient import exceptions as client_exceptions
client = self.get_client(admin=True)