# vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """ Auth driver using the DB as its backend. """ from nova import context from nova import db from nova import exception class DbDriver(object): """DB Auth driver Defines enter and exit and therefore supports the with/as syntax. """ def __init__(self): """Imports the LDAP module""" pass def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): pass def get_user(self, uid): """Retrieve user by id""" user = db.user_get(context.get_admin_context(), uid) return self._db_user_to_auth_user(user) def get_user_from_access_key(self, access): """Retrieve user by access key""" user = db.user_get_by_access_key(context.get_admin_context(), access) return self._db_user_to_auth_user(user) def get_project(self, pid): """Retrieve project by id""" project = db.project_get(context.get_admin_context(), pid) return self._db_project_to_auth_projectuser(project) def get_users(self): """Retrieve list of users""" return [self._db_user_to_auth_user(user) for user in db.user_get_all(context.get_admin_context())] def get_projects(self, uid=None): """Retrieve list of projects""" if uid: result = db.project_get_by_user(context.get_admin_context(), uid) else: result = db.project_get_all(context.get_admin_context()) return [self._db_project_to_auth_projectuser(proj) for proj in result] def create_user(self, name, access_key, secret_key, is_admin): """Create a user""" values = {'id': name, 'access_key': access_key, 'secret_key': secret_key, 'is_admin': is_admin} try: user_ref = db.user_create(context.get_admin_context(), values) return self._db_user_to_auth_user(user_ref) except (exception.Duplicate, exception.DBError) as e: raise exception.UserExists(user=name) def _db_user_to_auth_user(self, user_ref): return {'id': user_ref['id'], 'name': user_ref['id'], 'access': user_ref['access_key'], 'secret': user_ref['secret_key'], 'admin': user_ref['is_admin']} def _db_project_to_auth_projectuser(self, project_ref): member_ids = [member['id'] for member in project_ref['members']] return {'id': project_ref['id'], 'name': project_ref['name'], 'project_manager_id': project_ref['project_manager'], 'description': project_ref['description'], 'member_ids': member_ids} def create_project(self, name, manager_uid, description=None, member_uids=None): """Create a project""" manager = db.user_get(context.get_admin_context(), manager_uid) # description is a required attribute if description is None: description = name # First, we ensure that all the given users exist before we go # on to create the project. This way we won't have to destroy # the project again because a user turns out to be invalid. members = set([manager]) if member_uids is not None: for member_uid in member_uids: member = db.user_get(context.get_admin_context(), member_uid) members.add(member) values = {'id': name, 'name': name, 'project_manager': manager['id'], 'description': description} try: project = db.project_create(context.get_admin_context(), values) except exception.DBError: raise exception.ProjectExists(project=name) for member in members: db.project_add_member(context.get_admin_context(), project['id'], member['id']) # This looks silly, but ensures that the members element has been # correctly populated project_ref = db.project_get(context.get_admin_context(), project['id']) return self._db_project_to_auth_projectuser(project_ref) def modify_project(self, project_id, manager_uid=None, description=None): """Modify an existing project""" if not manager_uid and not description: return values = {} if manager_uid: manager = db.user_get(context.get_admin_context(), manager_uid) values['project_manager'] = manager['id'] if description: values['description'] = description db.project_update(context.get_admin_context(), project_id, values) if not self.is_in_project(manager_uid, project_id): self.add_to_project(manager_uid, project_id) def add_to_project(self, uid, project_id): """Add user to project""" user, project = self._validate_user_and_project(uid, project_id) db.project_add_member(context.get_admin_context(), project['id'], user['id']) def remove_from_project(self, uid, project_id): """Remove user from project""" user, project = self._validate_user_and_project(uid, project_id) db.project_remove_member(context.get_admin_context(), project['id'], user['id']) def is_in_project(self, uid, project_id): """Check if user is in project""" user, project = self._validate_user_and_project(uid, project_id) return user in project.members def has_role(self, uid, role, project_id=None): """Check if user has role If project is specified, it checks for local role, otherwise it checks for global role """ return role in self.get_user_roles(uid, project_id) def add_role(self, uid, role, project_id=None): """Add role for user (or user and project)""" if not project_id: db.user_add_role(context.get_admin_context(), uid, role) return db.user_add_project_role(context.get_admin_context(), uid, project_id, role) def remove_role(self, uid, role, project_id=None): """Remove role for user (or user and project)""" if not project_id: db.user_remove_role(context.get_admin_context(), uid, role) return db.user_remove_project_role(context.get_admin_context(), uid, project_id, role) def get_user_roles(self, uid, project_id=None): """Retrieve list of roles for user (or user and project)""" if project_id is None: roles = db.user_get_roles(context.get_admin_context(), uid) return roles else: roles = db.user_get_roles_for_project(context.get_admin_context(), uid, project_id) return roles def delete_user(self, id): """Delete a user""" user = db.user_get(context.get_admin_context(), id) db.user_delete(context.get_admin_context(), user['id']) def delete_project(self, project_id): """Delete a project""" db.project_delete(context.get_admin_context(), project_id) def modify_user(self, uid, access_key=None, secret_key=None, admin=None): """Modify an existing user""" if not access_key and not secret_key and admin is None: return values = {} if access_key: values['access_key'] = access_key if secret_key: values['secret_key'] = secret_key if admin is not None: values['is_admin'] = admin db.user_update(context.get_admin_context(), uid, values) def _validate_user_and_project(self, user_id, project_id): user = db.user_get(context.get_admin_context(), user_id) project = db.project_get(context.get_admin_context(), project_id) return user, project