def test_list_auth_roles(self): return_value = { "results": [ { "id": "project_admin", "name": "Project Admin", } ] } mock_requests = MagicMock() mock_requests.get.side_effect = [ fake_response_with_pages(status_code=200, json_return_value=return_value, num_pages=1) ] api = DataServiceApi(auth=self.create_mock_auth(config_page_size=100), url="something.com/v1/", http=mock_requests) resp = api.get_auth_roles(context='') self.assertEqual(1, len(resp.json()['results'])) self.assertEqual("Project Admin", resp.json()['results'][0]['name'])
def test_list_auth_roles(self): return_value = { "results": [{ "id": "project_admin", "name": "Project Admin", }] } mock_requests = MagicMock() mock_requests.get.side_effect = [ fake_response_with_pages(status_code=200, json_return_value=return_value, num_pages=1) ] api = DataServiceApi(auth=None, url="something.com/v1/", http=mock_requests) resp = api.get_auth_roles(context='') self.assertEqual(1, len(resp.json()['results'])) self.assertEqual("Project Admin", resp.json()['results'][0]['name'])
class RemoteStore(object): """ Fetches project tree data from remote store. """ def __init__(self, config): """ Setup to allow fetching project tree. :param config: ddsc.config.Config settings to use for connecting to the dataservice. """ self.config = config auth = DataServiceAuth(self.config) self.data_service = DataServiceApi(auth, self.config.url) def fetch_remote_project(self, project_name, must_exist=False, include_children=True): """ Retrieve the project via project_name. :param project_name: str name of the project to try and download :param must_exist: should we error if the project doesn't exist :param include_children: should we read children(folders/files) :return: RemoteProject project requested or None if not found(and must_exist=False) """ project = self._get_my_project(project_name) if project: if include_children: self._add_project_children(project) else: if must_exist: raise NotFoundError( u'There is no project with the name {}'.format( project_name).encode('utf-8')) return project def fetch_remote_project_by_id(self, id): """ Retrieves project from via id :param id: str id of project from data service :return: RemoteProject we downloaded """ response = self.data_service.get_project_by_id(id).json() return RemoteProject(response) def _get_my_project(self, project_name): """ Return project tree root for project_name. :param project_name: str name of the project to download :return: RemoteProject project we found or None """ response = self.data_service.get_projects().json() for project in response['results']: if project['name'] == project_name: return RemoteProject(project) return None def _add_project_children(self, project): """ Add the rest of the project tree from the remote store to the project object. :param project: RemoteProject root of the project tree to add children too """ response = self.data_service.get_project_children(project.id, '').json() project_children = RemoteProjectChildren(project.id, response['results']) for child in project_children.get_tree(): project.add_child(child) def lookup_or_register_user_by_email_or_username(self, email, username): """ Lookup user by email or username. Only fill in one field. For username it will try to register if not found. :param email: str: email address of the user :param username: netid of the user to find :return: RemoteUser """ if username: return self.get_or_register_user_by_username(username) else: # API doesn't support registering user by email address yet return self.lookup_user_by_email(email) def lookup_user_by_name(self, full_name): """ Query remote store for a single user with the name full_name or raise error. :param full_name: str Users full name separated by a space. :return: RemoteUser user info for single user with full_name """ res = self.data_service.get_users_by_full_name(full_name) json_data = res.json() results = json_data['results'] found_cnt = len(results) if found_cnt == 0: raise NotFoundError("User not found:" + full_name) elif found_cnt > 1: raise ValueError("Multiple users with name:" + full_name) user = RemoteUser(results[0]) if user.full_name.lower() != full_name.lower(): raise NotFoundError("User not found:" + full_name) return user def lookup_user_by_username(self, username): """ Finds the single user who has this username or raises ValueError. :param username: str username we are looking for :return: RemoteUser: user we found """ matches = [ user for user in self.fetch_all_users() if user.username == username ] if not matches: raise NotFoundError('Username not found: {}.'.format(username)) if len(matches) > 1: raise ValueError( 'Multiple users with same username found: {}.'.format( username)) return matches[0] def get_or_register_user_by_username(self, username): """ Try to lookup user by username. If not found try registering the user. :param username: str: username to lookup :return: RemoteUser: user we found """ try: return self.lookup_user_by_username(username) except NotFoundError: return self.register_user_by_username(username) def register_user_by_username(self, username): """ Tries to register user with the first non-deprecated auth provider. Raises ValueError if the data service doesn't have any non-deprecated providers. :param username: str: netid of the user we are trying to register :return: RemoteUser: user that was created for our netid """ current_providers = [ prov.id for prov in self.get_auth_providers() if not prov.is_deprecated ] if not current_providers: raise ValueError( "Unable to register user: no non-deprecated providers found!") auth_provider_id = current_providers[0] return self._register_user_by_username(auth_provider_id, username) def _register_user_by_username(self, auth_provider_id, username): """ Tries to register a user who has a valid netid but isn't registered with DukeDS yet under auth_provider_id. :param auth_provider_id: str: id from RemoteAuthProvider to use for registering :param username: str: netid of the user we are trying to register :return: RemoteUser: user that was created for our netid """ user_json = self.data_service.auth_provider_add_user( auth_provider_id, username).json() return RemoteUser(user_json) def get_auth_providers(self): """ Return the list of authorization providers. :return: [RemoteAuthProvider]: list of remote auth providers """ providers = [] response = self.data_service.get_auth_providers().json() for data in response['results']: providers.append(RemoteAuthProvider(data)) return providers def lookup_user_by_email(self, email): """ Finds the single user who has this email or raises ValueError. :param email: str email we are looking for :return: RemoteUser user we found """ matches = [ user for user in self.fetch_all_users() if user.email == email ] if not matches: raise ValueError('Email not found: {}.'.format(email)) if len(matches) > 1: raise ValueError( 'Multiple users with same email found: {}.'.format(email)) return matches[0] def get_current_user(self): """ Fetch info about the current user :return: RemoteUser user who we are logged in as(auth determines this). """ response = self.data_service.get_current_user().json() return RemoteUser(response) def fetch_all_users(self): """ Retrieves all users from data service. :return: [RemoteUser] list of all users we downloaded """ users = [] result = self.data_service.get_all_users() user_list_json = result.json() for user_json in user_list_json['results']: users.append(RemoteUser(user_json)) return users def fetch_user(self, id): """ Retrieves user from data service having a specific id :param id: str id of user from data service :return: RemoteUser user we downloaded """ response = self.data_service.get_user_by_id(id).json() return RemoteUser(response) def set_user_project_permission(self, project, user, auth_role): """ Update remote store for user giving auth_role permissions on project. :param project: RemoteProject project to give permissions to :param user: RemoteUser user who we are giving permissions to :param auth_role: str type of authorization to give user(project_admin) """ self.data_service.set_user_project_permission(project.id, user.id, auth_role) def revoke_user_project_permission(self, project, user): """ Update remote store for user removing auth_role permissions on project. :param project: RemoteProject project to remove permissions from :param user: RemoteUser user who we are removing permissions from """ # Server errors out with 500 if a user isn't found. try: self.data_service.get_user_project_permission(project.id, user.id) self.data_service.revoke_user_project_permission( project.id, user.id) except DataServiceError as e: if e.status_code != 404: raise def download_file(self, remote_file, path, watcher): """ Download a remote file associated with the remote uuid(file_id) into local path. :param remote_file: RemoteFile file to retrieve :param path: str file system path to save the contents to. :param watcher: object implementing send_item(item, increment_amt) that updates UI """ url_json = self.data_service.get_file_url(remote_file.id).json() http_verb = url_json['http_verb'] host = url_json['host'] url = url_json['url'] http_headers = url_json['http_headers'] response = self.data_service.receive_external(http_verb, host, url, http_headers) with open(path, 'wb') as f: for chunk in response.iter_content( chunk_size=DOWNLOAD_FILE_CHUNK_SIZE): if chunk: # filter out keep-alive new chunks f.write(chunk) watcher.transferring_item(remote_file, increment_amt=len(chunk)) def get_project_names(self): """ Return a list of names of the remote projects owned by this user. :return: [str]: the list of project names """ names = [] response = self.data_service.get_projects().json() for project in response['results']: names.append(project['name']) return names def delete_project_by_name(self, project_name): """ Find the project named project_name and delete it raise error if not found. :param project_name: str: Name of the project we want to be deleted """ project = self._get_my_project(project_name) if project: self.data_service.delete_project(project.id) else: raise ValueError( "No project named '{}' found.\n".format(project_name)) def get_active_auth_roles(self, context): """ Retrieve non-deprecated authorization roles based on a context. Context should be RemoteAuthRole.PROJECT_CONTEXT or RemoteAuthRole.SYSTEM_CONTEXT. :param context: str: context for which auth roles to retrieve :return: [RemoteAuthRole]: list of active auth_role objects """ response = self.data_service.get_auth_roles(context).json() return self.get_active_auth_roles_from_json(response) @staticmethod def get_active_auth_roles_from_json(json_data): """ Given a json blob response containing a list of authorization roles return the active ones in an array of RemoteAuthRole objects. :param json_data: list of dictionaries - data from dds in auth_role format :return: [RemoteAuthRole] list of active auth_role objects """ result = [] for auth_role_properties in json_data['results']: auth_role = RemoteAuthRole(auth_role_properties) if not auth_role.is_deprecated: result.append(auth_role) return result