def get(self, request, user_id): """ Get user info based on the user id. Will only find users in your project. """ id_manager = user_store.IdentityManager() user = id_manager.get_user(user_id) no_user = {'errors': ['No user with this id.']} if not user: return Response(no_user, status=404) class_conf = settings.TASK_SETTINGS.get(self.task_type, settings.DEFAULT_TASK_SETTINGS) role_blacklist = class_conf.get('role_blacklist', []) project_id = request.keystone_user['project_id'] project = id_manager.get_project(project_id) roles = [role.name for role in id_manager.get_roles(user, project)] roles_blacklisted = set(role_blacklist) & set(roles) if not roles or roles_blacklisted: return Response(no_user, status=404) return Response({ 'id': user.id, "username": user.name, "email": getattr(user, 'email', ''), 'roles': roles })
def delete(self, request, user_id): """ Remove this user from the project. This may cancel a pending user invite, or simply revoke roles. """ id_manager = user_store.IdentityManager() user = id_manager.get_user(user_id) project_id = request.keystone_user['project_id'] # NOTE(dale): For now, we only support cancelling pending invites. if user: return Response( { 'errors': [ 'Revoking keystone users not implemented. ' + 'Try removing all roles instead.' ] }, status=501) project_tasks = models.Task.objects.filter(project_id=project_id, task_type="invite_user", completed=0, cancelled=0) for task in project_tasks: if task.uuid == user_id: task.add_action_note(self.__class__.__name__, 'Cancelled.') task.cancelled = True task.save() return Response('Cancelled pending invite task!', status=200) return Response('Not found.', status=404)
def _validate_user_roles(self): id_manager = user_store.IdentityManager() user = self._get_target_user() project = id_manager.get_project(self.project_id) # user roles current_roles = id_manager.get_roles(user, project) current_role_names = {role.name for role in current_roles} # NOTE(adriant): Only allow someone to edit roles if all roles from # the target user can be managed by editor. can_manage_roles = user_store.get_managable_roles( self.action.task.keystone_user['roles']) if not set(can_manage_roles).issuperset(current_role_names): self.add_note('Not all target user roles are manageable.') return False if self.remove: remaining = set(current_role_names) & set(self.roles) if not remaining: self.action.state = "complete" self.add_note("User doesn't have roles to remove.") else: self.roles = list(remaining) self.add_note('User has roles to remove.') else: missing = set(self.roles) - set(current_role_names) if not missing: self.action.state = "complete" self.add_note('User already has roles.') else: self.roles = list(missing) self.add_note('User user missing roles.') # All paths are valid here # We've just set state and roles that need to be changed. return True
def _submit(self, token_data): """ The submit action is performed when a token is submitted. This is done to set a user password only, and so should now only change the user password. The project and user themselves are created on post_approve. """ self._validate_user_submit() if not self.valid: return project_id = self.get_cache('project_id') self.action.task.cache['project_id'] = project_id user_id = self.get_cache('user_id') self.action.task.cache['user_id'] = user_id id_manager = user_store.IdentityManager() if self.action.state in ["default", "disabled"]: user = id_manager.get_user(user_id) try: id_manager.update_user_password(user, token_data['password']) except Exception as e: self.add_note( "Error: '%s' while changing password for user: %s" % (e, self.username)) raise self.add_note('User %s password has been changed.' % self.username) elif self.action.state == "existing": # do nothing, everything is already done. self.add_note("Existing user '%s' already attached to project %s" % (user_id, project_id))
def _submit(self, token_data): self._validate() if not self.valid: return id_manager = user_store.IdentityManager() user = id_manager.find_user(self.username, None) roles = id_manager.get_roles(user, self.project_id) role_names = {role.name for role in roles} missing = set(self.roles) - role_names self.add_note("Accepted by %s" % self.action.task.keystone_user['username']) if not missing: self.add_note( 'Existing user %s already had roles %s in project %s.' % (self.username, self.roles, self.project_id)) else: self.roles = list(missing) self.grant_roles(user, self.roles, self.project_id) self.add_note( 'Existing user %s has been given roles %s in project %s.' % (self.username, self.roles, self.project_id))
def _validate_username_exists(self): id_manager = user_store.IdentityManager() self.user = id_manager.find_user(self.username, self.domain.id) if not self.user: self.add_note('No user present with username') return False return True
def _validate_domain_id(self): id_manager = user_store.IdentityManager() domain = id_manager.get_domain(self.domain_id) if not domain: self.add_note('Domain does not exist.') return False return True
def _get_target_user(self): """ Gets the target user by id """ id_manager = user_store.IdentityManager() user = id_manager.get_user(self.user_id) return user
def _get_target_user(self): """ Gets the target user by their username """ id_manager = user_store.IdentityManager() user = id_manager.find_user(self.username, self.domain_id) return user
def _validate_domain_name(self): id_manager = user_store.IdentityManager() self.domain = id_manager.find_domain(self.domain_name) if not self.domain: self.add_note('Domain does not exist.') return False # also store the domain_id separately for later use self.domain_id = self.domain.id return True
def update_user_name(self, username, user=None): id_manager = user_store.IdentityManager() try: if not user: user = self.find_user() id_manager.update_user_name(user, username) except Exception as e: self.add_note("Error: '%s' while changing username for user: %s" % (e, self.username)) raise
def get(self, request, user_id): """ Get role info based on the user id. """ id_manager = user_store.IdentityManager() user = id_manager.get_user(user_id) project_id = request.keystone_user['project_id'] project = id_manager.get_project(project_id) roles = [] for role in id_manager.get_roles(user, project): roles.append(role.to_dict()) return Response({"roles": roles})
def _validate_project_absent(self): id_manager = user_store.IdentityManager() project = id_manager.find_project(self.project_name, self.domain_id) if project: self.add_note("Existing project with name '%s'." % self.project_name) return False self.add_note("No existing project with name '%s'." % self.project_name) return True
def enable_user(self, user=None): id_manager = user_store.IdentityManager() try: if not user: user = self.find_user() id_manager.enable_user(user) except Exception as e: self.add_note( "Error: '%s' while re-enabling user: %s with roles: %s" % (e, self.username, self.roles)) raise
def _validate_parent_project(self): id_manager = user_store.IdentityManager() # NOTE(adriant): If parent id is None, Keystone defaults to the domain. # So we only care to validate if parent_id is not None. if self.parent_id: parent = id_manager.get_project(self.parent_id) if not parent: self.add_note("Parent id: '%s' does not exist." % self.project_name) return False return True
def _validate_users(self): id_manager = user_store.IdentityManager() all_found = True for user in self.users: ks_user = id_manager.find_user(user, self.domain_id) if ks_user: self.add_note('User: %s exists.' % user) else: self.add_note('ERROR: User: %s does not exist.' % user) all_found = False return all_found
def _validate_email_not_in_use(self): if settings.USERNAME_IS_EMAIL: self.domain_id = self.action.task.keystone_user[ 'project_domain_id'] id_manager = user_store.IdentityManager() if id_manager.find_user(self.new_email, self.domain_id): self.add_note("User with same username already exists") return False self.add_note("No user with same username") return True
def set_email(self, conf): self.emails = set() if conf.get('email_current_user'): self.add_note("Adding the current user's email address") if settings.USERNAME_IS_EMAIL: self.emails.add(self.action.task.keystone_user['username']) else: try: id_manager = user_store.IdentityManager() email = id_manager.get_user( self.action.task.keystone_user['user_id']).email self.emails.add(email) except AttributeError: self.add_note("Could not add current user email address") if conf.get('email_roles'): roles = set(conf.get('email_roles')) project_id = self.action.task.keystone_user['project_id'] self.add_note('Adding email addresses for roles %s in project %s' % (roles, project_id)) id_manager = user_store.IdentityManager() users = id_manager.list_users(project_id) for user in users: user_roles = [role.name for role in user.roles] if roles.intersection(user_roles): if settings.USERNAME_IS_EMAIL: self.emails.add(user.name) else: self.emails.add(user.email) if conf.get('email_task_cache'): task_emails = self.action.task.cache.get('additional_emails', []) if isinstance(task_emails, six.string_types): task_emails = [task_emails] for email in task_emails: self.emails.add(email) for email in conf.get('email_additional_addresses', []): self.emails.add(email)
def _validate_region(self): if not self.region: self.add_note('ERROR: No region given.') return False id_manager = user_store.IdentityManager() region = id_manager.get_region(self.region) if not region: self.add_note('ERROR: Region does not exist.') return False self.add_note('Region: %s exists.' % self.region) return True
def _validate_project_exists(self): if not self.project_id: self.add_note('No project_id set, previous action should have ' 'set it.') return False id_manager = user_store.IdentityManager() project = id_manager.get_project(self.project_id) if not project: self.add_note('Project with id %s does not exist.' % self.project_id) return False self.add_note('Project with id %s exists.' % self.project_id) return True
def create_user(self, password): id_manager = user_store.IdentityManager() try: user = id_manager.create_user( name=self.username, password=password, email=self.email, domain=self.domain_id, created_on=str(timezone.now())) except Exception as e: # TODO: Narrow the Exceptions caught to a relevant set. self.add_note( "Error: '%s' while creating user: %s with roles: %s" % (e, self.username, self.roles)) raise return user
def _create_project(self): id_manager = user_store.IdentityManager() try: project = id_manager.create_project( self.project_name, created_on=str(timezone.now()), parent=self.parent_id, domain=self.domain_id) except Exception as e: self.add_note( "Error: '%s' while creating project: %s" % (e, self.project_name)) raise # put project_id into action cache: self.action.task.cache['project_id'] = project.id self.set_cache('project_id', project.id) self.add_note("New project '%s' created." % project.name)
def _validate_project_id(self): # Handle an edge_case where some actions set their # own project_id value. if not self.project_id: self.add_note('No project_id given.') return False # Now actually check the project exists. id_manager = user_store.IdentityManager() project = id_manager.get_project(self.project_id) if not project: self.add_note('Project with id %s does not exist.' % self.project_id) return False self.add_note('Project with id %s exists.' % self.project_id) return True
def _validate_target_user(self): id_manager = user_store.IdentityManager() # check if user exists and is valid # this may mean we need a token. user = self._get_target_user() if not user: self.action.need_token = True # add to cache to use in template self.action.task.cache['user_state'] = "default" self.set_token_fields(["password"]) self.add_note( 'No user present with username. Need to create new user.') return True if user.email != self.email: self.add_note('Found matching username, but email did not match.' + 'Reporting as invalid.') return False if not user.enabled: self.action.need_token = True self.action.state = "disabled" # add to cache to use in template self.action.task.cache['user_state'] = "disabled" # as they are disabled we'll reset their password self.set_token_fields(["password"]) self.add_note('Existing disabled user with matching email.') return True # role_validation roles = id_manager.get_roles(user, self.project_id) role_names = {role.name for role in roles} missing = set(self.roles) - role_names if not missing: self.action.need_token = False self.action.state = "complete" self.add_note('Existing user already has roles.') else: self.roles = list(missing) self.action.need_token = True self.set_token_fields(["confirm"]) self.action.state = "existing" # add to cache to use in template self.action.task.cache['user_state'] = "existing" self.add_note('Existing user with matching email missing roles.') return True
def _validate_user_submit(self): user_id = self.get_cache('user_id') project_id = self.get_cache('project_id') id_manager = user_store.IdentityManager() user = id_manager.get_user(user_id) project = id_manager.get_project(project_id) if user and project: self.action.valid = True else: self.action.valid = False self.action.task.cache['user_state'] = self.action.state self.action.save()
def get(self, request): """Returns a list of roles that may be managed for this project""" # get roles for this user on the project user_roles = request.keystone_user['roles'] managable_role_names = user_store.get_managable_roles(user_roles) id_manager = user_store.IdentityManager() # look up role names and form output dict of valid roles managable_roles = [] for role_name in managable_role_names: role = id_manager.find_role(role_name) if role: managable_roles.append(role.to_dict()) return Response({'roles': managable_roles})
def _post_approve(self): id_manager = user_store.IdentityManager() self.project_id = self.action.task.cache.get('project_id', None) self._validate() if self.valid and not self.action.state == "completed": try: for user in self.users: ks_user = id_manager.find_user(user, self.domain_id) self.grant_roles(ks_user, self.roles, self.project_id) self.add_note( 'User: "******" given roles: %s on project: %s.' % (ks_user.name, self.roles, self.project_id)) except Exception as e: self.add_note("Error: '%s' while adding users to project: %s" % (e, self.project_id)) raise self.action.state = "completed" self.action.save() self.add_note("All users added.")
def _post_approve(self): project_id = self.get_cache('project_id') if project_id: self.action.task.cache['project_id'] = project_id self.add_note("Project already created.") else: self._validate() if not self.valid: return self._create_project() user_id = self.get_cache('user_id') if user_id: self.action.task.cache['user_id'] = user_id self.add_note("User already given roles.") else: default_roles = self.settings.get("default_roles", {}) project_id = self.get_cache('project_id') keystone_user = self.action.task.keystone_user try: id_manager = user_store.IdentityManager() user = id_manager.get_user(keystone_user['user_id']) self.grant_roles(user, default_roles, project_id) except Exception as e: self.add_note(("Error: '%s' while adding roles %s " "to user '%s' on project '%s'") % (e, default_roles, user.name, project_id)) raise # put user_id into action cache: self.action.task.cache['user_id'] = user.id self.set_cache('user_id', user.id) self.add_note( ("Existing user '%s' attached to project %s" + " with roles: %s") % (user.name, project_id, default_roles))
def _validate_user_roles(self): id_manager = user_store.IdentityManager() self.user = id_manager.find_user(self.username, self.domain.id) roles = id_manager.get_all_roles(self.user) user_roles = [] for roles in roles.itervalues(): user_roles.extend(role.name for role in roles) if set(self.blacklist) & set(user_roles): self.add_note('Cannot reset users with blacklisted roles.') return False if self.user.email == self.email: self.action.need_token = True self.set_token_fields(["password"]) self.add_note('Existing user with matching email.') return True else: self.add_note('Existing user with non-matching email.') return False
def _user_roles_edit(self, user, roles, project_id, remove=False): id_manager = user_store.IdentityManager() if not remove: action_fn = id_manager.add_user_role action_string = "granting" else: action_fn = id_manager.remove_user_role action_string = "removing" ks_roles = [] try: for role in roles: ks_role = id_manager.find_role(role) if ks_role: ks_roles.append(ks_role) else: raise TypeError("Keystone missing role: %s" % role) for role in ks_roles: action_fn(user, role, project_id) except Exception as e: self.add_note("Error: '%s' while %s the roles: %s on user: %s " % (e, action_string, roles, user)) raise