Exemple #1
0
    def _associate_users_by_email(self, event):
        # link objects to users by email where possible
        # event principals
        emails = [p.email for p in EventPrincipal.query.with_parent(event).filter_by(type=PrincipalType.email)]
        for user in User.query.filter(~User.is_deleted, User.all_emails.in_(emails)):
            EventPrincipal.replace_email_with_user(user, 'event')

        # session principals
        query = (SessionPrincipal.query
                 .filter(SessionPrincipal.session.has(Session.event == event),
                         SessionPrincipal.type == PrincipalType.email))
        emails = [p.email for p in query]
        for user in User.query.filter(~User.is_deleted, User.all_emails.in_(emails)):
            SessionPrincipal.replace_email_with_user(user, 'session')

        # contribution principals
        query = (ContributionPrincipal.query
                 .filter(ContributionPrincipal.contribution.has(Contribution.event == event),
                         ContributionPrincipal.type == PrincipalType.email))
        emails = [p.email for p in query]
        for user in User.query.filter(~User.is_deleted, User.all_emails.in_(emails)):
            ContributionPrincipal.replace_email_with_user(user, 'contribution')

        # event persons
        query = EventPerson.query.with_parent(event).filter(EventPerson.user_id.is_(None), EventPerson.email != '')
        for person in query:
            person.user = get_user_by_email(person.email)

        # registrations
        for registration in Registration.query.with_parent(event).filter(Registration.user_id.is_(None)):
            registration.user = get_user_by_email(registration.email)
Exemple #2
0
    def _synchronize_email(self, email, silent=False):
        from indico.modules.users import logger
        from indico.modules.users.tasks import update_gravatars
        from indico.modules.users.util import get_user_by_email

        if not validate_email(email, check_dns=False):
            logger.warning(
                'Cannot sync email for %r to %r; address is invalid', self,
                email)
            if not silent:
                flash(
                    _("Your email address could not be synchronized from '{old_value}' to "
                      "'{new_value}' since the new email address is not valid."
                      ).format(old_value=self.email, new_value=email),
                    'warning')
            return False

        if email not in self.secondary_emails:
            if other := get_user_by_email(email):
                logger.warning(
                    'Cannot sync email for %r to %r; already used by %r', self,
                    email, other)
                if not silent:
                    flash(
                        _("Your email address could not be synchronized from '{old_value}' to "
                          "'{new_value}' due to a conflict with another Indico profile."
                          ).format(old_value=self.email, new_value=email),
                        'warning')
                return False
            self.secondary_emails.add(email)
            signals.users.email_added.send(self, email=email, silent=silent)
    def _process(self):
        if self._getUser() is not None and self._getUser().isRegisteredInConf(self._conf):
            if (
                not self._conf.getRegistrationForm().inRegistrationPeriod()
                and not self._conf.getRegistrationForm().inModificationPeriod()
            ):
                flash(_("Your modification could not be recorded since the modification period is over."), "error")
                return redirect(url_for("event.confRegistrationFormDisplay", self._conf))
            else:
                rp = self._getUser().getRegistrantById(self._conf.getId())

                # Check if the email matches an existing user
                params = self._getRequestParams()
                email = self._regForm.getPersonalData().getValueFromParams(params, "email") or ""
                user = get_user_by_email(email)
                if user:
                    if not session.user:
                        flash(
                            _(
                                "The provided email ({email}) is linked to an Indico account. Please sign in with it "
                                "first."
                            ).format(email=email),
                            "error",
                        )
                        return redirect(url_for("event.confRegistrationFormDisplay-modify", self._conf))
                    elif session.user != user:
                        flash(
                            _(
                                "The provided email ({email}) is linked to another Indico account. Please sign in with "
                                "it first."
                            ).format(email=email),
                            "error",
                        )
                        return redirect(url_for("event.confRegistrationFormDisplay-modify", self._conf))

                # check if the email is being changed by another one that already exists
                if email != rp.getEmail() and self._conf.hasRegistrantByEmail(email):
                    raise FormValuesError(
                        _('There is already a user with the email "{email}". ' "Please choose another one.").format(
                            email or "--no email--"
                        )
                    )
                rp.setValues(self._getRequestParams(), self._getUser())
                log_msg = u"User modified his registration data: {}"
                self._conf.log(
                    EventLogRealm.participants,
                    EventLogKind.positive,
                    u"Registration",
                    log_msg.format(to_unicode(rp.getFullName(title=False, firstNameFirst=True))),
                    session.user,
                    data={u"Indico user": u"{} ({})".format(user.full_name, user.id) if user else u"None"},
                )
                notify_registration_modification(self._conf, rp)
                flash(_(u"Your registration has been modified successfully."), "success")
                if rp.doPay():
                    self._redirect(urlHandlers.UHConfRegistrationFormCreationDone.getURL(rp))
                else:
                    self._redirect(urlHandlers.UHConfRegistrationForm.getURL(self._conf))
        else:
            self._redirect(urlHandlers.UHConfRegistrationForm.getURL(self._conf))
Exemple #4
0
def create_registration(regform, data, invitation=None, management=False, notify_user=True, skip_moderation=None):
    user = session.user if session else None
    registration = Registration(registration_form=regform, user=get_user_by_email(data['email']),
                                base_price=regform.base_price, currency=regform.currency)
    if skip_moderation is None:
        skip_moderation = management
    for form_item in regform.active_fields:
        if form_item.parent.is_manager_only:
            value = form_item.field_impl.default_value
        else:
            value = data.get(form_item.html_field_name)
        data_entry = RegistrationData()
        registration.data.append(data_entry)
        for attr, value in form_item.field_impl.process_form_data(registration, value).items():
            setattr(data_entry, attr, value)
        if form_item.type == RegistrationFormItemType.field_pd and form_item.personal_data_type.column:
            setattr(registration, form_item.personal_data_type.column, value)
    if invitation is None:
        # Associate invitation based on email in case the user did not use the link
        invitation = (RegistrationInvitation.query
                      .filter_by(email=data['email'], registration_id=None)
                      .with_parent(regform)
                      .first())
    if invitation:
        invitation.state = InvitationState.accepted
        invitation.registration = registration
    registration.sync_state(_skip_moderation=skip_moderation)
    db.session.flush()
    signals.event.registration_created.send(registration, management=management, data=data)
    notify_registration_creation(registration, notify_user)
    logger.info('New registration %s by %s', registration, user)
    registration.log(EventLogRealm.management if management else EventLogRealm.participants,
                     EventLogKind.positive, 'Registration',
                     f'New registration: {registration.full_name}', user, data={'Email': registration.email})
    return registration
Exemple #5
0
def modify_registration(registration,
                        data,
                        management=False,
                        notify_user=True):
    old_price = registration.price
    personal_data_changes = {}
    regform = registration.registration_form
    data_by_field = registration.data_by_field
    if management or not registration.user:
        registration.user = get_user_by_email(data['email'])

    billable_items_locked = not management and registration.is_paid
    for form_item in regform.active_fields:
        field_impl = form_item.field_impl
        if management or not form_item.parent.is_manager_only:
            value = data.get(form_item.html_field_name)
        elif form_item.id not in data_by_field:
            # set default value for manager-only field if it didn't have one before
            value = field_impl.default_value
        else:
            # manager-only field that has data which should be preserved
            continue

        if form_item.id not in data_by_field:
            data_by_field[form_item.id] = RegistrationData(
                registration=registration, field_data=form_item.current_data)

        attrs = field_impl.process_form_data(
            registration,
            value,
            data_by_field[form_item.id],
            billable_items_locked=billable_items_locked)
        for key, val in attrs.iteritems():
            setattr(data_by_field[form_item.id], key, val)
        if form_item.type == RegistrationFormItemType.field_pd and form_item.personal_data_type.column:
            key = form_item.personal_data_type.column
            if getattr(registration, key) != value:
                personal_data_changes[key] = value
            setattr(registration, key, value)
    registration.sync_state()
    db.session.flush()
    # sanity check
    if billable_items_locked and old_price != registration.price:
        raise Exception(
            "There was an error while modifying your registration (price mismatch: %s / %s)",
            old_price, registration.price)
    if personal_data_changes:
        signals.event.registration_personal_data_modified.send(
            registration, change=personal_data_changes)
    signals.event.registration_updated.send(registration,
                                            management=management)
    notify_registration_modification(registration, notify_user)
    logger.info('Registration %s modified by %s', registration, session.user)
    registration.log(
        EventLogRealm.management if management else EventLogRealm.participants,
        EventLogKind.change,
        'Registration',
        'Registration modified: {}'.format(registration.full_name),
        session.user,
        data={'Email': registration.email})
Exemple #6
0
 def _get_person_link(self, data, extra_data=None):
     extra_data = extra_data or {}
     person = get_event_person(self.event, data, create_untrusted_persons=self.create_untrusted_persons,
                               allow_external=True)
     person_data = {'title': next((x.value for x in UserTitle if data.get('title') == orig_string(x.title)),
                                  UserTitle.none),
                    'first_name': data.get('firstName', ''), 'last_name': data['familyName'],
                    'affiliation': data.get('affiliation', ''), 'address': data.get('address', ''),
                    'phone': data.get('phone', ''), 'display_order': data['displayOrder']}
     person_data.update(extra_data)
     person_link = None
     if self.object and inspect(person).persistent:
         person_link = self.person_link_cls.query.filter_by(person=person, object=self.object).first()
     if not person_link:
         person_link = self.person_link_cls(person=person)
     person_link.populate_from_dict(person_data)
     email = data.get('email', '').lower()
     if email != person_link.email:
         if not self.event or not self.event.persons.filter_by(email=email).first():
             person_link.person.email = email
             person_link.person.user = get_user_by_email(email)
             if inspect(person).persistent:
                 signals.event.person_updated.send(person_link.person)
         else:
             raise UserValueError(_('There is already a person with the email {}').format(email))
     return person_link
Exemple #7
0
 def _get_person_link(self, data, extra_data=None):
     extra_data = extra_data or {}
     person = get_event_person(self.event, data, create_untrusted_persons=self.create_untrusted_persons,
                               allow_external=True)
     person_data = {'title': next((x.value for x in UserTitle if data.get('title') == orig_string(x.title)),
                                  UserTitle.none),
                    'first_name': data.get('firstName', ''), 'last_name': data['familyName'],
                    'affiliation': data.get('affiliation', ''), 'address': data.get('address', ''),
                    'phone': data.get('phone', ''), 'display_order': data['displayOrder']}
     person_data.update(extra_data)
     person_link = None
     if self.object and inspect(person).persistent:
         person_link = self.person_link_cls.find_first(person=person, object=self.object)
     if not person_link:
         person_link = self.person_link_cls(person=person)
     person_link.populate_from_dict(person_data)
     email = data.get('email', '').lower()
     if email != person_link.email:
         if not self.event or not self.event.persons.filter_by(email=email).first():
             person_link.person.email = email
             person_link.person.user = get_user_by_email(email)
             if inspect(person).persistent:
                 signals.event.person_updated.send(person_link.person)
         else:
             raise UserValueError(_('There is already a person with the email {}').format(email))
     return person_link
Exemple #8
0
def create_registration(regform, data, invitation=None, management=False, notify_user=True, skip_moderation=None):
    user = session.user if session else None
    registration = Registration(registration_form=regform, user=get_user_by_email(data['email']),
                                base_price=regform.base_price, currency=regform.currency)
    if skip_moderation is None:
        skip_moderation = management
    for form_item in regform.active_fields:
        if form_item.parent.is_manager_only:
            value = form_item.field_impl.default_value
        else:
            value = data.get(form_item.html_field_name)
        data_entry = RegistrationData()
        registration.data.append(data_entry)
        for attr, value in form_item.field_impl.process_form_data(registration, value).iteritems():
            setattr(data_entry, attr, value)
        if form_item.type == RegistrationFormItemType.field_pd and form_item.personal_data_type.column:
            setattr(registration, form_item.personal_data_type.column, value)
    if invitation is None:
        # Associate invitation based on email in case the user did not use the link
        invitation = (RegistrationInvitation
                      .find(email=data['email'], registration_id=None)
                      .with_parent(regform)
                      .first())
    if invitation:
        invitation.state = InvitationState.accepted
        invitation.registration = registration
    registration.sync_state(_skip_moderation=skip_moderation)
    db.session.flush()
    notify_registration_creation(registration, notify_user)
    logger.info('New registration %s by %s', registration, user)
    regform.event.log(EventLogRealm.management if management else EventLogRealm.participants,
                      EventLogKind.positive, 'Registration',
                      'New registration: {}'.format(registration.full_name), user, data={'Email': registration.email})
    return registration
Exemple #9
0
def create_registration(regform, data, invitation=None, management=False, notify_user=True):
    registration = Registration(registration_form=regform, user=get_user_by_email(data['email']),
                                base_price=regform.base_price, currency=regform.currency)
    for form_item in regform.active_fields:
        if form_item.parent.is_manager_only:
            with db.session.no_autoflush:
                value = form_item.field_impl.default_value
        else:
            value = data.get(form_item.html_field_name)
        with db.session.no_autoflush:
            data_entry = RegistrationData()
            registration.data.append(data_entry)
            for attr, value in form_item.field_impl.process_form_data(registration, value).iteritems():
                setattr(data_entry, attr, value)
        if form_item.type == RegistrationFormItemType.field_pd and form_item.personal_data_type.column:
            setattr(registration, form_item.personal_data_type.column, value)
    if invitation is None:
        # Associate invitation based on email in case the user did not use the link
        with db.session.no_autoflush:
            invitation = (RegistrationInvitation
                          .find(email=data['email'], registration_id=None)
                          .with_parent(regform)
                          .first())
    if invitation:
        invitation.state = InvitationState.accepted
        invitation.registration = registration
    registration.sync_state(_skip_moderation=management)
    db.session.flush()
    notify_registration_creation(registration, notify_user)
    logger.info('New registration %s by %s', registration, session.user)
    return registration
Exemple #10
0
def get_authors_from_author_index(event, limit):
    """Fetch the authors of an event with the most contributions. An author is a
    ContributionParticipation object or an Avatar object.

    :param event: The event to fetch the author index from
    :param limit: The limit of the authors to be returned
    :return: A list of authors.
    """
    author_index = event.getAuthorIndex()
    fav_users_emails = (set(
        itertools.chain.from_iterable(
            f.all_emails
            for f in session.user.favorite_users)) if session.user else [])
    sorted_authors = [
        x[0] for x in sorted((p for p in author_index.getParticipations()
                              if p[0].getEmail() not in fav_users_emails),
                             key=len,
                             reverse=True)
    ]
    authors = []
    # Check if there is a corresponding Avatar for the specific user and use that.
    for author in sorted_authors[:limit]:
        user = get_user_by_email(author.getEmail())
        authors.append(user.as_avatar if user else author)
    return authors
Exemple #11
0
def process_alternative_hosts(emails):
    """Convert a comma-concatenated list of alternative host e-mails into a list of identifiers."""
    from indico_vc_zoom.plugin import ZoomPlugin
    mode = ZoomPlugin.settings.get('user_lookup_mode')
    emails = re.findall(r'[^,;]+', emails)
    if mode in (UserLookupMode.all_emails, UserLookupMode.email_domains):
        users = {get_user_by_email(email) for email in emails}
    elif mode == UserLookupMode.authenticators:
        users = set()
        domain = ZoomPlugin.settings.get('enterprise_domain')
        usernames = {
            email.split('@')[0]
            for email in emails if email.endswith(f'@{domain}')
        }
        providers = ZoomPlugin.settings.get('authenticators')
        users = []
        if providers and usernames:
            criteria = db.or_(((Identity.provider == provider)
                               & (Identity.identifier == username))
                              for provider, username in itertools.product(
                                  providers, usernames))
            users = [
                identity.user for identity in Identity.query.filter(criteria)
            ]
    else:
        raise TypeError('invalid mode')
    return [u.identifier for u in users if u is not None]
Exemple #12
0
def check_registration_email(regform,
                             email,
                             registration=None,
                             management=False):
    """Checks whether an email address is suitable for registration.

    :param regform: The registration form
    :param email: The email address
    :param registration: The existing registration (in case of
                         modification)
    :param management: If it's a manager adding a new registration
    """
    email = email.lower().strip()
    user = get_user_by_email(email)
    email_registration = regform.get_registration(email=email)
    user_registration = regform.get_registration(user=user) if user else None
    if registration is not None:
        if email_registration and email_registration != registration:
            return dict(status='error', conflict='email-already-registered')
        elif user_registration and user_registration != registration:
            return dict(status='error', conflict='user-already-registered')
        elif user and registration.user and registration.user != user:
            return dict(status='warning' if management else 'error',
                        conflict='email-other-user',
                        user=user.full_name)
        elif not user and registration.user:
            return dict(status='warning' if management else 'error',
                        conflict='email-no-user',
                        user=registration.user.full_name)
        elif user:
            return dict(status='ok',
                        user=user.full_name,
                        self=(not management and user == session.user),
                        same=(user == registration.user))
        elif not validate_email(email):
            return dict(status='error', conflict='email-invalid')
        elif regform.require_user and (management
                                       or email != registration.email):
            return dict(status='warning' if management else 'error',
                        conflict='no-user')
        else:
            return dict(status='ok', user=None)
    else:
        if email_registration:
            return dict(status='error', conflict='email-already-registered')
        elif user_registration:
            return dict(status='error', conflict='user-already-registered')
        elif user:
            return dict(status='ok',
                        user=user.full_name,
                        self=(not management and user == session.user),
                        same=False)
        elif not validate_email(email):
            return dict(status='error', conflict='email-invalid')
        elif regform.require_user:
            return dict(status='warning' if management else 'error',
                        conflict='no-user')
        else:
            return dict(status='ok', user=None)
    def _process(self):
        canManageRegistration = self._conf.canManageRegistration(self._getUser())
        if not canManageRegistration and not self._regForm.isActivated():
            p = registrationForm.WPRegFormInactive(self, self._conf)
            return p.display()
        params = self._getRequestParams()
        email = self._regForm.getPersonalData().getValueFromParams(params, 'email')
        if email is None:
            raise FormValuesError(_("An email address has to be set in order to make the registration in the event."))
        elif not validMail(email, False):
            raise FormValuesError(_("The given email address is not valid."))

        # Check if the email matches an existing user
        user = get_user_by_email(email)
        avatar = user.as_avatar if user else None

        # Check if the user can register
        if not canManageRegistration:  # normal user registering. Managers can.
            if self._conf.getRegistrationForm().isFull():
                self._redirect(urlHandlers.UHConfRegistrationFormDisplay.getURL(self._conf))
                return
            elif not self._conf.getRegistrationForm().inRegistrationPeriod():
                flash(_("Your registration couldn't be recorded."), 'error')
                return redirect(url_for('event.confRegistrationFormDisplay', self._conf))
        if user is None:
            if self._conf.hasRegistrantByEmail(email):
                raise FormValuesError("There is already a user with the email \"%s\". Please choose another one" % email)
        else:
            if avatar.isRegisteredInConf(self._conf) or self._conf.hasRegistrantByEmail(email):
                if canManageRegistration:
                    raise FormValuesError("There is already a user with the email \"%s\". Please choose another one" % email)
                else:
                    raise FormValuesError("You have already registered with the email address \"%s\". If you need to modify your registration, please contact the managers of the conference." % email)

        rp = registration.Registrant()
        self._conf.addRegistrant(rp, avatar)
        rp.setValues(self._getRequestParams(), avatar)

        if avatar is not None:
            rp.setAvatar(avatar)

        notify_registration_confirmation(self._conf, rp)
        self._conf.log(EventLogRealm.management if self.is_manager else EventLogRealm.participants,
                       EventLogKind.positive, u'Registration',
                       u'User registered: {}'.format(to_unicode(rp.getFullName(title=False, firstNameFirst=True))),
                       session.user,
                       data={u'Indico user': u'{} ({})'.format(user.full_name, user.id) if user else u'None'})

        if self.is_manager:
            self._redirect(RHRegistrantListModif._uh.getURL(self._conf))
        else:
            params = {}
            if not rp.doPay() or not payment_event_settings.get(self._conf, 'enabled'):
                flash(_(u"Your registration has been recorded successfully."), 'success')
            if not session.user or session.user != user:
                params.update(rp.getLocator(), **{'authkey': rp.getRandomId()})
            else:
                params.update(self._conf.getLocator())
            return redirect(url_for('event.confRegistrationFormDisplay', **params))
Exemple #14
0
def import_user_records_from_csv(fileobj, columns):
    """Parse and do basic validation of user data from a CSV file.

    :param fileobj: the CSV file to be read
    :param columns: A list of column names, 'first_name', 'last_name', & 'email' are compulsory.
    :return: A list dictionaries each representing one row,
             the keys of which are given by the column names.
    """
    with csv_text_io_wrapper(fileobj) as ftxt:
        reader = csv.reader(ftxt.read().splitlines())
    used_emails = set()
    email_row_map = {}
    user_records = []
    for row_num, row in enumerate(reader, 1):
        values = [value.strip() for value in row]
        if len(columns) != len(values):
            raise UserValueError(
                _('Row {}: malformed CSV data - please check that the number of columns is correct'
                  ).format(row_num))
        record = dict(zip(columns, values))

        if not record['email']:
            raise UserValueError(
                _('Row {}: missing e-mail address').format(row_num))
        record['email'] = record['email'].lower()

        if not validate_email(record['email']):
            raise UserValueError(
                _('Row {}: invalid e-mail address').format(row_num))
        if not record['first_name'] or not record['last_name']:
            raise UserValueError(
                _('Row {}: missing first or last name').format(row_num))
        record['first_name'] = record['first_name'].title()
        record['last_name'] = record['last_name'].title()

        if record['email'] in used_emails:
            raise UserValueError(
                _('Row {}: email address is not unique').format(row_num))
        if conflict_row_num := email_row_map.get(record['email']):
            raise UserValueError(
                _('Row {}: email address belongs to the same user as in row {}'
                  ).format(row_num, conflict_row_num))

        used_emails.add(record['email'])
        if user := get_user_by_email(record['email']):
            email_row_map.update((e, row_num) for e in user.all_emails)
Exemple #15
0
def import_invitations_from_csv(regform,
                                fileobj,
                                email_from,
                                email_subject,
                                email_body,
                                skip_moderation=True,
                                skip_existing=False):
    """Import invitations from a CSV file.

    :return: A list of invitations and the number of skipped records which
             is zero if skip_existing=False
    """
    columns = ['first_name', 'last_name', 'affiliation', 'email']
    user_records = import_user_records_from_csv(fileobj, columns=columns)

    reg_data = (db.session.query(
        Registration.user_id, Registration.email).with_parent(regform).filter(
            Registration.is_active).all())
    registered_user_ids = {
        rd.user_id
        for rd in reg_data if rd.user_id is not None
    }
    registered_emails = {rd.email for rd in reg_data}
    invited_emails = {inv.email for inv in regform.invitations}

    filtered_records = []
    for row_num, user in enumerate(user_records, 1):
        if user['email'] in registered_emails:
            if skip_existing:
                continue
            raise UserValueError(
                _('Row {}: a registration with this email already exists').
                format(row_num))

        indico_user = get_user_by_email(user['email'])
        if indico_user and indico_user.id in registered_user_ids:
            if skip_existing:
                continue
            raise UserValueError(
                _('Row {}: a registration for this user already exists').
                format(row_num))

        if user['email'] in invited_emails:
            if skip_existing:
                continue
            raise UserValueError(
                _('Row {}: an invitation for this user already exists').format(
                    row_num))

        filtered_records.append(user)

    invitations = [
        create_invitation(regform, user, skip_moderation, email_from,
                          email_subject, email_body)
        for user in filtered_records
    ]
    skipped_records = len(user_records) - len(filtered_records)
    return invitations, skipped_records
Exemple #16
0
    def _parse_room_data(self, raw_data, coordinates, room_id):
        data = {}
        data['building'] = raw_data['BUILDING']
        data['floor'] = raw_data['FLOOR']
        data['number'] = raw_data['ROOM_NUMBER']
        email = raw_data['RESPONSIBLE_EMAIL']
        if not data['building'] or not data['floor'] or not data['number']:
            raise SkipRoom(
                'Error in Foundation - No value for BUILDING or FLOOR or ROOM_NUMBER'
            )

        email_warning = None
        if not email:
            email_warning = (
                '[%s] No value for RESPONSIBLE_EMAIL in Foundation', room_id)
            user = None
        else:
            user = get_user_by_email(email, create_pending=True)
            if not user:
                email_warning = (
                    '[%s] Bad RESPONSIBLE_EMAIL in Foundation: no user found with email %s',
                    email, room_id)

        data['owner'] = user
        data['verbose_name'] = (raw_data.get('FRIENDLY_NAME')
                                or '').strip() or None
        data['capacity'] = int(
            raw_data['CAPACITY']) if raw_data['CAPACITY'] else None
        data['surface_area'] = int(
            raw_data['SURFACE']) if raw_data['SURFACE'] else None
        data['division'] = raw_data.get('DEPARTMENT')
        data['telephone'] = raw_data.get('TELEPHONE') or ''
        data['key_location'] = self._html_to_markdown(
            raw_data.get('WHERE_IS_KEY') or '')
        data['comments'] = self._html_to_markdown(
            raw_data.get('COMMENTS')) if raw_data.get('COMMENTS') else ''
        data['reservations_need_confirmation'] = raw_data[
            'BOOKINGS_NEED_CONFIRMATION'] != 'N'

        is_reservable = raw_data['IS_RESERVABLE'] != 'N'
        data[
            'protection_mode'] = ProtectionMode.public if is_reservable else ProtectionMode.protected
        site = raw_data.get('SITE')
        site_map = {'MEYR': 'Meyrin', 'PREV': 'Prevessin'}
        data['site'] = site_map.get(site, site)

        building_coordinates = coordinates.get(int(data['building']))
        if building_coordinates:
            data['latitude'] = building_coordinates['latitude']
            data['longitude'] = building_coordinates['longitude']

        return data, email_warning
Exemple #17
0
def import_registrations_from_csv(regform, fileobj, skip_moderation=True, notify_users=False):
    """Import event registrants from a CSV file into a form."""
    with csv_text_io_wrapper(fileobj) as ftxt:
        reader = csv.reader(ftxt.read().splitlines())
    reg_data = (db.session.query(Registration.user_id, Registration.email)
                .with_parent(regform)
                .filter(Registration.is_active)
                .all())
    registered_user_ids = {rd.user_id for rd in reg_data if rd.user_id is not None}
    registered_emails = {rd.email for rd in reg_data}
    used_emails = set()
    email_row_map = {}
    todo = []
    for row_num, row in enumerate(reader, 1):
        try:
            first_name, last_name, affiliation, position, phone, email = [value.strip() for value in row]
            email = email.lower()
        except ValueError:
            raise UserValueError(_('Row {}: malformed CSV data - please check that the number of columns is correct')
                                 .format(row_num))

        if not email:
            raise UserValueError(_('Row {}: missing e-mail address').format(row_num))
        if not validate_email(email):
            raise UserValueError(_('Row {}: invalid e-mail address').format(row_num))
        if not first_name or not last_name:
            raise UserValueError(_('Row {}: missing first or last name').format(row_num))
        if email in registered_emails:
            raise UserValueError(_('Row {}: a registration with this email already exists').format(row_num))

        user = get_user_by_email(email)
        if user and user.id in registered_user_ids:
            raise UserValueError(_('Row {}: a registration for this user already exists').format(row_num))
        if email in used_emails:
            raise UserValueError(_('Row {}: email address is not unique').format(row_num))
        if conflict_row_num := email_row_map.get(email):
            raise UserValueError(_('Row {}: email address belongs to the same user as in row {}')
                                 .format(row_num, conflict_row_num))

        used_emails.add(email)
        if user:
            email_row_map.update((e, row_num) for e in user.all_emails)

        todo.append({
            'email': email,
            'first_name': first_name.title(),
            'last_name': last_name.title(),
            'affiliation': affiliation,
            'phone': phone,
            'position': position
        })
Exemple #18
0
def modify_registration(registration, data, management=False, notify_user=True):
    old_price = registration.price
    personal_data_changes = {}
    regform = registration.registration_form
    data_by_field = registration.data_by_field
    if management or not registration.user:
        registration.user = get_user_by_email(data['email'])

    billable_items_locked = not management and registration.is_paid
    for form_item in regform.active_fields:
        field_impl = form_item.field_impl
        if management or not form_item.parent.is_manager_only:
            value = data.get(form_item.html_field_name)
        elif form_item.id not in data_by_field:
            # set default value for manager-only field if it didn't have one before
            value = field_impl.default_value
        else:
            # manager-only field that has data which should be preserved
            continue

        if form_item.id not in data_by_field:
            data_by_field[form_item.id] = RegistrationData(registration=registration,
                                                           field_data=form_item.current_data)

        attrs = field_impl.process_form_data(registration, value, data_by_field[form_item.id],
                                             billable_items_locked=billable_items_locked)
        for key, val in attrs.iteritems():
            setattr(data_by_field[form_item.id], key, val)
        if form_item.type == RegistrationFormItemType.field_pd and form_item.personal_data_type.column:
            key = form_item.personal_data_type.column
            if getattr(registration, key) != value:
                personal_data_changes[key] = value
            setattr(registration, key, value)
    registration.sync_state()
    db.session.flush()
    # sanity check
    if billable_items_locked and old_price != registration.price:
        raise Exception("There was an error while modifying your registration (price mismatch: %s / %s)",
                        old_price, registration.price)
    if personal_data_changes:
        signals.event.registration_personal_data_modified.send(registration, change=personal_data_changes)
    signals.event.registration_updated.send(registration, management=management)
    notify_registration_modification(registration, notify_user)
    logger.info('Registration %s modified by %s', registration, session.user)
    regform.event.log(EventLogRealm.management if management else EventLogRealm.participants,
                      EventLogKind.change, 'Registration',
                      'Registration modified: {}'.format(registration.full_name),
                      session.user, data={'Email': registration.email})
Exemple #19
0
 def _getChairPersonsList(self):
     result = fossilize(self._conf.getChairList())
     for chair in result:
         user = get_user_by_email(chair['email'])
         chair['showManagerCB'] = True
         chair['showSubmitterCB'] = True
         email_submitters = {x.email for x in self._conf.as_event.acl_entries
                             if x.type == PrincipalType.email and x.has_management_role('submit', explicit=True)}
         if chair['email'] in email_submitters or (user and self._conf.as_event.can_manage(user, 'submit',
                                                                                           explicit_role=True)):
             chair['showSubmitterCB'] = False
         email_managers = {x.email for x in self._conf.as_event.acl_entries
                           if x.type == PrincipalType.email and x.has_management_role()}
         if chair['email'] in email_managers or (user and self._conf.as_event.can_manage(user, explicit_role=True)):
             chair['showManagerCB'] = False
     return result
Exemple #20
0
    def _update_managers(self, room, room_role_map, changes):
        new_managers = {room.owner}

        # add managers from aisroles (DKMs + DKAs)
        new_managers |= {get_user_by_email(email, create_pending=True)
                         for email in room_role_map[(room.building, room.floor, room.number)]}
        new_managers.discard(None)

        # compute the "diff" and update the principals accordingly (ignore groups)
        current_managers = {p for p in room.get_manager_list() if not isinstance(p, GroupProxy)}
        for principal in current_managers - new_managers:
            changes.append(f'Manager removed: {principal}')
            room.update_principal(principal, full_access=False)
        for principal in new_managers - current_managers:
            changes.append(f'Manager added: {principal}')
            room.update_principal(principal, full_access=True)
Exemple #21
0
def modify_registration(registration,
                        data,
                        management=False,
                        notify_user=True):
    old_price = registration.price
    with db.session.no_autoflush:
        regform = registration.registration_form
        data_by_field = registration.data_by_field
        if management or not registration.user:
            registration.user = get_user_by_email(data['email'])

        billable_items_locked = not management and registration.is_paid
        for form_item in regform.active_fields:
            field_impl = form_item.field_impl
            if management or not form_item.parent.is_manager_only:
                value = data.get(form_item.html_field_name)
            elif form_item.id not in data_by_field:
                # set default value for manager-only field if it didn't have one before
                value = field_impl.default_value
            else:
                # manager-only field that has data which should be preserved
                continue

            if form_item.id not in data_by_field:
                data_by_field[form_item.id] = RegistrationData(
                    registration=registration,
                    field_data=form_item.current_data)

            attrs = field_impl.process_form_data(
                registration,
                value,
                data_by_field[form_item.id],
                billable_items_locked=billable_items_locked)
            for key, val in attrs.iteritems():
                setattr(data_by_field[form_item.id], key, val)
            if form_item.type == RegistrationFormItemType.field_pd and form_item.personal_data_type.column:
                setattr(registration, form_item.personal_data_type.column,
                        value)
        registration.sync_state()
    db.session.flush()
    # sanity check
    if billable_items_locked and old_price != registration.price:
        raise Exception(
            "There was an error while modifying your registration (price mismatch: %s / %s)",
            old_price, registration.price)
    notify_registration_modification(registration, notify_user)
    logger.info('Registration %s modified by %s', registration, session.user)
Exemple #22
0
def check_registration_email(regform, email, registration=None, management=False):
    """Checks whether an email address is suitable for registration.

    :param regform: The registration form
    :param email: The email address
    :param registration: The existing registration (in case of
                         modification)
    :param management: If it's a manager adding a new registration
    """
    email = email.lower().strip()
    user = get_user_by_email(email)
    email_registration = regform.get_registration(email=email)
    user_registration = regform.get_registration(user=user) if user else None
    if registration is not None:
        if email_registration and email_registration != registration:
            return dict(status='error', conflict='email-already-registered')
        elif user_registration and user_registration != registration:
            return dict(status='error', conflict='user-already-registered')
        elif user and registration.user and registration.user != user:
            return dict(status='warning' if management else 'error', conflict='email-other-user', user=user.full_name)
        elif not user and registration.user:
            return dict(status='warning' if management else 'error', conflict='email-no-user',
                        user=registration.user.full_name)
        elif user:
            return dict(status='ok', user=user.full_name, self=(not management and user == session.user),
                        same=(user == registration.user))
        elif not validate_email(email):
            return dict(status='error', conflict='email-invalid')
        elif regform.require_user and (management or email != registration.email):
            return dict(status='warning' if management else 'error', conflict='no-user')
        else:
            return dict(status='ok', user=None)
    else:
        if email_registration:
            return dict(status='error', conflict='email-already-registered')
        elif user_registration:
            return dict(status='error', conflict='user-already-registered')
        elif user:
            return dict(status='ok', user=user.full_name, self=(not management and user == session.user), same=False)
        elif not validate_email(email):
            return dict(status='error', conflict='email-invalid')
        elif regform.require_user:
            return dict(status='warning' if management else 'error', conflict='no-user')
        else:
            return dict(status='ok', user=None)
Exemple #23
0
def get_authors_from_author_index(event, limit):
    """Fetch the authors of an event with the most contributions. An author is a
    ContributionParticipation object or an Avatar object.

    :param event: The event to fetch the author index from
    :param limit: The limit of the authors to be returned
    :return: A list of authors.
    """
    author_index = event.getAuthorIndex()
    fav_users_emails = (set(itertools.chain.from_iterable(f.all_emails for f in session.user.favorite_users))
                        if session.user else [])
    sorted_authors = [x[0] for x in sorted((p for p in author_index.getParticipations()
                                           if p[0].getEmail() not in fav_users_emails), key=len, reverse=True)]
    authors = []
    # Check if there is a corresponding Avatar for the specific user and use that.
    for author in sorted_authors[:limit]:
        user = get_user_by_email(author.getEmail())
        authors.append(user.as_avatar if user else author)
    return authors
Exemple #24
0
def modify_registration(registration, data, management=False, notify_user=True):
    old_price = registration.price
    with db.session.no_autoflush:
        regform = registration.registration_form
        data_by_field = registration.data_by_field
        if management or not registration.user:
            registration.user = get_user_by_email(data['email'])

        billable_items_locked = not management and registration.is_paid
        for form_item in regform.active_fields:
            field_impl = form_item.field_impl
            if management or not form_item.parent.is_manager_only:
                value = data.get(form_item.html_field_name)
            elif form_item.id not in data_by_field:
                # set default value for manager-only field if it didn't have one before
                value = field_impl.default_value
            else:
                # manager-only field that has data which should be preserved
                continue

            if form_item.id not in data_by_field:
                data_by_field[form_item.id] = RegistrationData(registration=registration,
                                                               field_data=form_item.current_data)

            attrs = field_impl.process_form_data(registration, value, data_by_field[form_item.id],
                                                 billable_items_locked=billable_items_locked)
            for key, val in attrs.iteritems():
                setattr(data_by_field[form_item.id], key, val)
            if form_item.type == RegistrationFormItemType.field_pd and form_item.personal_data_type.column:
                setattr(registration, form_item.personal_data_type.column, value)
        registration.sync_state()
    db.session.flush()
    # sanity check
    if billable_items_locked and old_price != registration.price:
        raise Exception("There was an error while modifying your registration (price mismatch: %s / %s)",
                        old_price, registration.price)
    notify_registration_modification(registration, notify_user)
    logger.info('Registration %s modified by %s', registration, session.user)
Exemple #25
0
def import_registrations_from_csv(regform,
                                  fileobj,
                                  skip_moderation=True,
                                  notify_users=False):
    """Import event registrants from a CSV file into a form."""
    columns = [
        'first_name', 'last_name', 'affiliation', 'position', 'phone', 'email'
    ]
    user_records = import_user_records_from_csv(fileobj, columns=columns)

    reg_data = (db.session.query(
        Registration.user_id, Registration.email).with_parent(regform).filter(
            Registration.is_active).all())
    registered_user_ids = {
        rd.user_id
        for rd in reg_data if rd.user_id is not None
    }
    registered_emails = {rd.email for rd in reg_data}

    for row_num, record in enumerate(user_records, 1):
        if record['email'] in registered_emails:
            raise UserValueError(
                _('Row {}: a registration with this email already exists').
                format(row_num))

        user = get_user_by_email(record['email'])
        if user and user.id in registered_user_ids:
            raise UserValueError(
                _('Row {}: a registration for this user already exists').
                format(row_num))

    return [
        create_registration(regform,
                            data,
                            notify_user=notify_users,
                            skip_moderation=skip_moderation)
        for data in user_records
    ]
Exemple #26
0
    def _parse_room_data(self, raw_data, coordinates):
        data = {}

        data['building'] = raw_data['BUILDING']
        data['floor'] = raw_data['FLOOR']
        data['number'] = raw_data['ROOM_NUMBER']
        data['email'] = raw_data['RESPONSIBLE_EMAIL']
        if not data['building'] or not data['floor'] or not data['number']:
            raise SkipRoom('Error in Foundation - No value for BUILDING or FLOOR or ROOM_NUMBER')
        if not data['email']:
            raise SkipRoom('Error in Foundation - No value for RESPONSIBLE_EMAIL')

        user = get_user_by_email(data['email'], create_pending=True)
        if not user:
            raise SkipRoom('Bad RESPONSIBLE_EMAIL in Foundation - No user found with email {}'.format(data['email']))

        data['owner'] = user
        data['name'] = (raw_data.get('FRIENDLY_NAME') or '').strip()
        data['capacity'] = int(raw_data['CAPACITY']) if raw_data['CAPACITY'] else None
        data['surface_area'] = int(raw_data['SURFACE']) if raw_data['SURFACE'] else None
        data['division'] = raw_data.get('DEPARTMENT')
        data['telephone'] = raw_data.get('TELEPHONE')
        data['key_location'] = raw_data.get('WHERE_IS_KEY')
        data['comments'] = raw_data.get('COMMENTS')
        data['is_reservable'] = raw_data['IS_RESERVABLE'] != 'N'
        data['reservations_need_confirmation'] = raw_data['BOOKINGS_NEED_CONFIRMATION'] != 'N'

        site = raw_data.get('SITE')
        site_map = {'MEYR': 'Meyrin', 'PREV': 'Prevessin'}
        data['site'] = site_map.get(site, site)

        building_coordinates = coordinates.get(int(data['building']))
        if building_coordinates:
            data['latitude'] = building_coordinates['latitude']
            data['longitude'] = building_coordinates['longitude']

        return data
    def _process(self):
        if self._getUser() is not None and self._getUser().isRegisteredInConf(self._conf):
            if not self._conf.getRegistrationForm().inRegistrationPeriod() and not self._conf.getRegistrationForm().inModificationPeriod():
                flash(_("Your modification could not be recorded since the modification period is over."), 'error')
                return redirect(url_for('event.confRegistrationFormDisplay', self._conf))
            else:
                rp = self._getUser().getRegistrantById(self._conf.getId())

                # Check if the email matches an existing user
                params = self._getRequestParams()
                email = self._regForm.getPersonalData().getValueFromParams(params, 'email') or ''
                user = get_user_by_email(email)
                if user:
                    if not session.user:
                        flash(_('The provided email ({email}) is linked to an Indico account. Please sign in with it '
                                'first.').format(email=email), 'error')
                        return redirect(url_for('event.confRegistrationFormDisplay-modify', self._conf))
                    elif session.user != user:
                        flash(_('The provided email ({email}) is linked to another Indico account. Please sign in with '
                                'it first.').format(email=email), 'error')
                        return redirect(url_for('event.confRegistrationFormDisplay-modify', self._conf))

                # check if the email is being changed by another one that already exists
                if email != rp.getEmail() and self._conf.hasRegistrantByEmail(email):
                    raise FormValuesError(_("There is already a user with the email \"{email}\". "
                                            "Please choose another one.").format(email or "--no email--"))
                rp.setValues(self._getRequestParams(), self._getUser())

                notify_registration_modification(self._conf, rp)
                flash(_(u"Your registration has been modified successfully."), 'success')
                if rp.doPay():
                    self._redirect(urlHandlers.UHConfRegistrationFormCreationDone.getURL(rp))
                else:
                    self._redirect(urlHandlers.UHConfRegistrationForm.getURL(self._conf))
        else:
            self._redirect(urlHandlers.UHConfRegistrationForm.getURL(self._conf))
    def _process(self):
        canManageRegistration = self._conf.canManageRegistration(self._getUser())
        if not canManageRegistration and not self._regForm.isActivated():
            p = registrationForm.WPRegFormInactive(self, self._conf)
            return p.display()
        params = self._getRequestParams()
        email = self._regForm.getPersonalData().getValueFromParams(params, 'email')
        if email is None:
            raise FormValuesError(_("An email address has to be set in order to make the registration in the event."))
        elif not validMail(email, False):
            raise FormValuesError(_("The given email address is not valid."))

        # Check if the email matches an existing user
        user = get_user_by_email(email)
        avatar = user.as_avatar if user else None
        if user:
            if not session.user:
                flash(_('The provided email ({email}) is linked to an Indico account. Please sign in with it '
                        'first.').format(email=email), 'error')
                return redirect(url_for('event.confRegistrationFormDisplay-creation', self._conf))
            elif session.user != user:
                flash(_('The provided email ({email}) is linked to another Indico account. Please sign in with it '
                        'first.').format(email=email), 'error')
                return redirect(url_for('event.confRegistrationFormDisplay-creation', self._conf))

        # Check if the user can register
        if not canManageRegistration:  # normal user registering. Managers can.
            if self._conf.getRegistrationForm().isFull():
                self._redirect(urlHandlers.UHConfRegistrationFormDisplay.getURL(self._conf))
                return
            elif not self._conf.getRegistrationForm().inRegistrationPeriod():
                flash(_("Your registration couldn't be recorded."), 'error')
                return redirect(url_for('event.confRegistrationFormDisplay', self._conf))
        if user is None:
            if self._conf.hasRegistrantByEmail(email):
                raise FormValuesError("There is already a user with the email \"%s\". Please choose another one" % email)
        else:
            if avatar.isRegisteredInConf(self._conf) or self._conf.hasRegistrantByEmail(email):
                if canManageRegistration:
                    raise FormValuesError("There is already a user with the email \"%s\". Please choose another one" % email)
                else:
                    raise FormValuesError("You have already registered with the email address \"%s\". If you need to modify your registration, please contact the managers of the conference." % email)

        rp = registration.Registrant()
        self._conf.addRegistrant(rp, avatar)
        rp.setValues(self._getRequestParams(), avatar)

        if avatar is not None:
            rp.setAvatar(avatar)

        notify_registration_confirmation(self._conf, rp)

        if canManageRegistration and user != session.user:
            self._redirect(RHRegistrantListModif._uh.getURL(self._conf))
        else:
            params = {}
            if not rp.doPay() or not payment_event_settings.get(self._conf, 'enabled'):
                flash(_(u"Your registration has been recorded successfully."), 'success')
            if not session.user:
                params.update(rp.getLocator(), **{'authkey': rp.getRandomId()})
            else:
                params.update(self._conf.getLocator())
            return redirect(url_for('event.confRegistrationFormDisplay', **params))
Exemple #29
0
 def validate_email(self, field):
     if get_user_by_email(field.data):
         raise ValidationError(
             _('There is already a user with this email address'))
Exemple #30
0
def get_user(email):
    if email not in user_cache:
        user_cache[email] = get_user_by_email(email)
    return user_cache[email]
Exemple #31
0
def check_registration_email(regform,
                             email,
                             registration=None,
                             management=False):
    """Check whether an email address is suitable for registration.

    :param regform: The registration form
    :param email: The email address
    :param registration: The existing registration (in case of
                         modification)
    :param management: If it's a manager adding a new registration
    """
    email = email.lower().strip()
    user = get_user_by_email(email)
    email_registration = regform.get_registration(email=email)
    user_registration = regform.get_registration(user=user) if user else None
    extra_checks = values_from_signal(
        signals.event.before_check_registration_email.send(
            regform,
            email=email,
            registration=registration,
            management=management,
            user=user,
            user_registration=user_registration,
            email_registration=email_registration),
        as_list=True)
    if extra_checks:
        return sorted(
            extra_checks,
            key=lambda x: ['error', 'warning', 'ok'].index(x['status']))[0]
    if registration is not None:
        if email_registration and email_registration != registration:
            return dict(status='error', conflict='email-already-registered')
        elif user_registration and user_registration != registration:
            return dict(status='error', conflict='user-already-registered')
        elif user and registration.user and registration.user != user:
            return dict(status='warning' if management else 'error',
                        conflict='email-other-user',
                        user=user.full_name)
        elif not user and registration.user:
            return dict(status='warning' if management else 'error',
                        conflict='email-no-user',
                        user=registration.user.full_name)
        elif user:
            return dict(status='ok',
                        user=user.full_name,
                        self=(not management and user == session.user),
                        same=(user == registration.user))
        email_err = validate_email_verbose(email)
        if email_err:
            return dict(status='error',
                        conflict='email-invalid',
                        email_error=email_err)
        if regform.require_user and (management
                                     or email != registration.email):
            return dict(status='warning' if management else 'error',
                        conflict='no-user')
        else:
            return dict(status='ok', user=None)
    else:
        if email_registration:
            return dict(status='error', conflict='email-already-registered')
        elif user_registration:
            return dict(status='error', conflict='user-already-registered')
        elif user:
            return dict(status='ok',
                        user=user.full_name,
                        self=(not management and user == session.user),
                        same=False)
        email_err = validate_email_verbose(email)
        if email_err:
            return dict(status='error',
                        conflict='email-invalid',
                        email_error=email_err)
        if regform.require_user:
            return dict(status='warning' if management else 'error',
                        conflict='no-user')
        else:
            return dict(status='ok', user=None)
Exemple #32
0
def modify_registration(registration,
                        data,
                        management=False,
                        notify_user=True):
    old_data = snapshot_registration_data(registration)
    old_price = registration.price
    personal_data_changes = {}
    regform = registration.registration_form
    data_by_field = registration.data_by_field
    if 'email' in data and (management or not registration.user):
        registration.user = get_user_by_email(data['email'])

    billable_items_locked = not management and registration.is_paid
    for form_item in regform.active_fields:
        if form_item.is_purged:
            continue

        field_impl = form_item.field_impl
        has_data = form_item.html_field_name in data
        can_modify = management or not form_item.parent.is_manager_only

        if has_data and can_modify:
            value = data.get(form_item.html_field_name)
        elif not has_data and form_item.id not in data_by_field:
            # set default value for a field if it didn't have one before (including manager-only fields)
            value = field_impl.default_value
        else:
            # keep current value
            continue

        if form_item.id not in data_by_field:
            data_by_field[form_item.id] = RegistrationData(
                registration=registration, field_data=form_item.current_data)

        attrs = field_impl.process_form_data(
            registration,
            value,
            data_by_field[form_item.id],
            billable_items_locked=billable_items_locked)
        for key, val in attrs.items():
            setattr(data_by_field[form_item.id], key, val)
        if form_item.type == RegistrationFormItemType.field_pd and form_item.personal_data_type.column:
            key = form_item.personal_data_type.column
            if getattr(registration, key) != value:
                personal_data_changes[key] = value
            setattr(registration, key, value)
    if not management and regform.needs_publish_consent:
        registration.consent_to_publish = data.get(
            'consent_to_publish', RegistrationVisibility.nobody)
    registration.sync_state()
    db.session.flush()
    # sanity check
    if billable_items_locked and old_price != registration.price:
        raise Exception(
            'There was an error while modifying your registration (price mismatch: %s / %s)',
            old_price, registration.price)
    if personal_data_changes:
        signals.event.registration_personal_data_modified.send(
            registration, change=personal_data_changes)
    signals.event.registration_updated.send(registration,
                                            management=management,
                                            data=data)

    new_data = snapshot_registration_data(registration)
    diff = diff_registration_data(old_data, new_data)
    notify_registration_modification(registration,
                                     notify_user,
                                     diff=diff,
                                     old_price=old_price)
    logger.info('Registration %s modified by %s', registration, session.user)
    registration.log(
        EventLogRealm.management if management else EventLogRealm.participants,
        LogKind.change,
        'Registration',
        f'Registration modified: {registration.full_name}',
        session.user,
        data={'Email': registration.email})
Exemple #33
0
class PersonLinkListFieldBase(PrincipalListField):
    #: class that inherits from `PersonLinkBase`
    person_link_cls = None
    #: name of the attribute on the form containing the linked object
    linked_object_attr = None
    #: If set to `True`, will be sorted alphabetically by default
    default_sort_alpha = True

    widget = None
    create_untrusted_persons = False

    def __init__(self, *args, **kwargs):
        super().__init__(*args,
                         allow_groups=False,
                         allow_external_users=True,
                         **kwargs)
        self.object = getattr(kwargs['_form'], self.linked_object_attr, None)

    @property
    def event(self):
        # The event should be a property as it may only be available later, such as, in creation forms
        return getattr(self.get_form(), 'event', None)

    @property
    def has_predefined_affiliations(self):
        return Affiliation.query.filter(~Affiliation.is_deleted).has_rows()

    @no_autoflush
    def _get_person_link(self, data):
        from indico.modules.events.persons.schemas import PersonLinkSchema
        identifier = data.get('identifier')
        data = PersonLinkSchema(unknown=EXCLUDE).load(data)
        if identifier and identifier.startswith('ExternalUser:'******'external-user')
            external_user_data = cache.get(
                identifier.removeprefix('ExternalUser:'******'affiliation_data'))
                    and data['affiliation'] == affiliation_data['name']):
                data['affiliation_link'] = Affiliation.get_or_create_from_data(
                    affiliation_data)
                data['affiliation'] = data['affiliation_link'].name
        person = get_event_person(
            self.event,
            data,
            create_untrusted_persons=self.create_untrusted_persons,
            allow_external=True)
        person_link = None
        if self.object and inspect(person).persistent:
            person_link = self.person_link_cls.query.filter_by(
                person=person, object=self.object).first()
        if not person_link:
            person_link = self.person_link_cls(person=person)
        person_link.populate_from_dict(
            data,
            keys=('first_name', 'last_name', 'affiliation', 'affiliation_link',
                  'address', 'phone', '_title', 'display_order'))
        email = data.get('email', '').lower()
        if email != person_link.email:
            if not self.event or not self.event.persons.filter_by(
                    email=email).first():
                person_link.person.email = email
                person_link.person.user = get_user_by_email(email)
                if inspect(person).persistent:
                    signals.event.person_updated.send(person_link.person)
            else:
                raise UserValueError(
                    _('There is already a person with the email {email}').
                    format(email=email))
        return person_link