def __init__(self): self.logger = get_logger(self.__class__.__module__) self.user_service = UserService() self.flow_service = FlowService() analyze_category = self.flow_service.get_launchable_non_viewers() self.analyze_category_link = '/flow/step/' + str(analyze_category.id) self.analyze_adapters = None self.connectivity_tab_link = '/flow/step_connectivity' view_category = self.flow_service.get_visualisers_category() conn_id = self.flow_service.get_algorithm_by_module_and_class(CONNECTIVITY_MODULE, CONNECTIVITY_CLASS)[1].id connectivity_link = self.get_url_adapter(view_category.id, conn_id) self.connectivity_submenu = [dict(title="Large Scale Connectivity", subsection="connectivity", description="View Connectivity Regions. Perform Connectivity lesions", link=connectivity_link), dict(title="Local Connectivity", subsection="local", link='/spatial/localconnectivity/step_1/1', description="Create or view existent Local Connectivity entities.")] self.burst_submenu = [dict(link='/burst', subsection='burst', title='Simulation Cockpit', description='Manage simulations'), dict(link='/burst/dynamic', subsection='dynamic', title='Phase plane', description='Configure model dynamics')]
def __init__(self): self.logger = get_logger(self.__class__.__module__) self.user_service = UserService() self.flow_service = FlowService() self.analyze_category_link = '/flow/step_analyzers' self.analyze_adapters = None self.connectivity_tab_link = '/flow/step_connectivity' view_category = self.flow_service.get_visualisers_category() conn_id = self.flow_service.get_algorithm_by_module_and_class(CONNECTIVITY_MODULE, CONNECTIVITY_CLASS).id connectivity_link = self.get_url_adapter(view_category.id, conn_id) self.connectivity_submenu = [dict(title="Large Scale Connectivity", link=connectivity_link, subsection=WebStructure.SUB_SECTION_CONNECTIVITY, description="View Connectivity Regions. Perform Connectivity lesions"), dict(title="Local Connectivity", link='/spatial/localconnectivity/step_1/1', subsection=WebStructure.SUB_SECTION_LOCAL_CONNECTIVITY, description="Create or view existent Local Connectivity entities.")] allen_algo = self.flow_service.get_algorithm_by_module_and_class(ALLEN_CREATOR_MODULE, ALLEN_CREATOR_CLASS) if allen_algo: # Only add the Allen Creator if AllenSDK is installed allen_link = self.get_url_adapter(allen_algo.fk_category, allen_algo.id) self.connectivity_submenu.append(dict(title="Allen Connectome Downloader", link=allen_link, subsection=WebStructure.SUB_SECTION_ALLEN, description="Download a mouse connectivity from Allen dataset")) self.burst_submenu = [dict(link='/burst', subsection=WebStructure.SUB_SECTION_BURST, title='Simulation Cockpit', description='Manage simulations'), dict(link='/burst/dynamic', subsection='dynamic', title='Phase plane', description='Configure model dynamics')]
def setUp(self): """ Reset the database before each test . """ self.clean_database() self.user_service = UserService() self.user_service.create_user(username=TvbProfile.current.web.admin.ADMINISTRATOR_NAME, password=TvbProfile.current.web.admin.ADMINISTRATOR_PASSWORD, email=TvbProfile.current.web.admin.ADMINISTRATOR_EMAIL, role=model.ROLE_ADMINISTRATOR, skip_import=True) available_users = dao.get_all_users() if len(available_users) != 1: self.fail("Something went wrong with database initialization!")
def transactional_setup_method(self): """ Reset the database before each test . """ self.clean_database() self.user_service = UserService() self.user_service.create_user(username=TvbProfile.current.web.admin.ADMINISTRATOR_NAME, display_name=TvbProfile.current.web.admin.ADMINISTRATOR_DISPLAY_NAME, password=TvbProfile.current.web.admin.ADMINISTRATOR_PASSWORD, email=TvbProfile.current.web.admin.ADMINISTRATOR_EMAIL, role=model_project.ROLE_ADMINISTRATOR, skip_import=True) available_users = dao.get_all_users() if len(available_users) != 1: raise AssertionError("Something went wrong with database initialization!")
def _convert_to_python(self, value, state): """ Fancy validate for Unique user-name """ if not UserService().is_username_valid(value): raise formencode.Invalid( 'Please choose another user-name, this one is already in use!', value, state) return value
class ProjectMembersResource(RestResource): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.project_service = ProjectService() self.user_service = UserService() self.project_dao = CaseDAO() def put(self, project_gid): """ Add members to the given project :param project_gid: project gid :param """ try: project = self.project_service.find_project_lazy_by_gid(project_gid) except Exception: raise InvalidIdentifierException("Invalid project identifier.") if get_current_user().id != project.fk_admin: raise AuthorizationRequestException("Your are not allowed to edit given project") input_data = flask.request.json new_members_gid = input_data[ FormKeyInput.NEW_MEMBERS_GID.value] if FormKeyInput.NEW_MEMBERS_GID.value in input_data else [] new_members_id = [] for gid in new_members_gid: user = self.user_service.get_user_by_gid(gid) if user is None: raise InvalidInputException("Invalid user gid {}".format(gid)) new_members_id.append(user.id) self.project_dao.add_members_to_project(project.id, new_members_id)
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.logger = get_logger(self.__class__.__module__) self.operation_service = OperationService() self.project_service = ProjectService() self.user_service = UserService() self.files_helper = FilesHelper()
def initialize(introspected_modules, load_xml_events=True): """ Initialize when Application is starting. Check for new algorithms or new DataTypes. """ SettingsService().check_db_url(TvbProfile.current.db.DB_URL) ## Initialize DB is_db_empty = initialize_startup() ## Create Projects storage root in case it does not exist. initialize_storage() ## Populate DB algorithms, by introspection event_folders = [] start_introspection_time = datetime.datetime.now() for module in introspected_modules: introspector = Introspector(module) # Introspection is always done, even if DB was not empty. introspector.introspect(True) event_path = introspector.get_events_path() if event_path: event_folders.append(event_path) # Now remove or mark as removed any unverified Algo-Group, Algo-Category or Portlet to_invalidate, to_remove = dao.get_non_validated_entities( start_introspection_time) for entity in to_invalidate: entity.removed = True dao.store_entities(to_invalidate) for entity in to_remove: dao.remove_entity(entity.__class__, entity.id) ## Populate events if load_xml_events: read_events(event_folders) if not TvbProfile.is_first_run(): ## Create default users. if is_db_empty: dao.store_entity( model.User(TvbProfile.current.web.admin.SYSTEM_USER_NAME, None, None, True, None)) UserService().create_user( username=TvbProfile.current.web.admin.ADMINISTRATOR_NAME, password=TvbProfile.current.web.admin.ADMINISTRATOR_PASSWORD, email=TvbProfile.current.web.admin.ADMINISTRATOR_EMAIL, role=model.ROLE_ADMINISTRATOR) ## In case actions related to latest code-changes are needed, make sure they are executed. CodeUpdateManager().run_all_updates() ## In case the H5 version changed, run updates on all DataTypes if TvbProfile.current.version.DATA_CHECKED_TO_VERSION < TvbProfile.current.version.DATA_VERSION: thread = threading.Thread( target=FilesUpdateManager().run_all_updates) thread.start() ## Clean tvb-first-time-run temporary folder, as we are no longer at the first run: shutil.rmtree(TvbProfile.current.FIRST_RUN_STORAGE, True)
class ProjectService: """ Services layer for Project entities. """ def __init__(self): self.logger = get_logger(__name__) self.structure_helper = FilesHelper() def store_project(self, current_user, is_create, selected_id, **data): """ We want to create/update a project entity. """ #Validate Unique Name new_name = data["name"] if len(new_name) < 1: raise ProjectServiceException("Invalid project name!") projects_no = dao.count_projects_for_name(new_name, selected_id) if projects_no > 0: err = {'name': 'Please choose another name, this one is used!'} raise formencode.Invalid("Duplicate Name Error", {}, None, error_dict=err) started_operations = dao.get_operation_numbers(selected_id)[1] if started_operations > 0: raise ProjectServiceException("A project can not be renamed while operations are still running!") if is_create: current_proj = model.Project(new_name, current_user.id, data["description"]) self.structure_helper.get_project_folder(current_proj) else: try: current_proj = dao.get_project_by_id(selected_id) except Exception, excep: self.logger.exception("An error has occurred!") raise ProjectServiceException(str(excep)) if current_proj.name != new_name: self.structure_helper.rename_project_structure(current_proj.name, new_name) current_proj.name = new_name current_proj.description = data["description"] #Commit to make sure we have a valid ID current_proj.refresh_update_date() self.structure_helper.write_project_metadata(current_proj) current_proj = dao.store_entity(current_proj) #Retrieve, to initialize lazy attributes current_proj = dao.get_project_by_id(current_proj.id) #Update share settings on current Project entity visited_pages = [] prj_admin = current_proj.administrator.username if 'visited_pages' in data and data['visited_pages']: visited_pages = data['visited_pages'].split(',') for page in visited_pages: members = UserService.retrieve_all_users(prj_admin, int(page))[0] members = [m.id for m in members] dao.delete_members_for_project(current_proj.id, members) selected_user_ids = data["users"] dao.add_members_to_project(current_proj.id, selected_user_ids) #Finish operation self.logger.debug("Edit/Save OK for project:" + str(current_proj.id) + ' by user:' + current_user.username) return current_proj
def new_project(name): usr = UserService.get_administrators()[0] proj = ProjectService().store_project(usr, True, None, name=name, description=name, users=[usr]) return proj
def get(self, username): """ :return a list of user's projects """ user = UserService.get_user_by_name(username) if user is None: raise InvalidIdentifierException( 'No user registered with username: %s' % username) projects = ProjectService.retrieve_all_user_projects(user_id=user.id) return [ProjectDto(project) for project in projects]
def get(self): """ :return: a list of TVB users """ user_list, pages_no = UserService.retrieve_all_users( get_current_user().username) return { "users": [UserDto(user) for user in user_list], "pages_no": pages_no }
def run_import(project_path): ## If we would know a UserID to have as admin, next step would not be necessary. ## Make sure at least one user exists in TVB DB: user_service = UserService() admins = user_service.get_administrators() if admins: admin = admins[0] else: ## No Admin user was found, we will create one user_service.create_user("admin", "pass", role=model.ROLE_ADMINISTRATOR, email="*****@*****.**", validated=True) admin = user_service.get_administrators()[0] ## Do the actual import of a project from ZIP: import_service = ImportService() import_service.import_project_structure(project_path, admin.id) print "Project imported successfully. Check the Web UI!"
def setUp(self): """ Reset the database before each test . """ self.clean_database() self.user_service = UserService() self.user_service.create_user(username=TvbProfile.current.web.admin.ADMINISTRATOR_NAME, password=TvbProfile.current.web.admin.ADMINISTRATOR_PASSWORD, email=TvbProfile.current.web.admin.ADMINISTRATOR_EMAIL, role=model.ROLE_ADMINISTRATOR) available_users = dao.get_all_users() if len(available_users) != 1: self.fail("Something went wrong with database initialization!")
def transactional_setup_method(self): """ Reset the database before each test . """ self.clean_database() self.user_service = UserService() self.user_service.create_user(username=TvbProfile.current.web.admin.ADMINISTRATOR_NAME, password=TvbProfile.current.web.admin.ADMINISTRATOR_PASSWORD, email=TvbProfile.current.web.admin.ADMINISTRATOR_EMAIL, role=model.ROLE_ADMINISTRATOR, skip_import=True) available_users = dao.get_all_users() if len(available_users) != 1: raise AssertionError("Something went wrong with database initialization!")
def store_project(self, current_user, is_create, selected_id, **data): """ We want to create/update a project entity. """ # Validate Unique Name new_name = data["name"] if len(new_name) < 1: raise ProjectServiceException("Invalid project name!") projects_no = dao.count_projects_for_name(new_name, selected_id) if projects_no > 0: err = {'name': 'Please choose another name, this one is used!'} raise formencode.Invalid("Duplicate Name Error", {}, None, error_dict=err) started_operations = dao.get_operation_numbers(selected_id)[1] if started_operations > 0: raise ProjectServiceException("A project can not be renamed while operations are still running!") if is_create: current_proj = model.Project(new_name, current_user.id, data["description"]) self.structure_helper.get_project_folder(current_proj) else: try: current_proj = dao.get_project_by_id(selected_id) except Exception as excep: self.logger.exception("An error has occurred!") raise ProjectServiceException(str(excep)) if current_proj.name != new_name: self.structure_helper.rename_project_structure(current_proj.name, new_name) current_proj.name = new_name current_proj.description = data["description"] # Commit to make sure we have a valid ID current_proj.refresh_update_date() self.structure_helper.write_project_metadata(current_proj) current_proj = dao.store_entity(current_proj) # Retrieve, to initialize lazy attributes current_proj = dao.get_project_by_id(current_proj.id) # Update share settings on current Project entity visited_pages = [] prj_admin = current_proj.administrator.username if 'visited_pages' in data and data['visited_pages']: visited_pages = data['visited_pages'].split(',') for page in visited_pages: members = UserService.retrieve_all_users(prj_admin, int(page))[0] members = [m.id for m in members] dao.delete_members_for_project(current_proj.id, members) selected_user_ids = data["users"] dao.add_members_to_project(current_proj.id, selected_user_ids) # Finish operation self.logger.debug("Edit/Save OK for project:" + str(current_proj.id) + ' by user:' + current_user.username) return current_proj
class ProjectFacade: def __init__(self): self.project_service = ProjectService() self.user_service = UserService() self.project_dao = CaseDAO() @staticmethod def retrieve_logged_user_projects(logged_user_id): projects = ProjectService.retrieve_all_user_projects(user_id=logged_user_id) return [ProjectDto(project) for project in projects] def create_project(self, logged_user, project_name, project_description): self.project_service.store_project(logged_user, True, None, name=project_name, description=project_description) def get_datatypes_in_project(self, project_gid): try: project = self.project_service.find_project_lazy_by_gid(project_gid) except ProjectServiceException: raise InvalidIdentifierException() datatypes = self.project_service.get_datatypes_in_project(project.id) return [DataTypeDto(datatype) for datatype in datatypes] def get_project_operations(self, project_gid, page_number): try: project = self.project_service.find_project_lazy_by_gid(project_gid) except ProjectServiceException: raise InvalidIdentifierException() _, _, operations, pages = self.project_service.retrieve_project_full(project.id, current_page=int(page_number)) return [OperationDto(operation) for operation in operations], pages def add_members_to_project(self, current_user_id, project_gid, new_members_gid): try: project = self.project_service.find_project_lazy_by_gid(project_gid) except Exception: raise InvalidIdentifierException("Invalid project identifier.") if current_user_id != project.fk_admin: raise AuthorizationRequestException("Your are not allowed to edit given project") new_members_id = [] for gid in new_members_gid: user = self.user_service.get_user_by_gid(gid) if user is None: raise InvalidInputException("Invalid user gid {}".format(gid)) new_members_id.append(user.id) self.project_dao.add_members_to_project(project.id, new_members_id)
def deco(*a, **b): authorization = request.headers[Strings.AUTH_HEADER.value] if Strings.AUTH_HEADER.value in request.headers \ else None if not authorization: raise AuthorizationRequestException() token = authorization.replace(Strings.BEARER.value, "") try: # Load user details kc_user_info = AuthorizationManager.get_keycloak_instance().userinfo(token) external_id = kc_user_info['sub'] db_user = UserService.get_user_by_external_id(external_id) if db_user is None: db_user = UserService().create_external_service_user(kc_user_info) set_current_user(db_user) except KeycloakError as kc_error: try: error_message = json.loads(kc_error.error_message.decode())['error_description'] except (KeyError, TypeError): error_message = kc_error.error_message.decode() raise AuthorizationRequestException(message=error_message, code=kc_error.response_code) return func(*a, **b)
def initialize(skip_import=False, skip_updates=False): """ Initialize when Application is starting. Check for new algorithms or new DataTypes. """ SettingsService().check_db_url(TvbProfile.current.db.DB_URL) # Initialize DB is_db_empty = initialize_startup() # Create Projects storage root in case it does not exist. initialize_storage() # Populate DB algorithms, by introspection start_introspection_time = datetime.now() # Introspection is always done, even if DB was not empty. introspector = Introspector() introspector.introspect() to_invalidate = dao.get_non_validated_entities(start_introspection_time) for entity in to_invalidate: entity.removed = True dao.store_entities(to_invalidate) if not TvbProfile.is_first_run() and not skip_updates: # Create default users. if is_db_empty: dao.store_entity( User(TvbProfile.current.web.admin.SYSTEM_USER_NAME, TvbProfile.current.web.admin.SYSTEM_USER_NAME, None, None, True, None)) UserService().create_user(username=TvbProfile.current.web.admin.ADMINISTRATOR_NAME, display_name=TvbProfile.current.web.admin.ADMINISTRATOR_DISPLAY_NAME, password=TvbProfile.current.web.admin.ADMINISTRATOR_PASSWORD, email=TvbProfile.current.web.admin.ADMINISTRATOR_EMAIL, role=ROLE_ADMINISTRATOR, skip_import=skip_import) # In case actions related to latest code-changes are needed, make sure they are executed. CodeUpdateManager().run_all_updates() # In case the H5 version changed, run updates on all DataTypes thread = None if TvbProfile.current.version.DATA_CHECKED_TO_VERSION < TvbProfile.current.version.DATA_VERSION: thread = threading.Thread(target=FilesUpdateManager().run_all_updates) thread.start() # Clean tvb-first-time-run temporary folder, as we are no longer at the first run: shutil.rmtree(TvbProfile.current.FIRST_RUN_STORAGE, True) return thread
def run_import(project_path): ## If we would know a UserID to have as admin, next step would not be necessary. ## Make sure at least one user exists in TVB DB: user_service = UserService() admins = user_service.get_administrators() if admins: admin = admins[0] else: ## No Admin user was found, we will create one user_service.create_user("admin", "pass", role=model.ROLE_ADMINISTRATOR, email="*****@*****.**", validated=True, skip_import=True) admin = user_service.get_administrators()[0] ## Do the actual import of a project from ZIP: import_service = ImportService() import_service.import_project_structure(project_path, admin.id) print("Project imported successfully. Check the Web UI!")
class BaseController(object): """ This class contains the methods served at the root of the Web site. """ def __init__(self): self.logger = get_logger(self.__class__.__module__) self.user_service = UserService() self.flow_service = FlowService() self.analyze_category_link = '/flow/step_analyzers' self.analyze_adapters = None self.connectivity_tab_link = '/flow/step_connectivity' view_category = self.flow_service.get_visualisers_category() conn_id = self.flow_service.get_algorithm_by_module_and_class( IntrospectionRegistry.CONNECTIVITY_MODULE, IntrospectionRegistry.CONNECTIVITY_CLASS).id connectivity_link = self.get_url_adapter(view_category.id, conn_id) self.connectivity_submenu = [ dict(title="Large Scale Connectivity", link=connectivity_link, subsection=WebStructure.SUB_SECTION_CONNECTIVITY, description= "View Connectivity Regions. Perform Connectivity lesions"), dict(title="Local Connectivity", link='/spatial/localconnectivity/step_1/1', subsection=WebStructure.SUB_SECTION_LOCAL_CONNECTIVITY, description= "Create or view existent Local Connectivity entities.") ] allen_algo = self.flow_service.get_algorithm_by_module_and_class( IntrospectionRegistry.ALLEN_CREATOR_MODULE, IntrospectionRegistry.ALLEN_CREATOR_CLASS) if allen_algo and not allen_algo.removed: # Only add the Allen Creator if AllenSDK is installed allen_link = self.get_url_adapter(allen_algo.fk_category, allen_algo.id) self.connectivity_submenu.append( dict( title="Allen Connectome Builder", link=allen_link, subsection=WebStructure.SUB_SECTION_ALLEN, description= "Download data from Allen dataset and create a mouse connectome" )) self.burst_submenu = [ dict(link='/burst', subsection=WebStructure.SUB_SECTION_BURST, title='Simulation Cockpit', description='Manage simulations'), dict(link='/burst/dynamic', subsection='dynamic', title='Phase plane', description='Configure model dynamics') ] @staticmethod def mark_file_for_delete(file_name, delete_parent_folder=False): """ This method stores provided file name in session, and later on when request is done, all these files/folders are deleted :param file_name: name of the file or folder to be deleted :param delete_parent_folder: specify if the parent folder of the file should be removed too. """ # No processing if no file specified if file_name is None: return files_list = common.get_from_session(FILES_TO_DELETE_ATTR) if files_list is None: files_list = [] common.add2session(FILES_TO_DELETE_ATTR, files_list) # Now add file/folder to list if delete_parent_folder: folder_name = os.path.split(file_name)[0] files_list.append(folder_name) else: files_list.append(file_name) def _mark_selected(self, project): """ Set the project passed as parameter as the selected project. """ previous_project = common.get_current_project() ### Update project stored in selection, with latest Project entity from DB. members = self.user_service.get_users_for_project("", project.id)[1] project.members = members common.remove_from_session(common.KEY_CACHED_SIMULATOR_TREE) common.add2session(common.KEY_PROJECT, project) if previous_project is None or previous_project.id != project.id: ### Clean Burst selection from session in case of a different project. common.remove_from_session(common.KEY_BURST_CONFIG) ### Store in DB new project selection user = common.get_from_session(common.KEY_USER) if user is not None: self.user_service.save_project_to_user(user.id, project.id) ### Display info message about project change self.logger.debug("Selected project is now " + project.name) common.set_info_message("Your current working project is: " + str(project.name)) @staticmethod def get_url_adapter(step_key, adapter_id, back_page=None): """ Compute the URLs for a given adapter. Same URL is used both for GET and POST. """ result_url = '/flow/' + str(step_key) + '/' + str(adapter_id) if back_page is not None: result_url = result_url + "?back_page=" + str(back_page) return result_url @cherrypy.expose def index(self): """ / Path response Redirects to /tvb """ raise cherrypy.HTTPRedirect('/user') @cherrypy.expose() @using_template('user/base_user') def tvb(self, error=False, **data): """ /tvb URL Returns the home page with the messages stored in the user's session. """ self.logger.debug("Unused submit attributes:" + str(data)) template_dictionary = dict(mainContent="../index", title="The Virtual Brain Project") template_dictionary = self._fill_user_specific_attributes( template_dictionary) if common.get_from_session(common.KEY_IS_RESTART): template_dictionary[common.KEY_IS_RESTART] = True common.remove_from_session(common.KEY_IS_RESTART) return self.fill_default_attributes(template_dictionary, error) @cherrypy.expose @using_template('user/base_user') def error(self, **data): """Error page to redirect when something extremely bad happened""" template_specification = dict(mainContent="../error", title="Error page", data=data) template_specification = self._fill_user_specific_attributes( template_specification) return self.fill_default_attributes(template_specification) def _populate_user_and_project(self, template_dictionary, escape_db_operations=False): """ Populate the template dictionary with current logged user (from session). """ logged_user = common.get_logged_user() template_dictionary[common.KEY_USER] = logged_user show_help = logged_user is not None and logged_user.is_online_help_active( ) template_dictionary[common.KEY_SHOW_ONLINE_HELP] = show_help project = common.get_current_project() template_dictionary[common.KEY_PROJECT] = project if project is not None and not escape_db_operations: self.update_operations_count() return template_dictionary @staticmethod def _populate_message(template_dictionary): """ Populate the template dictionary with current message stored in session. Also specify the message type (default INFO). Clear from session current message (to avoid displaying it twice). """ msg = common.pop_message_from_session() template_dictionary.update(msg) return template_dictionary def _populate_menu(self, template_dictionary): """ Populate current template with information for the Left Menu. """ if common.KEY_FIRST_RUN not in template_dictionary: template_dictionary[common.KEY_FIRST_RUN] = False template_dictionary[ common.KEY_LINK_ANALYZE] = self.analyze_category_link template_dictionary[ common.KEY_LINK_CONNECTIVITY_TAB] = self.connectivity_tab_link if common.KEY_BACK_PAGE not in template_dictionary: template_dictionary[common.KEY_BACK_PAGE] = False template_dictionary[ common.KEY_SECTION_TITLES] = WebStructure.WEB_SECTION_TITLES template_dictionary[ common.KEY_SUBSECTION_TITLES] = WebStructure.WEB_SUBSECTION_TITLES return template_dictionary def _populate_section(self, algorithm, result_template, is_burst=True): """ Populate Section and Sub-Section fields from current Algorithm-Group. """ if algorithm.module == IntrospectionRegistry.CONNECTIVITY_MODULE: result_template[ common.KEY_SECTION] = WebStructure.SECTION_CONNECTIVITY result_template[ common.KEY_SUB_SECTION] = WebStructure.SUB_SECTION_CONNECTIVITY result_template[ common.KEY_SUBMENU_LIST] = self.connectivity_submenu elif algorithm.module == IntrospectionRegistry.ALLEN_CREATOR_MODULE: result_template[ common.KEY_SECTION] = WebStructure.SECTION_CONNECTIVITY result_template[ common.KEY_SUB_SECTION] = WebStructure.SUB_SECTION_ALLEN result_template[ common.KEY_SUBMENU_LIST] = self.connectivity_submenu elif algorithm.algorithm_category.display: ## We are having a visualizer: if is_burst: result_template[ common.KEY_SECTION] = WebStructure.SECTION_BURST result_template[common.KEY_SUBMENU_LIST] = self.burst_submenu else: result_template[ common.KEY_SECTION] = WebStructure.SECTION_PROJECT result_template[ common.KEY_SUB_SECTION] = 'view_' + algorithm.subsection_name elif algorithm.algorithm_category.rawinput: ### Upload algorithms result_template[common.KEY_SECTION] = WebStructure.SECTION_PROJECT result_template[ common. KEY_SUB_SECTION] = WebStructure.SUB_SECTION_DATA_STRUCTURE elif 'RAW_DATA' in algorithm.algorithm_category.defaultdatastate: ### Creators result_template[common.KEY_SECTION] = WebStructure.SECTION_STIMULUS result_template[ common. KEY_SUB_SECTION] = WebStructure.SUB_SECTION_STIMULUS_MENU else: ### Analyzers result_template[ common. KEY_SECTION] = algorithm.algorithm_category.displayname.lower( ) result_template[common.KEY_SUB_SECTION] = algorithm.subsection_name result_template[common.KEY_SUBMENU_LIST] = self.analyze_adapters def _fill_user_specific_attributes(self, template_dictionary): """ Attributes needed for base_user template. """ template_dictionary[common.KEY_INCLUDE_TOOLTIP] = False template_dictionary[common.KEY_WRAP_CONTENT_IN_MAIN_DIV] = True template_dictionary[common.KEY_CURRENT_TAB] = 'none' return template_dictionary def fill_default_attributes(self, template_dictionary, escape_db_operations=False): """ Fill into 'template_dictionary' data that we want to have ready in UI. """ template_dictionary = self._populate_user_and_project( template_dictionary, escape_db_operations) template_dictionary = self._populate_message(template_dictionary) template_dictionary = self._populate_menu(template_dictionary) if common.KEY_ERRORS not in template_dictionary: template_dictionary[common.KEY_ERRORS] = {} if common.KEY_FORM_DATA not in template_dictionary: template_dictionary[common.KEY_FORM_DATA] = {} if common.KEY_SUB_SECTION not in template_dictionary and common.KEY_SECTION in template_dictionary: template_dictionary[common.KEY_SUB_SECTION] = template_dictionary[ common.KEY_SECTION] if common.KEY_SUBMENU_LIST not in template_dictionary: template_dictionary[common.KEY_SUBMENU_LIST] = None template_dictionary[ common. KEY_CURRENT_VERSION] = TvbProfile.current.version.BASE_VERSION template_dictionary[ common. KEY_CURRENT_JS_VERSION] = TvbProfile.current.version.BASE_VERSION.replace( ".", "") return template_dictionary def fill_overlay_attributes(self, template_dictionary, title, description, content_template, css_class, tabs_horizontal=None, overlay_indexes=None, tabs_vertical=None): """ This method prepares parameters for rendering overlay (overlay.html) :param title: overlay title :param description: overlay description :param content_template: path&name of the template file which will fill overlay content (without .html) :param css_class: CSS class to be applied on overlay :param tabs_horizontal: list of strings containing names of the tabs spread horizontally :param tabs_vertical: list of strings containing names of the tabs spread vertically """ if template_dictionary is None: template_dictionary = dict() template_dictionary[common.KEY_OVERLAY_TITLE] = title template_dictionary[common.KEY_OVERLAY_DESCRIPTION] = description template_dictionary[ common.KEY_OVERLAY_CONTENT_TEMPLATE] = content_template template_dictionary[common.KEY_OVERLAY_CLASS] = css_class template_dictionary[common.KEY_OVERLAY_TABS_HORIZONTAL] = tabs_horizontal if tabs_horizontal is not None else [] template_dictionary[common.KEY_OVERLAY_TABS_VERTICAL] = tabs_vertical if tabs_vertical is not None else [] if overlay_indexes is not None: template_dictionary[common.KEY_OVERLAY_INDEXES] = overlay_indexes else: template_dictionary[common.KEY_OVERLAY_INDEXES] = list(range(len(tabs_horizontal))) \ if tabs_horizontal is not None else [] template_dictionary[common.KEY_OVERLAY_PAGINATION] = False return template_dictionary @cherrypy.expose @using_template('overlay_blocker') def showBlockerOverlay(self, **data): """ Returns the content of the blocking overlay (covers entire page and do not allow any action) """ return self.fill_default_attributes(dict(data)) def update_operations_count(self): """ If a project is selected, update Operation Numbers in call-out. """ project = common.get_current_project() if project is not None: fns, sta, err, canceled, pending = self.flow_service.get_operation_numbers( project.id) project.operations_finished = fns project.operations_started = sta project.operations_error = err project.operations_canceled = canceled project.operations_pending = pending common.add2session(common.KEY_PROJECT, project)
def store_project(self, current_user, is_create, selected_id, **data): """ We want to create/update a project entity. """ # Validate Unique Name new_name = data["name"] if len(new_name) < 1: raise ProjectServiceException("Invalid project name!") projects_no = dao.count_projects_for_name(new_name, selected_id) if projects_no > 0: err = {'name': 'Please choose another name, this one is used!'} raise formencode.Invalid("Duplicate Name Error", {}, None, error_dict=err) started_operations = dao.get_operation_numbers(selected_id)[1] if started_operations > 0: raise ProjectServiceException("A project can not be renamed while operations are still running!") if is_create: current_proj = Project(new_name, current_user.id, data["description"]) self.structure_helper.get_project_folder(current_proj) else: try: current_proj = dao.get_project_by_id(selected_id) except Exception as excep: self.logger.exception("An error has occurred!") raise ProjectServiceException(str(excep)) if current_proj.name != new_name: project_folder = self.structure_helper.get_project_folder(current_proj) if encryption_handler.encryption_enabled() and not encryption_handler.is_in_usage(project_folder): raise ProjectServiceException( "A project can not be renamed while sync encryption operations are running") self.structure_helper.rename_project_structure(current_proj.name, new_name) encrypted_path = encryption_handler.compute_encrypted_folder_path(project_folder) if os.path.exists(encrypted_path): new_encrypted_path = encryption_handler.compute_encrypted_folder_path( self.structure_helper.get_project_folder(new_name)) os.rename(encrypted_path, new_encrypted_path) current_proj.name = new_name current_proj.description = data["description"] # Commit to make sure we have a valid ID current_proj.refresh_update_date() self.structure_helper.write_project_metadata(current_proj) current_proj = dao.store_entity(current_proj) # Retrieve, to initialize lazy attributes current_proj = dao.get_project_by_id(current_proj.id) # Update share settings on current Project entity visited_pages = [] prj_admin = current_proj.administrator.username if 'visited_pages' in data and data['visited_pages']: visited_pages = data['visited_pages'].split(',') for page in visited_pages: members = UserService.retrieve_users_except([prj_admin], int(page), MEMBERS_PAGE_SIZE)[0] members = [m.id for m in members] dao.delete_members_for_project(current_proj.id, members) selected_user_ids = data["users"] if is_create and current_user.id not in selected_user_ids: # Make the project admin also member of the current project selected_user_ids.append(current_user.id) dao.add_members_to_project(current_proj.id, selected_user_ids) # Finish operation self.logger.debug("Edit/Save OK for project:" + str(current_proj.id) + ' by user:' + current_user.username) return current_proj
class BaseController(object): """ This class contains the methods served at the root of the Web site. """ def __init__(self): self.logger = get_logger(self.__class__.__module__) self.user_service = UserService() self.flow_service = FlowService() analyze_category = self.flow_service.get_launchable_non_viewers() self.analyze_category_link = '/flow/step/' + str(analyze_category.id) self.analyze_adapters = None self.connectivity_tab_link = '/flow/step_connectivity' view_category = self.flow_service.get_visualisers_category() conn_id = self.flow_service.get_algorithm_by_module_and_class(CONNECTIVITY_MODULE, CONNECTIVITY_CLASS)[1].id connectivity_link = self.get_url_adapter(view_category.id, conn_id) self.connectivity_submenu = [dict(title="Large Scale Connectivity", subsection="connectivity", description="View Connectivity Regions. Perform Connectivity lesions", link=connectivity_link), dict(title="Local Connectivity", subsection="local", link='/spatial/localconnectivity/step_1/1', description="Create or view existent Local Connectivity entities.")] self.burst_submenu = [dict(link='/burst', subsection='burst', title='Simulation Cockpit', description='Manage simulations'), dict(link='/burst/dynamic', subsection='dynamic', title='Phase plane', description='Configure model dynamics')] @staticmethod def mark_file_for_delete(file_name, delete_parent_folder=False): """ This method stores provided file name in session, and later on when request is done, all these files/folders are deleted :param file_name: name of the file or folder to be deleted :param delete_parent_folder: specify if the parent folder of the file should be removed too. """ # No processing if no file specified if file_name is None: return files_list = common.get_from_session(FILES_TO_DELETE_ATTR) if files_list is None: files_list = [] common.add2session(FILES_TO_DELETE_ATTR, files_list) # Now add file/folder to list if delete_parent_folder: folder_name = os.path.split(file_name)[0] files_list.append(folder_name) else: files_list.append(file_name) def _mark_selected(self, project): """ Set the project passed as parameter as the selected project. """ previous_project = common.get_current_project() ### Update project stored in selection, with latest Project entity from DB. members = self.user_service.get_users_for_project("", project.id)[1] project.members = members common.remove_from_session(common.KEY_CACHED_SIMULATOR_TREE) common.add2session(common.KEY_PROJECT, project) if previous_project is None or previous_project.id != project.id: ### Clean Burst selection from session in case of a different project. common.remove_from_session(common.KEY_BURST_CONFIG) ### Store in DB new project selection user = common.get_from_session(common.KEY_USER) if user is not None: self.user_service.save_project_to_user(user.id, project.id) ### Display info message about project change self.logger.debug("Selected project is now " + project.name) common.set_info_message("Your current working project is: " + str(project.name)) @staticmethod def get_url_adapter(step_key, adapter_id, back_page=None): """ Compute the URLs for a given adapter. Same URL is used both for GET and POST. """ result_url = '/flow/' + str(step_key) + '/' + str(adapter_id) if back_page is not None: result_url = result_url + "?back_page=" + str(back_page) return result_url @cherrypy.expose def index(self): """ / Path response Redirects to /tvb """ raise cherrypy.HTTPRedirect('/user') @cherrypy.expose() @using_template('user/base_user') def tvb(self, error=False, **data): """ /tvb URL Returns the home page with the messages stored in the user's session. """ self.logger.debug("Unused submit attributes:" + str(data)) template_dictionary = dict(mainContent="../index", title="The Virtual Brain Project") template_dictionary = self._fill_user_specific_attributes(template_dictionary) if common.get_from_session(common.KEY_IS_RESTART): template_dictionary[common.KEY_IS_RESTART] = True common.remove_from_session(common.KEY_IS_RESTART) return self.fill_default_attributes(template_dictionary, error) @cherrypy.expose @using_template('user/base_user') def error(self, **data): """Error page to redirect when something extremely bad happened""" template_specification = dict(mainContent="../error", title="Error page", data=data) template_specification = self._fill_user_specific_attributes(template_specification) return self.fill_default_attributes(template_specification) def _populate_user_and_project(self, template_dictionary, escape_db_operations=False): """ Populate the template dictionary with current logged user (from session). """ logged_user = common.get_logged_user() template_dictionary[common.KEY_USER] = logged_user show_help = logged_user is not None and logged_user.is_online_help_active() template_dictionary[common.KEY_SHOW_ONLINE_HELP] = show_help project = common.get_current_project() template_dictionary[common.KEY_PROJECT] = project if project is not None and not escape_db_operations: self.update_operations_count() return template_dictionary @staticmethod def _populate_message(template_dictionary): """ Populate the template dictionary with current message stored in session. Also specify the message type (default INFO). Clear from session current message (to avoid displaying it twice). """ msg = common.pop_message_from_session() template_dictionary.update(msg) return template_dictionary def _populate_menu(self, template_dictionary): """ Populate current template with information for the Left Menu. """ if common.KEY_FIRST_RUN not in template_dictionary: template_dictionary[common.KEY_FIRST_RUN] = False template_dictionary[common.KEY_LINK_ANALYZE] = self.analyze_category_link template_dictionary[common.KEY_LINK_CONNECTIVITY_TAB] = self.connectivity_tab_link if common.KEY_BACK_PAGE not in template_dictionary: template_dictionary[common.KEY_BACK_PAGE] = False template_dictionary[common.KEY_SECTION_TITLES] = WebStructure.WEB_SECTION_TITLES template_dictionary[common.KEY_SUBSECTION_TITLES] = WebStructure.WEB_SUBSECTION_TITLES return template_dictionary def _populate_section(self, algo_group, result_template, is_burst=True): """ Populate Section and Sub-Section fields from current Algorithm-Group. """ if algo_group.module == CONNECTIVITY_MODULE: result_template[common.KEY_SECTION] = 'connectivity' result_template[common.KEY_SUB_SECTION] = 'connectivity' result_template[common.KEY_SUBMENU_LIST] = self.connectivity_submenu elif algo_group.group_category.display: ## We are having a visualizer: if is_burst: result_template[common.KEY_SECTION] = 'burst' result_template[common.KEY_SUBMENU_LIST] = self.burst_submenu else: result_template[common.KEY_SECTION] = 'project' result_template[common.KEY_SUB_SECTION] = 'view_' + algo_group.subsection_name elif algo_group.group_category.rawinput: ### Upload algorithms result_template[common.KEY_SECTION] = 'project' result_template[common.KEY_SUB_SECTION] = 'data' elif 'RAW_DATA' in algo_group.group_category.defaultdatastate: ### Creators result_template[common.KEY_SECTION] = 'stimulus' result_template[common.KEY_SUB_SECTION] = 'stimulus' else: ### Analyzers result_template[common.KEY_SECTION] = algo_group.group_category.displayname.lower() result_template[common.KEY_SUB_SECTION] = algo_group.subsection_name result_template[common.KEY_SUBMENU_LIST] = self.analyze_adapters def _fill_user_specific_attributes(self, template_dictionary): """ Attributes needed for base_user template. """ template_dictionary[common.KEY_INCLUDE_TOOLTIP] = False template_dictionary[common.KEY_WRAP_CONTENT_IN_MAIN_DIV] = True template_dictionary[common.KEY_CURRENT_TAB] = 'none' return template_dictionary def fill_default_attributes(self, template_dictionary, escape_db_operations=False): """ Fill into 'template_dictionary' data that we want to have ready in UI. """ template_dictionary = self._populate_user_and_project(template_dictionary, escape_db_operations) template_dictionary = self._populate_message(template_dictionary) template_dictionary = self._populate_menu(template_dictionary) if common.KEY_ERRORS not in template_dictionary: template_dictionary[common.KEY_ERRORS] = {} if common.KEY_FORM_DATA not in template_dictionary: template_dictionary[common.KEY_FORM_DATA] = {} if common.KEY_SUB_SECTION not in template_dictionary and common.KEY_SECTION in template_dictionary: template_dictionary[common.KEY_SUB_SECTION] = template_dictionary[common.KEY_SECTION] if common.KEY_SUBMENU_LIST not in template_dictionary: template_dictionary[common.KEY_SUBMENU_LIST] = None template_dictionary[common.KEY_CURRENT_VERSION] = TvbProfile.current.version.BASE_VERSION template_dictionary[common.KEY_CURRENT_JS_VERSION] = TvbProfile.current.version.BASE_VERSION.replace(".", "") return template_dictionary def fill_overlay_attributes(self, template_dictionary, title, description, content_template, css_class, tabs_horizontal=None, overlay_indexes=None, tabs_vertical=None): """ This method prepares parameters for rendering overlay (overlay.html) :param title: overlay title :param description: overlay description :param content_template: path&name of the template file which will fill overlay content (without .html) :param css_class: CSS class to be applied on overlay :param tabs_horizontal: list of strings containing names of the tabs spread horizontally :param tabs_vertical: list of strings containing names of the tabs spread vertically """ if template_dictionary is None: template_dictionary = dict() template_dictionary[common.KEY_OVERLAY_TITLE] = title template_dictionary[common.KEY_OVERLAY_DESCRIPTION] = description template_dictionary[common.KEY_OVERLAY_CONTENT_TEMPLATE] = content_template template_dictionary[common.KEY_OVERLAY_CLASS] = css_class template_dictionary[common.KEY_OVERLAY_TABS_HORIZONTAL] = tabs_horizontal if tabs_horizontal is not None else [] template_dictionary[common.KEY_OVERLAY_TABS_VERTICAL] = tabs_vertical if tabs_vertical is not None else [] if overlay_indexes is not None: template_dictionary[common.KEY_OVERLAY_INDEXES] = overlay_indexes else: template_dictionary[common.KEY_OVERLAY_INDEXES] = range(len(tabs_horizontal)) \ if tabs_horizontal is not None else [] template_dictionary[common.KEY_OVERLAY_PAGINATION] = False return template_dictionary @cherrypy.expose @using_template('overlay_blocker') def showBlockerOverlay(self, **data): """ Returns the content of the blocking overlay (covers entire page and do not allow any action) """ return self.fill_default_attributes(dict(data)) def update_operations_count(self): """ If a project is selected, update Operation Numbers in call-out. """ project = common.get_current_project() if project is not None: fns, sta, err, canceled, pending = self.flow_service.get_operation_numbers(project.id) project.operations_finished = fns project.operations_started = sta project.operations_error = err project.operations_canceled = canceled project.operations_pending = pending common.add2session(common.KEY_PROJECT, project)
class TestUserService(TransactionalTestCase): """ This class contains tests for the tvb.core.services.user_service module. """ NOT_EXISTENT_PROJECT_ID = 43 def transactional_setup_method(self): """ Reset the database before each test . """ self.clean_database() self.user_service = UserService() self.user_service.create_user(username=TvbProfile.current.web.admin.ADMINISTRATOR_NAME, password=TvbProfile.current.web.admin.ADMINISTRATOR_PASSWORD, email=TvbProfile.current.web.admin.ADMINISTRATOR_EMAIL, role=model.ROLE_ADMINISTRATOR, skip_import=True) available_users = dao.get_all_users() if len(available_users) != 1: raise AssertionError("Something went wrong with database initialization!") def transactional_teardown_method(self): """ Reset database at test finish. """ self.delete_project_folders() def test_create_user_happy_flow(self): """ Standard flow for creating a user. """ initial_user_count = dao.get_all_users() data = dict(username="******", password=md5("test_password").hexdigest(), email="*****@*****.**", role="user", comment="") self.user_service.create_user(**data) final_user_count = dao.get_all_users() assert len(initial_user_count) == len(final_user_count) - 1, "User count was not increased after create." inserted_user = dao.get_user_by_name("test_user") assert inserted_user.password == md5("test_password").hexdigest(), "Incorrect password" assert inserted_user.email == "*****@*****.**", "The email inserted is not correct." assert inserted_user.role == "user", "The role inserted is not correct." assert not inserted_user.validated, "User validation is not correct." def test_create_user_empty_password(self): """ Try to create a user with an empty password field. """ data = dict(username="******", password="", email="*****@*****.**", role="user", comment="") with pytest.raises(UsernameException): self.user_service.create_user(**data) def test_create_user_no_password(self): """ Try to create a user with no password data. """ data = dict(username="******", email="*****@*****.**", role="user", comment="") with pytest.raises(UsernameException): self.user_service.create_user(**data) def test_create_user_empty_username(self): """ Try to create a user with an empty username field. """ data = dict(username="", password="******", email="*****@*****.**", role="user", comment="") with pytest.raises(UsernameException): self.user_service.create_user(**data) def test_create_user_no_username(self): """ Try to create a user with no username data. """ data = dict(password="******", email="*****@*****.**", role="user", comment="") with pytest.raises(UsernameException): self.user_service.create_user(**data) def test_create_user_no_email(self): """ Try to create a user with an empty email field. """ data = dict(username="******", password="******", email="", role="user", comment="") with pytest.raises(UsernameException): self.user_service.create_user(**data) def test_reset_password_happy_flow(self): """ Test method for the reset password method. Happy flow. """ data = dict(username="******", password=md5("test_password").hexdigest(), email="*****@*****.**", role="user", comment="") self.user_service.create_user(**data) inserted_user = dao.get_user_by_name("test_user") assert inserted_user.password == md5("test_password").hexdigest(), "Incorrect password" reset_pass_data = dict(username="******", email="*****@*****.**") self.user_service.reset_password(**reset_pass_data) inserted_user = dao.get_user_by_name("test_user") assert inserted_user.password != md5("test_password"), "Password not reset for some reason!" def test_reset_pass_wrong_email(self): """ Test method for the reset password method. Email is not valid, should raise exception """ data = dict(username="******", password=md5("test_password").hexdigest(), email="*****@*****.**", role="user", comment="") self.user_service.create_user(**data) inserted_user = dao.get_user_by_name("test_user") assert inserted_user.password == md5("test_password").hexdigest(), "Incorrect password" reset_pass_data = dict(username="******", email="*****@*****.**") with pytest.raises(UsernameException): self.user_service.reset_password(**reset_pass_data) def test_change_password_happy_flow(self): """ Test method for the change password method. Happy flow. """ inserted_user = self._prepare_user_for_change_pwd() self.user_service.edit_user(inserted_user, md5("test_password").hexdigest()) changed_user = dao.get_user_by_name("test_user") assert changed_user.password == md5("new_test_password").hexdigest(), "The password did not change." def test_change_password_wrong_old(self): """ Test method for the change password method. Old password is wrong, should return false. """ inserted_user = self._prepare_user_for_change_pwd() params = dict(edited_user=inserted_user, old_password=md5("wrong_old_pwd").hexdigest()) with pytest.raises(UsernameException): self.user_service.edit_user(**params) user = dao.get_user_by_name("test_user") assert user.password == md5("test_password").hexdigest(), "The password should have not been changed!" def _prepare_user_for_change_pwd(self): """Private method to prepare password change operation""" data = dict(username="******", password=md5("test_password").hexdigest(), email="*****@*****.**", role="user", comment="") self.user_service.create_user(**data) self.user_service.validate_user("test_user") inserted_user = dao.get_user_by_name("test_user") assert inserted_user.password == md5("test_password").hexdigest(), "The password inserted is not correct." inserted_user.password = md5('new_test_password').hexdigest() return inserted_user def test_is_username_valid(self): """ Test the method that checks if a userName is valid or not (if it already exists in the database the userName is not valid). """ user = model.User("test_user", "test_pass", "*****@*****.**", False, "user") dao.store_entity(user) assert not self.user_service.is_username_valid("test_user"), "Should be False but got True" assert self.user_service.is_username_valid("test_user2"), "Should be True but got False" def test_validate_user_happy_flow(self): """ Standard flow for a validate user action. """ user = model.User("test_user", "test_pass", "*****@*****.**", False, "user") dao.store_entity(user) assert self.user_service.validate_user("test_user"), "Validation failed when it shouldn't have." def test_validate_user_validated(self): """ Flow for trying to validate a user that was already validated. """ user = model.User("test_user", "test_pass", "*****@*****.**", True, "user") dao.store_entity(user) assert not self.user_service.validate_user("test_user"), "Validation invalid." def test_validate_user_non_existent(self): """ Flow for trying to validate a user that doesn't exist in the database. """ user = model.User("test_user", "test_pass", "*****@*****.**", True, "user") dao.store_entity(user) assert not self.user_service.validate_user("test_user2"), "Validation done even tho user is non-existent" def test_check_login_happy_flow(self): """ Standard login flow with a valid username and password. """ user = model.User("test_user", md5("test_pass").hexdigest(), "*****@*****.**", True, "user") dao.store_entity(user) available_users = dao.get_all_users() assert 2 == len(available_users) assert self.user_service.check_login("test_user", "test_pass") is not None, "Login failed when it shouldn't." def test_check_login_bad_pass(self): """ Flow for entering a bad/invalid password. """ user = model.User("test_user", md5("test_pass").hexdigest(), "*****@*****.**", True, "user") dao.store_entity(user) available_users = dao.get_all_users() assert 2 == len(available_users) assert self.user_service.check_login("test_user", "bad_pass") is None, "Login succeeded with bad password." def test_check_login_bad_user(self): """ Flow for entering a bad/invalid username. """ user = model.User("test_user", md5("test_pass").hexdigest(), "*****@*****.**", True, "user") dao.store_entity(user) available_users = dao.get_all_users() assert 2 == len(available_users) assert self.user_service.check_login("bad_user", "test_pass") is None, "Login succeeded with bad userName." def test_get_users_for_project(self): """ Get all members of a project except the current user. """ user_1 = model.User("test_user1", "test_pass", "*****@*****.**", False, "user") dao.store_entity(user_1) user_2 = model.User("test_user2", "test_pass", "*****@*****.**", False, "user") dao.store_entity(user_2) user_3 = model.User("test_user3", "test_pass", "*****@*****.**", False, "user") dao.store_entity(user_3) user_4 = model.User("test_user4", "test_pass", "*****@*****.**", False, "user") dao.store_entity(user_4) user_5 = model.User("test_user5", "test_pass", "*****@*****.**", False, "user") dao.store_entity(user_5) admin = dao.get_user_by_name("test_user1") member1 = dao.get_user_by_name("test_user2") member2 = dao.get_user_by_name("test_user5") data = dict(name="test_proj", description="test_desc", users=[member1.id, member2.id]) project = ProjectService().store_project(admin, True, None, **data) all_users, members, pag = self.user_service.get_users_for_project(admin.username, project.id) assert len(members) == 2, "More members than there should be." assert len(all_users) == 5, "Admin should not be viewed as member. " \ "Neither should users that were not part of the project's users list." assert pag == 1, "Invalid total pages number." for user in all_users: assert user.username != admin.username, "Admin is in members!" def test_get_users_second_page(self): """ Try to get the second page of users for a given project """ for i in range(USERS_PAGE_SIZE + 3): exec 'user_' + str(i) + '= model.User("test_user' + str( i) + '", "test_pass", "*****@*****.**", False, "user")' exec "dao.store_entity(user_" + str(i) + ")" for i in range(USERS_PAGE_SIZE + 3): exec 'member' + str(i) + '=dao.get_user_by_name("test_user' + str(i) + '")' admin = dao.get_user_by_name("test_user1") data = dict(name='test_proj', description='test_desc', users=[eval('member' + str(i) + '.id') for i in range(USERS_PAGE_SIZE + 3)]) project = ProjectService().store_project(admin, True, None, **data) page_users, all_users, pag = self.user_service.get_users_for_project(admin.username, project.id, 2) assert len(page_users) == (USERS_PAGE_SIZE + 3) % USERS_PAGE_SIZE assert len(all_users) == USERS_PAGE_SIZE + 3, 'Not all members returned' assert pag == 2, 'Invalid page number returned' def test_get_users_second_page_del(self): """ Try to get the second page of users for a given project where only one user on last page. Then delete that user. """ for i in range(USERS_PAGE_SIZE + 1): exec 'user_' + str(i) + '= model.User("test_user' + str(i) + \ '", "test_pass", "*****@*****.**", False, "user")' exec "dao.store_entity(user_" + str(i) + ")" for i in range(USERS_PAGE_SIZE + 1): exec 'member' + str(i) + '=dao.get_user_by_name("test_user' + str(i) + '")' admin = dao.get_user_by_name("test_user1") data = dict(name='test_proj', description='test_desc', users=[eval('member' + str(i) + '.id') for i in range(USERS_PAGE_SIZE + 1)]) project = ProjectService().store_project(admin, True, None, **data) page_users, all_users, pag = self.user_service.get_users_for_project(admin.username, project.id, 2) assert len(page_users) == 1, 'Paging not working properly' assert len(all_users) == USERS_PAGE_SIZE + 1, 'Not all members returned' assert pag == 2, 'Invalid page number returned' self.user_service.delete_user(member2.id) page_users, all_users, pag = self.user_service.get_users_for_project(admin.username, project.id, 2) assert len(page_users) == 0, 'Paging not working properly' assert len(all_users) == USERS_PAGE_SIZE, 'Not all members returned' assert pag == 1, 'Invalid page number returned' page_users, all_users, pag = self.user_service.get_users_for_project(admin.username, project.id, 1) assert len(page_users) == USERS_PAGE_SIZE, 'Paging not working properly' assert len(all_users) == USERS_PAGE_SIZE, 'Not all members returned' assert pag == 1, 'Invalid page number returned' def test_edit_user_happy_flow(self): """ Test the method of editing a user. """ data = dict(username="******", password=md5("test_password").hexdigest(), email="*****@*****.**", role="user", comment="") self.user_service.create_user(**data) inserted_user = dao.get_user_by_name("test_user") assert inserted_user.password == md5("test_password").hexdigest(), "Incorrect password" inserted_user.role = "new_role" inserted_user.validated = 1 self.user_service.edit_user(inserted_user) changed_user = dao.get_user_by_name("test_user") assert changed_user.role == "new_role", "role unchanged" assert changed_user.validated == 1, "user not validated" def test_get_users_when_no_projects(self): """ Assert exception is thrown when no project is found gor the given ID. """ with pytest.raises(UsernameException): self.user_service.get_users_for_project(TvbProfile.current.web.admin.ADMINISTRATOR_NAME, self.NOT_EXISTENT_PROJECT_ID)
def get_users(except_username, page_no, page_size): user_list, pages_no = UserService.retrieve_users_except( [except_username], page_no, page_size) return [UserDto(user) for user in user_list], pages_no
def __init__(self): self.logger = get_logger(self.__class__.__module__) self.operation_service = OperationService() self.project_service = ProjectService() self.user_service = UserService()
def __init__(self): self.project_service = ProjectService() self.user_service = UserService() self.project_dao = CaseDAO()
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.project_service = ProjectService() self.user_service = UserService() self.project_dao = CaseDAO()
def get(self): """ :return a list of system's users """ users = UserService.fetch_all_users(page_size=USERS_PAGE_SIZE) return [UserDto(user) for user in users]
class UserServiceTest(TransactionalTestCase): """ This class contains tests for the tvb.core.services.user_service module. """ def setUp(self): """ Reset the database before each test . """ self.clean_database() self.user_service = UserService() self.user_service.create_user( username=TvbProfile.current.web.admin.ADMINISTRATOR_NAME, password=TvbProfile.current.web.admin.ADMINISTRATOR_PASSWORD, email=TvbProfile.current.web.admin.ADMINISTRATOR_EMAIL, role=model.ROLE_ADMINISTRATOR) available_users = dao.get_all_users() if len(available_users) != 1: self.fail("Something went wrong with database initialization!") def tearDown(self): """ Reset database at test finish. """ self.delete_project_folders() def test_create_user_happy_flow(self): """ Standard flow for creating a user. """ initial_user_count = dao.get_all_users() data = dict(username="******", password=md5("test_password").hexdigest(), email="*****@*****.**", role="user", comment="") self.user_service.create_user(**data) final_user_count = dao.get_all_users() self.assertEqual(len(initial_user_count), len(final_user_count) - 1, "User count was not increased after create.") inserted_user = dao.get_user_by_name("test_user") self.assertEqual(inserted_user.password, md5("test_password").hexdigest(), "Incorrect password") self.assertEqual(inserted_user.email, "*****@*****.**", "The email inserted is not correct.") self.assertEqual(inserted_user.role, "user", "The role inserted is not correct.") self.assertFalse(inserted_user.validated, "User validation is not correct.") def test_create_user_empty_password(self): """ Try to create a user with an empty password field. """ data = dict(username="******", password="", email="*****@*****.**", role="user", comment="") self.assertRaises(UsernameException, self.user_service.create_user, **data) def test_create_user_no_password(self): """ Try to create a user with no password data. """ data = dict(username="******", email="*****@*****.**", role="user", comment="") self.assertRaises(UsernameException, self.user_service.create_user, **data) def test_create_user_empty_username(self): """ Try to create a user with an empty username field. """ data = dict(username="", password="******", email="*****@*****.**", role="user", comment="") self.assertRaises(UsernameException, self.user_service.create_user, **data) def test_create_user_no_username(self): """ Try to create a user with no username data. """ data = dict(password="******", email="*****@*****.**", role="user", comment="") self.assertRaises(UsernameException, self.user_service.create_user, **data) def test_create_user_no_email(self): """ Try to create a user with an empty email field. """ data = dict(username="******", password="******", email="", role="user", comment="") self.assertRaises(UsernameException, self.user_service.create_user, **data) def test_reset_password_happy_flow(self): """ Test method for the reset password method. Happy flow. """ data = dict(username="******", password=md5("test_password").hexdigest(), email="*****@*****.**", role="user", comment="") self.user_service.create_user(**data) inserted_user = dao.get_user_by_name("test_user") self.assertEqual(inserted_user.password, md5("test_password").hexdigest(), "Incorrect password") reset_pass_data = dict(username="******", email="*****@*****.**") self.user_service.reset_password(**reset_pass_data) inserted_user = dao.get_user_by_name("test_user") self.assertNotEqual(inserted_user.password, md5("test_password"), "Password not reset for some reason!") def test_reset_pass_wrong_email(self): """ Test method for the reset password method. Email is not valid, should raise exception """ data = dict(username="******", password=md5("test_password").hexdigest(), email="*****@*****.**", role="user", comment="") self.user_service.create_user(**data) inserted_user = dao.get_user_by_name("test_user") self.assertEqual(inserted_user.password, md5("test_password").hexdigest(), "Incorrect password") reset_pass_data = dict(username="******", email="*****@*****.**") self.assertRaises(UsernameException, self.user_service.reset_password, **reset_pass_data) def test_change_password_happy_flow(self): """ Test method for the change password method. Happy flow. """ inserted_user = self._prepare_user_for_change_pwd() self.user_service.edit_user(inserted_user, md5("test_password").hexdigest()) changed_user = dao.get_user_by_name("test_user") self.assertEqual(changed_user.password, md5("new_test_password").hexdigest(), "The password did not change.") def test_change_password_wrong_old(self): """ Test method for the change password method. Old password is wrong, should return false. """ inserted_user = self._prepare_user_for_change_pwd() params = dict(edited_user=inserted_user, old_password=md5("wrong_old_pwd").hexdigest()) self.assertRaises(UsernameException, self.user_service.edit_user, **params) user = dao.get_user_by_name("test_user") self.assertEqual(user.password, md5("test_password").hexdigest(), "The password should have not been changed!") def _prepare_user_for_change_pwd(self): """Private method to prepare password change operation""" data = dict(username="******", password=md5("test_password").hexdigest(), email="*****@*****.**", role="user", comment="") self.user_service.create_user(**data) self.user_service.validate_user("test_user") inserted_user = dao.get_user_by_name("test_user") self.assertEqual(inserted_user.password, md5("test_password").hexdigest(), "The password inserted is not correct.") inserted_user.password = md5('new_test_password').hexdigest() return inserted_user def test_is_username_valid(self): """ Test the method that checks if a userName is valid or not (if it already exists in the database the userName is not valid). """ user = model.User("test_user", "test_pass", "*****@*****.**", False, "user") dao.store_entity(user) self.assertFalse(self.user_service.is_username_valid("test_user"), "Should be False but got True") self.assertTrue(self.user_service.is_username_valid("test_user2"), "Should be True but got False") def test_validate_user_happy_flow(self): """ Standard flow for a validate user action. """ user = model.User("test_user", "test_pass", "*****@*****.**", False, "user") dao.store_entity(user) self.assertTrue(self.user_service.validate_user("test_user"), "Validation failed when it shouldn't have.") def test_validate_user_validated(self): """ Flow for trying to validate a user that was already validated. """ user = model.User("test_user", "test_pass", "*****@*****.**", True, "user") dao.store_entity(user) self.assertFalse(self.user_service.validate_user("test_user"), "Validation invalid.") def test_validate_user_non_existent(self): """ Flow for trying to validate a user that doesn't exist in the database. """ user = model.User("test_user", "test_pass", "*****@*****.**", True, "user") dao.store_entity(user) self.assertFalse(self.user_service.validate_user("test_user2"), "Validation done even tho user is non-existent") def test_check_login_happy_flow(self): """ Standard login flow with a valid username and password. """ user = model.User("test_user", md5("test_pass").hexdigest(), "*****@*****.**", True, "user") dao.store_entity(user) available_users = dao.get_all_users() if len(available_users) != 2: self.fail("Something went wrong with database reset!") self.assertTrue( self.user_service.check_login("test_user", "test_pass") is not None, "Login failed when it shouldn't.") def test_check_login_bad_pass(self): """ Flow for entering a bad/invalid password. """ user = model.User("test_user", md5("test_pass").hexdigest(), "*****@*****.**", True, "user") dao.store_entity(user) available_users = dao.get_all_users() if len(available_users) != 2: self.fail("Something went wrong with database reset!") self.assertTrue( self.user_service.check_login("test_user", "bad_pass") is None, "Login succeeded with bad password.") def test_check_login_bad_user(self): """ Flow for entering a bad/invalid username. """ user = model.User("test_user", md5("test_pass").hexdigest(), "*****@*****.**", True, "user") dao.store_entity(user) available_users = dao.get_all_users() if len(available_users) != 2: self.fail("Something went wrong with database reset!") self.assertTrue( self.user_service.check_login("bad_user", "test_pass") is None, "Login succeeded with bad userName.") def test_get_users_for_project(self): """ Get all members of a project except the current user. """ user_1 = model.User("test_user1", "test_pass", "*****@*****.**", False, "user") dao.store_entity(user_1) user_2 = model.User("test_user2", "test_pass", "*****@*****.**", False, "user") dao.store_entity(user_2) user_3 = model.User("test_user3", "test_pass", "*****@*****.**", False, "user") dao.store_entity(user_3) user_4 = model.User("test_user4", "test_pass", "*****@*****.**", False, "user") dao.store_entity(user_4) user_5 = model.User("test_user5", "test_pass", "*****@*****.**", False, "user") dao.store_entity(user_5) admin = dao.get_user_by_name("test_user1") member1 = dao.get_user_by_name("test_user2") member2 = dao.get_user_by_name("test_user5") data = dict(name="test_proj", description="test_desc", users=[member1.id, member2.id]) project = ProjectService().store_project(admin, True, None, **data) all_users, members, pag = self.user_service.get_users_for_project( admin.username, project.id) self.assertEquals(len(members), 2, "More members than there should be.") self.assertEquals( len(all_users), 5, "Admin should not be viewed as member. " "Neither should users that were not part of the project's users list." ) self.assertEqual(pag, 1, "Invalid total pages number.") for user in all_users: self.assertNotEqual(user.username, admin.username, "Admin is in members!") def test_get_users_second_page(self): """ Try to get the second page of users for a given project """ for i in range(USERS_PAGE_SIZE + 3): exec 'user_' + str(i) + '= model.User("test_user' + str( i) + '", "test_pass", "*****@*****.**", False, "user")' exec "dao.store_entity(user_" + str(i) + ")" for i in range(USERS_PAGE_SIZE + 3): exec 'member' + str(i) + '=dao.get_user_by_name("test_user' + str( i) + '")' admin = dao.get_user_by_name("test_user1") data = dict(name='test_proj', description='test_desc', users=[ eval('member' + str(i) + '.id') for i in range(USERS_PAGE_SIZE + 3) ]) project = ProjectService().store_project(admin, True, None, **data) page_users, all_users, pag = self.user_service.get_users_for_project( admin.username, project.id, 2) self.assertEqual(len(page_users), (USERS_PAGE_SIZE + 3) % USERS_PAGE_SIZE) self.assertEqual(len(all_users), USERS_PAGE_SIZE + 3, 'Not all members returned') self.assertEqual(pag, 2, 'Invalid page number returned') def test_get_users_second_page_del(self): """ Try to get the second page of users for a given project where only one user on last page. Then delete that user. """ for i in range(USERS_PAGE_SIZE + 1): exec 'user_' + str(i) + '= model.User("test_user' + str(i) + \ '", "test_pass", "*****@*****.**", False, "user")' exec "dao.store_entity(user_" + str(i) + ")" for i in range(USERS_PAGE_SIZE + 1): exec 'member' + str(i) + '=dao.get_user_by_name("test_user' + str( i) + '")' admin = dao.get_user_by_name("test_user1") data = dict(name='test_proj', description='test_desc', users=[ eval('member' + str(i) + '.id') for i in range(USERS_PAGE_SIZE + 1) ]) project = ProjectService().store_project(admin, True, None, **data) page_users, all_users, pag = self.user_service.get_users_for_project( admin.username, project.id, 2) self.assertEqual(len(page_users), 1, 'Paging not working properly') self.assertEqual(len(all_users), USERS_PAGE_SIZE + 1, 'Not all members returned') self.assertEqual(pag, 2, 'Invalid page number returned') self.user_service.delete_user(member2.id) page_users, all_users, pag = self.user_service.get_users_for_project( admin.username, project.id, 2) self.assertEqual(len(page_users), 0, 'Paging not working properly') self.assertEqual(len(all_users), USERS_PAGE_SIZE, 'Not all members returned') self.assertEqual(pag, 1, 'Invalid page number returned') page_users, all_users, pag = self.user_service.get_users_for_project( admin.username, project.id, 1) self.assertEqual(len(page_users), USERS_PAGE_SIZE, 'Paging not working properly') self.assertEqual(len(all_users), USERS_PAGE_SIZE, 'Not all members returned') self.assertEqual(pag, 1, 'Invalid page number returned') def test_edit_user_happy_flow(self): """ Test the method of editing a user. """ data = dict(username="******", password=md5("test_password").hexdigest(), email="*****@*****.**", role="user", comment="") self.user_service.create_user(**data) inserted_user = dao.get_user_by_name("test_user") self.assertEqual(inserted_user.password, md5("test_password").hexdigest(), "Incorrect password") inserted_user.role = "new_role" inserted_user.validated = 1 self.user_service.edit_user(inserted_user) changed_user = dao.get_user_by_name("test_user") self.assertEqual(changed_user.role, "new_role", "role unchanged") self.assertEqual(changed_user.validated, 1, "user not validated") def test_create_project_no_projects(self): """ Standard flow for creating a new project. """ self.assertRaises(UsernameException, self.user_service.get_users_for_project, "admin", 1)
class TestUserService(TransactionalTestCase): """ This class contains tests for the tvb.core.services.user_service module. """ NOT_EXISTENT_PROJECT_ID = 43 def transactional_setup_method(self): """ Reset the database before each test . """ self.clean_database() self.user_service = UserService() self.user_service.create_user(username=TvbProfile.current.web.admin.ADMINISTRATOR_NAME, display_name=TvbProfile.current.web.admin.ADMINISTRATOR_DISPLAY_NAME, password=TvbProfile.current.web.admin.ADMINISTRATOR_PASSWORD, email=TvbProfile.current.web.admin.ADMINISTRATOR_EMAIL, role=model_project.ROLE_ADMINISTRATOR, skip_import=True) available_users = dao.get_all_users() if len(available_users) != 1: raise AssertionError("Something went wrong with database initialization!") def transactional_teardown_method(self): """ Reset database at test finish. """ self.delete_project_folders() def test_create_user_happy_flow(self): """ Standard flow for creating a user. """ initial_user_count = dao.get_all_users() data = dict(username="******", display_name="test_name", password=hash_password("test_password"), email="*****@*****.**", role="user", comment="") self.user_service.create_user(**data) final_user_count = dao.get_all_users() assert len(initial_user_count) == len(final_user_count) - 1, "User count was not increased after create." inserted_user = dao.get_user_by_name("test_user") assert inserted_user.password == hash_password("test_password"), "Incorrect password" assert inserted_user.email == "*****@*****.**", "The email inserted is not correct." assert inserted_user.role == "user", "The role inserted is not correct." assert not inserted_user.validated, "User validation is not correct." def test_create_user_empty_password(self): """ Try to create a user with an empty password field. """ data = dict(username="******", display_name="test_name", password="", email="*****@*****.**", role="user", comment="") with pytest.raises(UsernameException): self.user_service.create_user(**data) def test_create_user_no_password(self): """ Try to create a user with no password data. """ data = dict(username="******", display_name="test_name", email="*****@*****.**", role="user", comment="") with pytest.raises(UsernameException): self.user_service.create_user(**data) def test_create_user_empty_username(self): """ Try to create a user with an empty username field. """ data = dict(username="", display_name="test_name", password="******", email="*****@*****.**", role="user", comment="") with pytest.raises(UsernameException): self.user_service.create_user(**data) def test_create_user_no_username(self): """ Try to create a user with no username data. """ data = dict(password="******", display_name="test_name", email="*****@*****.**", role="user", comment="") with pytest.raises(UsernameException): self.user_service.create_user(**data) def test_create_user_no_email(self): """ Try to create a user with an empty email field. """ data = dict(username="******", display_name="test_name", password="******", email="", role="user", comment="") with pytest.raises(UsernameException): self.user_service.create_user(**data) def test_reset_password_happy_flow(self): """ Test method for the reset password method. Happy flow. """ data = dict(username="******", display_name="test_name", password=hash_password("test_password"), email="*****@*****.**", role="user", comment="") self.user_service.create_user(**data) inserted_user = dao.get_user_by_name("test_user") assert inserted_user.password == hash_password("test_password"), "Incorrect password" reset_pass_data = dict(username="******", email="*****@*****.**") self.user_service.reset_password(**reset_pass_data) inserted_user = dao.get_user_by_name("test_user") assert inserted_user.password != hash_password("test_password"), "Password not reset for some reason!" def test_reset_pass_wrong_email(self): """ Test method for the reset password method. Email is not valid, should raise exception """ data = dict(username="******", display_name="test_name", password=hash_password("test_password"), email="*****@*****.**", role="user", comment="") self.user_service.create_user(**data) inserted_user = dao.get_user_by_name("test_user") assert inserted_user.password == hash_password("test_password"), "Incorrect password" reset_pass_data = dict(username="******", email="*****@*****.**") with pytest.raises(UsernameException): self.user_service.reset_password(**reset_pass_data) def test_change_password_happy_flow(self): """ Test method for the change password method. Happy flow. """ inserted_user = self._prepare_user_for_change_pwd() self.user_service.edit_user(inserted_user, hash_password("test_password")) changed_user = dao.get_user_by_name("test_user") assert changed_user.password == hash_password("new_test_password"), "The password did not change." def test_change_password_wrong_old(self): """ Test method for the change password method. Old password is wrong, should return false. """ inserted_user = self._prepare_user_for_change_pwd() params = dict(edited_user=inserted_user, old_password=hash_password("wrong_old_pwd")) with pytest.raises(UsernameException): self.user_service.edit_user(**params) user = dao.get_user_by_name("test_user") assert user.password == hash_password("test_password"), "The password should have not been changed!" def _prepare_user_for_change_pwd(self): """Private method to prepare password change operation""" data = dict(username="******", display_name="test_name", password=hash_password("test_password"), email="*****@*****.**", role="user", comment="") self.user_service.create_user(**data) self.user_service.validate_user("test_user") inserted_user = dao.get_user_by_name("test_user") assert inserted_user.password == hash_password("test_password"), "The password inserted is not correct." inserted_user.password = hash_password("new_test_password") return inserted_user def test_is_username_valid(self): """ Test the method that checks if a userName is valid or not (if it already exists in the database the userName is not valid). """ user = model_project.User("test_user", "test_name", "test_pass", "*****@*****.**", False, "user") dao.store_entity(user) assert not self.user_service.is_username_valid("test_user"), "Should be False but got True" assert self.user_service.is_username_valid("test_user2"), "Should be True but got False" def test_validate_user_happy_flow(self): """ Standard flow for a validate user action. """ user = model_project.User("test_user", "test_name", "test_pass", "*****@*****.**", False, "user") dao.store_entity(user) assert self.user_service.validate_user("test_user"), "Validation failed when it shouldn't have." def test_validate_user_validated(self): """ Flow for trying to validate a user that was already validated. """ user = model_project.User("test_user", "test_name", "test_pass", "*****@*****.**", True, "user") dao.store_entity(user) assert not self.user_service.validate_user("test_user"), "Validation invalid." def test_validate_user_non_existent(self): """ Flow for trying to validate a user that doesn't exist in the database. """ user = model_project.User("test_user", "test_name", "test_pass", "*****@*****.**", True, "user") dao.store_entity(user) assert not self.user_service.validate_user("test_user2"), "Validation done even tho user is non-existent" def test_check_login_happy_flow(self): """ Standard login flow with a valid username and password. """ user = model_project.User("test_user", 'test_name', hash_password("test_pass"), "*****@*****.**", True, "user") dao.store_entity(user) available_users = dao.get_all_users() assert 2 == len(available_users) assert self.user_service.check_login("test_user", "test_pass") is not None, "Login failed when it shouldn't." def test_check_login_bad_pass(self): """ Flow for entering a bad/invalid password. """ user = model_project.User("test_user", 'test_user_name', hash_password("test_pass"), "*****@*****.**", True, "user") dao.store_entity(user) available_users = dao.get_all_users() assert 2 == len(available_users) assert self.user_service.check_login("test_user", "bad_pass") is None, "Login succeeded with bad password." def test_check_login_bad_user(self): """ Flow for entering a bad/invalid username. """ user = model_project.User("test_user", 'test_name', hash_password("test_pass"), "*****@*****.**", True, "user") dao.store_entity(user) available_users = dao.get_all_users() assert 2 == len(available_users) assert self.user_service.check_login("bad_user", "test_pass") is None, "Login succeeded with bad userName." def test_get_users_for_project(self): """ Get all members of a project except the current user. """ user_1 = model_project.User("test_user1", "test_name1", "test_pass", "*****@*****.**", False, "user") dao.store_entity(user_1) user_2 = model_project.User("test_user2", "test_name2", "test_pass", "*****@*****.**", False, "user") dao.store_entity(user_2) user_3 = model_project.User("test_user3", "test_name3", "test_pass", "*****@*****.**", False, "user") dao.store_entity(user_3) user_4 = model_project.User("test_user4", "test_name4", "test_pass", "*****@*****.**", False, "user") dao.store_entity(user_4) user_5 = model_project.User("test_user5", "test_name5", "test_pass", "*****@*****.**", False, "user") dao.store_entity(user_5) admin = dao.get_user_by_name("test_user1") member1 = dao.get_user_by_name("test_user2") member2 = dao.get_user_by_name("test_user5") data = dict(name="test_proj", description="test_desc", users=[member1.id, member2.id]) project = ProjectService().store_project(admin, True, None, **data) all_users, members, pag = self.user_service.get_users_for_project(admin.username, project.id) assert len(members) == 2, "More members than there should be." assert len(all_users) == 5, "Admin should not be viewed as member. " \ "Neither should users that were not part of the project's users list." assert pag == 1, "Invalid total pages number." for user in all_users: assert user.username != admin.username, "Admin is in members!" def test_get_users_second_page(self): """ Try to get the second page of users for a given project """ for i in range(USERS_PAGE_SIZE + 3): exec('user_' + str(i) + '= model_project.User("test_user' + str( i) + '", "test_pass", "*****@*****.**", False, "user")') exec("dao.store_entity(user_" + str(i) + ")") for i in range(USERS_PAGE_SIZE + 3): exec('member' + str(i) + '=dao.get_user_by_name("test_user' + str(i) + '")') admin = dao.get_user_by_name("test_user1") scope = locals() data = dict(name='test_proj', description='test_desc', users=[eval('member' + str(i) + '.id', scope) for i in range(USERS_PAGE_SIZE + 3)]) project = ProjectService().store_project(admin, True, None, **data) page_users, all_users, pag = self.user_service.get_users_for_project(admin.username, project.id, 2) assert len(page_users) == (USERS_PAGE_SIZE + 3) % USERS_PAGE_SIZE assert len(all_users) == USERS_PAGE_SIZE + 3, 'Not all members returned' assert pag == 2, 'Invalid page number returned' def test_get_users_second_page_del(self): """ Try to get the second page of users for a given project where only one user on last page. Then delete that user. """ for i in range(USERS_PAGE_SIZE + 1): exec('user_' + str(i) + '= model_project.User("test_user' + str(i) + \ '", "test_pass", "*****@*****.**", False, "user")') exec("dao.store_entity(user_" + str(i) + ")") for i in range(USERS_PAGE_SIZE + 1): exec('member' + str(i) + '=dao.get_user_by_name("test_user' + str(i) + '")') admin = dao.get_user_by_name("test_user1") scope = locals() data = dict(name='test_proj', description='test_desc', users=[eval('member' + str(i) + '.id', scope) for i in range(USERS_PAGE_SIZE + 1)]) project = ProjectService().store_project(admin, True, None, **data) page_users, all_users, pag = self.user_service.get_users_for_project(admin.username, project.id, 2) assert len(page_users) == 1, 'Paging not working properly' assert len(all_users) == USERS_PAGE_SIZE + 1, 'Not all members returned' assert pag == 2, 'Invalid page number returned' self.user_service.delete_user(scope['member2'].id) page_users, all_users, pag = self.user_service.get_users_for_project(admin.username, project.id, 2) assert len(page_users) == 0, 'Paging not working properly' assert len(all_users) == USERS_PAGE_SIZE, 'Not all members returned' assert pag == 1, 'Invalid page number returned' page_users, all_users, pag = self.user_service.get_users_for_project(admin.username, project.id, 1) assert len(page_users) == USERS_PAGE_SIZE, 'Paging not working properly' assert len(all_users) == USERS_PAGE_SIZE, 'Not all members returned' assert pag == 1, 'Invalid page number returned' def test_edit_user_happy_flow(self): """ Test the method of editing a user. """ data = dict(username="******", display_name="test_name", password=hash_password("test_password"), email="*****@*****.**", role="user", comment="") self.user_service.create_user(**data) inserted_user = dao.get_user_by_name("test_user") assert inserted_user.password == hash_password("test_password"), "Incorrect password" inserted_user.role = "new_role" inserted_user.validated = 1 self.user_service.edit_user(inserted_user) changed_user = dao.get_user_by_name("test_user") assert changed_user.role == "new_role", "role unchanged" assert changed_user.validated == 1, "user not validated" def test_get_users_when_no_projects(self): """ Assert exception is thrown when no project is found gor the given ID. """ with pytest.raises(UsernameException): self.user_service.get_users_for_project(TvbProfile.current.web.admin.ADMINISTRATOR_NAME, self.NOT_EXISTENT_PROJECT_ID)