示例#1
0
    def _process(self, source):
        self.user.picture_source = source

        if source == ProfilePictureSource.standard:
            self.user.picture = None
            self.user.picture_metadata = None
            logger.info('Profile picture of user %s removed by %s', self.user, session.user)
            return '', 204

        if source == ProfilePictureSource.custom:
            f = request.files['picture']
            try:
                pic = Image.open(f)
            except OSError:
                raise UserValueError(_('You cannot upload this file as profile picture.'))
            if pic.format.lower() not in {'jpeg', 'png', 'gif', 'webp'}:
                raise UserValueError(_('The file has an invalid format ({format}).').format(format=pic.format))
            if pic.mode not in ('RGB', 'RGBA'):
                pic = pic.convert('RGB')
            pic = square(pic)
            if pic.height > 256:
                pic = pic.resize((256, 256), resample=Image.BICUBIC)
            image_bytes = BytesIO()
            pic.save(image_bytes, 'PNG')
            image_bytes.seek(0)
            set_user_avatar(self.user, image_bytes.read(), f.filename)
        else:
            content, lastmod = get_gravatar_for_user(self.user, source == ProfilePictureSource.identicon, 256)
            set_user_avatar(self.user, content, source.name, lastmod)

        logger.info('Profile picture of user %s updated by %s', self.user, session.user)
        return '', 204
示例#2
0
 def _process_POST(self):
     data = dict({
         'background_position': 'stretch',
         'items': []
     }, **request.json['template'])
     self.validate_json(TEMPLATE_DATA_JSON_SCHEMA, data)
     invalid_placeholders = {x['type']
                             for x in data['items']} - set(
                                 get_placeholder_options())
     if invalid_placeholders:
         raise UserValueError('Invalid item types: {}'.format(
             ', '.join(invalid_placeholders)))
     image_items = [
         item for item in data['items'] if item['type'] == 'fixed_image'
     ]
     template_images = {img.id for img in self.template.images}
     for image_item in image_items:
         if 'image_id' not in image_item:
             raise UserValueError(
                 _('A Fixed Image element must contain an image'))
         if image_item['image_id'] not in template_images:
             raise UserValueError(
                 _('The image file does not belong to this template'))
     update_template(
         self.template,
         title=request.json['title'],
         data=data,
         backside_template_id=request.json['backside_template_id'],
         is_clonable=request.json['is_clonable'],
         clear_background=request.json['clear_background'])
     flash(_('Template successfully saved.'), 'success')
     return jsonify_data()
示例#3
0
 def _process(self):
     f = request.files['picture']
     try:
         pic = Image.open(f)
     except IOError:
         raise UserValueError(
             _('You cannot upload this file as profile picture.'))
     if pic.format.lower() not in {'jpeg', 'png', 'gif'}:
         raise UserValueError(
             _('The file has an invalid format ({format}).').format(
                 format=pic.format))
     if pic.mode not in {'RGB', 'RGBA'}:
         pic = pic.convert('RGB')
     image_bytes = BytesIO()
     pic = square(pic)
     if pic.height > 256:
         pic = pic.resize((256, 256), resample=Image.BICUBIC)
     pic.save(image_bytes, 'PNG')
     image_bytes.seek(0)
     content = image_bytes.read()
     self.user.picture = content
     self.user.picture_metadata = {
         'hash': crc32(content),
         'size': len(content),
         'filename':
         os.path.splitext(secure_filename(f.filename, 'user'))[0] + '.png',
         'content_type': 'image/png'
     }
     flash(_('Profile picture uploaded'), 'success')
     logger.info('Profile picture of user %s uploaded by %s', self.user,
                 session.user)
     return jsonify_data(content=get_picture_data(self.user))
示例#4
0
    def import_members_from_csv(self, f):
        with csv_text_io_wrapper(f) as ftxt:
            reader = csv.reader(ftxt.read().splitlines())

        emails = set()
        for num_row, row in enumerate(reader, 1):
            if len(row) != 1:
                raise UserValueError(
                    _('Row {}: malformed CSV data').format(num_row))
            email = row[0].strip().lower()

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

        users = set(
            User.query.filter(~User.is_deleted, User.all_emails.in_(emails)))
        users_emails = {user.email for user in users}
        unknown_emails = emails - users_emails
        new_members = users - self.role.members
        return new_members, users, unknown_emails
示例#5
0
 def _process(self):
     new_start_dt = self.event_new.tzinfo.localize(
         dateutil.parser.parse(
             request.form.get('startDate'))).astimezone(utc)
     new_end_dt = self.event_new.tzinfo.localize(
         dateutil.parser.parse(request.form.get('endDate'))).astimezone(utc)
     new_duration = new_end_dt - new_start_dt
     is_session_block = self.entry.type == TimetableEntryType.SESSION_BLOCK
     tzinfo = self.event_new.tzinfo
     if is_session_block and new_end_dt.astimezone(tzinfo).date(
     ) != self.entry.start_dt.astimezone(tzinfo).date():
         raise UserValueError(
             _('Session block cannot span more than one day'))
     with track_time_changes(auto_extend=True,
                             user=session.user) as changes:
         update_timetable_entry_object(self.entry,
                                       {'duration': new_duration})
         if is_session_block:
             self.entry.move(new_start_dt)
         if not is_session_block:
             update_timetable_entry(self.entry, {'start_dt': new_start_dt})
     if is_session_block and self.entry.children:
         if new_end_dt < max(self.entry.children,
                             key=attrgetter('end_dt')).end_dt:
             raise UserValueError(
                 _("Session block cannot be shortened this much because contributions contained "
                   "wouldn't fit."))
     notifications = get_time_changes_notifications(
         changes, tzinfo=self.event_new.tzinfo, entry=self.entry)
     return jsonify_data(flash=False,
                         update=serialize_entry_update(
                             self.entry, session_=self.session),
                         notifications=notifications)
示例#6
0
def import_registrations_from_csv(regform, fileobj, skip_moderation=True, notify_users=False):
    """Import event registrants from a CSV file into a form."""
    reader = csv.reader(fileobj)
    registrations = []
    for row_num, row in enumerate(reader, 1):
        try:
            first_name, last_name, affiliation, position, phone, email = [to_unicode(value).strip() for value in row]
        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 first_name or not last_name:
            raise UserValueError(_('Row {}: missing first or last name').format(row_num))

        with db.session.no_autoflush:
            registrations.append(create_registration(regform, {
                'email': email,
                'first_name': first_name.title(),
                'last_name': last_name.title(),
                'affiliation': affiliation,
                'phone': phone,
                'position': position
            }, notify_user=notify_users, skip_moderation=skip_moderation))
    return registrations
示例#7
0
def track_time_changes(auto_extend=False, user=None):
    """Track time changes of event objects.

    This provides a list of changes while the context manager was
    active and also triggers `times_changed` signals.

    If the code running inside the ``with`` block of this context
    manager raises an exception, no signals will be triggered.

    :param auto_extend: Whether entry parents will get their boundaries
                        automatically extended or not. Passing ``'start'`` will
                        extend only start datetime, ``'end'`` to extend only
                        end datetime.
    :param user: The `User` that will trigger time changes.
    """
    if auto_extend:
        assert user is not None
    if 'old_times' in g:
        raise RuntimeError('time change tracking may not be nested')
    g.old_times = defaultdict(dict)
    changes = defaultdict(dict)
    try:
        yield changes
    except Exception:
        del g.old_times
        raise
    else:
        if auto_extend:
            by_start = auto_extend in (True, 'start')
            by_end = auto_extend in (True, 'end')
            initial_changes = set(g.old_times)
            # g.old_times changes during iteration
            for obj in list(g.old_times):
                if not isinstance(obj, Event):
                    obj.extend_parent(by_start=by_start, by_end=by_end)
            cascade_changes = set(g.old_times) - initial_changes
            for obj in cascade_changes:
                if isinstance(obj, Event):
                    if not obj.can_manage(user):
                        # TODO: raise Forbidden exceptions after adding protection check in the UI
                        raise UserValueError(_("Your action requires modification of event boundaries, but you are "
                                               "not authorized to manage the event."))
                elif not obj.object.can_manage(user):
                    # TODO: raise Forbidden exceptions after adding protection check in the UI
                    raise UserValueError(_("Your action requires modification of session block boundaries, but you are "
                                           "not authorized to manage the session block."))
        old_times = g.pop('old_times')
        for obj, info in old_times.items():
            if isinstance(obj, TimetableEntry):
                obj = obj.object
            if obj.start_dt != info['start_dt']:
                changes[obj]['start_dt'] = (info['start_dt'], obj.start_dt)
            if obj.duration != info['duration']:
                changes[obj]['duration'] = (info['duration'], obj.duration)
            if obj.end_dt != info['end_dt']:
                changes[obj]['end_dt'] = (info['end_dt'], obj.end_dt)
        for obj, obj_changes in changes.items():
            entry = None if isinstance(obj, Event) else obj.timetable_entry
            signals.event.times_changed.send(type(obj), entry=entry, obj=obj, changes=obj_changes)
示例#8
0
文件: util.py 项目: javfg/indico
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
示例#9
0
    def _process_DELETE(self):
        if EditingRevisionFile.query.with_parent(self.file_type).has_rows():
            raise UserValueError(_('Cannot delete file type which already has files'))

        if self.file_type.review_conditions:
            raise UserValueError(_('Cannot delete file type which is used in a review condition'))
        if self.file_type.publishable:
            is_last = not (EditingFileType.query
                           .with_parent(self.event)
                           .filter(EditingFileType.publishable, EditingFileType.id != self.file_type.id)
                           .has_rows())
            if is_last:
                raise UserValueError(_('Cannot delete the only publishable file type'))
        delete_file_type(self.file_type)
        return '', 204
示例#10
0
    def create_form(self,
                    event,
                    existing_vc_room=None,
                    existing_event_vc_room=None):
        """Override the default room form creation mechanism."""

        if existing_vc_room and request.method != 'POST':
            try:
                self.refresh_room(existing_vc_room, event)
            except VCRoomNotFoundError as exc:
                raise UserValueError(str(exc))
            except VCRoomError:
                # maybe a temporary issue - we just keep going and fail when saving in
                # case it's something more persistent
                pass

        form = super().create_form(
            event,
            existing_vc_room=existing_vc_room,
            existing_event_vc_room=existing_event_vc_room)

        if existing_vc_room:
            form.host_choice.render_kw = {'disabled': True}
            form.host_user.render_kw = {'disabled': True}
            if self.settings.get('allow_webinars'):
                # if we're editing a VC room, we will not allow the meeting type to be changed
                form.meeting_type.render_kw = {'disabled': True}

                if form.data['meeting_type'] == 'webinar':
                    # webinar hosts cannot be changed through the API
                    form.host_choice.render_kw = {'disabled': True}
                    form.host_user.render_kw = {'disabled': True}
        elif not form.is_submitted():
            form.password.data = gen_random_password()
        return form
示例#11
0
 def _reschedule_duration(self):
     for entry, successor in window(self._entries):
         duration = successor.start_dt - entry.start_dt - self.gap
         if duration <= timedelta(0):
             raise UserValueError(_("The chosen time gap would result in an entry with a duration of less than a "
                                    "minute. Please choose a smaller gap between entries."))
         entry.object.duration = duration
示例#12
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
示例#13
0
 def _get_person_link(self, data, extra_data=None):
     extra_data = extra_data or {}
     person = self._get_event_person(data)
     person_data = {
         'title':
         next((x.value for x in UserTitle if data.get('title') == 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', '')
     }
     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.persons.filter_by(email=email).first():
             person_link.person.email = email
         else:
             raise UserValueError(
                 _('There is already a person with the email {}').format(
                     email))
     return person_link
示例#14
0
 def _process(self):
     data = request.json
     required_keys = {'contribution_ids', 'day'}
     allowed_keys = required_keys | {'session_block_id'}
     if set(data.viewkeys()) > allowed_keys:
         raise BadRequest('Invalid keys found')
     elif required_keys > set(data.viewkeys()):
         raise BadRequest('Required keys missing')
     entries = []
     day = dateutil.parser.parse(data['day']).date()
     query = Contribution.query.with_parent(self.event_new).filter(
         Contribution.id.in_(data['contribution_ids']))
     with track_time_changes(auto_extend='end',
                             user=session.user) as changes:
         for contribution in query:
             start_dt = find_next_start_dt(
                 contribution.duration,
                 obj=self.session_block or self.event_new,
                 day=None if self.session_block else day,
                 force=True)
             entry = self._schedule(contribution, start_dt)
             if entry.end_dt.astimezone(
                     entry.event_new.tzinfo).date() > day:
                 raise UserValueError(
                     _("Contribution '{}' could not be scheduled since it doesn't fit on this day."
                       ).format(contribution.title))
             entries.append(entry)
     notifications = get_time_changes_notifications(
         changes, tzinfo=self.event_new.tzinfo)
     return jsonify_data(update=serialize_entry_update(
         entries[0], session_=self.session) if entries else None,
                         notifications=notifications,
                         flash=False)
示例#15
0
 def _process_POST(self):
     f = request.files['photo']
     try:
         photo = Image.open(f)
     except OSError:
         raise UserValueError(_('You cannot upload this file as a room picture.'))
     if photo.format.lower() not in {'jpeg', 'png', 'gif'}:
         raise UserValueError(_('The file has an invalid format ({format}).').format(format=photo.format))
     if photo.mode != 'RGB':
         photo = photo.convert('RGB')
     image_bytes = BytesIO()
     photo.save(image_bytes, 'JPEG')
     image_bytes.seek(0)
     self.room.photo = Photo(data=image_bytes.read())
     token = build_rooms_spritesheet()
     return jsonify(rooms_sprite_token=str(token))
示例#16
0
    def _process(self):
        if self.editable:
            raise UserValueError(_('Editable already exists'))

        args = parser.parse({
            'files':
            EditingFilesField(self.event,
                              self.contrib,
                              self.editable_type,
                              required=True)
        })
        service_url = editing_settings.get(self.event, 'service_url')
        initial_state = InitialRevisionState.new if service_url else InitialRevisionState.ready_for_review

        editable = create_new_editable(self.contrib, self.editable_type,
                                       session.user, args['files'],
                                       initial_state)
        if service_url:
            try:
                service_handle_new_editable(editable, session.user)
            except ServiceRequestFailed:
                raise ServiceUnavailable(
                    _('Submission failed, please try again later.'))

        return '', 201
示例#17
0
 def _process(self):
     language = request.form['lang']
     if language not in get_all_locales():
         raise UserValueError('Invalid language')
     session.lang = language
     if session.user:
         session.user.settings.set('lang', language)
     return '', 204
示例#18
0
 def _process(self, id):
     last_rev = self.contrib.paper.get_last_revision()
     if last_rev:
         found = next((f for f in last_rev.files if f.id == id), None)
         if found:
             with found.open() as stream:
                 return self._save_file(found, stream)
     raise UserValueError(_('No such file was found within the paper'))
示例#19
0
 def _process_args(self):
     self.backend_name = request.view_args['backend']
     try:
         self.backend = current_plugin.backend_classes[self.backend_name]
     except KeyError:
         raise NotFound
     if self.backend.unique and LiveSyncAgent.query.filter_by(backend_name=self.backend_name).has_rows():
         raise UserValueError(_('This backend is already in use'))
示例#20
0
    def _process(self):
        if self.editable:
            raise UserValueError(_('Editable already exists'))

        args = parser.parse({
            'files': EditingFilesField(self.event, self.contrib, required=True)
        })

        create_new_editable(self.contrib, self.editable_type, session.user, args['files'])
        return '', 201
示例#21
0
 def _process(self):
     if not self.registrations:
         raise UserValueError(_("The selected registrants have been removed."))
     registration = self.registrations[0]
     email_body = replace_placeholders('registration-email', request.form['body'], regform=self.regform,
                                       registration=registration)
     tpl = get_template_module('events/registration/emails/custom_email.html', email_subject=request.form['subject'],
                               email_body=email_body)
     html = render_template('events/registration/management/email_preview.html', subject=tpl.get_subject(),
                            body=tpl.get_body())
     return jsonify(html=html)
示例#22
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
        })
示例#23
0
 def _process_POST(self):
     data = dict({'background_position': 'stretch', 'items': []}, **request.json['template'])
     self.validate_json(TEMPLATE_DATA_JSON_SCHEMA, data)
     invalid_placeholders = {x['type'] for x in data['items']} - set(get_placeholder_options()) - {'fixed'}
     if invalid_placeholders:
         raise UserValueError('Invalid item types: {}'.format(', '.join(invalid_placeholders)))
     update_template(self.template, title=request.json['title'], data=data,
                     backside_template_id=request.json['backside_template_id'],
                     is_clonable=request.json['is_clonable'],
                     clear_background=request.json['clear_background'])
     flash(_("Template successfully saved."), 'success')
     return jsonify_data()
示例#24
0
 def _process(self):
     access_request = self.registration.cern_access_request
     if not access_request or access_request.has_identity_info:
         raise UserValueError(_('The personal data for this registrant has already been entered'))
     form = AccessIdentityDataForm()
     if form.validate_on_submit():
         form.populate_obj(access_request)
         db.session.flush()
         send_ticket(self.registration)
         return jsonify_data(html=render_plugin_template('cern_access_status.html', registration=self.registration,
                                                         header=False))
     return jsonify_template('identity_data_form_management.html', render_plugin_template, form=form,
                             registration=self.registration)
示例#25
0
文件: util.py 项目: javfg/indico
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
    ]
示例#26
0
文件: util.py 项目: kuba111333/indico
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())
    query = db.session.query(Registration.email).with_parent(regform).filter(
        Registration.is_active)
    registered_emails = {email for (email, ) in query}
    used_emails = set()
    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))
        if email in used_emails:
            raise UserValueError(
                _('Row {}: email address is not unique').format(row_num))

        used_emails.add(email)
        todo.append({
            'email': email,
            'first_name': first_name.title(),
            'last_name': last_name.title(),
            'affiliation': affiliation,
            'phone': phone,
            'position': position
        })
    return [
        create_registration(regform,
                            data,
                            notify_user=notify_users,
                            skip_moderation=skip_moderation) for data in todo
    ]
示例#27
0
 def adjust_payment_form_data(self, data):
     data['postfinance_methods'] = get_payment_methods(data['event'], data['currency'])
     data['selected_method'] = selected_method = request.args.get('postfinance_method', '')
     base_amount = data['amount']
     if selected_method:
         method = get_payment_method(data['event'], data['currency'], selected_method)
         if method is None:
             raise UserValueError(_('Invalid currency'))
         modifier = Decimal(1 / (1 - method['fee'] / 100))
         data['amount'] = base_amount * modifier
         data['fee'] = data['amount'] - base_amount
         data['form_data'] = self._generate_form_data(data['amount'], data)
     else:
         data['form_data'] = None
         data['fee'] = None
         if data['event_settings']['apply_fees']:  # we don't know the final price
             data['amount'] = None
示例#28
0
def move_timetable_entry(entry, parent=None, day=None):
    """Move the `entry` to another session or top-level timetable

    :param entry: `TimetableEntry` to be moved
    :param parent: If specified then the entry will be set as a child
                         of parent
    :param day: If specified then the entry will be moved to the
                        top-level timetable on this day
    """
    if bool(parent) + bool(day) != 1:
        raise TypeError("Wrong number of arguments")

    from indico.modules.events.contributions.operations import update_contribution

    updates = {}
    contrib_update_data = {}
    if day:
        new_start_dt = entry.start_dt.replace(day=day.day, month=day.month)
        updates['start_dt'] = new_start_dt
        updates['parent'] = None
        contrib_update_data = {'session_id': None, 'session_block_id': None}
    elif parent:
        new_start_dt = find_latest_entry_end_dt(
            parent.object) or parent.start_dt
        tz = entry.event.tzinfo
        if (new_start_dt + entry.duration
            ).astimezone(tz).date() != parent.start_dt.astimezone(tz).date():
            raise UserValueError(
                _('Session block cannot span more than one day'))
        updates['parent'] = parent
        updates['start_dt'] = new_start_dt
        contrib_update_data = {
            'session': parent.session_block.session,
            'session_block': parent.session_block
        }

    update_timetable_entry(entry, updates)
    if entry.type == TimetableEntryType.CONTRIBUTION:
        update_contribution(entry.object, contrib_update_data)
    if parent and entry.end_dt > parent.end_dt:
        duration = parent.object.duration + (entry.end_dt - parent.end_dt)
        update_session_block(parent.object, {'duration': duration})
示例#29
0
    def _generate_form_data(self, amount, data):
        if amount is None:
            return {}
        registration = data['registration']
        personal_data = registration.get_personal_data()
        event = data['event']
        currency = data['currency']
        seed = data['settings']['hash_seed_{}'.format(currency.lower())]
        shop_id = data['settings']['shop_id_{}'.format(currency.lower())]
        method = get_payment_method(event, currency, data['selected_method'])
        if method is None:
            raise UserValueError(_('Invalid currency'))
        template_page = ''  # yes, apparently it's supposed to be empty..
        template_hash = sha512((seed + template_page).encode('utf-8')).hexdigest()
        order_id = self._get_order_id(data)
        locator = registration.locator.uuid

        address = re.sub(r'(\r?\n)+', ', ', personal_data.get('address', ''))
        form_data = {
            'PSPID': shop_id,
            'ORDERID': order_id,
            'AMOUNT': int(amount * 100),
            'CURRENCY': currency,
            'LANGUAGE': session.lang,
            'CN': unicode_to_ascii(remove_accents(registration.full_name[:35], False)),
            'EMAIL': registration.email[:50],
            'OWNERADDRESS': address[:35],
            'OWNERTELNO': personal_data.get('phone', '')[:30],
            'TP': template_page + '&hash=' + template_hash,
            'PM': method['type'],
            'BRAND': method['name'],
            'PARAMVAR': data['settings']['server_url_suffix'],
            'HOMEURL': url_for('event_registration.display_regform', locator, _external=True),
            'ACCEPTURL': url_for_plugin('payment_cern.success', locator, _external=True),
            'CANCELURL': url_for_plugin('payment_cern.cancel', locator, _external=True),
            'DECLINEURL': url_for_plugin('payment_cern.decline', locator, _external=True),
            'EXCEPTIONURL': url_for_plugin('payment_cern.uncertain', locator, _external=True),
            'BACKURL': url_for('payment.event_payment', locator, _external=True)
        }

        form_data['SHASIGN'] = create_hash(seed, form_data)
        return form_data
示例#30
0
    def _process(self):
        new_identifier = session.user.identifier
        if new_identifier == self.vc_room.data['host'] or new_identifier in self.vc_room.data['alternative_hosts']:
            flash(_('You were already an (alternative) host of this meeting'), 'warning')
            return jsonify(success=False)

        try:
            self.plugin.refresh_room(self.vc_room, self.event)
            self.vc_room.data['alternative_hosts'].append(new_identifier)
            flag_modified(self.vc_room, 'data')
            self.plugin.update_room(self.vc_room, self.event)
        except VCRoomNotFoundError as exc:
            db.session.rollback()
            raise UserValueError(str(exc)) from exc
        except VCRoomError:
            db.session.rollback()
            raise
        else:
            flash(_("You are now an alternative host of room '{room}'").format(room=self.vc_room.name), 'success')
        return jsonify(success=True)