251 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			251 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # 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.
 | |
| """
 | |
| 
 | |
| import logging
 | |
| import sys
 | |
| 
 | |
| from nova import context
 | |
| from nova import exception
 | |
| from nova import db
 | |
| 
 | |
| 
 | |
| 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
 | |
|         db
 | |
| 
 | |
|     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, e:
 | |
|             raise exception.Duplicate('User %s already exists' % 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)
 | |
|         if not manager:
 | |
|             raise exception.NotFound("Project can't be created because "
 | |
|                                      "manager %s doesn't exist" % 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 != None:
 | |
|             for member_uid in member_uids:
 | |
|                 member = db.user_get(context.get_admin_context(), member_uid)
 | |
|                 if not member:
 | |
|                     raise exception.NotFound("Project can't be created "
 | |
|                                              "because user %s doesn't exist"
 | |
|                                              % 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.Duplicate:
 | |
|             raise exception.Duplicate("Project can't be created because "
 | |
|                                       "project %s already exists" % 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)
 | |
|             if not manager:
 | |
|                 raise exception.NotFound("Project can't be modified because "
 | |
|                                           "manager %s doesn't exist" %
 | |
|                                           manager_uid)
 | |
|             values['project_manager'] = manager['id']
 | |
|         if description:
 | |
|             values['description'] = description
 | |
| 
 | |
|         db.project_update(context.get_admin_context(), project_id, values)
 | |
| 
 | |
|     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)
 | |
|         if not user:
 | |
|             raise exception.NotFound('User "%s" not found' % user_id)
 | |
|         project = db.project_get(context.get_admin_context(), project_id)
 | |
|         if not project:
 | |
|             raise exception.NotFound('Project "%s" not found' % project_id)
 | |
|         return user, project
 | 
