Exemple #1
0
    def _getHTMLHeader( self ):
        from MaKaC.webinterface.rh.base import RHModificationBaseProtected
        from MaKaC.webinterface.rh.admins import RHAdminBase

        area=""
        if isinstance(self._rh, RHModificationBaseProtected):
            area=i18nformat(""" - _("Management area")""")
        elif isinstance(self._rh, RHAdminBase):
            area=i18nformat(""" - _("Administrator area")""")

        info = HelperMaKaCInfo().getMaKaCInfoInstance()

        plugin_css = values_from_signal(signals.plugin.inject_css.send(self.__class__), as_list=True,
                                        multi_value_types=list)
        plugin_js = values_from_signal(signals.plugin.inject_js.send(self.__class__), as_list=True,
                                       multi_value_types=list)

        return wcomponents.WHTMLHeader().getHTML({
            "area": area,
            "baseurl": self._getBaseURL(),
            "conf": Config.getInstance(),
            "page": self,
            "printCSS": map(self._fix_path, self.getPrintCSSFiles()),
            "extraCSS": map(self._fix_path, self.getCSSFiles() + plugin_css + self.get_extra_css_files()),
            "extraJSFiles": map(self._fix_path, self.getJSFiles() + plugin_js),
            "language": session.lang or info.getLang(),
            "social": info.getSocialAppConfig(),
            "assets": self._asset_env
        })
Exemple #2
0
    def display(self, **params):
        from indico.modules.admin import RHAdminBase
        from indico.modules.core.settings import core_settings, social_settings

        title_parts = [to_unicode(self._getTitle())]
        if self.MANAGEMENT:
            title_parts.append(_('Management area'))
        elif isinstance(self._rh, RHAdminBase):
            title_parts.append(_('Administration area'))

        plugin_css = values_from_signal(signals.plugin.inject_css.send(self.__class__), as_list=True,
                                        multi_value_types=list)
        plugin_js = values_from_signal(signals.plugin.inject_js.send(self.__class__), as_list=True,
                                       multi_value_types=list)
        custom_js = self._asset_env['custom_js'].urls() if 'custom_js' in self._asset_env else []
        custom_css = self._asset_env['custom_sass'].urls() if 'custom_sass' in self._asset_env else []
        css_files = map(self._fix_path, self.getCSSFiles() + plugin_css + self.get_extra_css_files() + custom_css)
        print_css_files = map(self._fix_path, self.getPrintCSSFiles())
        js_files = map(self._fix_path, self.getJSFiles() + plugin_js + custom_js)

        body = to_unicode(self._display(params))

        return render_template('indico_base.html',
                               css_files=css_files, print_css_files=print_css_files, js_files=js_files,
                               site_name=core_settings.get('site_title'),
                               social=social_settings.get_all(),
                               page_title=' - '.join(title_parts),
                               head_content=to_unicode(self._getHeadContent()),
                               body=body)
Exemple #3
0
def test_values_from_signal_multi_value_types():
    vals = ('a', ['b', 'c'])
    signal_response = _make_signal_response(vals)
    with pytest.raises(TypeError):
        # list is unhashable, can't be added to a set
        values_from_signal(signal_response)
    assert values_from_signal(signal_response, as_list=True) == list(vals)
    assert values_from_signal(signal_response, multi_value_types=list) == {'a', 'b', 'c'}
Exemple #4
0
 def settings(self):
     core_path = os.path.join(get_root_path('indico'), 'modules', 'events', 'themes.yaml')
     with open(core_path) as f:
         core_data = f.read()
     core_settings = yaml.safe_load(core_data)
     # YAML doesn't give us access to anchors so we need to include the base yaml.
     # Since duplicate keys are invalid (and may start failing in the future) we
     # rename them - this also makes it easy to throw them away after parsing the
     # file provided by a plugin.
     core_data = re.sub(r'^(\S+:)$', r'__core_\1', core_data, flags=re.MULTILINE)
     for plugin, path in values_from_signal(signals.plugin.get_event_themes_files.send(), return_plugins=True):
         with open(path) as f:
             data = f.read()
         settings = {k: v
                     for k, v in yaml.safe_load(core_data + '\n' + data).viewitems()
                     if not k.startswith('__core_')}
         # We assume there's no more than one theme plugin that provides defaults.
         # If that's not the case the last one "wins". We could reject this but it
         # is quite unlikely that people have multiple theme plugins in the first
         # place, even more so theme plugins that specify defaults.
         core_settings['defaults'].update(settings.get('defaults', {}))
         # Same for definitions - we assume plugin authors are responsible enough
         # to avoid using definition names that are likely to cause collisions.
         # Either way, if someone does this on purpose chances are good they want
         # to override a default style so let them do so...
         for name, definition in settings.get('definitions', {}).viewitems():
             definition['plugin'] = plugin
             definition.setdefault('user_visible', False)
             core_settings['definitions'][name] = definition
     return core_settings
Exemple #5
0
    def display(self, **params):
        from indico.modules.admin import RHAdminBase
        from indico.modules.core.settings import core_settings, social_settings

        title_parts = [self.title]
        if self.MANAGEMENT:
            title_parts.insert(0, _('Management'))
        elif isinstance(self._rh, RHAdminBase):
            title_parts.insert(0, _('Administration'))

        injected_bundles = values_from_signal(signals.plugin.inject_bundle.send(self.__class__), as_list=True,
                                              multi_value_types=list)
        custom_js = list(current_app.manifest['__custom.js'])
        custom_css = list(current_app.manifest['__custom.css'])
        css_files = map(self._fix_path, self.get_extra_css_files() + custom_css)
        js_files = map(self._fix_path, custom_js)

        body = to_unicode(self._display(params))
        bundles = itertools.chain((current_app.manifest[x] for x in self._resolve_bundles()
                                   if x in current_app.manifest._entries),
                                  self.additional_bundles['screen'], injected_bundles)
        print_bundles = itertools.chain((current_app.manifest[x] for x in self.print_bundles),
                                        self.additional_bundles['print'])

        return render_template('indico_base.html',
                               css_files=css_files, js_files=js_files,
                               bundles=bundles, print_bundles=print_bundles,
                               site_name=core_settings.get('site_title'),
                               social=social_settings.get_all(),
                               page_title=' - '.join(unicode(x) for x in title_parts if x),
                               head_content=to_unicode(self._getHeadContent()),
                               body=body)
Exemple #6
0
    def display(cls, template_name, **params):
        from indico.modules.admin import RHAdminBase
        from indico.modules.core.settings import core_settings, social_settings

        title_parts = [cls.title]
        if cls.MANAGEMENT:
            title_parts.insert(0, _('Management'))
        elif isinstance(g.rh, RHAdminBase):
            title_parts.insert(0, _('Administration'))

        injected_bundles = values_from_signal(signals.plugin.inject_bundle.send(cls), as_list=True,
                                              multi_value_types=list)
        custom_js = list(current_app.manifest['__custom.js'])
        custom_css = list(current_app.manifest['__custom.css'])
        css_files = map(cls._fix_path, custom_css)
        js_files = map(cls._fix_path, custom_js)

        bundles = itertools.chain((current_app.manifest[x] for x in cls._resolve_bundles()
                                   if x in current_app.manifest._entries),
                                  cls.additional_bundles['screen'], injected_bundles)
        print_bundles = itertools.chain((current_app.manifest[x] for x in cls.print_bundles),
                                        cls.additional_bundles['print'])
        template = cls._prefix_template(template_name)
        return render_template(template,
                               css_files=css_files, js_files=js_files,
                               bundles=bundles, print_bundles=print_bundles,
                               site_name=core_settings.get('site_title'),
                               social=social_settings.get_all(),
                               page_title=' - '.join(unicode(x) for x in title_parts if x),
                               **params)
Exemple #7
0
    def can_access(self, user, allow_admin=True):
        """Checks if the user can access the object.

        :param user: The :class:`.User` to check. May be None if the
                     user is not logged in.
        :param allow_admin: If admin users should always have access
        """

        # Trigger signals for protection overrides
        rv = values_from_signal(
            signals.acl.can_access.send(type(self), obj=self, user=user, allow_admin=allow_admin), single_value=True
        )
        if rv:
            # in case of contradictory results (shouldn't happen at all)
            # we stay on the safe side and deny access
            return all(rv)

        # Usually admins can access everything, so no need for checks
        if allow_admin and user and user.is_admin:
            return True

        if self.protection_mode == ProtectionMode.public:
            # if it's public we completely ignore the parent protection
            # this is quite ugly which is why it should only be allowed
            # in rare cases (e.g. events which might be in a protected
            # category but should be public nonetheless)
            return True
        elif self.protection_mode == ProtectionMode.protected:
            # if it's protected, we also ignore the parent protection
            # and only check our own ACL
            return user is not None and any(user in entry.principal for entry in iter_acl(self.acl_entries))
        elif self.protection_mode == ProtectionMode.inheriting:
            # if it's inheriting, we only check the parent protection
            # unless `inheriting_have_acl` is set, in which case we
            # might not need to check the parents at all
            if (
                self.inheriting_have_acl
                and user is not None
                and any(user in entry.principal for entry in iter_acl(self.acl_entries))
            ):
                return True
            # the parent can be either an object inheriting from this
            # mixin or a legacy object with an AccessController
            parent = self.protection_parent
            if parent is None:
                # This should be the case for the top-level object,
                # i.e. the root category, which shouldn't allow
                # ProtectionMode.inheriting as it makes no sense.
                raise TypeError("protection_parent of {} is None".format(self))
            elif hasattr(parent, "can_access"):
                return parent.can_access(user, allow_admin=allow_admin)
            elif hasattr(parent, "canAccess"):
                return parent.canAccess(AccessWrapper(user.as_avatar if user else None))
            else:
                raise TypeError("protection_parent of {} is of invalid type {} ({})".format(self, type(parent), parent))
        else:
            # should never happen, but since this is a sensitive area
            # we better fail loudly if we have garbage
            raise ValueError("Invalid protection mode: {}".format(self.protection_mode))
Exemple #8
0
    def can_access(self, user, acl_attr='acl', legacy_method='canAccess', allow_admin=True):
        """Checks if the user can access the object.

        When using a custom `acl_attr` on an object that supports
        inherited proection, ALL possible `protection_parent` objects
        need to have an ACL with the same name too!

        :param user: The :class:`.User` to check. May be None if the
                     user is not logged in.
        :param acl_attr: The name of the property that contains the
                         set of authorized principals.
        :param legacy_method: The method name to use when inheriting
                              the protection from a legacy object.
        :param allow_admin: If admin users should always have access
        """

        # Trigger signals for protection overrides
        rv = values_from_signal(signals.acl.can_access.send(type(self), obj=self, user=user, acl_attr=acl_attr,
                                                            legacy_method=legacy_method, allow_admin=allow_admin),
                                single_value=True)
        if rv:
            # in case of contradictory results (shouldn't happen at all)
            # we stay on the safe side and deny access
            return all(rv)

        # Usually admins can access everything, so no need for checks
        if allow_admin and user and user.is_admin:
            return True

        if self.protection_mode == ProtectionMode.public:
            # if it's public we completely ignore the parent protection
            # this is quite ugly which is why it should only be allowed
            # in rare cases (e.g. events which might be in a protected
            # category but should be public nonetheless)
            return True
        elif self.protection_mode == ProtectionMode.protected:
            # if it's protected, we also ignore the parent protection
            # and only check our own ACL
            return any(user in principal for principal in iter_acl(getattr(self, acl_attr)))
        elif self.protection_mode == ProtectionMode.inheriting:
            # if it's inheriting, we only check the parent protection.
            # the parent can be either an object inheriting from this
            # mixin or a legacy object with an AccessController
            parent = self.protection_parent
            if parent is None:
                # This should be the case for the top-level object,
                # i.e. the root category, which shouldn't allow
                # ProtectionMode.inheriting as it makes no sense.
                raise TypeError('protection_parent of {} is None'.format(self))
            elif hasattr(parent, 'can_access'):
                return parent.can_access(user, acl_attr=acl_attr)
            elif legacy_method is not None and hasattr(parent, legacy_method):
                return getattr(parent, legacy_method)(AccessWrapper(user.as_avatar if user else None))
            else:
                raise TypeError('protection_parent of {} is of invalid type {} ({})'.format(self, type(parent), parent))
        else:
            # should never happen, but since this is a sensitive area
            # we better fail loudly if we have garbage
            raise ValueError('Invalid protection mode: {}'.format(self.protection_mode))
Exemple #9
0
 def _checkParams(self, params):
     RHConferenceModifBase._checkParams(self, params)
     from MaKaC.webinterface.rh.reviewingModif import RCPaperReviewManager, RCReferee
     self._isPRM = RCPaperReviewManager.hasRights(self)
     self._isReferee = RCReferee.hasRights(self)
     self._requests_manager = is_request_manager(session.user)
     self._plugin_urls = values_from_signal(signals.event_management.management_url.send(self.event_new),
                                            single_value=True)
Exemple #10
0
 def _check_can_access_override(self, user, allow_admin, authorized=None):
     # Trigger signals for protection overrides
     rv = values_from_signal(signals.acl.can_access.send(type(self), obj=self, user=user, allow_admin=allow_admin,
                                                         authorized=authorized),
                             single_value=True)
     # in case of contradictory results (shouldn't happen at all)
     # we stay on the safe side and deny access
     return all(rv) if rv else None
Exemple #11
0
 def validate(self):
     valid = super(IndicoForm, self).validate()
     if not valid:
         return False
     if not all(values_from_signal(signals.form_validated.send(self), single_value=True)):
         return False
     self.post_validate()
     return True
Exemple #12
0
    def _createSideMenu(self):
        self._sideMenu = wcomponents.ManagementSideMenu()

        mainSection = wcomponents.SideMenuSection(id='general')
        securitySection = wcomponents.SideMenuSection(_('Security'), id='security', icon='icon-shield')
        userManagementSection = wcomponents.SideMenuSection(_('User management'), id='user_management',
                                                            icon='icon-users')
        pluginsSection = wcomponents.SideMenuSection(_('Plugins'), id='plugins', icon='icon-settings')
        customizationSection = wcomponents.SideMenuSection(_('Customization'), id='customization', icon='icon-wrench')
        integrationSection = wcomponents.SideMenuSection(_('Integration'), id='integration', icon='icon-earth')

        self._sideMenu.addSection(mainSection)
        self._sideMenu.addSection(securitySection)
        self._sideMenu.addSection(userManagementSection)
        self._sideMenu.addSection(pluginsSection)
        self._sideMenu.addSection(customizationSection)
        self._sideMenu.addSection(integrationSection)

        self._generalSettingsMenuItem = wcomponents.SideMenuItem(
            _("General settings"),
            urlHandlers.UHAdminArea.getURL(), section='general')
        self._sideMenu.addItem(self._generalSettingsMenuItem)

        self._domainsMenuItem = wcomponents.SideMenuItem(
            _("IP Domains"),
            urlHandlers.UHDomains.getURL(), section='security')
        self._sideMenu.addItem(self._domainsMenuItem)

        self._templatesMenuItem = wcomponents.SideMenuItem(
            _("Layout"),
            urlHandlers.UHAdminLayoutGeneral.getURL(), section='customization')
        self._sideMenu.addItem(self._templatesMenuItem)

        self._ipProtectionMenuItem = wcomponents.SideMenuItem(
            _("IP-based ACL"),
            urlHandlers.UHIPBasedACL.getURL(), section='security')
        self._sideMenu.addItem(self._ipProtectionMenuItem)

        self._homepageMenuItem = wcomponents.SideMenuItem(
            _("Homepage"),
            urlHandlers.UHUpdateNews.getURL(), section='customization')
        self._sideMenu.addItem(self._homepageMenuItem)

        self._systemMenuItem = wcomponents.SideMenuItem(
            _("System"),
            urlHandlers.UHAdminsSystem.getURL(), section='general')
        self._sideMenu.addItem(self._systemMenuItem)

        self._protectionMenuItem = wcomponents.SideMenuItem(
            _("Protection"),
            urlHandlers.UHAdminsProtection.getURL(), section='security')
        self._sideMenu.addItem(self._protectionMenuItem)

        self.extra_menu_items = {}
        for name, item in sorted(values_from_signal(signals.admin_sidemenu.send()),
                                 key=lambda x: x[1]._title):
            self.extra_menu_items[name] = item
            self._sideMenu.addItem(item)
Exemple #13
0
 def _getBody(self, params):
     extra_items = sorted(values_from_signal(signals.users.profile_sidemenu.send(params['user'])),
                          key=attrgetter('title'))
     params['user_menu_items'] = [
         MenuItem(_('Dashboard'), 'users.user_dashboard'),
         MenuItem(_('Personal data'), 'users.user_profile'),
         MenuItem(_('Emails'), 'users.user_emails'),
         MenuItem(_('Preferences'), 'users.user_preferences'),
         MenuItem(_('Favorites'), 'users.user_favorites'),
     ] + extra_items
     return self._getPageContent(params)
Exemple #14
0
    def _do_process(self):
        try:
            args_result = self._process_args()
            signals.rh.process_args.send(type(self), rh=self, result=args_result)
            if isinstance(args_result, (current_app.response_class, Response)):
                return args_result
        except NoResultFound:  # sqlalchemy .one() not finding anything
            raise NotFound(_('The specified item could not be found.'))

        rv = self.normalize_url()
        if rv is not None:
            return rv

        self._check_access()
        signals.rh.check_access.send(type(self), rh=self)
        if self.CHECK_HTML:
            Sanitization.sanitizationCheck(create_flat_args(), self.NOT_SANITIZED_FIELDS)

        signal_rv = values_from_signal(signals.rh.before_process.send(type(self), rh=self),
                                       single_value=True, as_list=True)
        if signal_rv and len(signal_rv) != 1:
            raise Exception('More than one signal handler returned custom RH result')
        elif signal_rv:
            return signal_rv[0]

        if config.PROFILE:
            result = [None]
            profile_path = os.path.join(config.TEMP_DIR, '{}-{}.prof'.format(type(self).__name__, time.time()))
            cProfile.runctx('result[0] = self._process()', globals(), locals(), profile_path)
            rv = result[0]
        else:
            rv = self._process()

        signal_rv = values_from_signal(signals.rh.process.send(type(self), rh=self, result=rv),
                                       single_value=True, as_list=True)
        if signal_rv and len(signal_rv) != 1:
            raise Exception('More than one signal handler returned new RH result')
        elif signal_rv:
            return signal_rv[0]
        else:
            return rv
Exemple #15
0
    def _check_access(self):
        if not session.user:
            raise Forbidden
        # If the user cannot manage the whole event see if anything gives them
        # limited management access.
        if not self.event.can_manage(session.user):
            urls = sorted(values_from_signal(signals.event_management.management_url.send(self.event),
                                             single_value=True))
            response = redirect(urls[0]) if urls else None
            raise Forbidden(response=response)

        RHManageEventBase._check_access(self)  # mainly to trigger the legacy "event locked" check
Exemple #16
0
    def _check_access(self):
        if not session.user:
            raise Forbidden
        # If the user cannot manage the whole event see if anything gives them
        # limited management access.
        if not self.event.can_manage(session.user):
            urls = sorted(values_from_signal(signals.event_management.management_url.send(self.event),
                                             single_value=True))
            response = redirect(urls[0]) if urls else None
            raise Forbidden(response=response)

        RHManageEventBase._check_access(self)  # mainly to trigger the legacy "event locked" check
Exemple #17
0
    def _process(self):
        detail_level = request.args.get('detail', 'events')
        data = serialize_event_for_ical(self.event, detail_level)

        # check whether the plugins want to add/override any data
        for update in values_from_signal(
                signals.event.metadata_postprocess.send('ical-export', event=self.event, data=data), as_list=True):
            data.update(update)

        response = {'results': data}
        serializer = Serializer.create('ics')
        return send_file('event.ics', BytesIO(serializer(response)), 'text/calendar')
Exemple #18
0
 def _check_can_access_override(self, user, allow_admin, authorized=None):
     # Trigger signals for protection overrides
     rv = values_from_signal(signals.acl.can_access.send(
         type(self),
         obj=self,
         user=user,
         allow_admin=allow_admin,
         authorized=authorized),
                             single_value=True)
     # in case of contradictory results (shouldn't happen at all)
     # we stay on the safe side and deny access
     return all(rv) if rv else None
Exemple #19
0
 def _getBody(self, params):
     extra_items = sorted(values_from_signal(
         signals.users.profile_sidemenu.send(params['user'])),
                          key=attrgetter('title'))
     params['user_menu_items'] = [
         MenuItem(_('Dashboard'), 'users.user_dashboard'),
         MenuItem(_('Personal data'), 'users.user_profile'),
         MenuItem(_('Emails'), 'users.user_emails'),
         MenuItem(_('Preferences'), 'users.user_preferences'),
         MenuItem(_('Favorites'), 'users.user_favorites'),
         # TODO: other menu items
     ] + extra_items
     return self._getPageContent(params)
Exemple #20
0
def add_plugin_blueprints(app):
    blueprint_names = set()
    for plugin, blueprint in values_from_signal(signals.plugin.get_blueprints.send(app), return_plugins=True):
        expected_names = {'plugin_{}'.format(plugin.name), 'plugin_compat_{}'.format(plugin.name)}
        if blueprint.name not in expected_names:
            raise Exception("Blueprint '{}' does not match plugin name '{}'".format(blueprint.name, plugin.name))
        if blueprint.name in blueprint_names:
            raise Exception("Blueprint '{}' defined by multiple plugins".format(blueprint.name))
        if not app.config['INDICO_COMPAT_ROUTES'] and blueprint.name.startswith('plugin_compat_'):
            continue
        blueprint_names.add(blueprint.name)
        with plugin.plugin_context():
            app.register_blueprint(blueprint)
Exemple #21
0
def add_plugin_blueprints(app):
    blueprint_names = set()
    for plugin, blueprint in values_from_signal(signals.plugin.get_blueprints.send(app), return_plugins=True):
        expected_names = {'plugin_{}'.format(plugin.name), 'plugin_compat_{}'.format(plugin.name)}
        if blueprint.name not in expected_names:
            raise Exception("Blueprint '{}' does not match plugin name '{}'".format(blueprint.name, plugin.name))
        if blueprint.name in blueprint_names:
            raise Exception("Blueprint '{}' defined by multiple plugins".format(blueprint.name))
        if not app.config['INDICO_COMPAT_ROUTES'] and blueprint.name.startswith('plugin_compat_'):
            continue
        blueprint_names.add(blueprint.name)
        with plugin.plugin_context():
            app.register_blueprint(blueprint)
Exemple #22
0
def add_plugin_blueprints(app):
    blueprint_names = set()
    for plugin, blueprint in values_from_signal(signals.plugin.get_blueprints.send(app), return_plugins=True):
        expected_names = {f'plugin_{plugin.name}', f'plugin_compat_{plugin.name}'}
        if blueprint.name not in expected_names:
            raise Exception(f"Blueprint '{blueprint.name}' does not match plugin name '{plugin.name}'")
        if blueprint.name in blueprint_names:
            raise Exception(f"Blueprint '{blueprint.name}' defined by multiple plugins")
        if not config.ROUTE_OLD_URLS and blueprint.name.startswith('plugin_compat_'):
            continue
        blueprint_names.add(blueprint.name)
        with plugin.plugin_context():
            app.register_blueprint(blueprint)
Exemple #23
0
    def _do_process(self):
        try:
            args_result = self._process_args()
            signals.rh.process_args.send(type(self), rh=self, result=args_result)
            if isinstance(args_result, (current_app.response_class, Response)):
                return args_result
        except NoResultFound:  # sqlalchemy .one() not finding anything
            raise NotFound(_('The specified item could not be found.'))

        rv = self.normalize_url()
        if rv is not None:
            return rv

        self._check_access()
        signals.rh.check_access.send(type(self), rh=self)

        signal_rv = values_from_signal(signals.rh.before_process.send(type(self), rh=self),
                                       single_value=True, as_list=True)
        if signal_rv and len(signal_rv) != 1:
            raise Exception('More than one signal handler returned custom RH result')
        elif signal_rv:
            return signal_rv[0]

        if config.PROFILE:
            result = [None]
            profile_path = os.path.join(config.TEMP_DIR, '{}-{}.prof'.format(type(self).__name__, time.time()))
            cProfile.runctx('result[0] = self._process()', globals(), locals(), profile_path)
            rv = result[0]
        else:
            rv = self._process()

        signal_rv = values_from_signal(signals.rh.process.send(type(self), rh=self, result=rv),
                                       single_value=True, as_list=True)
        if signal_rv and len(signal_rv) != 1:
            raise Exception('More than one signal handler returned new RH result')
        elif signal_rv:
            return signal_rv[0]
        else:
            return rv
Exemple #24
0
    def getVars( self ):
        vars = WTemplated.getVars(self)

        vars["currentUser"] = self._currentuser

        config =  Config.getInstance()
        imgLogin = config.getSystemIconURL("login")

        vars["imgLogin"] = imgLogin
        vars["isFrontPage"] = self._isFrontPage
        vars["currentCategory"] = self.__currentCategory
        vars['prot_obj'] = self._prot_obj

        current_locale = get_current_locale()
        vars["ActiveTimezone"] = session.timezone
        """
            Get the timezone for displaying on top of the page.
            1. If the user has "LOCAL" timezone then show the timezone
            of the event/category. If that's not possible just show the
            standard timezone.
            2. If the user has a custom timezone display that one.
        """
        vars["ActiveTimezoneDisplay"] = self._getTimezoneDisplay(vars["ActiveTimezone"])

        vars["SelectedLanguage"] = str(current_locale)
        vars["SelectedLanguageName"] = current_locale.language_name
        vars["Languages"] = get_all_locales()

        if DBMgr.getInstance().isConnected():
            vars["title"] = info.HelperMaKaCInfo.getMaKaCInfoInstance().getTitle()
            vars["organization"] = info.HelperMaKaCInfo.getMaKaCInfoInstance().getOrganisation()
        else:
            vars["title"] = "Indico"
            vars["organization"] = ""

        vars['roomBooking'] = Config.getInstance().getIsRoomBookingActive()
        vars['protectionDisclaimerProtected'] = legal_settings.get('network_protected_disclaimer')
        vars['protectionDisclaimerRestricted'] = legal_settings.get('restricted_disclaimer')
        #Build a list of items for the administration menu
        adminItemList = []
        if session.user and session.user.is_admin:
            adminItemList.append({'id': 'serverAdmin', 'url': urlHandlers.UHAdminArea.getURL(),
                                  'text': _("Server admin")})

        vars["adminItemList"] = adminItemList
        vars['extra_items'] = HeaderMenuEntry.group(values_from_signal(signals.indico_menu.send()))
        vars["getProtection"] = self._getProtection

        vars["show_contact"] = config.getPublicSupportEmail() is not None

        return vars
Exemple #25
0
    def _createSideMenu(self):
        self._sideMenu = wcomponents.ManagementSideMenu()

        mainSection = wcomponents.SideMenuSection()

        self._generalSettingsMenuItem = wcomponents.SideMenuItem(
            _("General settings"), urlHandlers.UHAdminArea.getURL())
        mainSection.addItem(self._generalSettingsMenuItem)

        self._domainsMenuItem = wcomponents.SideMenuItem(
            _("IP Domains"), urlHandlers.UHDomains.getURL())
        mainSection.addItem(self._domainsMenuItem)

        self._roomsMenuItem = wcomponents.SideMenuItem(
            _("Rooms"), url_for('rooms_admin.settings'))
        mainSection.addItem(self._roomsMenuItem)

        self._templatesMenuItem = wcomponents.SideMenuItem(
            _("Layout"), urlHandlers.UHAdminLayoutGeneral.getURL())
        mainSection.addItem(self._templatesMenuItem)

        self._servicesMenuItem = wcomponents.SideMenuItem(
            _("Services"), urlHandlers.UHIPBasedACL.getURL())
        mainSection.addItem(self._servicesMenuItem)

        self._pluginsMenuItem = wcomponents.SideMenuItem(
            _("Plugins"), url_for('plugins.index'))
        mainSection.addItem(self._pluginsMenuItem)

        self._homepageMenuItem = wcomponents.SideMenuItem(
            _("Homepage"), urlHandlers.UHUpdateNews.getURL())
        mainSection.addItem(self._homepageMenuItem)

        self._systemMenuItem = wcomponents.SideMenuItem(
            _("System"), urlHandlers.UHAdminsSystem.getURL())
        mainSection.addItem(self._systemMenuItem)

        self._protectionMenuItem = wcomponents.SideMenuItem(
            _("Protection"), urlHandlers.UHAdminsProtection.getURL())
        mainSection.addItem(self._protectionMenuItem)

        self.extra_menu_items = {}
        for name, item in sorted(values_from_signal(
                signals.admin_sidemenu.send()),
                                 key=lambda x: x[1]._title):
            self.extra_menu_items[name] = item
            mainSection.addItem(item)

        self._sideMenu.addSection(mainSection)
Exemple #26
0
def get_search_provider():
    from indico.modules.search.controllers import InternalSearch
    providers = values_from_signal(signals.get_search_providers.send(),
                                   as_list=True)

    if not providers:
        return InternalSearch
    elif len(providers) == 1:
        return providers[0]
    else:
        providers_str = ', '.join(f'{x.__module__}.{x.__name__}'
                                  for x in providers)
        raise RuntimeError(
            f'Only one search provider can be defined (found: {providers_str})'
        )
Exemple #27
0
def _notify_registration(registration, template, to_managers=False):
    attachments = None
    regform = registration.registration_form
    tickets_handled = values_from_signal(signals.event.is_ticketing_handled.send(regform), single_value=True)
    if (not to_managers and
            regform.tickets_enabled and
            regform.ticket_on_email and
            not any(tickets_handled) and
            registration.state == RegistrationState.complete):
        attachments = get_ticket_attachment(registration)

    template = get_template_module('events/registration/emails/{}'.format(template), registration=registration)
    to_list = registration.email if not to_managers else registration.registration_form.manager_notification_recipients
    from_address = registration.registration_form.sender_address if not to_managers else None
    mail = make_email(to_list=to_list, template=template, html=True, from_address=from_address, attachments=attachments)
    send_email(mail, event=registration.registration_form.event, module='Registration', user=session.user)
Exemple #28
0
def _notify_registration(registration,
                         template_name,
                         to_managers=False,
                         attach_rejection_reason=False,
                         diff=None,
                         old_price=None):
    from indico.modules.events.registration.util import get_ticket_attachments
    attachments = []
    regform = registration.registration_form
    tickets_handled = values_from_signal(
        signals.event.is_ticketing_handled.send(regform), single_value=True)
    if (not to_managers and regform.tickets_enabled and regform.ticket_on_email
            and not any(tickets_handled)
            and registration.state == RegistrationState.complete):
        attachments += get_ticket_attachments(registration)
    if not to_managers and registration.registration_form.attach_ical:
        event_ical = event_to_ical(registration.event,
                                   method='REQUEST',
                                   organizer=(core_settings.get('site_title'),
                                              config.NO_REPLY_EMAIL))
        attachments.append(MIMECalendar('event.ics', event_ical))

    tpl = get_template_module(f'events/registration/emails/{template_name}',
                              registration=registration,
                              attach_rejection_reason=attach_rejection_reason,
                              diff=diff,
                              old_price=old_price)
    to_list = registration.email if not to_managers else registration.registration_form.manager_notification_recipients
    from_address = registration.registration_form.notification_sender_address if not to_managers else None
    mail = make_email(to_list=to_list,
                      template=tpl,
                      html=True,
                      from_address=from_address,
                      attachments=attachments)
    user = session.user if session else None
    signals.core.before_notification_send.send(
        'notify-registration',
        email=mail,
        registration=registration,
        template_name=template_name,
        attach_rejection_reason=attach_rejection_reason)
    send_email(mail,
               event=registration.registration_form.event,
               module='Registration',
               user=user,
               log_metadata={'registration_id': registration.id})
Exemple #29
0
    def _createSideMenu(self):
        self._sideMenu = wcomponents.ManagementSideMenu()

        mainSection = wcomponents.SideMenuSection()

        self._generalSettingsMenuItem = wcomponents.SideMenuItem(_("General settings"),
            urlHandlers.UHAdminArea.getURL())
        mainSection.addItem( self._generalSettingsMenuItem)

        self._domainsMenuItem = wcomponents.SideMenuItem(_("IP Domains"),
            urlHandlers.UHDomains.getURL())
        mainSection.addItem( self._domainsMenuItem)

        self._roomsMenuItem = wcomponents.SideMenuItem(_("Rooms"), url_for('rooms_admin.settings'))
        mainSection.addItem(self._roomsMenuItem)

        self._templatesMenuItem = wcomponents.SideMenuItem(_("Layout"),
            urlHandlers.UHAdminLayoutGeneral.getURL())
        mainSection.addItem( self._templatesMenuItem)

        self._servicesMenuItem = wcomponents.SideMenuItem(_("Services"), urlHandlers.UHIPBasedACL.getURL())
        mainSection.addItem(self._servicesMenuItem)

        self._pluginsMenuItem = wcomponents.SideMenuItem(_("Plugins"), url_for('plugins.index'))
        mainSection.addItem(self._pluginsMenuItem)

        self._homepageMenuItem = wcomponents.SideMenuItem(_("Homepage"),
            urlHandlers.UHUpdateNews.getURL())
        mainSection.addItem( self._homepageMenuItem)

        self._systemMenuItem = wcomponents.SideMenuItem(_("System"),
            urlHandlers.UHAdminsSystem.getURL())
        mainSection.addItem( self._systemMenuItem)

        self._protectionMenuItem = wcomponents.SideMenuItem(_("Protection"),
            urlHandlers.UHAdminsProtection.getURL())
        mainSection.addItem( self._protectionMenuItem)

        self.extra_menu_items = {}
        for name, item in sorted(values_from_signal(signals.admin_sidemenu.send()),
                                 key=lambda x: x[1]._title):
            self.extra_menu_items[name] = item
            mainSection.addItem(item)

        self._sideMenu.addSection(mainSection)
Exemple #30
0
 def _process(self):
     extra_preferences = [pref(self.user) for pref in values_from_signal(signals.users.preferences.send(self.user))]
     form_class = UserPreferencesForm
     defaults = FormDefaults(**self.user.settings.get_all(self.user))
     for pref in extra_preferences:
         form_class = pref.extend_form(form_class)
         pref.extend_defaults(defaults)
     form = form_class(obj=defaults)
     if form.validate_on_submit():
         data = form.data
         for pref in extra_preferences:
             pref.process_form_data(data)
         self.user.settings.set_multi(data)
         session.timezone = (self.user.settings.get('timezone') if self.user.settings.get('force_timezone')
                             else 'LOCAL')
         flash(_('Preferences saved'), 'success')
         return redirect(url_for('.user_preferences'))
     return WPUser.render_template('preferences.html', user=self.user, form=form)
Exemple #31
0
def get_search_provider(only_active=True):
    """Get the search provider to use for a search.

    :param only_active: Whether to check that the provider is active;
                        in case it isn't, the default InternalSearch
                        provider will be used.
    """
    from indico.modules.search.controllers import InternalSearch
    providers = values_from_signal(signals.get_search_providers.send(), as_list=True)

    if not providers:
        return InternalSearch
    elif len(providers) == 1:
        provider = providers[0]
        return provider if not only_active or provider.active else InternalSearch
    else:
        providers_str = ', '.join(f'{x.__module__}.{x.__name__}' for x in providers)
        raise RuntimeError(f'Only one search provider can be defined (found: {providers_str})')
Exemple #32
0
def call_template_hook(*name, **kwargs):
    """Template function to let plugins add their own data to a template.

    :param name: The name of the hook.  Only accepts one argument.
    :param as_list: Return a list instead of a concatenated string
    :param kwargs: Data to pass to the signal receivers.
    """
    if len(name) != 1:
        raise TypeError(f'call_template_hook() accepts only one positional argument, {len(name)} given')
    name = name[0]
    as_list = kwargs.pop('as_list', False)
    values = []
    for snippet in values_from_signal(signals.plugin.template_hook.send(str(name), **kwargs),
                                      multi_value_types=tuple, as_list=True):
        if not (value := snippet.content):
            continue
        if snippet.markup:
            value = Markup(value)
        values.append((snippet.priority, value))
Exemple #33
0
def _notify_registration(registration, template, to_managers=False):
    from indico.modules.events.registration.util import get_ticket_attachments
    attachments = None
    regform = registration.registration_form
    tickets_handled = values_from_signal(signals.event.is_ticketing_handled.send(regform), single_value=True)
    if (not to_managers and
            regform.tickets_enabled and
            regform.ticket_on_email and
            not any(tickets_handled) and
            registration.state == RegistrationState.complete):
        attachments = get_ticket_attachments(registration)

    template = get_template_module(f'events/registration/emails/{template}', registration=registration)
    to_list = registration.email if not to_managers else registration.registration_form.manager_notification_recipients
    from_address = registration.registration_form.sender_address if not to_managers else None
    mail = make_email(to_list=to_list, template=template, html=True, from_address=from_address, attachments=attachments)
    user = session.user if session else None
    send_email(mail, event=registration.registration_form.event, module='Registration', user=user,
               log_metadata={'registration_id': registration.id})
Exemple #34
0
 def _process(self):
     extra_preferences = [pref(self.user) for pref in values_from_signal(signals.users.preferences.send(self.user))]
     form_class = UserPreferencesForm
     defaults = FormDefaults(**self.user.settings.get_all(self.user))
     for pref in extra_preferences:
         form_class = pref.extend_form(form_class)
         pref.extend_defaults(defaults)
     form = form_class(obj=defaults)
     if form.validate_on_submit():
         data = form.data
         for pref in extra_preferences:
             pref.process_form_data(data)
         self.user.settings.set_multi(data)
         session.lang = self.user.settings.get('lang')
         session.timezone = (self.user.settings.get('timezone') if self.user.settings.get('force_timezone')
                             else 'LOCAL')
         flash(_('Preferences saved'), 'success')
         return redirect(url_for('.user_preferences'))
     return WPUser.render_template('preferences.html', 'preferences', user=self.user, form=form)
Exemple #35
0
    def display(self, **params):
        from indico.modules.admin import RHAdminBase
        from indico.modules.core.settings import core_settings, social_settings

        title_parts = [self.title]
        if self.MANAGEMENT:
            title_parts.insert(0, _('Management'))
        elif isinstance(self._rh, RHAdminBase):
            title_parts.insert(0, _('Administration'))

        injected_bundles = values_from_signal(
            signals.plugin.inject_bundle.send(self.__class__),
            as_list=True,
            multi_value_types=list)
        custom_js = list(current_app.manifest['__custom.js'])
        custom_css = list(current_app.manifest['__custom.css'])
        css_files = list(
            map(self._fix_path,
                self.get_extra_css_files() + custom_css))
        js_files = list(map(self._fix_path, custom_js))

        body = self._display(params)
        bundles = itertools.chain(
            (current_app.manifest[x] for x in self._resolve_bundles()
             if x in current_app.manifest._entries),
            self.additional_bundles['screen'], injected_bundles)
        print_bundles = itertools.chain(
            (current_app.manifest[x] for x in self.print_bundles),
            self.additional_bundles['print'])

        return render_template('indico_base.html',
                               css_files=css_files,
                               js_files=js_files,
                               bundles=bundles,
                               print_bundles=print_bundles,
                               site_name=core_settings.get('site_title'),
                               social=social_settings.get_all(),
                               page_metadata=self.page_metadata,
                               page_title=' - '.join(
                                   str(x) for x in title_parts if x),
                               head_content=self._get_head_content(),
                               body=body)
Exemple #36
0
 def __call__(cls, *args, **kwargs):
     # If we are instantiating a form that was just extended, don't
     # send the signal again - it's pointless to extend the extended
     # form and doing so could actually result in infinite recursion
     # if the signal receiver didn't specify a sender.
     if kwargs.pop('__extended', False):
         return super(IndicoFormMeta, cls).__call__(*args, **kwargs)
     extra_fields = values_from_signal(signals.add_form_fields.send(cls))
     # If there are no extra fields, we don't need any custom logic
     # and simply create an instance of the original form.
     if not extra_fields:
         return super(IndicoFormMeta, cls).__call__(*args, **kwargs)
     kwargs['__extended'] = True
     ext_cls = type(b'_Extended' + cls.__name__, (cls,), {})
     for name, field in extra_fields:
         name = 'ext__' + name
         if hasattr(ext_cls, name):
             raise RuntimeError('Field name collision in {}: {}'.format(cls.__name__, name))
         setattr(ext_cls, name, field)
     return ext_cls(*args, **kwargs)
Exemple #37
0
 def __call__(cls, *args, **kwargs):
     # If we are instantiating a form that was just extended, don't
     # send the signal again - it's pointless to extend the extended
     # form and doing so could actually result in infinite recursion
     # if the signal receiver didn't specify a sender.
     if kwargs.pop('__extended', False):
         return super(IndicoFormMeta, cls).__call__(*args, **kwargs)
     extra_fields = values_from_signal(signals.add_form_fields.send(cls))
     # If there are no extra fields, we don't need any custom logic
     # and simply create an instance of the original form.
     if not extra_fields:
         return super(IndicoFormMeta, cls).__call__(*args, **kwargs)
     kwargs['__extended'] = True
     ext_cls = type(b'_Extended' + cls.__name__, (cls,), {})
     for name, field in extra_fields:
         name = 'ext__' + name
         if hasattr(ext_cls, name):
             raise RuntimeError('Preference collision in {}: {}'.format(cls.__name__, name))
         setattr(ext_cls, name, field)
     return ext_cls(*args, **kwargs)
Exemple #38
0
 def settings(self):
     core_path = os.path.join(get_root_path('indico'), 'modules', 'events',
                              'themes.yaml')
     with open(core_path) as f:
         core_data = f.read()
     core_settings = yaml.safe_load(core_data)
     # YAML doesn't give us access to anchors so we need to include the base yaml.
     # Since duplicate keys are invalid (and may start failing in the future) we
     # rename them - this also makes it easy to throw them away after parsing the
     # file provided by a plugin.
     core_data = re.sub(r'^(\S+:)$',
                        r'__core_\1',
                        core_data,
                        flags=re.MULTILINE)
     for plugin, path in values_from_signal(
             signals.plugin.get_event_themes_files.send(),
             return_plugins=True):
         with open(path) as f:
             data = f.read()
         settings = {
             k: v
             for k, v in yaml.safe_load(core_data + '\n' +
                                        data).viewitems()
             if not k.startswith('__core_')
         }
         # We assume there's no more than one theme plugin that provides defaults.
         # If that's not the case the last one "wins". We could reject this but it
         # is quite unlikely that people have multiple theme plugins in the first
         # place, even more so theme plugins that specify defaults.
         core_settings['defaults'].update(settings.get('defaults', {}))
         # Same for definitions - we assume plugin authors are responsible enough
         # to avoid using definition names that are likely to cause collisions.
         # Either way, if someone does this on purpose changes are good they want
         # to override a default style so let them do so...
         for name, definition in settings.get('definitions',
                                              {}).viewitems():
             definition['plugin'] = plugin
             if definition.get('stylesheet'):
                 definition['stylesheet'] = definition['stylesheet']
             core_settings['definitions'][name] = definition
     return core_settings
Exemple #39
0
def call_template_hook(*name, **kwargs):
    """Template function to let plugins add their own data to a template.

    :param name: The name of the hook.  Only accepts one argument.
    :param as_list: Return a list instead of a concatenated string
    :param kwargs: Data to pass to the signal receivers.
    """
    if len(name) != 1:
        raise TypeError('call_template_hook() accepts only one positional argument, {} given'.format(len(name)))
    name = name[0]
    as_list = kwargs.pop('as_list', False)
    values = []
    for is_markup, priority, value in values_from_signal(signals.plugin.template_hook.send(unicode(name), **kwargs),
                                                         single_value=True):
        if value:
            if is_markup:
                value = Markup(value)
            heappush(values, (priority, value))
    if as_list:
        return [x[1] for x in values]
    else:
        return Markup(u'\n').join(x[1] for x in values) if values else u''
Exemple #40
0
def _notify_registration(registration,
                         template_name,
                         to_managers=False,
                         attach_rejection_reason=False):
    from indico.modules.events.registration.util import get_ticket_attachments
    attachments = []
    regform = registration.registration_form
    tickets_handled = values_from_signal(
        signals.event.is_ticketing_handled.send(regform), single_value=True)
    if (not to_managers and regform.tickets_enabled and regform.ticket_on_email
            and not any(tickets_handled)
            and registration.state == RegistrationState.complete):
        attachments += get_ticket_attachments(registration)
    if not to_managers and registration.registration_form.attach_ical:
        event_ical = event_to_ical(registration.event)
        attachments.append(('event.ics', event_ical, 'text/calendar'))

    tpl = get_template_module(f'events/registration/emails/{template_name}',
                              registration=registration,
                              attach_rejection_reason=attach_rejection_reason)
    to_list = registration.email if not to_managers else registration.registration_form.manager_notification_recipients
    from_address = registration.registration_form.sender_address if not to_managers else None
    mail = make_email(to_list=to_list,
                      template=tpl,
                      html=True,
                      from_address=from_address,
                      attachments=attachments)
    user = session.user if session else None
    signals.core.before_notification_send.send(
        'notify-registration',
        email=mail,
        registration=registration,
        template_name=template_name,
        attach_rejection_reason=attach_rejection_reason)
    send_email(mail,
               event=registration.registration_form.event,
               module='Registration',
               user=user,
               log_metadata={'registration_id': registration.id})
Exemple #41
0
    def display(cls, template_name, **params):
        from indico.modules.admin import RHAdminBase
        from indico.modules.core.settings import core_settings, social_settings

        title_parts = [cls.title]
        if cls.MANAGEMENT:
            title_parts.insert(0, _('Management'))
        elif isinstance(g.rh, RHAdminBase):
            title_parts.insert(0, _('Administration'))

        injected_bundles = values_from_signal(
            signals.plugin.inject_bundle.send(cls),
            as_list=True,
            multi_value_types=list)
        custom_js = list(current_app.manifest['__custom.js'])
        custom_css = list(current_app.manifest['__custom.css'])
        css_files = map(cls._fix_path, custom_css)
        js_files = map(cls._fix_path, custom_js)

        bundles = itertools.chain(
            (current_app.manifest[x] for x in cls._resolve_bundles()
             if x in current_app.manifest._entries),
            cls.additional_bundles['screen'], injected_bundles)
        print_bundles = itertools.chain(
            (current_app.manifest[x] for x in cls.print_bundles),
            cls.additional_bundles['print'])
        template = cls._prefix_template(template_name)
        return render_template(template,
                               css_files=css_files,
                               js_files=js_files,
                               page_metadata=cls.page_metadata,
                               bundles=bundles,
                               print_bundles=print_bundles,
                               site_name=core_settings.get('site_title'),
                               social=social_settings.get_all(),
                               page_title=' - '.join(
                                   unicode(x) for x in title_parts if x),
                               **params)
Exemple #42
0
def generate_event_component(event, user=None):
    """Generate an event icalendar component from an Indico event."""
    uid = f'indico-event-{event.id}@{url_parse(config.BASE_URL).host}'
    component = generate_basic_component(event, uid)

    # add contact information
    contact_info = event.contact_emails + event.contact_phones
    if contact_info:
        component.add('contact', ';'.join(contact_info))

    # add logo url if event is public
    if event.effective_protection_mode == ProtectionMode.public and event.has_logo:
        component.add('image', event.external_logo_url, {'VALUE': 'URI'})

    # send description to plugins in case one wants to add anything to it
    data = {'description': component.get('description', '')}
    for update in values_from_signal(signals.event.metadata_postprocess.send(
            'ical-export', event=event, data=data, user=user),
                                     as_list=True):
        data.update(update)
    component.add('description', data['description'])

    return component
Exemple #43
0
def _notify_registration(registration, template, to_managers=False):
    attachments = None
    regform = registration.registration_form
    tickets_handled = values_from_signal(
        signals.event.is_ticketing_handled.send(regform), single_value=True)
    if (not to_managers and regform.tickets_enabled and regform.ticket_on_email
            and not any(tickets_handled)
            and registration.state == RegistrationState.complete):
        attachments = get_ticket_attachment(registration)

    template = get_template_module(
        'events/registration/emails/{}'.format(template),
        registration=registration)
    to_list = registration.email if not to_managers else registration.registration_form.manager_notification_recipients
    from_address = registration.registration_form.sender_address if not to_managers else None
    mail = make_email(to_list=to_list,
                      template=template,
                      html=True,
                      from_address=from_address,
                      attachments=attachments)
    send_email(mail,
               event=registration.registration_form.event,
               module='Registration',
               user=session.user)
Exemple #44
0
def test_values_from_signal_as_list():
    vals = ('a', 'b', 'c')
    signal_response = _make_signal_response(vals)
    assert values_from_signal(signal_response, as_list=True) == list(vals)
    assert values_from_signal(signal_response) == set(vals)
Exemple #45
0
def get_file_previewers():
    return values_from_signal(signals.attachments.get_file_previewers.send())
 def _checkProtection(self):
     # check users allowed by plugins
     if any(values_from_signal(signals.event.has_read_access.send(self._conf, user=session.user))):
         return
     RHConferenceBaseDisplay._checkProtection(self)
Exemple #47
0
    def can_manage(self,
                   user,
                   role=None,
                   allow_admin=True,
                   check_parent=True,
                   explicit_role=False):
        """Checks if the user can manage the object.

        :param user: The :class:`.User` to check. May be None if the
                     user is not logged in.
        :param: role: The management role that is needed for the
                      check to succeed.  If not specified, full
                      management privs are required.  May be set to
                      the string ``'ANY'`` to check if the user has
                      any management privileges.  If the user has
                      `full_access` privileges, he's assumed to have
                      all possible roles.
        :param allow_admin: If admin users should always have access
        :param check_parent: If the parent object should be checked.
                             In this case the role is ignored; only
                             full management access is inherited to
                             children.
        :param explicit_role: If the specified role should be checked
                              explicitly instead of short-circuiting
                              the check for Indico admins or managers.
                              When this option is set to ``True``, the
                              values of `allow_admin` and `check_parent`
                              are ignored.  This also applies if `role`
                              is None in which case this argument being
                              set to ``True`` is equivalent to
                              `allow_admin` and `check_parent` being set
                              to ``False``.
        """
        if role is not None and role != 'ANY' and role not in get_available_roles(
                type(self)):
            raise ValueError("role '{}' is not valid for '{}' objects".format(
                role,
                type(self).__name__))

        if user is None:
            # An unauthorized user is never allowed to perform management operations.
            # Not even signals may override this since management code generally
            # expects session.user to be not None.
            # XXX: Legacy modification keys are checked outside
            return False

        # Trigger signals for protection overrides
        rv = values_from_signal(signals.acl.can_manage.send(
            type(self),
            obj=self,
            user=user,
            role=role,
            allow_admin=allow_admin,
            check_parent=check_parent,
            explicit_role=explicit_role),
                                single_value=True)
        if rv:
            # in case of contradictory results (shouldn't happen at all)
            # we stay on the safe side and deny access
            return all(rv)

        # Usually admins can access everything, so no need for checks
        if not explicit_role and allow_admin and user.is_admin:
            return True

        if any(user in entry.principal for entry in iter_acl(self.acl_entries)
               if entry.has_management_role(
                   role, explicit=(explicit_role and role is not None))):
            return True

        if not check_parent or explicit_role:
            return False

        # the parent can be either an object inheriting from this
        # mixin or a legacy object with an AccessController
        parent = self.protection_parent
        if parent is None:
            # This should be the case for the top-level object,
            # i.e. the root category
            return False
        elif hasattr(parent, 'can_manage'):
            return parent.can_manage(user, allow_admin=allow_admin)
        elif hasattr(parent, 'canUserModify'):
            return parent.canUserModify(user.as_avatar)
        else:
            raise TypeError(
                'protection_parent of {} is of invalid type {} ({})'.format(
                    self, type(parent), parent))
Exemple #48
0
    def can_access(self, user, allow_admin=True):
        """Checks if the user can access the object.

        :param user: The :class:`.User` to check. May be None if the
                     user is not logged in.
        :param allow_admin: If admin users should always have access
        """

        # Trigger signals for protection overrides
        rv = values_from_signal(signals.acl.can_access.send(
            type(self), obj=self, user=user, allow_admin=allow_admin),
                                single_value=True)
        if rv:
            # in case of contradictory results (shouldn't happen at all)
            # we stay on the safe side and deny access
            return all(rv)

        # Usually admins can access everything, so no need for checks
        if allow_admin and user and user.is_admin:
            return True

        if self.protection_mode == ProtectionMode.public:
            # if it's public we completely ignore the parent protection
            # this is quite ugly which is why it should only be allowed
            # in rare cases (e.g. events which might be in a protected
            # category but should be public nonetheless)
            return True
        elif self.protection_mode == ProtectionMode.protected:
            # if it's protected, we also ignore the parent protection
            # and only check our own ACL
            if user is None:
                return False
            elif any(user in entry.principal
                     for entry in iter_acl(self.acl_entries)):
                return True
            elif isinstance(self, ProtectionManagersMixin):
                return self.can_manage(user, allow_admin=allow_admin)
            else:
                return False
        elif self.protection_mode == ProtectionMode.inheriting:
            # if it's inheriting, we only check the parent protection
            # unless `inheriting_have_acl` is set, in which case we
            # might not need to check the parents at all
            if (self.inheriting_have_acl and user is not None
                    and any(user in entry.principal
                            for entry in iter_acl(self.acl_entries))):
                return True
            # the parent can be either an object inheriting from this
            # mixin or a legacy object with an AccessController
            parent = self.protection_parent
            if parent is None:
                # This should be the case for the top-level object,
                # i.e. the root category, which shouldn't allow
                # ProtectionMode.inheriting as it makes no sense.
                raise TypeError('protection_parent of {} is None'.format(self))
            elif hasattr(parent, 'can_access'):
                return parent.can_access(user, allow_admin=allow_admin)
            elif hasattr(parent, 'canAccess'):
                return parent.canAccess(
                    AccessWrapper(user.as_avatar if user else None))
            else:
                raise TypeError(
                    'protection_parent of {} is of invalid type {} ({})'.
                    format(self, type(parent), parent))
        else:
            # should never happen, but since this is a sensitive area
            # we better fail loudly if we have garbage
            raise ValueError('Invalid protection mode: {}'.format(
                self.protection_mode))
Exemple #49
0
 def is_ticket_blocked(self):
     """Check whether the ticket is blocked by a plugin"""
     return any(
         values_from_signal(signals.event.is_ticket_blocked.send(self),
                            single_value=True))
Exemple #50
0
def test_values_from_signal_as_list():
    vals = ('a', 'b', 'c')
    signal_response = _make_signal_response(vals)
    assert values_from_signal(signal_response, as_list=True) == list(vals)
    assert values_from_signal(signal_response) == set(vals)
Exemple #51
0
def test_values_from_signal_skip_none():
    vals = ('a', None, 'b', 'c')
    signal_response = _make_signal_response(vals)
    assert values_from_signal(signal_response, skip_none=False) == set(vals)
    assert values_from_signal(signal_response) == set(vals) - {None}
Exemple #52
0
def test_values_from_signal_single_value():
    vals = ('a', _make_gen('b', 'c'))
    signal_response = _make_signal_response(vals)
    assert values_from_signal(signal_response, single_value=True) == set(vals)
    assert values_from_signal(signal_response) == {'a', 'b', 'c'}
Exemple #53
0
 def __init__(self, rh, event_, **kwargs):
     custom_links = dict(values_from_signal(signals.event.timetable_buttons.send(self)))
     WPEventManagement.__init__(self, rh, event_, custom_links=custom_links, **kwargs)
Exemple #54
0
 def __init__(self, rh, conference, **kwargs):
     custom_links = dict(values_from_signal(signals.event.timetable_buttons.send(self)))
     WPConferenceModifBase.__init__(self, rh, conference, custom_links=custom_links, **kwargs)
Exemple #55
0
def get_file_previewers():
    return values_from_signal(signals.attachments.get_file_previewers.send())
Exemple #56
0
def test_values_from_signal_return_plugins():
    vals = ('a', 'b', 'c')
    signal_response = _make_signal_response(vals) + [(MagicMock(indico_plugin='foo'), 'd')]
    assert values_from_signal(signal_response, return_plugins=True) == set(zip([None] * 3, vals) + [('foo', 'd')])
    assert values_from_signal(signal_response) == set(vals + ('d',))
Exemple #57
0
def setup_jinja_customization(app):
    # add template customization paths provided by plugins
    paths = values_from_signal(
        signals.plugin.get_template_customization_paths.send())
    app.jinja_env.loader.fs_loader.searchpath += sorted(paths)
Exemple #58
0
    def _build_event_api_data(self, event):
        can_manage = self.user is not None and event.can_manage(self.user)
        data = self._build_event_api_data_base(event)
        data.update({
            '_fossil': self.fossils_mapping['event'].get(self._detail_level),
            'categoryId': event.category_id,
            'category': event.category.title,
            'note': build_note_api_data(event.note),
            'roomFullname': event.room_name,
            'url': event.external_url,
            'creationDate': self._serialize_date(event.created_dt),
            'creator': self._serialize_person(event.creator, person_type='Avatar', can_manage=can_manage),
            'hasAnyProtection': event.effective_protection_mode != ProtectionMode.public,
            'roomMapURL': event.room.map_url if event.room else None,
            'folders': build_folders_api_data(event),
            'chairs': self._serialize_persons(event.person_links, person_type='ConferenceChair', can_manage=can_manage),
            'material': build_material_legacy_api_data(event) + filter(None, [build_note_legacy_api_data(event.note)])
        })

        event_category_path = event.category.chain
        visibility = {'id': '', 'name': 'Everywhere'}
        if event.visibility is None:
            pass  # keep default
        elif event.visibility == 0:
            visibility['name'] = 'Nowhere'
        elif event.visibility:
            try:
                path_segment = event_category_path[-event.visibility]
            except IndexError:
                pass
            else:
                visibility['id'] = path_segment['id']
                visibility['name'] = path_segment['title']
        data['visibility'] = visibility

        if can_manage:
            data['allowed'] = self._serialize_access_list(event)
        if self._detail_level in {'contributions', 'subcontributions'}:
            data['contributions'] = []
            for contribution in event.contributions:
                include_subcontribs = self._detail_level == 'subcontributions'
                serialized_contrib = self._serialize_contribution(contribution, include_subcontribs)
                data['contributions'].append(serialized_contrib)
        elif self._detail_level == 'sessions':
            # Contributions without a session
            data['contributions'] = []
            for contribution in event.contributions:
                if not contribution.session:
                    serialized_contrib = self._serialize_contribution(contribution)
                    data['contributions'].append(serialized_contrib)

            data['sessions'] = []
            for session_ in event.sessions:
                data['sessions'].extend(self._build_session_api_data(session_))
        if self._occurrences:
            data['occurrences'] = fossilize(self._calculate_occurrences(event, self._fromDT, self._toDT,
                                            pytz.timezone(config.DEFAULT_TIMEZONE)),
                                            {Period: IPeriodFossil}, tz=self._tz, naiveTZ=config.DEFAULT_TIMEZONE)
        # check whether the plugins want to add/override any data
        for update in values_from_signal(
                signals.event.metadata_postprocess.send('http-api', event=event, data=data), as_list=True):
            data.update(update)
        return data