def test_values_from_signal_return_plugins(): vals = ('a', 'b', 'c') signal_response = _make_signal_response(vals) + [ (MagicMock(fossir_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', ))
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'}
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)
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('\n').join(x[1] for x in values) if values else ''
def _notify_registration(registration, template, to_managers=False): from fossir.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( '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)
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)
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
def validate(self): valid = super(fossirForm, 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
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
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(fossirFormMeta, 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(fossirFormMeta, 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)
def settings(self): core_path = os.path.join(get_root_path('fossir'), '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 core_settings['definitions'][name] = definition return core_settings
def get_file_previewers(): return values_from_signal(signals.attachments.get_file_previewers.send())
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 fossir 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. 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) else: raise TypeError('protection_parent of {} is of invalid type {} ({})'.format(self, type(parent), parent))
def get_plugin_conference_themes(): data = values_from_signal(signals.plugin.get_conference_themes.send(), return_plugins=True) return {':'.join((plugin.name, name)): (path, title) for plugin, (name, path, title) in data}
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'}
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)
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}
def test_values_from_signal(retvals, expected): signal_response = _make_signal_response(retvals) assert values_from_signal(signal_response) == expected
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))