Exemplo n.º 1
0
    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')]
Exemplo n.º 2
0
    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!")
Exemplo n.º 4
0
 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!")
Exemplo n.º 5
0
 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
Exemplo n.º 6
0
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)
Exemplo n.º 7
0
 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()
Exemplo n.º 8
0
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)
Exemplo n.º 9
0
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
Exemplo n.º 10
0
def new_project(name):
    usr = UserService.get_administrators()[0]
    proj = ProjectService().store_project(usr,
                                          True,
                                          None,
                                          name=name,
                                          description=name,
                                          users=[usr])
    return proj
Exemplo n.º 11
0
 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]
Exemplo n.º 12
0
 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
     }
Exemplo n.º 13
0
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!"
Exemplo n.º 14
0
 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!")
Exemplo n.º 15
0
 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
Exemplo n.º 17
0
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)
Exemplo n.º 18
0
    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)
Exemplo n.º 19
0
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
Exemplo n.º 20
0
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!")
Exemplo n.º 21
0
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)
Exemplo n.º 22
0
    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
Exemplo n.º 23
0
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)
            
                    
            
            
            
Exemplo n.º 24
0
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)
Exemplo n.º 25
0
 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
Exemplo n.º 26
0
 def __init__(self):
     self.logger = get_logger(self.__class__.__module__)
     self.operation_service = OperationService()
     self.project_service = ProjectService()
     self.user_service = UserService()
Exemplo n.º 27
0
 def __init__(self):
     self.project_service = ProjectService()
     self.user_service = UserService()
     self.project_dao = CaseDAO()
Exemplo n.º 28
0
def new_project(name):
    usr = UserService.get_administrators()[0]
    proj = ProjectService().store_project(usr, True, None, name=name, description=name, users=[usr])
    return proj
Exemplo n.º 29
0
 def __init__(self, *args, **kwargs):
     super().__init__(*args, **kwargs)
     self.project_service = ProjectService()
     self.user_service = UserService()
     self.project_dao = CaseDAO()
Exemplo n.º 30
0
 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]
Exemplo n.º 31
0
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)
Exemplo n.º 32
0
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)