Example #1
0
def flash_if_unregistered(event, get_person_links):
    """Flash message when adding users with no indico account

    :param event: Current event
    :param get_person_links: Callable returning list of person links to
                             check
    """
    old_non_users = {pl for pl in get_person_links() if pl.person.user is None}
    yield
    new_non_users = {pl for pl in get_person_links() if pl.person.user is None}
    added_non_users = len(new_non_users - old_non_users)
    if not added_non_users:
        return
    warning = ngettext('You have added a user with no Indico account.',
                       'You have added {} users with no Indico account.', added_non_users).format(added_non_users)
    msg = _('An Indico account may be needed to upload materials and/or manage contents.')
    if event.can_manage(session.user):
        continue_msg = (escape(_('To invite them, please go to the {link_start}Roles page{link_end}'))
                        .format(link_start=Markup('<a href="{}">').format(url_for('persons.person_list', event)),
                                link_end=Markup('</a>')))
    else:
        continue_msg = ngettext('Please contact the manager if you think this user should be able to access these '
                                'features.',
                                'Please contact the manager if you think these users should be able to access '
                                'these features.', added_non_users)
    flash(Markup(' ').join([warning, msg, continue_msg]), 'warning')
Example #2
0
def process_vc_room_association(plugin, event, vc_room, form, event_vc_room=None, allow_same_room=False):
    # disable autoflush, so that the new event_vc_room does not influence the result
    with db.session.no_autoflush:
        if event_vc_room is None:
            event_vc_room = VCRoomEventAssociation()

        plugin.update_data_association(event, vc_room, event_vc_room, form.data)

        existing = set()
        if event_vc_room.link_object is not None:
            # check whether there is a room-event association already present
            # for the given event, room and plugin
            q = VCRoomEventAssociation.find(
                VCRoomEventAssociation.event_new == event,
                VCRoomEventAssociation.link_object == event_vc_room.link_object,
                _join=VCRoom
            )
            if allow_same_room:
                q = q.filter(VCRoom.id != vc_room.id)
            existing = {x.vc_room for x in q}

    if event_vc_room.link_type != VCRoomLinkType.event and existing:
        transaction.abort()
        flash(_("There is already a VC room attached to '{link_object_title}'.").format(
            link_object_title=resolve_title(event_vc_room.link_object)), 'error')
        return None
    elif event_vc_room.link_type == VCRoomLinkType.event and vc_room in existing:
        transaction.abort()
        flash(_("This {plugin_name} room is already attached to the event.").format(plugin_name=plugin.friendly_name),
              'error')
        return None
    else:
        return event_vc_room
Example #3
0
 def _check_access(self):
     if not self.category.can_access(session.user):
         msg = [_("You are not authorized to access this category.")]
         if self.category.no_access_contact:
             msg.append(_("If you believe you should have access, please contact {}")
                        .format(self.category.no_access_contact))
         raise Forbidden(' '.join(msg))
Example #4
0
def get_visibility_options(category_or_event, allow_invisible=True):
    """Return the visibility options available for the category or event."""
    if isinstance(category_or_event, Event):
        category = category_or_event.category
        event = category_or_event
    else:
        category = category_or_event
        event = None

    def _category_above_message(number):
        return ngettext('From the category above', 'From {} categories above', number).format(number)

    options = [(n + 1, ('{} \N{RIGHTWARDS ARROW} "{}"'.format(_category_above_message(n).format(n), title)))
               for n, title in enumerate(category.chain_titles[::-1])]
    if event is None:
        options[0] = (1, _("From this category only"))
    else:
        options[0] = (1, '{} \N{RIGHTWARDS ARROW} "{}"'.format(_("From the current category only"), category.title))
    options[-1] = ('', _("From everywhere"))

    if allow_invisible:
        options.insert(0, (0, _("Invisible")))

    # In case the current visibility is higher than the distance to the root category
    if category_or_event.visibility is not None and not any(category_or_event.visibility == x[0] for x in options):
        options.append((category_or_event.visibility,
                        '({} \N{RIGHTWARDS ARROW} {})'.format(_category_above_message(category_or_event.visibility),
                                                              _("Everywhere"))))
    return options
Example #5
0
 def _getBody(self, params):
     params['period_options'] = [
         ('pastmonth', _('Past month')),
         ('thisyear', _('This year')),
         ('sinceever', _('Since ever'))
     ]
     return WTemplated('RoomBookingRoomStats').getHTML(params)
Example #6
0
 def _checkSessionUser(self):
     if session.user is None:
         raise Forbidden(response=redirect_to_login(reason=_('You are trying to sign an agreement that requires '
                                                             'you to be logged in')))
     if self.agreement.user != session.user:
         raise Forbidden(_('Please log in as {name} to sign this agreement.')
                         .format(name=self.agreement.user.full_name))
Example #7
0
 def _process(self):
     f = request.files['logo']
     try:
         img = Image.open(f)
     except IOError:
         flash(_('You cannot upload this file as a logo.'), 'error')
         return jsonify_data(content=None)
     if img.format.lower() not in {'jpeg', 'png', 'gif'}:
         flash(_('The file has an invalid format ({format})').format(format=img.format), 'error')
         return jsonify_data(content=None)
     if img.mode == 'CMYK':
         flash(_('The logo you uploaded is using the CMYK colorspace and has been converted to RGB. Please check if '
                 'the colors are correct and convert it manually if necessary.'), 'warning')
         img = img.convert('RGB')
     image_bytes = BytesIO()
     img.save(image_bytes, 'PNG')
     image_bytes.seek(0)
     content = image_bytes.read()
     self.event.logo = content
     self.event.logo_metadata = {
         'hash': crc32(content),
         'size': len(content),
         'filename': os.path.splitext(secure_filename(f.filename, 'logo'))[0] + '.png',
         'content_type': 'image/png'
     }
     flash(_('New logo saved'), 'success')
     logger.info("New logo '%s' uploaded by %s (%s)", f.filename, session.user, self.event)
     return jsonify_data(content=get_logo_data(self.event))
Example #8
0
File: forms.py Project: fph/indico
 def __init__(self, *args, **kwargs):
     super(SplitCategoryForm, self).__init__(*args, **kwargs)
     if self.all_selected.data:
         self.event_id.data = []
         self.first_category.label.text = _('Category name')
         self.first_category.description = _('The events will be moved into a new sub-category with this title.')
         del self.second_category
Example #9
0
    def _process(self):
        if self.verification_email_sent and 'token' in request.args:
            email = secure_serializer.loads(request.args['token'], max_age=3600, salt='link-identity-email')
            if email not in self.emails:
                raise BadData('Emails do not match')
            session['login_identity_info']['email_verified'] = True
            session.modified = True
            flash(_('You have successfully validated your email address and can now proceed with the login.'),
                  'success')
            return redirect(url_for('.link_account', provider=self.identity_info['provider']))

        if self.must_choose_email:
            form = SelectEmailForm()
            form.email.choices = zip(self.emails, self.emails)
        else:
            form = IndicoForm()

        if form.validate_on_submit():
            if self.email_verified:
                return self._create_identity()
            elif not self.verification_email_sent:
                return self._send_confirmation(form.email.data if self.must_choose_email else self.emails[0])
            else:
                flash(_('The validation email has already been sent.'), 'warning')

        return WPAuth.render_template('link_identity.html', identity_info=self.identity_info, user=self.user,
                                      email_sent=self.verification_email_sent, emails=' / '.join(self.emails),
                                      form=form, must_choose_email=self.must_choose_email)
Example #10
0
File: admins.py Project: fph/indico
    def _createTabCtrl(self):
        self._tabCtrl = wcomponents.TabControl()

        self._subTabConfiguration = self._tabCtrl.newTab("configuration", _("Configuration"),
                                                         urlHandlers.UHAdminsSystem.getURL())
        self._subTabMaintenance = self._tabCtrl.newTab("maintenance", _("Maintenance"),
                                                       urlHandlers.UHMaintenance.getURL())
Example #11
0
File: base.py Project: NIIF/indico
 def _processForbidden(self, e):
     message = _("Access Denied")
     if e.description == Forbidden.description:
         explanation = _("You are not allowed to access this page.")
     else:
         explanation = e.description
     return WErrorWSGI((message, explanation)).getHTML()
Example #12
0
 def _process(self):
     quiet = request.form.get('quiet') == '1'
     force = request.form.get('force') == '1'
     persistent = request.form.get('persistent') == '1' and api_settings.get('allow_persistent')
     old_key = self.user.api_key
     if old_key:
         if not force:
             raise BadRequest('There is already an API key for this user')
         if old_key.is_blocked and not session.user.is_admin:
             raise Forbidden
         old_key.is_active = False
         db.session.flush()
     key = APIKey(user=self.user)
     db.session.add(key)
     if persistent:
         key.is_persistent_allowed = persistent
     elif old_key:
         key.is_persistent_allowed = old_key.is_persistent_allowed
     if not quiet:
         if old_key:
             flash(_('Your API key has been successfully replaced.'), 'success')
             if old_key.use_count:
                 flash(_('Please update any applications which use old key.'), 'warning')
         else:
             flash(_('Your API key has been successfully created.'), 'success')
     db.session.flush()
     return redirect_or_jsonify(url_for('api.user_profile'), flash=not quiet,
                                is_persistent_allowed=key.is_persistent_allowed)
Example #13
0
def test_translation_plugins(app, tmpdir):
    session.lang = 'fr_FR'
    plugin = MockPlugin(plugin_engine, app)
    app.extensions['pluginengine'].plugins['dummy'] = plugin
    plugin.root_path = tmpdir.strpath
    french_core_str = DICTIONARIES['fr_FR']['This is not a string']
    french_plugin_str = "This is not le french string"

    trans_dir = os.path.join(plugin.root_path, 'translations', 'fr_FR', 'LC_MESSAGES')
    os.makedirs(trans_dir)

    # Create proper *.mo file for plugin translation
    with open(os.path.join(trans_dir, 'messages.mo'), 'wb') as f:
        catalog = Catalog(locale='fr_FR', domain='plugin')
        catalog.add("This is not a string", "This is not le french string")
        write_mo(f, catalog)

    gettext_plugin = make_bound_gettext('dummy')

    assert _(u'This is not a string') == french_core_str
    assert gettext_context(u"This is not a string") == french_core_str
    assert gettext_plugin(u"This is not a string") == french_plugin_str

    with plugin.plugin_context():
        assert _(u'This is not a string') == french_core_str
        assert gettext_context(u"This is not a string") == french_plugin_str
        assert gettext_plugin(u"This is not a string") == french_plugin_str
Example #14
0
    def _check_currencies(self, form):
        """Checks if the currencies are valid.

        :return: `(auto_currency, invalid_currency)` - tuple containing the currency that should
                 be automatically set on the event and a flag if the currency issues cannot be resolved
                 automatically and require user interaction (i.e. saving the plugin settings is disallowed)
        """
        messages = []
        event = self._conf
        valid_currencies = self.plugin.valid_currencies
        currency = event_settings.get(event, 'currency')
        if valid_currencies is None or currency in valid_currencies:
            return None, False, messages

        if len(valid_currencies) == 1:
            auto_currency = list(valid_currencies)[0]
            for plugin in get_active_payment_plugins(event).itervalues():
                if plugin.valid_currencies is not None and auto_currency not in plugin.valid_currencies:
                    messages.append(('error', _("This payment method only supports {}, but the payment method "
                                                "'{}' doesn't.").format(auto_currency, plugin.title)))
                    return None, True, messages
            if not form.is_submitted():
                messages.append(('warning', _("This payment method only supports {0}. Enabling it will automatically "
                                              "change the currency of the event to {0}!").format(auto_currency)))
            return auto_currency, False, messages

        if not form.is_submitted():
            messages.append(('error', _("To enable this payment method, please use one of the following "
                                        "currencies: {}").format(', '.join(valid_currencies))))
        return None, True, messages
Example #15
0
 def _getNavigationDrawer(self):
     if "user_id" in request.view_args:
         user = User.get(request.view_args["user_id"])
         profile_breadcrumb = _("Profile of {name}").format(name=user.full_name)
     else:
         profile_breadcrumb = _("My Profile")
     return WSimpleNavigationDrawer(profile_breadcrumb)
Example #16
0
 def _process(self):
     query = LocalGroup.query.options(joinedload(LocalGroup.members)).order_by(db.func.lower(LocalGroup.name))
     groups = [g.proxy for g in query]
     providers = [p for p in multipass.identity_providers.itervalues() if p.supports_groups]
     form = SearchForm(obj=FormDefaults(exact=True))
     if not providers:
         del form.provider
     else:
         form.provider.choices = [("", _("All")), ("indico", _("Local Groups"))] + [
             (p.name, p.title) for p in sorted(providers, key=attrgetter("title"))
         ]
     search_results = None
     if form.validate_on_submit():
         search_providers = None if not providers or not form.provider.data else {form.provider.data}
         search_results = GroupProxy.search(form.name.data, exact=form.exact.data, providers=search_providers)
         search_results.sort(key=attrgetter("provider", "name"))
     provider_titles = {p.name: p.title for p in multipass.identity_providers.itervalues()}
     provider_titles[None] = _("Local")
     return WPGroupsAdmin.render_template(
         "groups.html",
         groups=groups,
         providers=providers,
         form=form,
         search_results=search_results,
         provider_titles=provider_titles,
     )
Example #17
0
File: forms.py Project: fph/indico
 def validate_email(self, field):
     user = self.user
     if user is None:
         raise ValidationError(_('There is no profile with this email address.'))
     elif not user.local_identities:
         # XXX: Should we allow creating a new identity instead? Would be user-friendly for sure!
         raise ValidationError(_('This profile has no local account.'))
Example #18
0
def get_time_changes_notifications(changes, tzinfo, entry=None):
    notifications = []
    for obj, change in changes.iteritems():
        if entry:
            if entry.object == obj:
                continue
            if not isinstance(obj, Event) and obj.timetable_entry in entry.children:
                continue
        msg = None
        if isinstance(obj, Event):
            if 'start_dt' in change:
                new_time = change['start_dt'][1]
                msg = _("Event start time changed to {}")
            elif 'end_dt' in change:
                new_time = change['end_dt'][1]
                msg = _("Event end time changed to {}")
            else:
                raise ValueError("Invalid change in event.")
        elif isinstance(obj, SessionBlock):
            if 'start_dt' in change:
                new_time = change['start_dt'][1]
                msg = _("Session block start time changed to {}")
            elif 'end_dt' in change:
                new_time = change['end_dt'][1]
                msg = _("Session block end time changed to {}")
            else:
                raise ValueError("Invalid change in session block.")
        if msg:
            notifications.append(msg.format(format_time(new_time, timezone=tzinfo)))
    return notifications
Example #19
0
 def _checkParams(self, params):
     l = locators.CategoryWebLocator(params)
     self._target = l.getObject()
     if self._target is None:
         raise NotFoundError(_("The category with id '{}' does not exist or has been deleted").format(
                             params["categId"]),
                             title=_("Category not found"))
Example #20
0
def _extend_event_menu(sender, **kwargs):
    from indico.modules.events.registration.models.forms import RegistrationForm
    from indico.modules.events.registration.models.registrations import Registration

    def _visible_registration(event):
        if not event.has_feature('registration'):
            return False
        if RegistrationForm.query.with_parent(event).filter(RegistrationForm.is_scheduled).has_rows():
            return True
        if not session.user:
            return False
        return (Registration.query.with_parent(event)
                .join(Registration.registration_form)
                .filter(Registration.user == session.user,
                        ~Registration.is_deleted,
                        ~RegistrationForm.is_deleted)
                .has_rows())

    def _visible_participant_list(event):
        return event.has_feature('registration')

    yield MenuEntryData(_('Registration'), 'registration', 'event_registration.display_regform_list', position=10,
                        visible=_visible_registration)
    yield MenuEntryData(_('Participant List'), 'participants', 'event_registration.participant_list', position=11,
                        visible=_visible_participant_list, static_site=True)
Example #21
0
def _sidemenu_sections(sender, **kwargs):
    user_has_rooms = session.user is not None and Room.user_owns_rooms(session.user)

    yield SideMenuSection('search', _("Search"), 40, icon='search', active=True)
    if user_has_rooms:
        yield SideMenuSection('my_rooms', _("My Rooms"), 30, icon='user')
    yield SideMenuSection('blocking', _("Room Blocking"), 20, icon='lock')
Example #22
0
def event_or_shorturl(confId, shorturl_namespace=False, force_overview=False):
    func = None
    event_ = Event.get(int(confId)) if confId.isdigit() else None
    if event_ and event_.is_deleted:
        raise NotFound(_('This event has been deleted.'))
    elif event_:
        # For obvious reasons an event id always comes first.
        # If it's used within the short url namespace we redirect to the event namespace, otherwise
        # we call the RH to display the event
        if shorturl_namespace:
            func = lambda: redirect(event_.url)
        else:
            request.view_args['confId'] = int(request.view_args['confId'])
            func = lambda: RHDisplayEvent().process()
    else:
        shorturl_event = (Event.query
                          .filter(db.func.lower(Event.url_shortcut) == confId.lower(),
                                  ~Event.is_deleted)
                          .one_or_none())
        if (shorturl_namespace or config.ROUTE_OLD_URLS) and shorturl_event:
            if shorturl_namespace:
                # Correct namespace => redirect to the event
                func = lambda: redirect(shorturl_event.url)
            else:
                # Old event namespace => 301-redirect to the new shorturl first to get Google etc. to update it
                func = lambda: redirect(shorturl_event.short_url, 301)
        elif is_legacy_id(confId):
            mapping = LegacyEventMapping.find_first(legacy_event_id=confId)
            if mapping is not None:
                url = url_for('events.display', confId=mapping.event_id)
                func = lambda: redirect(url, 301)

    if func is None:
        raise NotFound(_('An event with this ID/shortcut does not exist.'))
    return func()
Example #23
0
 def _getBody(self, params):
     params["period_options"] = [
         ("pastmonth", _("Past month")),
         ("thisyear", _("This year")),
         ("sinceever", _("Since ever")),
     ]
     return WTemplated("RoomBookingRoomStats").getHTML(params)
Example #24
0
 def _getNavigationDrawer(self):
     if 'user_id' in request.view_args:
         user = User.get(request.view_args['user_id'])
         profile_breadcrumb = _('Profile of {name}').format(name=user.full_name)
     else:
         profile_breadcrumb = _('My Profile')
     return WSimpleNavigationDrawer(profile_breadcrumb)
Example #25
0
 def pre_validate(self, form):
     if self.best_unit in self.units:
         return
     if self.object_data is None:
         raise ValueError(_('Please choose a valid unit.'))
     if self.object_data != self.data:
         raise ValueError(_('Please choose a different unit or keep the previous value.'))
Example #26
0
    def process_form(self):
        form = self.form
        if not form.validate_on_submit():
            return
        if not self.request or not self.request.can_be_modified:
            req = Request(event=self.event, definition=self.definition, created_by_user=session.user)
            new = True
        else:
            req = self.request
            new = False

        try:
            with db.session.no_autoflush:
                self.definition.send(req, form.data)
        except RequestModuleError:
            self.commit = False
            flash_msg = _('There was a problem sending your request ({0}). Please contact support.')
            flash(flash_msg.format(self.definition.title), 'error')
        else:
            if new:
                flash_msg = (_("Your request ({0}) has been accepted.") if req.state == RequestState.accepted
                             else _("Your request ({0}) has been sent."))
            else:
                flash_msg = _("Your request ({0}) has been modified.")
            flash(flash_msg.format(self.definition.title), 'success')
        if self.is_manager:
            return redirect(url_for('.event_requests_details', self.event, type=self.definition.name))
        else:
            return redirect(url_for('.event_requests', self.event))
Example #27
0
 def process_form(self):
     form = self.manager_form
     if self.request.state == RequestState.withdrawn:
         return
     elif not form.validate_on_submit():
         # very unlikely, unless the definition uses a custom form
         return
     if 'action_accept' in form and form.action_accept.data:
         action = 'accept'
     elif 'action_reject' in form and form.action_reject.data:
         action = 'reject'
     elif 'action_save' in form and form.action_save.data:
         action = 'save'
     else:
         # This happens when the request was already processed, e.g. in another
         # tab or if you simply click the submit button twice.  No nee to fail;
         # just don't do anything.
         return redirect(url_for('.event_requests_details', self.request))
     if action == 'accept':
         self.definition.accept(self.request, self.manager_form.data, session.user)
         flash(_('You have accepted this request.'), 'info')
     elif action == 'reject':
         self.definition.reject(self.request, self.manager_form.data, session.user)
         flash(_('You have rejected this request.'), 'info')
     elif action == 'save':
         self.definition.manager_save(self.request, self.manager_form.data)
         flash(_("You have updated the request (only management-specific data)."), 'info')
     return redirect(url_for('.event_requests_details', self.request))
Example #28
0
    def _process(self):
        if session.user:
            return redirect(url_for('misc.index'))
        handler = MultipassRegistrationHandler(self) if self.identity_info else LocalRegistrationHandler(self)
        verified_email = self._get_verified_email()
        if verified_email is not None:
            handler.email_verified(verified_email)
            flash(_('You have successfully validated your email address and can now proceeed with the registration.'),
                  'success')
            return redirect(url_for('.register', provider=self.provider_name))

        form = handler.create_form()
        # Check for pending users if we have verified emails
        pending = None
        if not handler.must_verify_email:
            pending = User.find_first(~User.is_deleted, User.is_pending,
                                      User.all_emails.contains(db.func.any(list(handler.get_all_emails(form)))))

        if form.validate_on_submit():
            if handler.must_verify_email:
                return self._send_confirmation(form.email.data)
            else:
                return self._create_user(form, handler, pending)
        elif not form.is_submitted() and pending:
            # If we have a pending user, populate empty fields with data from that user
            for field in form:
                value = getattr(pending, field.short_name, '')
                if value and not field.data:
                    field.data = value
        if pending:
            flash(_("There is already some information in Indico that concerns you. "
                    "We are going to link it automatically."), 'info')
        return WPAuth.render_template('register.html', form=form, local=(not self.identity_info),
                                      must_verify_email=handler.must_verify_email, widget_attrs=handler.widget_attrs,
                                      email_sent=session.pop('register_verification_email_sent', False))
Example #29
0
 def __call__(self, form, field):
     if field.data is None:
         return
     field_dt = as_utc(field.data)
     earliest_dt = self.get_earliest(form, field)
     latest_dt = self.get_latest(form, field)
     if field_dt != field.object_data:
         if earliest_dt and field_dt < earliest_dt:
             if self.earliest_now:
                 msg = _("'{}' can't be in the past ({})").format(
                     field.label, field.timezone)
             else:
                 dt = format_datetime(earliest_dt, timezone=field.timezone)
                 msg = _("'{}' can't be before {} ({})").format(
                     field.label, dt, field.timezone)
             raise ValidationError(msg)
         if latest_dt and field_dt > latest_dt:
             if self.latest_now:
                 msg = _("'{}' can't be in the future ({})").format(
                     field.label, field.timezone)
             else:
                 dt = format_datetime(latest_dt, timezone=field.timezone)
                 msg = _("'{}' can't be after {} ({})").format(
                     field.label, dt, field.timezone)
             raise ValidationError(msg)
Example #30
0
 def _checkProtection(self):
     LoggedOnlyService._checkProtection(self)
     if self._aw.getUser():
         if not self._target.canModify(self._aw):
             raise ServiceError("ERR-U6", _("You are not allowed to perform this request"))
     else:
         raise ServiceError("ERR-U7", _("You are currently not authenticated. Please log in again."))
Example #31
0
class RegistrationFullNameNoTitlePlaceholderD(FullNamePlaceholderBase):
    name = 'full_name_no_title_d'
    description = _("Full Name D (abbrev., no title)")
    with_title = False
    name_options = {'last_name_upper': True, 'abbrev_first_name': True}
Example #32
0
class RegistrationAffiliationPlaceholder(RegistrationPDPlaceholder):
    name = 'affiliation'
    description = _("Institution")
    field = 'affiliation'
Example #33
0
class RegistrationAmountPlaceholder(RegistrationPlaceholder):
    name = 'amount'
    description = _("Amount")
    field = 'price'
Example #34
0
class RegistrationEmailPlaceholder(RegistrationPlaceholder):
    name = 'email'
    description = _("E-mail")
    field = 'email'
Example #35
0
class RegistrationLastNamePlaceholder(RegistrationPlaceholder):
    name = 'last_name'
    description = _("Last Name")
    field = 'last_name'
Example #36
0
class RegistrationFirstNamePlaceholder(RegistrationPlaceholder):
    name = 'first_name'
    description = _("First Name")
    field = 'first_name'
Example #37
0
class RegistrationTitlePlaceholder(RegistrationPDPlaceholder):
    name = 'title'
    description = _("Title")
    field = 'title'
Example #38
0
class RegistrationFullNamePlaceholderC(FullNamePlaceholderBase):
    name = 'full_name_c'
    description = _("Full Name C")
    with_title = True
    name_options = {'last_name_first': False, 'last_name_upper': True}
Example #39
0
class RegistrationFullNamePlaceholderB(FullNamePlaceholderBase):
    name = 'full_name_b'
    description = _("Full Name B")
    with_title = True
    name_options = {'last_name_first': False}
Example #40
0
class RegistrationFullNameNoTitlePlaceholderC(FullNamePlaceholderBase):
    name = 'full_name_no_title_c'
    description = _("Full Name C (no title)")
    with_title = False
    name_options = {'last_name_upper': True}
Example #41
0
class RegistrationFullNamePlaceholder(FullNamePlaceholderBase):
    name = 'full_name'
    description = _("Full Name")
    with_title = True
    name_options = {}
Example #42
0
class RegistrationFullNameNoTitlePlaceholderB(FullNamePlaceholderBase):
    name = 'full_name_b_no_title'
    description = _("Full Name B (no title)")
    with_title = False
    name_options = {'last_name_first': False}
Example #43
0
def _extend_admin_menu(sender, **kwargs):
    if session.user.is_admin:
        return SideMenuItem('groups',
                            _('Groups'),
                            url_for('groups.groups'),
                            section='user_management')
Example #44
0
class RegistrationFullNameNoTitlePlaceholder(FullNamePlaceholderBase):
    name = 'full_name_no_title'
    description = _("Full Name (no title)")
    with_title = False
    name_options = {}
Example #45
0
 def validate_url_template(self, field):
     if field.data and '{value}' not in field.data:
         raise ValidationError(
             _("The URL template must contain the placeholder '{value}'."))
Example #46
0
           'RegistrationFullNamePlaceholderC',
           'RegistrationFullNameNoTitlePlaceholderC',
           'RegistrationFullNamePlaceholderD',
           'RegistrationFullNameNoTitlePlaceholderD',
           'RegistrationTitlePlaceholder', 'RegistrationFirstNamePlaceholder',
           'RegistrationLastNamePlaceholder',
           'RegistrationTicketQRPlaceholder', 'RegistrationEmailPlaceholder',
           'RegistrationAmountPlaceholder',
           'RegistrationAffiliationPlaceholder',
           'RegistrationPositionPlaceholder', 'RegistrationAddressPlaceholder',
           'RegistrationCountryPlaceholder', 'RegistrationPhonePlaceholder',
           'EventTitlePlaceholder', 'CategoryTitlePlaceholder',
           'EventRoomPlaceholder', 'EventVenuePlaceholder',
           'EventSpeakersPlaceholder')

GROUP_TITLES = {'registrant': _("Registrant Data"), 'event': _("Event Data")}


class RegistrationPlaceholder(Placeholder):
    group = 'registrant'

    @classmethod
    def render(cls, registration):
        return getattr(registration, cls.field)


class RegistrationPDPlaceholder(Placeholder):
    group = 'registrant'

    @classmethod
    def render(cls, registration):
Example #47
0
 def _check_for_correct_filename_template(self, template):
     if template is not None and '.' in template:
         raise ValidationError(_('Filename template cannot include dots'))
Example #48
0
 def validate_category(self, field):
     if not field.data.can_create_events(session.user):
         raise ValidationError(
             _('You are not allowed to create events in this category.'))
Example #49
0
 def _process_args(self):
     RHManageCategorySelectedEventsBase._process_args(self)
     self.target_category = Category.get_one(int(request.form['target_category_id']), is_deleted=False)
     if not self.target_category.can_create_events(session.user):
         raise Forbidden(_("You may only move events to categories where you are allowed to create events."))
Example #50
0
 def _check_for_correct_extensions_format(self, extensions):
     for extension in extensions:
         if re.match(r'^[*.]+', extension):
             raise ValidationError(_('Extensions cannot have leading dots'))
Example #51
0
def create_mock_abstract(event):
    """Create a mock abstract that can be used in previews.

    Brace for geek references.
    """
    User = namedtuple('Author',
                      ['first_name', 'last_name', 'title', 'full_name'])
    Track = namedtuple('Track', ['title'])
    Session = namedtuple('Session', ['title'])
    ContributionType = namedtuple('ContributionType', ['name'])
    Contribution = namedtuple('Contribution',
                              ['title', 'track', 'session', 'type', 'locator'])
    Abstract = namedtuple('Abstract', [
        'friendly_id', 'title', 'event', 'submitter', 'contribution',
        'primary_authors', 'secondary_authors', 'locator', 'judgment_comment',
        'accepted_track', 'accepted_contrib_type', 'state', 'merged_into'
    ])

    englert = User(full_name="Fran\xe7ois Englert",
                   first_name="Fran\xe7ois",
                   last_name="Englert",
                   title="Prof.")
    brout = User(full_name="Robert Brout",
                 first_name="Robert",
                 last_name="Brout",
                 title="Prof.")
    guralnik = User(full_name="Gerald Guralnik",
                    first_name="Gerald",
                    last_name="Guralnik",
                    title="Prof.")
    hagen = User(full_name="Carl Hagen",
                 first_name="Carl",
                 last_name="Hagen",
                 title="Prof.")
    kibble = User(full_name="Tom Kibble",
                  first_name="Tom",
                  last_name="Kibble",
                  title="Prof.")
    higgs = User(full_name="Peter Higgs",
                 first_name="Peter",
                 last_name="Higgs",
                 title="Prof.")

    track = Track(title=_("Higgs Fields"))
    session = Session(title=_("Higgs Fields Posters"))
    contribution_type = ContributionType(name=_("Poster"))
    contribution = Contribution(
        title="Broken Symmetry and the Mass of Gauge Vector Mesons",
        track=track,
        session=session,
        type=contribution_type,
        locator={
            'confId': -314,
            'contrib_id': 1234
        })

    target_abstract = Abstract(
        friendly_id=315,
        title="Broken Symmetry",
        accepted_track=track,
        accepted_contrib_type=contribution_type,
        event=event,
        submitter=brout,
        state=AbstractState.accepted,
        contribution=contribution,
        primary_authors=[englert, brout],
        secondary_authors=[guralnik, hagen, kibble, higgs],
        locator={
            'confId': -314,
            'abstract_id': 1235
        },
        judgment_comment='Vague but interesting!',
        merged_into=None)

    abstract = Abstract(
        friendly_id=314,
        title="Broken Symmetry and the Mass of Gauge Vector Mesons",
        accepted_track=track,
        accepted_contrib_type=contribution_type,
        event=event,
        submitter=brout,
        state=AbstractState.accepted,
        contribution=contribution,
        primary_authors=[englert, brout],
        secondary_authors=[guralnik, hagen, kibble, higgs],
        locator={
            'confId': -314,
            'abstract_id': 1234
        },
        judgment_comment='Vague but interesting!',
        merged_into=target_abstract)

    return abstract
Example #52
0
class ContributionCloner(EventCloner):
    name = 'contributions'
    friendly_name = _('Contributions')
    requires = {'event_persons', 'sessions', 'contribution_types', 'contribution_fields'}
    is_internal = True

    # We do not override `is_available` as we have cloners depending
    # on this internal cloner even if it won't clone anything.

    @classmethod
    @no_autoflush
    def clone_single_contribution(cls, contribution, preserve_session=False):
        """Clone a single contribution within the same event.

        :param contribution: The `Contribution` to clone
        :param preserve_session: Whether to assign and schedule
        :return: The newly created contribution
        """
        event = contribution.event
        cloner = cls(event)
        cloner._person_map = dict(zip(event.persons, event.persons))
        cloner._session_map = {contribution.session: contribution.session}
        cloner._session_block_map = {contribution.session_block: contribution.session_block}
        cloner._contrib_type_map = {contribution.type: contribution.type}
        cloner._contrib_field_map = dict(zip(event.contribution_fields, event.contribution_fields))
        cloner._contrib_map = {}
        cloner._subcontrib_map = {}
        new_contribution = cloner._create_new_contribution(event, contribution,
                                                           preserve_session=preserve_session,
                                                           excluded_attrs={'friendly_id'})
        if preserve_session:
            entry = schedule_contribution(new_contribution, contribution.timetable_entry.start_dt,
                                          session_block=new_contribution.session_block)
            event.timetable_entries.append(entry)
        db.session.flush()
        return new_contribution

    def run(self, new_event, cloners, shared_data):
        self._person_map = shared_data['event_persons']['person_map']
        self._session_map = shared_data['sessions']['session_map']
        self._session_block_map = shared_data['sessions']['session_block_map']
        self._contrib_type_map = shared_data['contribution_types']['contrib_type_map']
        self._contrib_field_map = shared_data['contribution_fields']['contrib_field_map']
        self._contrib_map = {}
        self._subcontrib_map = {}
        with db.session.no_autoflush:
            self._clone_contribs(new_event)
        self._synchronize_friendly_id(new_event)
        db.session.flush()
        return {'contrib_map': self._contrib_map, 'subcontrib_map': self._subcontrib_map}

    def _create_new_contribution(self, event, old_contrib, preserve_session=True, excluded_attrs=None):
        attrs = (get_simple_column_attrs(Contribution) | {'own_room', 'own_venue'}) - {'abstract_id'}
        if excluded_attrs is not None:
            attrs -= excluded_attrs
        new_contrib = Contribution()
        new_contrib.populate_from_attrs(old_contrib, attrs)
        new_contrib.subcontributions = list(self._clone_subcontribs(old_contrib.subcontributions))
        new_contrib.acl_entries = clone_principals(ContributionPrincipal, old_contrib.acl_entries)
        new_contrib.references = list(self._clone_references(ContributionReference, old_contrib.references))
        new_contrib.person_links = list(self._clone_person_links(ContributionPersonLink, old_contrib.person_links))
        new_contrib.field_values = list(self._clone_fields(old_contrib.field_values))
        if old_contrib.type is not None:
            new_contrib.type = self._contrib_type_map[old_contrib.type]
        if preserve_session:
            if old_contrib.session is not None:
                new_contrib.session = self._session_map[old_contrib.session]
            if old_contrib.session_block is not None:
                new_contrib.session_block = self._session_block_map[old_contrib.session_block]
        event.contributions.append(new_contrib)
        return new_contrib

    def _clone_contribs(self, new_event):
        query = (Contribution.query.with_parent(self.old_event)
                 .options(undefer('_last_friendly_subcontribution_id'),
                          joinedload('own_venue'),
                          joinedload('own_room').lazyload('*'),
                          joinedload('session'),
                          joinedload('session_block').lazyload('session'),
                          joinedload('type'),
                          subqueryload('acl_entries'),
                          subqueryload('subcontributions').joinedload('references'),
                          subqueryload('references'),
                          subqueryload('person_links'),
                          subqueryload('field_values')))
        for old_contrib in query:
            self._contrib_map[old_contrib] = self._create_new_contribution(new_event, old_contrib)

    def _clone_subcontribs(self, subcontribs):
        attrs = get_simple_column_attrs(SubContribution)
        for old_subcontrib in subcontribs:
            subcontrib = SubContribution()
            subcontrib.populate_from_attrs(old_subcontrib, attrs)
            subcontrib.references = list(self._clone_references(SubContributionReference, old_subcontrib.references))
            subcontrib.person_links = list(self._clone_person_links(SubContributionPersonLink,
                                                                    old_subcontrib.person_links))
            self._subcontrib_map[old_subcontrib] = subcontrib
            yield subcontrib

    def _clone_references(self, cls, references):
        attrs = get_simple_column_attrs(cls) | {'reference_type'}
        for old_ref in references:
            ref = cls()
            ref.populate_from_attrs(old_ref, attrs)
            yield ref

    def _clone_person_links(self, cls, person_links):
        attrs = get_simple_column_attrs(cls)
        for old_link in person_links:
            link = cls()
            link.populate_from_attrs(old_link, attrs)
            link.person = self._person_map[old_link.person]
            yield link

    def _clone_fields(self, fields):
        attrs = get_simple_column_attrs(ContributionFieldValue)
        for old_field_value in fields:
            field_value = ContributionFieldValue()
            field_value.contribution_field = self._contrib_field_map[old_field_value.contribution_field]
            field_value.populate_from_attrs(old_field_value, attrs)
            yield field_value

    def _synchronize_friendly_id(self, new_event):
        new_event._last_friendly_contribution_id = (
            db.session
            .query(db.func.max(Contribution.friendly_id))
            .filter(Contribution.event_id == new_event.id)
            .scalar() or 0
        )
Example #53
0
def _topmenu_items(sender, **kwargs):
    if session.user and session.user.is_admin:
        yield TopMenuItem('admin', _('Administration'),
                          url_for('core.admin_dashboard'), 70)
Example #54
0
 def _process(self):
     move_category(self.category, self.target_category)
     flash(_('Category "{}" moved to "{}".').format(self.category.title, self.target_category.title), 'success')
     return jsonify_data(flash=False)
 def __call__(self, form, field):
     if field.data is not None and field.data > self.max_duration:
         raise ValidationError(_('Duration cannot exceed {}').format(format_human_timedelta(self.max_duration)))
Example #56
0
class SessionForm(IndicoForm):
    title = StringField(_('Title'), [DataRequired()])
    code = StringField(
        _('Session code'),
        description=_('The code that will identify the session in the Book of '
                      'Abstracts.'))
    description = TextAreaField(_('Description'))
    default_contribution_duration = TimeDeltaField(
        _('Default contribution duration'),
        units=('minutes', 'hours'),
        description=_('Duration that a contribution created within this '
                      'session will have by default.'),
        default=timedelta(minutes=20))
    location_data = IndicoLocationField(
        _("Default location"),
        description=_("Default location for blocks inside the session."))
    colors = IndicoPalettePickerField(_('Colours'), color_list=get_colors())
    is_poster = BooleanField(
        _('Poster session'),
        widget=SwitchWidget(),
        description=
        _('Whether the session is a poster session or contains normal presentations.'
          ))

    def __init__(self, *args, **kwargs):
        event = kwargs.pop('event')
        super(SessionForm, self).__init__(*args, **kwargs)
        if event.type != 'conference':
            del self.is_poster
            del self.code
Example #57
0
 def _process(self):
     self.user.reset_signing_secret()
     flash(_('All your token-based links have been invalidated'), 'success')
     return redirect(url_for('api.user_profile'))
 def __init__(self, fieldname):
     super().__init__(fieldname, message=_('The passwords do not match.'))
Example #59
0
class EventCreationForm(EventCreationFormBase):
    _field_order = ('title', 'start_dt', 'end_dt', 'timezone', 'location_data', 'protection_mode')
    _advanced_field_order = ()
    start_dt = IndicoDateTimeField(_("Start"), [InputRequired()], default_time=time(8), allow_clear=False)
    end_dt = IndicoDateTimeField(_("End"), [InputRequired(), LinkedDateTime('start_dt', not_equal=True)],
                                 default_time=time(18), allow_clear=False)
 def __call__(self, form, field):
     if field.data and not is_valid_mail(field.data, self.multi):
         msg = _('Invalid email address list') if self.multi else _('Invalid email address')
         raise ValidationError(msg)