Esempio n. 1
0
def test_get_event_person_edit(db, dummy_event, dummy_user):
    data = {
        'email': '*****@*****.**',
        'firstName': 'John',
        'familyName': 'Doe',
        'affiliation': 'ACME Inc.'
    }
    person_1 = get_event_person(dummy_event,
                                dict(data, _type='Avatar', id=dummy_user.id))
    assert person_1.id is None
    assert person_1.user == dummy_user
    db.session.add(person_1)
    db.session.flush()

    person_2 = get_event_person(
        dummy_event, dict(data, _type='EventPerson', id=person_1.id))
    assert person_2 == person_1

    person_3 = get_event_person(
        dummy_event, dict(data, _type='PersonLink', personId=person_1.id))
    assert person_3 == person_1

    with pytest.raises(ValueError):
        get_event_person(dummy_event, dict(data,
                                           _type='UnsupportedPersonType'))
Esempio n. 2
0
def test_get_event_person(db, dummy_event, dummy_user):
    data = {
        'email': '*****@*****.**',
        'firstName': 'John',
        'familyName': 'Doe',
        'affiliation': 'ACME Inc.'
    }
    person_1 = get_event_person(dummy_event, data)
    # Person doesn't exist in the DB
    assert person_1.id is None
    # User neither
    assert person_1.user is None
    # save in the DB for later
    db.session.add(person_1)
    db.session.flush()

    data = {
        'email': '*****@*****.**',
        'firstName': 'Sea',
        'familyName': 'Pig',
        'affiliation': 'ACME Inc.'
    }
    person_2 = get_event_person(dummy_event, data)
    # Person not in the DB either
    assert person_2.id is None
    # User exists, however (matched by e-mail)
    assert person_2.user == dummy_user
    assert person_2.full_name == 'Guinea Pig'

    db.session.add(person_2)
    db.session.flush()
    person = get_event_person(dummy_event, data)
    # Retrieved person should now be in the DB
    assert person.id == person_2.id

    # User for whom there is already an EventPerson in this event
    data = {
        'email': '*****@*****.**',
        'firstName': 'JOHN',
        'familyName': 'DOE',
        'affiliation': 'ACME'
    }
    person_3 = get_event_person(dummy_event, data)
    # We should get the first person
    assert person_3.id == person_1.id
    assert person_3.user is None
    assert person_3.full_name == 'John Doe'

    data = {
        'firstName': 'Foo',
        'familyName': 'Bar'
    }
    person_4 = get_event_person(dummy_event, data)
    # We should get a new person
    assert person_4.id is None
    assert person_4.user is None
    assert person_4.email == ''
    assert person_4.full_name == 'Foo Bar'
Esempio n. 3
0
def test_get_event_person(db, dummy_event, dummy_user):
    data = {
        'email': '*****@*****.**',
        'firstName': 'John',
        'familyName': 'Doe',
        'affiliation': 'ACME Inc.'
    }
    person_1 = get_event_person(dummy_event, data)
    # Person doesn't exist in the DB
    assert person_1.id is None
    # User neither
    assert person_1.user is None
    # save in the DB for later
    db.session.add(person_1)
    db.session.flush()

    data = {
        'email': '*****@*****.**',
        'firstName': 'Sea',
        'familyName': 'Pig',
        'affiliation': 'ACME Inc.'
    }
    person_2 = get_event_person(dummy_event, data)
    # Person not in the DB either
    assert person_2.id is None
    # User exists, however (matched by e-mail)
    assert person_2.user == dummy_user
    assert person_2.full_name == 'Guinea Pig'

    db.session.add(person_2)
    db.session.flush()
    person = get_event_person(dummy_event, data)
    # Retrieved person should now be in the DB
    assert person.id == person_2.id

    # User for whom there is already an EventPerson in this event
    data = {
        'email': '*****@*****.**',
        'firstName': 'JOHN',
        'familyName': 'DOE',
        'affiliation': 'ACME'
    }
    person_3 = get_event_person(dummy_event, data)
    # We should get the first person
    assert person_3.id == person_1.id
    assert person_3.user is None
    assert person_3.full_name == 'John Doe'

    data = {
        'firstName': 'Foo',
        'familyName': 'Bar'
    }
    person_4 = get_event_person(dummy_event, data)
    # We should get a new person
    assert person_4.id is None
    assert person_4.user is None
    assert person_4.email == ''
    assert person_4.full_name == 'Foo Bar'
Esempio n. 4
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
Esempio n. 5
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
Esempio n. 6
0
 def _convert_data(self, data):
     result = []
     for person_data in data:
         person = get_event_person(person_data, create_untrusted_persons=self.create_untrusted_persons,
                                   allow_pending=self.allow_external, allow_emails=self.allow_emails,
                                   allow_networks=self.allow_networks, existing_data=self.object_data)
         self.event_person_conversions[person] = data
         result.append(person)
     return map(get_event_person, data)
Esempio n. 7
0
def test_get_event_person_edit(db, dummy_event, dummy_user):
    data = {
        'email': '*****@*****.**',
        'firstName': 'John',
        'familyName': 'Doe',
        'affiliation': 'ACME Inc.'
    }
    person_1 = get_event_person(dummy_event, dict(data, _type='Avatar', id=dummy_user.id))
    assert person_1.id is None
    assert person_1.user == dummy_user
    db.session.add(person_1)
    db.session.flush()

    person_2 = get_event_person(dummy_event, dict(data, _type='EventPerson', id=person_1.id))
    assert person_2 == person_1

    person_3 = get_event_person(dummy_event, dict(data, _type='PersonLink', personId=person_1.id))
    assert person_3 == person_1

    with pytest.raises(ValueError):
        get_event_person(dummy_event, dict(data, _type='UnsupportedPersonType'))
Esempio n. 8
0
def import_contributions_from_csv(event, f):
    """Import timetable contributions from a CSV file into an event."""
    with csv_text_io_wrapper(f) as ftxt:
        reader = csv.reader(ftxt.read().splitlines())

    contrib_data = []
    for num_row, row in enumerate(reader, 1):
        try:
            start_dt, duration, title, first_name, last_name, affiliation, 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(num_row))
        try:
            parsed_start_dt = event.tzinfo.localize(
                dateutil.parser.parse(start_dt)) if start_dt else None
        except ValueError:
            raise UserValueError(
                _('Row {row}: can\'t parse date: "{date}"').format(
                    row=num_row, date=start_dt))

        try:
            parsed_duration = timedelta(
                minutes=int(duration)) if duration else None
        except ValueError:
            raise UserValueError(
                _("Row {row}: can't parse duration: {duration}").format(
                    row=num_row, duration=duration))

        if not title:
            raise UserValueError(
                _('Row {}: contribution title is required').format(num_row))

        if email and not validate_email(email):
            raise UserValueError(
                _('Row {row}: invalid email address: {email}').format(
                    row=num_row, email=email))

        contrib_data.append({
            'start_dt':
            parsed_start_dt,
            'duration':
            parsed_duration or timedelta(minutes=20),
            'title':
            title,
            'speaker': {
                'first_name': first_name,
                'last_name': last_name,
                'affiliation': affiliation,
                'email': email
            }
        })

    # now that we're sure the data is OK, let's pre-allocate the friendly ids
    # for the contributions in question
    Contribution.allocate_friendly_ids(event, len(contrib_data))
    contributions = []
    all_changes = defaultdict(list)

    for contrib_fields in contrib_data:
        speaker_data = contrib_fields.pop('speaker')

        with track_time_changes() as changes:
            contribution = create_contribution(event,
                                               contrib_fields,
                                               extend_parent=True)

        contributions.append(contribution)
        for key, val in changes[event].items():
            all_changes[key].append(val)

        email = speaker_data['email']
        if not email:
            continue

        # set the information of the speaker
        person = get_event_person(event, speaker_data)
        link = ContributionPersonLink(person=person, is_speaker=True)
        link.populate_from_dict({
            'first_name': speaker_data['first_name'],
            'last_name': speaker_data['last_name'],
            'affiliation': speaker_data['affiliation']
        })
        contribution.person_links.append(link)

    return contributions, all_changes
Esempio n. 9
0
def import_contributions_from_csv(event, f):
    """Import timetable contributions from a CSV file into an event."""
    reader = csv.reader(f.read().splitlines())
    contrib_data = []

    for num_row, row in enumerate(reader, 1):
        try:
            start_dt, duration, title, first_name, last_name, affiliation, email = \
                [to_unicode(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(num_row))
        try:
            parsed_start_dt = event.tzinfo.localize(dateutil.parser.parse(start_dt)) if start_dt else None
        except ValueError:
            raise UserValueError(_("Row {row}: can't parse date: \"{date}\"").format(row=num_row, date=start_dt))

        try:
            parsed_duration = timedelta(minutes=int(duration)) if duration else None
        except ValueError:
            raise UserValueError(_("Row {row}: can't parse duration: {duration}").format(row=num_row,
                                                                                         duration=duration))

        if not title:
            raise UserValueError(_("Row {}: contribution title is required").format(num_row))

        if email and not validate_email(email):
            raise UserValueError(_("Row {row}: invalid email address: {email}").format(row=num_row, email=email))

        contrib_data.append({
            'start_dt': parsed_start_dt,
            'duration': parsed_duration or timedelta(minutes=20),
            'title': title,
            'speaker': {
                'first_name': first_name,
                'last_name': last_name,
                'affiliation': affiliation,
                'email': email
            }
        })

    # now that we're sure the data is OK, let's pre-allocate the friendly ids
    # for the contributions in question
    Contribution.allocate_friendly_ids(event, len(contrib_data))
    contributions = []
    all_changes = defaultdict(list)

    for contrib_fields in contrib_data:
        speaker_data = contrib_fields.pop('speaker')

        with track_time_changes() as changes:
            contribution = create_contribution(event, contrib_fields, extend_parent=True)

        contributions.append(contribution)
        for key, val in changes[event].viewitems():
            all_changes[key].append(val)

        email = speaker_data['email']
        if not email:
            continue

        # set the information of the speaker
        person = get_event_person(event, {
            'firstName': speaker_data['first_name'],
            'familyName': speaker_data['last_name'],
            'affiliation': speaker_data['affiliation'],
            'email': email
        })
        link = ContributionPersonLink(person=person, is_speaker=True)
        link.populate_from_dict({
            'first_name': speaker_data['first_name'],
            'last_name': speaker_data['last_name'],
            'affiliation': speaker_data['affiliation']
        })
        contribution.person_links.append(link)

    return contributions, all_changes
Esempio n. 10
0
def import_contributions_from_csv(event, f):
    """Import timetable contributions from a CSV file into an event."""
    reader = csv.reader(f)
    contributions = []
    all_changes = defaultdict(list)
    for num_row, row in enumerate(reader, 1):
        try:
            start_dt, duration, title, first_name, last_name, affiliation, email = row
        except ValueError:
            raise UserValueError(
                _('Row {}: malformed CSV data - please check that the number of columns is correct'
                  ).format(num_row))
        try:
            parsed_start_dt = event.tzinfo.localize(
                dateutil.parser.parse(start_dt)) if start_dt else None
        except ValueError:
            raise UserValueError(
                _("Row {}: can't parse date: \"{}\"").format(
                    num_row, start_dt))

        try:
            parsed_duration = timedelta(
                minutes=int(duration)) if duration else None
        except ValueError:
            raise UserValueError(
                _("Row {}: can't parse duration: {}").format(
                    num_row, duration))

        if not title:
            raise UserValueError(
                _("Row {}: contribution title is required").format(num_row))

        with track_time_changes() as changes:
            contribution = create_contribution(
                event, {
                    'start_dt': parsed_start_dt,
                    'duration': parsed_duration or timedelta(minutes=20),
                    'title': title
                },
                extend_parent=True)

        contributions.append(contribution)
        for key, val in changes[event].viewitems():
            all_changes[key].append(val)

        if not email:
            continue

        # set the information of the speaker
        person = get_event_person(
            event, {
                'firstName': first_name,
                'familyName': last_name,
                'affiliation': affiliation,
                'email': email
            })
        link = ContributionPersonLink(person=person, is_speaker=True)
        link.populate_from_dict({
            'first_name': first_name,
            'last_name': last_name,
            'affiliation': affiliation,
            'email': email
        })
        contribution.person_links.append(link)

    return contributions, all_changes
Esempio n. 11
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