Exemplo n.º 1
0
    def test_app_links_hide(self):
        """Test visibility of app links with timeline hidden"""
        url = reverse(
            'projectroles:detail', kwargs={'project': self.project.sodar_uuid}
        )
        expected = [
            (self.superuser, len(get_active_plugins())),
            (self.user_owner, len(get_active_plugins()) - 1),
        ]

        self.assert_element_count(expected, url, 'sodar-pr-nav-app-plugin')
Exemplo n.º 2
0
    def get_all_settings(cls, project=None, user=None, post_safe=False):
        """
        Return all setting values. If the value is not found, return
        the default.

        :param project: Project object (can be None)
        :param user: User object (can be None)
        :param post_safe: Whether POST safe values should be returned (bool)
        :return: Dict
        :raise: ValueError if neither project nor user are set
        """
        if not project and not user:
            raise ValueError('Project and user are both unset')

        ret = {}
        app_plugins = get_active_plugins()

        for plugin in app_plugins:
            p_settings = cls.get_setting_defs(APP_SETTING_SCOPE_PROJECT,
                                              plugin=plugin)

            for s_key in p_settings:
                ret['settings.{}.{}'.format(plugin.name,
                                            s_key)] = cls.get_app_setting(
                                                plugin.name, s_key, project,
                                                user, post_safe)

        return ret
Exemplo n.º 3
0
    def get_all_settings(cls, project=None, user=None):
        """
        Return all setting values. If the value is not found, return
        the default.

        :param project: Project object (can be None)
        :param user: User object (can be None)
        :return: Dict
        :raise: ValueError if neither project nor user are set
        """
        cls._check_project_and_user(project, user)

        ret = {}
        app_plugins = get_active_plugins()

        for plugin in app_plugins:
            p_settings = cls.get_setting_defs(plugin,
                                              APP_SETTING_SCOPE_PROJECT)

            for s_key in p_settings:
                ret['settings.{}.{}'.format(plugin.name,
                                            s_key)] = cls.get_app_setting(
                                                plugin.name, s_key, project,
                                                user)

        return ret
def get_site_app_messages(user):
    """Get messages from site apps"""
    plugins = get_active_plugins('site_app')
    ret = []

    for p in plugins:
        ret += p.get_messages(user)

    return ret
Exemplo n.º 5
0
    def get_context_data(self, *args, **kwargs):
        context = super().get_context_data(*args, **kwargs)

        # App plugins
        context['project_plugins'] = get_active_plugins('project_app')
        context['site_plugins'] = get_active_plugins('site_app')
        context['backend_plugins'] = get_active_plugins('backend')

        # Project statistics
        context['project_count'] = Project.objects.filter(
            type=PROJECT_TYPE_PROJECT
        ).count()
        context['category_count'] = Project.objects.filter(
            type=PROJECT_TYPE_CATEGORY
        ).count()

        # User statistics
        context['user_total_count'] = User.objects.all().count()
        context['user_ldap_count'] = User.objects.exclude(
            groups__name__in=['', SYSTEM_USER_GROUP]
        ).count()
        context['user_local_count'] = User.objects.filter(
            groups__name__in=['', SYSTEM_USER_GROUP]
        ).count()
        context['user_admin_count'] = User.objects.filter(
            is_superuser=True
        ).count()

        # Basic site info
        context['site_title'] = settings.SITE_TITLE
        context['site_subtitle'] = settings.SITE_SUBTITLE
        context['site_instance_title'] = settings.SITE_INSTANCE_TITLE

        # Remote site info
        context['site_mode'] = settings.PROJECTROLES_SITE_MODE

        if settings.PROJECTROLES_SITE_MODE == SITE_MODE_SOURCE:
            context['site_target_count'] = RemoteSite.objects.filter(
                mode=SITE_MODE_TARGET
            ).count()

        return context
Exemplo n.º 6
0
    def test_include_none_value(self):
        """Test get_backend_include none attribute check"""
        # TODO: Replace with get_app_plugin once implemented for backend plugins
        backend_plugin = get_active_plugins('backend')[0]
        type(backend_plugin).javascript_url = None
        type(backend_plugin).css_url = None

        self.assertEqual(c_tags.get_backend_include(backend_plugin.name, 'js'),
                         '')
        self.assertEqual(
            c_tags.get_backend_include(backend_plugin.name, 'css'), '')
Exemplo n.º 7
0
    def handle(self, *args, **options):

        if 'sodar_cache' not in settings.ENABLED_BACKEND_PLUGINS:
            logger.error(
                'SodarCache backend not enabled in settings, cancelled!'
            )
            return

        cache_backend = get_backend_api('sodar_cache')

        if not cache_backend:
            logger.error('SodarCache backend plugin not available, cancelled!')
            return

        update_kwargs = {}

        if 'project' in options and options['project']:
            try:
                project = Project.objects.get(sodar_uuid=options['project'])
                update_kwargs['project'] = project
                logger.info(
                    'Limiting sync to project "{}" ({})"'.format(
                        project.title, project.sodar_uuid
                    )
                )

            except Project.DoesNotExist:
                logger.error(
                    'Project not found with UUID={}'.format(options['project'])
                )
                return

            except ValidationError:
                logger.error('Not a valid UUID: {}'.format(options['project']))
                return

        if not update_kwargs:
            logger.info('Synchronizing cache for all projects')

        plugins = get_active_plugins(plugin_type='project_app')

        for plugin in plugins:
            try:
                plugin.update_cache(**update_kwargs)

            except Exception as ex:
                logger.error(
                    'Update failed for plugin "{}": "{}"'.format(
                        plugin.name, ex
                    )
                )

        logger.info('Cache synchronization OK')
Exemplo n.º 8
0
    def setUp(self):
        super().setUp()

        self.sidebar_ids = [
            'sodar-pr-nav-project-detail',
            'sodar-pr-nav-project-roles',
            'sodar-pr-nav-project-update',
        ]

        # Add app plugin navs
        for p in get_active_plugins():
            self.sidebar_ids.append('sodar-pr-nav-app-plugin-{}'.format(p.name))
Exemplo n.º 9
0
    def update_cache(cls, name=None, project=None, user=None):
        """
        Update items by certain name within a project by calling implemented
        functions in project app plugins.

        :param name: Item name to limit update to (string, optional)
        :param project: Project object to limit update to (optional)
        :param user: User object to denote user triggering the update (optional)
        """
        plugins = get_active_plugins(plugin_type='project_app')

        for plugin in plugins:
            plugin.update_cache(name, project, user)
Exemplo n.º 10
0
    def test_include_invalid_url(self):
        """Test get_backend_include file existence check"""
        # TODO: Replace with get_app_plugin once implemented for backend plugins
        backend_plugin = get_active_plugins('backend')[0]

        type(backend_plugin
             ).javascript_url = 'example_backend_app/js/NOT_EXISTING_JS.js'
        type(backend_plugin
             ).css_url = 'example_backend_app/css/NOT_EXISTING_CSS.css'

        self.assertEqual(c_tags.get_backend_include(backend_plugin.name, 'js'),
                         '')
        self.assertEqual(
            c_tags.get_backend_include(backend_plugin.name, 'css'), '')
Exemplo n.º 11
0
    def _get_user_settings(self):
        for plugin in get_active_plugins():
            p_settings = app_settings.get_setting_defs(
                plugin, APP_SETTING_SCOPE_USER, user_modifiable=True
            )

            for s_key, s_val in p_settings.items():
                yield {
                    'label': s_val.get('label')
                    or '{}.{}'.format(plugin.name, s_key),
                    'value': app_settings.get_app_setting(
                        plugin.name, s_key, user=self.request.user
                    ),
                    'description': s_val.get('description'),
                }
Exemplo n.º 12
0
    def _sync_apps(self):
        """Run taskflow synchronization methods in project app plugins"""

        plugins = get_active_plugins(plugin_type='project_app')

        for plugin in plugins:
            sync_data = plugin.get_taskflow_sync_data()
            logger.info('Synchronizing app "{}"...'.format(plugin.name))

            if sync_data:
                self._submit_sync(plugin.name,
                                  sync_data,
                                  raise_exception=False)

            else:
                logger.info('Nothing to synchronize.')
Exemplo n.º 13
0
    def __init__(self, *args, **kwargs):
        #: The user to display the settings for.
        self.user = kwargs.pop('current_user')

        super().__init__(*args, **kwargs)

        # Add settings fields
        self.app_plugins = get_active_plugins()

        for plugin in self.app_plugins:
            p_settings = app_settings.get_setting_defs(plugin,
                                                       APP_SETTING_SCOPE_USER,
                                                       user_modifiable=True)

            for s_key, s_val in p_settings.items():
                s_field = 'settings.{}.{}'.format(plugin.name, s_key)
                field_kwarg = {
                    'required':
                    False,
                    'label':
                    s_val.get('label') or '{}.{}'.format(plugin.name, s_key),
                    'help_text':
                    s_val.get('description'),
                }
                widget_attrs = {
                    'placeholder': s_val.get('placeholder') or None
                }

                if s_val['type'] == 'STRING':
                    self.fields[s_field] = forms.CharField(
                        max_length=APP_SETTING_VAL_MAXLENGTH,
                        widget=forms.TextInput(attrs=widget_attrs),
                        **field_kwarg,
                    )

                elif s_val['type'] == 'INTEGER':
                    self.fields[s_field] = forms.IntegerField(
                        widget=forms.TextInput(attrs=widget_attrs),
                        **field_kwarg,
                    )

                elif s_val['type'] == 'BOOLEAN':
                    self.fields[s_field] = forms.BooleanField(**field_kwarg)

                # Set initial value
                self.initial[s_field] = app_settings.get_app_setting(
                    app_name=plugin.name, setting_name=s_key, user=self.user)
Exemplo n.º 14
0
def get_project_list_columns():
    """Return custom project list columns as a sorted list"""
    cols = []
    i = 0

    for app_plugin in [
            ap for ap in get_active_plugins(plugin_type='project_app')
            if ap.project_list_columns
    ]:
        for k, v in app_plugin.project_list_columns.items():
            v['app_plugin'] = app_plugin
            v['key'] = k
            v['ordering'] = v.get('ordering') or i
            cols.append(v)
            i += 1

    return sorted(cols, key=lambda x: x['ordering'])
Exemplo n.º 15
0
    def test_get_backend_include(self):
        """Test get_backend_include"""
        # TODO: Replace with get_app_plugin once implemented for backend plugins
        backend_plugin = get_active_plugins('backend')[0]

        type(backend_plugin
             ).javascript_url = 'example_backend_app/js/greeting.js'
        type(backend_plugin).css_url = 'example_backend_app/css/greeting.css'

        self.assertEqual(
            c_tags.get_backend_include(backend_plugin.name, 'js'),
            '<script type="text/javascript" '
            'src="/static/example_backend_app/js/greeting.js"></script>',
        )
        self.assertEqual(
            c_tags.get_backend_include(backend_plugin.name, 'css'),
            '<link rel="stylesheet" type="text/css" '
            'href="/static/example_backend_app/css/greeting.css"/>',
        )
Exemplo n.º 16
0
    def get_all_defaults(cls, scope):
        """
        Get all default settings for a scope.

        :param scope:
        :return:
        """
        cls._check_scope(scope)

        ret = {}
        app_plugins = get_active_plugins()

        for plugin in app_plugins:
            p_settings = cls.get_setting_defs(plugin, scope)

            for s_key in p_settings:
                ret['settings.{}.{}'.format(plugin.name,
                                            s_key)] = cls.get_default_setting(
                                                plugin.name, s_key)

        return ret
Exemplo n.º 17
0
    def get_all_defaults(cls, scope, post_safe=False):
        """
        Get all default settings for a scope.

        :param scope: Setting scope (PROJECT, USER or PROJECT_USER)
        :param post_safe: Whether POST safe values should be returned (bool)
        :return: Dict
        """
        cls._check_scope(scope)

        ret = {}
        app_plugins = get_active_plugins()

        for plugin in app_plugins:
            p_settings = cls.get_setting_defs(scope, plugin=plugin)

            for s_key in p_settings:
                ret['settings.{}.{}'.format(plugin.name,
                                            s_key)] = cls.get_default_setting(
                                                plugin.name, s_key, post_safe)

        return ret
Exemplo n.º 18
0
def get_site_apps():
    """Get active site apps"""
    return get_active_plugins('site_app')
Exemplo n.º 19
0
 def setUp(self):
     super().setUp()
     self.plugin_count = len(get_active_plugins())
Exemplo n.º 20
0
    def test_get_project_column_count(self):
        """Test get_project_column_count()"""
        app_plugins = get_active_plugins()

        self.assertEqual(tags.get_project_column_count(app_plugins), 4)
        self.assertEqual(tags.get_project_column_count([]), 2)
Exemplo n.º 21
0
    def handle(self, *args, **options):
        if 'taskflow' not in settings.ENABLED_BACKEND_PLUGINS:
            print_msg('Taskflow not enabled in settings, cancelled!')
            raise CommandError

        taskflow = get_backend_api('taskflow')

        if not taskflow:
            print_msg('Taskflow backend plugin not available, cancelled!')
            raise CommandError

        def submit_sync(app_name, sync_data, raise_exception=False):
            """Submit flows found in an app's sync_data structure"""
            for item in sync_data:
                project = Project.objects.get(sodar_uuid=item['project_uuid'])

                print_msg('Syncing flow "{}" by {} for "{}" ({})'.format(
                    item['flow_name'],
                    app_name,
                    project.title,
                    project.sodar_uuid,
                ))

                try:
                    taskflow.submit(
                        project_uuid=item['project_uuid'],
                        flow_name=item['flow_name'],
                        flow_data=item['flow_data'],
                        targets=TARGETS,
                    )

                except taskflow.FlowSubmitException as ex:
                    print_msg('Exception raised by flow!')
                    print(str(ex))

                    # If we don't want to continue on failure
                    if raise_exception:
                        raise ex

        print_msg('Synchronizing project data with taskflow...')
        print_msg('Target(s) = ' + ', '.join([t for t in TARGETS]))

        # Only sync PROJECT type projects as we (currently) don't have any
        # use for CATEGORY projects in taskflow
        projects = Project.objects.filter(
            type=PROJECT_TYPE_PROJECT).order_by('pk')

        ####################
        # Projectroles sync
        ####################

        # NOTE: For projectroles, this is done here as projects must be created
        #       or we can not continue with sync.. Also, removed projects are
        #       NOT deleted automatically (they shouldn't be deleted anyway).
        #       We first set up the projects and exit if syncing them fails.

        project_sync_data = []
        role_sync_data = []

        for project in projects:
            owner_as = project.get_owner()

            # Create project
            project_sync_data.append({
                'project_uuid': str(project.sodar_uuid),
                'project_title': project.title,
                'flow_name': 'project_create',
                'flow_data': {
                    'project_title':
                    project.title,
                    'project_description':
                    project.description,
                    'parent_uuid':
                    str(project.parent.sodar_uuid) if project.parent else 0,
                    'owner_username':
                    owner_as.user.username,
                    'owner_uuid':
                    str(owner_as.user.sodar_uuid),
                    'owner_role_pk':
                    owner_as.role.pk,
                },
            })

            # Set up roles
            role_sync_data.append({
                'project_uuid': str(project.sodar_uuid),
                'project_title': project.title,
                'flow_name': 'role_sync_delete_all',
                'flow_data': {
                    'owner_username': owner_as.user.username
                },
            })

            for role_as in project.roles.exclude(role=Role.objects.get(
                    name=SODAR_CONSTANTS['PROJECT_ROLE_OWNER'])):
                role_sync_data.append({
                    'project_uuid': str(project.sodar_uuid),
                    'project_title': project.title,
                    'flow_name': 'role_update',
                    'flow_data': {
                        'username': role_as.user.username,
                        'user_uuid': str(role_as.user.sodar_uuid),
                        'role_pk': str(role_as.role.pk),
                    },
                })

        try:
            submit_sync('projectroles',
                        project_sync_data,
                        raise_exception=True)

        # In case of a failure here we can't continue with the rest of the sync
        except taskflow.FlowSubmitException:
            print_msg('Project creation failed! Unable to continue, exiting..')
            return

        submit_sync('projectroles', role_sync_data, raise_exception=False)

        ###########
        # App sync
        ###########

        plugins = get_active_plugins(plugin_type='project_app')

        for plugin in plugins:
            sync_data = plugin.get_taskflow_sync_data()
            print_msg('Synchronizing app "{}"...'.format(plugin.name))

            if sync_data:
                submit_sync(plugin.name, sync_data, raise_exception=False)

            else:
                print_msg('Nothing to synchronize.')

        print_msg('Project data synchronized.')
Exemplo n.º 22
0
    def __init__(self, *args, **kwargs):
        #: The user to display the settings for.
        self.user = kwargs.pop('current_user')

        super().__init__(*args, **kwargs)

        # Add settings fields
        self.app_plugins = get_active_plugins(plugin_type='project_app')
        self.user_plugins = get_active_plugins(plugin_type='site_app')
        self.app_plugins = self.app_plugins + self.user_plugins

        for plugin in self.app_plugins:
            p_settings = app_settings.get_setting_defs(APP_SETTING_SCOPE_USER,
                                                       plugin=plugin,
                                                       user_modifiable=True)

            for s_key, s_val in p_settings.items():
                s_field = 'settings.{}.{}'.format(plugin.name, s_key)
                s_widget_attrs = s_val.get('widget_attrs') or {}
                s_widget_attrs['placeholder'] = s_val.get('placeholder')
                setting_kwargs = {
                    'required':
                    False,
                    'label':
                    s_val.get('label') or '{}.{}'.format(plugin.name, s_key),
                    'help_text':
                    s_val.get('description'),
                }

                if s_val['type'] == 'STRING':
                    self.fields[s_field] = forms.CharField(
                        max_length=APP_SETTING_VAL_MAXLENGTH, **setting_kwargs)

                elif s_val['type'] == 'INTEGER':
                    self.fields[s_field] = forms.IntegerField(**setting_kwargs)

                elif s_val['type'] == 'BOOLEAN':
                    self.fields[s_field] = forms.BooleanField(**setting_kwargs)

                elif s_val['type'] == 'JSON':
                    # NOTE: Attrs MUST be supplied here (#404)
                    if 'class' in s_widget_attrs:
                        s_widget_attrs['class'] += ' sodar-json-input'

                    else:
                        s_widget_attrs['class'] = 'sodar-json-input'

                    self.fields[s_field] = forms.CharField(
                        widget=forms.Textarea(attrs=s_widget_attrs),
                        **setting_kwargs,
                    )

                # Modify initial value and attributes
                if s_val['type'] != 'JSON':
                    # Add optional attributes from plugin (#404)
                    # NOTE: Experimental! Use at your own risk!
                    self.fields[s_field].widget.attrs.update(s_widget_attrs)

                    self.initial[s_field] = app_settings.get_app_setting(
                        app_name=plugin.name,
                        setting_name=s_key,
                        user=self.user)

                else:
                    self.initial[s_field] = json.dumps(
                        app_settings.get_app_setting(
                            app_name=plugin.name,
                            setting_name=s_key,
                            user=self.user,
                        ))
Exemplo n.º 23
0
    def _init_app_settings(self):
        # Set up setting query kwargs
        self.p_kwargs = ({
            'user_modifiable': True
        } if not self.current_user.is_superuser else {})
        self.app_settings = AppSettingAPI()
        self.app_plugins = sorted(get_active_plugins(), key=lambda x: x.name)

        for plugin in self.app_plugins:
            # Show non-modifiable settings to superusers
            p_settings = self.app_settings.get_setting_defs(
                APP_SETTING_SCOPE_PROJECT, plugin=plugin, **self.p_kwargs)

            for s_key, s_val in p_settings.items():
                s_field = 'settings.{}.{}'.format(plugin.name, s_key)
                s_widget_attrs = s_val.get('widget_attrs') or {}
                setting_kwargs = {
                    'required':
                    False,
                    'label':
                    s_val.get('label') or '{}.{}'.format(plugin.name, s_key),
                    'help_text':
                    s_val['description'],
                }

                if s_val['type'] == 'JSON':
                    # NOTE: Attrs MUST be supplied here (#404)
                    if 'class' in s_widget_attrs:
                        s_widget_attrs['class'] += ' sodar-json-input'

                    else:
                        s_widget_attrs['class'] = 'sodar-json-input'

                    self.fields[s_field] = forms.CharField(
                        widget=forms.Textarea(attrs=s_widget_attrs),
                        **setting_kwargs)
                    if self.instance.pk:
                        self.initial[s_field] = json.dumps(
                            self.app_settings.get_app_setting(
                                app_name=plugin.name,
                                setting_name=s_key,
                                project=self.instance,
                            ))

                    else:
                        self.initial[s_field] = json.dumps(
                            self.app_settings.get_default_setting(
                                app_name=plugin.name, setting_name=s_key))
                else:
                    if s_val['type'] == 'STRING':
                        self.fields[s_field] = forms.CharField(
                            max_length=APP_SETTING_VAL_MAXLENGTH,
                            **setting_kwargs)

                    elif s_val['type'] == 'INTEGER':
                        self.fields[s_field] = forms.IntegerField(
                            **setting_kwargs)

                    elif s_val['type'] == 'BOOLEAN':
                        self.fields[s_field] = forms.BooleanField(
                            **setting_kwargs)

                    # Add optional attributes from plugin (#404)
                    # NOTE: Experimental! Use at your own risk!
                    self.fields[s_field].widget.attrs.update(s_widget_attrs)

                    # Set initial value
                    if self.instance.pk:
                        self.initial[
                            s_field] = self.app_settings.get_app_setting(
                                app_name=plugin.name,
                                setting_name=s_key,
                                project=self.instance,
                            )

                    else:
                        self.initial[
                            s_field] = self.app_settings.get_default_setting(
                                app_name=plugin.name, setting_name=s_key)

                # Add hidden note
                if s_val.get('user_modifiable') is False:
                    self.fields[s_field].label += ' [HIDDEN]'
                    self.fields[s_field].help_text += ' [HIDDEN FROM USERS]'
Exemplo n.º 24
0
def get_backend_plugins():
    """Get active backend plugins"""
    return get_active_plugins('backend')