def test_modifying_registration_field_changed( dummy_event, dummy_regform, create_accompanying_persons_field, max_persons, persons_count_against_limit, registration_limit, expected_limit, old_num_persons, new_num_persons): set_feature_enabled(dummy_event, 'registration', True) dummy_regform.registration_limit = registration_limit expected_occupied_slots = 1 + old_num_persons if persons_count_against_limit else 1 reg = dummy_event.registrations.one() field = create_accompanying_persons_field(max_persons, persons_count_against_limit, registration=reg, num_persons=old_num_persons) validator = field.field_impl.get_validators(reg) _assert_occupied_slots(reg, expected_occupied_slots) _assert_registration_count(dummy_regform, expected_occupied_slots) assert field.field_impl._get_field_available_places(reg) == expected_limit if registration_limit and expected_occupied_slots >= registration_limit: assert dummy_regform.limit_reached else: assert not dummy_regform.limit_reached if expected_limit and new_num_persons > old_num_persons and new_num_persons > expected_limit: with pytest.raises(ValidationError): validator(_create_accompanying_persons(new_num_persons)) else: validator(_create_accompanying_persons(new_num_persons))
def migrate_regforms(self): try: self.old_participation = self.conf._participation except AttributeError: self.print_info('Event has no participation') return if not self.old_participation._participantList and not self.old_participation._pendingParticipantList: self.print_info('Participant lists are empty') return set_feature_enabled(self.event, 'registration', True) with db.session.no_autoflush: self.regform = RegistrationForm( event_id=self.event.id, title=PARTICIPATION_FORM_TITLE, is_participation=True, currency=payment_settings.get('currency')) if not self.quiet: self.print_success('%[cyan]{}'.format(self.regform.title)) self._migrate_settings() self._create_form() self._migrate_participants() db.session.add(self.regform) db.session.flush()
def test_visibility_duration(dummy_event, dummy_regform, freeze_time): set_feature_enabled(dummy_event, 'registration', True) reg = dummy_event.registrations.one() dummy_regform.publish_registrations_participants = PublishRegistrationsMode.show_all dummy_regform.publish_registrations_public = PublishRegistrationsMode.show_all freeze_time(datetime(2022, 1, 1, tzinfo=utc)) dummy_event.start_dt = datetime(2020, 1, 1, tzinfo=utc) dummy_event.end_dt = datetime(2021, 1, 1, tzinfo=utc) assert not reg.participant_hidden assert reg.is_active assert reg.state == RegistrationState.complete assert dummy_regform.publish_registrations_duration is None assert_visibility(reg, RegistrationVisibility.all) dummy_regform.publish_registrations_duration = timedelta(days=1 * 30) assert_visibility(reg, RegistrationVisibility.nobody, test_visibility_prop=False) dummy_regform.publish_registrations_duration = timedelta(days=12 * 30) assert_visibility(reg, RegistrationVisibility.nobody, test_visibility_prop=False) dummy_regform.publish_registrations_duration = timedelta(days=13 * 30) assert_visibility(reg, RegistrationVisibility.all) dummy_regform.publish_registrations_duration = timedelta(days=20 * 30) assert_visibility(reg, RegistrationVisibility.all)
def _process(self): regform = self.event.participation_regform registration_enabled = self.event.has_feature('registration') participant_visibility = (PublishRegistrationsMode.show_with_consent if self.event.type_ == EventType.lecture else PublishRegistrationsMode.show_all) public_visibility = (PublishRegistrationsMode.show_with_consent if self.event.type_ == EventType.lecture else PublishRegistrationsMode.show_all) form = RegistrationFormCreateForm(title='Participants', visibility=[participant_visibility.name, public_visibility.name, None]) if form.validate_on_submit(): set_feature_enabled(self.event, 'registration', True) if not regform: regform = RegistrationForm(event=self.event, is_participation=True, currency=payment_settings.get('currency')) create_personal_data_fields(regform) form.populate_obj(regform, skip=['visibility']) participant_visibility, public_visibility, visibility_duration = form.visibility.data regform.publish_registrations_participants = PublishRegistrationsMode[participant_visibility] regform.publish_registrations_public = PublishRegistrationsMode[public_visibility] regform.publish_registrations_duration = (timedelta(days=visibility_duration*30) if visibility_duration is not None else None) db.session.add(regform) db.session.flush() signals.event.registration_form_created.send(regform) self.event.log(EventLogRealm.management, LogKind.positive, 'Registration', f'Registration form "{regform.title}" has been created', session.user) return redirect(url_for('event_registration.manage_regform', regform)) if not regform or not registration_enabled: return WPManageParticipants.render_template('management/participants.html', self.event, form=form, regform=regform, registration_enabled=registration_enabled) return redirect(url_for('event_registration.manage_regform', regform))
def enable_features(self): self.print_step("Enabling registration features") event_ids = [x[0] for x in set(db.session.query(RegistrationForm.event_id) .filter(RegistrationForm.title == PARTICIPATION_FORM_TITLE))] it = verbose_iterator(event_ids, len(event_ids), lambda x: x, lambda x: self.zodb_root['conferences'][str(x)].title) for event_id in committing_iterator(it): set_feature_enabled(self.zodb_root['conferences'][str(event_id)], 'registration', True)
def _process_POST(self): regform = self.event_new.participation_regform set_feature_enabled(self.event, 'registration', True) if not regform: regform = RegistrationForm(event_new=self.event_new, title="Participants", is_participation=True) create_personal_data_fields(regform) db.session.add(regform) db.session.flush() self.event.log(EventLogRealm.management, EventLogKind.positive, 'Registration', 'Registration form "{}" has been created'.format(regform.title), session.user) return redirect(url_for('event_registration.manage_regform', regform))
def test_unused_event_person(db, dummy_user, dummy_event, create_contribution, create_subcontribution, create_abstract): person = EventPerson.create_from_user(dummy_user, event=dummy_event) assert not person.has_links dummy_event.person_links.append(EventPersonLink(person=person)) db.session.flush() assert person.has_links dummy_event.person_links.clear() db.session.flush() assert not person.has_links set_feature_enabled(dummy_event, 'abstracts', True) abstract = create_abstract(dummy_event, 'Dummy abstract', submitter=dummy_user, person_links=[ AbstractPersonLink( person=person, is_speaker=True, author_type=AuthorType.primary) ]) assert person.has_links abstract.is_deleted = True assert not person.has_links contrib = create_contribution( dummy_event, 'Dummy contribution', person_links=[ContributionPersonLink(person=person, is_speaker=True)]) assert person.has_links contrib.is_deleted = True assert not person.has_links db.session.delete(contrib) contrib = create_contribution(dummy_event, 'Dummy contribution', person_links=[]) assert not person.has_links create_subcontribution(contrib, 'Dummy subcontribution', person_links=[ SubContributionPersonLink(person=person, is_speaker=True) ]) assert person.has_links contrib.is_deleted = True assert not person.has_links db.session.delete(contrib) assert not person.has_links
def _event_type_changed(event, **kwargs): from indico.modules.events.features.util import (format_feature_names, get_disallowed_features, get_enabled_features, set_feature_enabled) conflicting = get_enabled_features(event, only_explicit=True) & get_disallowed_features(event) if conflicting: for feature in conflicting: set_feature_enabled(event, feature, False) # XXX: we cannot flash a message in the legacy js ajax editor for the event type. # remove this check once we don't use it anymore (on the general settings page) flash(ngettext('Feature disabled: {features} (not available for this event type)', 'Features disabled: {features} (not available for this event type)', len(conflicting)) .format(features=format_feature_names(conflicting)), 'warning')
def migrate(self): if not hasattr(self.conf, '_registrationForm') or not hasattr( self.conf, '_modPay'): self.event_ns.misc_data['payment_currency'] = payment_settings.get( 'currency') self.event_ns.payment_messages.update({ 'register': '', 'success': '' }) self.print_info('Event has no legacy payment/registration data') return old_payment = self.conf._modPay default_conditions = payment_settings.get('conditions') conditions = (getattr(old_payment, 'paymentConditions', default_conditions) if (getattr(old_payment, 'paymentConditionsEnabled', False) and convert_to_unicode( getattr(old_payment, 'specificPaymentConditions', '')).strip() == '') else getattr(old_payment, 'specificPaymentConditions', '')) # Get rid of the most terrible part of the old default conditions conditions = convert_to_unicode(conditions).replace( 'CANCELLATION :', 'CANCELLATION:') payment_enabled = getattr(old_payment, 'activated', False) if payment_enabled: set_feature_enabled(self.event, 'payment', True) payment_event_settings.set(self.event, 'conditions', conditions) register_email = getattr(old_payment, 'receiptMsg', '') success_email = getattr(old_payment, 'successMsg', '') # The new messages are shown in an "additional info" section, so the old defaults can always go away if convert_to_unicode( register_email) == 'Please, see the summary of your order:': register_email = '' if convert_to_unicode( success_email ) == 'Congratulations, your payment was successful.': success_email = '' # save these messages for later, since the settings # are now part of the reg. form currency = getattr(self.conf._registrationForm, '_currency', '') if not re.match(r'^[A-Z]{3}$', currency): currency = '' self.event_ns.misc_data['payment_currency'] = currency self.event_ns.payment_messages['register'] = register_email self.event_ns.payment_messages['success'] = success_email self.print_success("Payment enabled={0}, currency={1}".format( payment_enabled, currency))
def enable_features(self): self.print_step("Enabling registration features") event_ids = [ x[0] for x in set( db.session.query(RegistrationForm.event_id).filter( RegistrationForm.title == PARTICIPATION_FORM_TITLE)) ] it = verbose_iterator( event_ids, len(event_ids), lambda x: x, lambda x: self.zodb_root['conferences'][str(x)].title) for event_id in committing_iterator(it): set_feature_enabled(self.zodb_root['conferences'][str(event_id)], 'registration', True)
def test_access_participants_registered(dummy_contribution, dummy_user, dummy_event): set_feature_enabled(dummy_event, 'registration', True) menu_entry = MenuEntry(event=dummy_event, type=MenuEntryType.page, access=MenuEntryAccess.registered_participants) person = EventPerson.create_from_user(dummy_user, dummy_event) assert menu_entry.can_access(dummy_user) contrib_person_link = ContributionPersonLink(person=person) dummy_contribution.person_links.append(contrib_person_link) assert menu_entry.can_access(dummy_user) contrib_person_link.is_speaker = True assert menu_entry.can_access(dummy_user)
def _event_type_changed(event, **kwargs): from indico.modules.events.features.util import (get_enabled_features, get_disallowed_features, set_feature_enabled, format_feature_names) conflicting = get_enabled_features(event, only_explicit=True) & get_disallowed_features(event) if conflicting: for feature in conflicting: set_feature_enabled(event, feature, False) if request.endpoint != 'api.jsonrpc': # XXX: we cannot flash a message in the legacy js ajax editor for the event type. # remove this check once we don't use it anymore (on the general settings page) flash(ngettext('Feature disabled: {features} (not available for this event type)', 'Features disabled: {features} (not available for this event type)', len(conflicting)) .format(features=format_feature_names(conflicting)), 'warning')
def _process_POST(self): regform = self.event_new.participation_regform set_feature_enabled(self.event_new, 'registration', True) if not regform: regform = RegistrationForm(event_new=self.event_new, title="Participants", is_participation=True, currency=payment_settings.get('currency')) create_personal_data_fields(regform) db.session.add(regform) db.session.flush() signals.event.registration_form_created.send(regform) self.event_new.log(EventLogRealm.management, EventLogKind.positive, 'Registration', 'Registration form "{}" has been created'.format(regform.title), session.user) return redirect(url_for('event_registration.manage_regform', regform))
def test_registration_clone(dummy_event, dummy_regform, create_event, dummy_user): set_feature_enabled(dummy_event, 'registration', True) assert dummy_regform.event == dummy_event assert dummy_event.registrations.one().user == dummy_user assert dummy_event.registrations.one().checked_in copied_event = create_event() EventCloner.run_cloners(dummy_event, copied_event, {'registrations', 'registration_forms'}) copied_registration = copied_event.registrations.one() assert copied_registration.event == copied_event assert copied_registration.user == dummy_user assert not copied_registration.checked_in
def _process_DELETE(self): feature = get_feature_definition(request.view_args['feature']) if set_feature_enabled(self.event, feature.name, False): flash(_('Feature disabled: {feature}').format(feature=feature.friendly_name), 'warning') logger.info("Feature '{}' for event {} was disabled by {}".format(feature, self.event, session.user)) self.event.log(EventLogRealm.management, EventLogKind.negative, 'Features', 'Disabled {}'.format(feature.friendly_name), session.user) return jsonify_data(enabled=False, event_menu=self.render_event_menu())
def _process_PUT(self): feature = get_feature_definition(request.view_args['feature']) if set_feature_enabled(self.event, feature.name, True): flash(_('Feature enabled: {feature}').format(feature=feature.friendly_name), 'success') logger.info("Feature '{}' for event {} was enabled by {}".format(feature, self.event, session.user)) self.event.log(EventLogRealm.management, EventLogKind.positive, 'Features', 'Enabled {}'.format(feature.friendly_name), session.user) return jsonify_data(enabled=True, event_menu=self.render_event_menu())
def test_access_speakers_subcontrib(dummy_contribution, dummy_user, dummy_event): set_feature_enabled(dummy_event, 'registration', True) menu_entry = MenuEntry(event=dummy_event, type=MenuEntryType.page, access=MenuEntryAccess.speakers) person = EventPerson.create_from_user(dummy_user, dummy_event) assert not menu_entry.can_access(dummy_user) subcontrib = SubContribution(contribution=dummy_contribution, title='sc', duration=timedelta(minutes=10)) subcontrib_person_link = SubContributionPersonLink(person=person) subcontrib.person_links.append(subcontrib_person_link) assert menu_entry.can_access(dummy_user) dummy_contribution.is_deleted = True assert not menu_entry.can_access(dummy_user) dummy_contribution.is_deleted = False subcontrib.is_deleted = True assert not menu_entry.can_access(dummy_user)
def test_new_registration(dummy_event, dummy_regform, create_accompanying_persons_field, max_persons, persons_count_against_limit, registration_limit, expected_limit): set_feature_enabled(dummy_event, 'registration', True) field = create_accompanying_persons_field(max_persons, persons_count_against_limit) validator = field.field_impl.get_validators(None) dummy_regform.registration_limit = registration_limit assert field.field_impl._get_field_available_places(None) == expected_limit assert not dummy_regform.limit_reached validator(_create_accompanying_persons(0)) if expected_limit: validator(_create_accompanying_persons(expected_limit)) with pytest.raises(ValidationError): validator(_create_accompanying_persons(expected_limit + 1)) else: validator(_create_accompanying_persons(1)) validator(_create_accompanying_persons(10))
def _process_DELETE(self): prev = get_enabled_features(self.event) feature = get_feature_definition(request.view_args['feature']) changed = set() if set_feature_enabled(self.event, feature.name, False): current = get_enabled_features(self.event) changed = prev - current flash(ngettext('Feature disabled: {features}', 'Features disabled: {features}', len(changed)) .format(features=self._format_feature_names(changed)), 'warning') logger.info("Feature '%s' for event %s disabled by %s", feature, self.event, session.user) self.event.log(EventLogRealm.management, EventLogKind.negative, 'Features', 'Disabled {}'.format(feature.friendly_name), session.user) return jsonify_data(enabled=False, event_menu=self.render_event_menu(), changed=list(changed))
def _process_PUT(self): prev = get_enabled_features(self.event) feature = get_feature_definition(request.view_args['feature']) changed = set() if set_feature_enabled(self.event, feature.name, True): current = get_enabled_features(self.event) changed = current - prev flash(ngettext('Feature enabled: {features}', 'Features enabled: {features}', len(changed)) .format(features=self._format_feature_names(changed)), 'success') logger.info("Feature '%s' for event %s enabled by %s", feature, self.event, session.user) self.event.log(EventLogRealm.management, EventLogKind.positive, 'Features', 'Enabled {}'.format(feature.friendly_name), session.user) return jsonify_data(enabled=True, event_menu=self.render_event_menu(), changed=list(changed))
def _process_DELETE(self): prev = get_enabled_features(self.event) feature = get_feature_definition(request.view_args['feature']) changed = set() if set_feature_enabled(self.event, feature.name, False): current = get_enabled_features(self.event) changed = prev - current flash(ngettext('Feature disabled: {features}', 'Features disabled: {features}', len(changed)) .format(features=format_feature_names(changed)), 'warning') logger.info("Feature '%s' for event %s disabled by %s", feature.name, self.event, session.user) self.event.log(EventLogRealm.management, EventLogKind.negative, 'Features', f'Disabled {feature.friendly_name}', session.user) return jsonify_data(enabled=False, event_menu=self.render_event_menu(), changed=list(changed))
def _process_POST(self): regform = self.event_new.participation_regform set_feature_enabled(self.event, "registration", True) if not regform: regform = RegistrationForm( event_new=self.event_new, title="Participants", is_participation=True, currency=payment_global_settings.get("currency"), ) create_personal_data_fields(regform) db.session.add(regform) db.session.flush() signals.event.registration_form_created.send(regform) self.event.log( EventLogRealm.management, EventLogKind.positive, "Registration", 'Registration form "{}" has been created'.format(regform.title), session.user, ) return redirect(url_for("event_registration.manage_regform", regform))
def _process_PUT(self): prev = get_enabled_features(self.event) feature = get_feature_definition(request.view_args['feature']) if feature.name in get_disallowed_features(self.event): raise Forbidden('Feature not available') changed = set() if set_feature_enabled(self.event, feature.name, True): current = get_enabled_features(self.event) changed = current - prev flash(ngettext('Feature enabled: {features}', 'Features enabled: {features}', len(changed)) .format(features=format_feature_names(changed)), 'success') logger.info("Feature '%s' for event %s enabled by %s", feature.name, self.event, session.user) self.event.log(EventLogRealm.management, EventLogKind.positive, 'Features', f'Enabled {feature.friendly_name}', session.user) return jsonify_data(enabled=True, event_menu=self.render_event_menu(), changed=list(changed))
def test_modifying_registration_field_untouched( db, dummy_event, dummy_regform, create_accompanying_persons_field, max_persons, persons_count_against_limit, registration_limit, num_persons): set_feature_enabled(dummy_event, 'registration', True) dummy_regform.registration_limit = registration_limit expected_occupied_slots = 1 + num_persons if persons_count_against_limit else 1 reg = dummy_event.registrations.one() data = _create_accompanying_persons(num_persons) field = create_accompanying_persons_field(max_persons, persons_count_against_limit, registration=reg, data=data) db.session.flush() validator = field.field_impl.get_validators(reg) _assert_occupied_slots(reg, expected_occupied_slots) _assert_registration_count(dummy_regform, expected_occupied_slots) if registration_limit and expected_occupied_slots >= registration_limit: assert dummy_regform.limit_reached else: assert not dummy_regform.limit_reached validator(data)
def _process_PUT(self): prev = get_enabled_features(self.event) feature = get_feature_definition(request.view_args['feature']) changed = set() if set_feature_enabled(self.event, feature.name, True): current = get_enabled_features(self.event) changed = current - prev flash( ngettext('Feature enabled: {features}', 'Features enabled: {features}', len(changed)).format( features=self._format_feature_names(changed)), 'success') logger.info("Feature '{}' for event {} was enabled by {}".format( feature, self.event, session.user)) self.event.log(EventLogRealm.management, EventLogKind.positive, 'Features', 'Enabled {}'.format(feature.friendly_name), session.user) return jsonify_data(enabled=True, event_menu=self.render_event_menu(), changed=list(changed))
def _migrate_feature(self): if self.amgr._activated: set_feature_enabled(self.event, 'abstracts', True)
def test_registration_visibility(dummy_event, dummy_regform): set_feature_enabled(dummy_event, 'registration', True) reg = dummy_event.registrations.one() assert dummy_regform.publish_registrations_public == PublishRegistrationsMode.hide_all assert dummy_regform.publish_registrations_participants == PublishRegistrationsMode.show_with_consent assert reg.consent_to_publish == RegistrationVisibility.nobody assert not reg.participant_hidden assert reg.is_active assert reg.state == RegistrationState.complete assert_visibility(reg, RegistrationVisibility.nobody) reg.consent_to_publish = RegistrationVisibility.participants assert_visibility(reg, RegistrationVisibility.participants) reg.consent_to_publish = RegistrationVisibility.all assert_visibility(reg, RegistrationVisibility.participants) dummy_regform.publish_registrations_participants = PublishRegistrationsMode.show_all reg.consent_to_publish = RegistrationVisibility.nobody assert_visibility(reg, RegistrationVisibility.participants) reg.consent_to_publish = RegistrationVisibility.participants assert_visibility(reg, RegistrationVisibility.participants) reg.consent_to_publish = RegistrationVisibility.all assert_visibility(reg, RegistrationVisibility.participants) dummy_regform.publish_registrations_participants = PublishRegistrationsMode.hide_all reg.consent_to_publish = RegistrationVisibility.nobody assert_visibility(reg, RegistrationVisibility.nobody) reg.consent_to_publish = RegistrationVisibility.participants assert_visibility(reg, RegistrationVisibility.nobody) reg.consent_to_publish = RegistrationVisibility.all assert_visibility(reg, RegistrationVisibility.nobody) dummy_regform.publish_registrations_public = PublishRegistrationsMode.show_with_consent dummy_regform.publish_registrations_participants = PublishRegistrationsMode.show_with_consent reg.consent_to_publish = RegistrationVisibility.nobody assert_visibility(reg, RegistrationVisibility.nobody) reg.consent_to_publish = RegistrationVisibility.participants assert_visibility(reg, RegistrationVisibility.participants) reg.consent_to_publish = RegistrationVisibility.all assert_visibility(reg, RegistrationVisibility.all) dummy_regform.publish_registrations_participants = PublishRegistrationsMode.show_all reg.consent_to_publish = RegistrationVisibility.nobody assert_visibility(reg, RegistrationVisibility.participants) reg.consent_to_publish = RegistrationVisibility.participants assert_visibility(reg, RegistrationVisibility.participants) reg.consent_to_publish = RegistrationVisibility.all assert_visibility(reg, RegistrationVisibility.all) dummy_regform.publish_registrations_public = PublishRegistrationsMode.show_all dummy_regform.publish_registrations_participants = PublishRegistrationsMode.show_all reg.consent_to_publish = RegistrationVisibility.nobody assert_visibility(reg, RegistrationVisibility.all) reg.consent_to_publish = RegistrationVisibility.participants assert_visibility(reg, RegistrationVisibility.all) reg.consent_to_publish = RegistrationVisibility.all assert_visibility(reg, RegistrationVisibility.all) reg.state = RegistrationState.rejected assert not reg.is_active assert_visibility(reg, RegistrationVisibility.nobody, test_visibility_prop=False) reg.state = RegistrationState.withdrawn assert not reg.is_active assert_visibility(reg, RegistrationVisibility.nobody, test_visibility_prop=False) reg.state = RegistrationState.pending assert reg.is_active assert_visibility(reg, RegistrationVisibility.nobody, test_visibility_prop=False)
def _migrate_feature(self): if self.pr._choice != CPR_NO_REVIEWING: set_feature_enabled(self.event, 'papers', True)