class AttachmentPackageForm(IndicoForm): added_since = IndicoDateField( _('Added Since'), [Optional()], description=_('Include only attachments uploaded after this date')) filter_type = IndicoRadioField(_('Include'), [DataRequired()]) sessions = IndicoSelectMultipleCheckboxField( _('Sessions'), [ UsedIf(lambda form, _: form.filter_type.data == 'sessions'), DataRequired() ], description=_('Include materials from selected sessions'), coerce=int) contributions = IndicoSelectMultipleCheckboxField( _('Contributions'), [ UsedIf(lambda form, _: form.filter_type.data == 'contributions'), DataRequired() ], description=_('Include materials from selected contributions'), coerce=int) dates = IndicoSelectMultipleCheckboxField( _('Events scheduled on'), [ UsedIf(lambda form, _: form.filter_type.data == 'dates'), DataRequired() ], description=_( 'Include materials from sessions/contributions scheduled ' 'on the selected dates'))
class AttachmentPackageForm(IndicoForm): added_since = DateField( _('Added Since'), [Optional()], parse_kwargs={'dayfirst': True}, description=_('Include only attachments uploaded after this date')) filter_type = IndicoRadioField(_('Include'), [DataRequired()]) sessions = IndicoSelectMultipleCheckboxField( _('Sessions'), [HiddenUnless('filter_type', 'sessions'), DataRequired()], description=_('Include materials from selected sessions'), coerce=int) contributions = IndicoSelectMultipleCheckboxField( _('Contributions'), [HiddenUnless('filter_type', 'contributions'), DataRequired()], description=_('Include materials from selected contributions'), coerce=int) dates = IndicoSelectMultipleCheckboxField( _('Events scheduled on'), [HiddenUnless('filter_type', 'dates'), DataRequired()], description=_( 'Include materials from sessions/contributions scheduled ' 'on the selected dates'))
class TimetablePDFExportForm(IndicoForm): _pdf_options_fields = {'pagesize', 'fontsize', 'firstPageNumber'} advanced = BooleanField(_("Advanced timetable"), widget=SwitchWidget(), description=_("Advanced customization options")) document_settings = IndicoSelectMultipleCheckboxField( _('Document settings'), [HiddenUnless('advanced')], choices=_DOCUMENT_SETTINGS_CHOICES) contribution_info = IndicoSelectMultipleCheckboxField( _('Contributions related info'), [HiddenUnless('advanced')], choices=_CONTRIBUTION_CHOICES) session_info = IndicoSelectMultipleCheckboxField( _('Sessions related info'), [HiddenUnless('advanced')], choices=_SESSION_CHOICES) visible_entries = IndicoSelectMultipleCheckboxField( _('Breaks and contributions'), [HiddenUnless('advanced')], choices=_VISIBLE_ENTRIES_CHOICES) other = IndicoSelectMultipleCheckboxField(_('Miscellaneous'), choices=_OTHER_CHOICES) pagesize = SelectField(_('Page size'), choices=[('A0', 'A0'), ('A1', 'A1'), ('A2', 'A2'), ('A3', 'A3'), ('A4', 'A4'), ('A5', 'A5'), ('Letter', 'Letter')], default='A4') fontsize = SelectField(_('Font size'), choices=[('xxx-small', _('xxx-small')), ('xx-small', _('xx-small')), ('x-small', _('x-small')), ('smaller', _('smaller')), ('small', _('small')), ('normal', _('normal')), ('large', _('large')), ('larger', _('larger'))], default='normal') firstPageNumber = IntegerField(_('Number for the first page'), [NumberRange(min=1)], default=1, widget=NumberInput(step=1)) submitted = HiddenField() def is_submitted(self): return 'submitted' in request.args @property def data_for_format(self): if not self.advanced.data: fields = ('visible_entries', ) else: fields = set( get_form_field_names(TimetablePDFExportForm) ) - self._pdf_options_fields - {'csrf_token', 'advanced'} return defaultdict( bool, { option: True for field in fields for option in getattr(self, field).data })
class AVRequestForm(RequestFormBase): services = IndicoSelectMultipleCheckboxField(_('Services'), [DataRequired()], choices=SERVICES.items(), widget=JinjaWidget('service_type_widget.html', 'audiovisual'), description=_("Please choose whether you want a webcast, recording or " "both.")) all_contributions = BooleanField(_('All contributions'), description=_('Uncheck this if you want to select only certain contributions.')) contributions = IndicoSelectMultipleCheckboxField(_('Contributions'), [UsedIf(lambda form, field: not form.all_contributions.data), DataRequired()], widget=JinjaWidget('contribution_list_widget.html', 'audiovisual', SubContribution=SubContribution)) webcast_audience = SelectField(_('Webcast Audience'), description=_("Select the audience to which the webcast will be restricted")) comments = TextAreaField(_('Comments'), description=_('If you have any additional comments or instructions, please write them ' 'down here.')) def __init__(self, *args, **kwargs): super(AVRequestForm, self).__init__(*args, **kwargs) self._update_audiences() self._update_contribution_fields() def _update_audiences(self): audiences = [('', _("No restriction - everyone can watch the public webcast"))] audiences += sorted((x['audience'], x['audience']) for x in current_plugin.settings.get('webcast_audiences')) self.webcast_audience.choices = audiences def _update_contribution_fields(self): if self.event.type == 'lecture': # lectures don't have contributions del self.all_contributions del self.contributions else: choices = self.contributions.choices = [] disabled_contribs = self.contributions._disabled_contributions = [] contributions = self.contributions._contributions = {} is_manager = is_av_manager(session.user) selected = set(self.request.data.get('contributions', [])) if self.request else set() for contrib, capable, custom_room in get_contributions(self.event): is_subcontrib = isinstance(contrib, SubContribution) id_ = contribution_id(contrib) contributions[id_] = contrib line = Markup(render_template('audiovisual:contribution_list_entry.html', contrib=contrib, is_subcontrib=is_subcontrib, capable=capable, custom_room=custom_room)) if not capable and not is_manager and contrib.id not in selected: disabled_contribs.append((contrib, line)) else: choices.append((id_, line))
class ApplicationForm(IndicoForm): name = StringField(_("Name"), [DataRequired()]) description = TextAreaField(_("Description")) redirect_uris = RedirectURIField(_("Allowed authorization callback URLs"), [DataRequired()], description=_("More than one URL can be specified adding new lines. The " "redirect_uri sent by the OAuth client must use the same protocol " "and host/port. If an entry contains a path, the redirect_uri's " "path must start with this path.")) default_scopes = IndicoSelectMultipleCheckboxField('Allowed scopes', [DataRequired()], choices=sorted(list(SCOPES.items()), key=itemgetter(1))) is_enabled = BooleanField(_("Enabled"), widget=SwitchWidget(), description=_("If an application is not enabled, its OAuth tokens cannot be used and " "user cannot be prompted to authorize the application.")) is_trusted = BooleanField(_("Trusted"), widget=SwitchWidget(), description=_("Trusted applications will be granted authorization automatically and " "no intermediate page will be displayed during the authorization process.")) def __init__(self, *args, **kwargs): self.application = kwargs.pop('application', None) super().__init__(*args, **kwargs) if self.application is not None: for field in self.application.system_app_type.enforced_data: # preserve existing value for disabled fields self[field].data = self[field].object_data def validate_name(self, field): query = OAuthApplication.find(name=field.data) if self.application: query = query.filter(db.func.lower(OAuthApplication.name) != self.application.name.lower()) if query.count(): raise ValidationError(_("There is already an application with this name"))
class CloneContentsForm(CloneRepeatabilityForm): selected_items = IndicoSelectMultipleCheckboxField(_('What to clone')) def __init__(self, event, set_defaults=False, **kwargs): options = EventCloner.get_cloners(event) visible_options = filter(attrgetter('is_visible'), options) default_selected_items = kwargs.get( 'selected_items', [option.name for option in options if option.is_default]) if set_defaults: default_category = kwargs['category'][ 'id'] if 'category' in kwargs else None form_params = { 'repeatability': request.form.get('repeatability', kwargs.pop('repeatability', None)), 'selected_items': (request.form.getlist('selected_items') or default_selected_items), 'category': request.form.get('category', default_category), 'csrf_token': request.form.get('csrf_token') } kwargs['formdata'] = ImmutableMultiDict(form_params) super(CloneContentsForm, self).__init__(**kwargs) self.selected_items.choices = [(option.name, option.friendly_name) for option in visible_options] self.selected_items.disabled_choices = [ option.name for option in visible_options if not option.is_available ]
class CERNAccessForm(RequestFormBase): regforms = IndicoSelectMultipleCheckboxField(_('Registration forms'), [DataRequired(_('At least one registration form has to be selected'))], widget=JinjaWidget('regform_list_widget.html', 'cern_access')) regform_data_mode = IndicoEnumSelectField(_('Show during user registration'), enum=RegformDataMode, keep_enum=False, description=_("When enabled, users can request site access while " "registering and provide their additional personal data " "in the registration form. When set to required, the user " "cannot register without providing this data. In any case, " "site access is only granted after a manager explicitly " "enables it for the registrations.")) start_dt_override = IndicoDateTimeField(_('Start date override'), [Optional()], description=_("If set, CERN access will be granted starting at the " "specified date instead of the event's start date")) end_dt_override = IndicoDateTimeField(_('End date override'), [Optional(), LinkedDateTime('start_dt_override', not_equal=True)], description=_("If set, CERN access will be granted until the specified date " "instead of the event's end date")) def __init__(self, *args, **kwargs): super(CERNAccessForm, self).__init__(*args, **kwargs) regforms = get_regforms(self.event) self._regform_map = {unicode(rf.id): rf for rf in regforms} self.regforms.choices = [(unicode(rf.id), rf.title) for rf in regforms] self.start_dt_override.default_time = self.event.start_dt_local.time() self.end_dt_override.default_time = self.event.end_dt_local.time() def validate_start_dt_override(self, field): if bool(self.start_dt_override.data) != bool(self.end_dt_override.data): raise ValidationError(_('You need to specify both date overrides or neither of them.')) validate_end_dt_override = validate_start_dt_override
class CERNAccessForm(RequestFormBase): regforms = IndicoSelectMultipleCheckboxField( _('Registration forms'), widget=JinjaWidget('regform_list_widget.html', 'cern_access')) start_dt_override = IndicoDateTimeField( _('Start date override'), [Optional()], description=_("If set, CERN access will be granted starting at the " "specified date instead of the event's start date")) end_dt_override = IndicoDateTimeField( _('End date override'), [Optional(), LinkedDateTime('start_dt_override', not_equal=True)], description=_( "If set, CERN access will be granted until the specified date " "instead of the event's end date")) def __init__(self, *args, **kwargs): super(CERNAccessForm, self).__init__(*args, **kwargs) regforms = get_regforms(self.event) self._regform_map = {unicode(rf.id): rf for rf in regforms} self.regforms.choices = [(unicode(rf.id), rf.title) for rf in regforms] self.start_dt_override.default_time = self.event.start_dt_local.time() self.end_dt_override.default_time = self.event.end_dt_local.time() def validate_start_dt_override(self, field): if bool(self.start_dt_override.data) != bool( self.end_dt_override.data): raise ValidationError( _('You need to specify both date overrides or neither of them.' )) validate_end_dt_override = validate_start_dt_override
class CloneContentsForm(CloneRepeatabilityForm): selected_items = IndicoSelectMultipleCheckboxField(_('What to clone')) refresh_users = BooleanField(_('Refresh user information'), description=_('When checked, names and affiliations of users in the cloned event will ' 'be synchronized with their Indico user profiles.')) def __init__(self, event, set_defaults=False, **kwargs): visible_options = list(filter(attrgetter('is_visible'), EventCloner.get_cloners(event))) default_selected_items = kwargs.get('selected_items', [option.name for option in visible_options if option.is_default and option.is_available]) if set_defaults: default_category = kwargs['category']['id'] if 'category' in kwargs else None form_params = { 'repeatability': request.form.get('repeatability', kwargs.pop('repeatability', None)), 'selected_items': (request.form.getlist('selected_items') or default_selected_items), 'refresh_users': 'refresh_users' in request.form if 'selected_items' in request.form else True, 'category': request.form.get('category', default_category), 'csrf_token': request.form.get('csrf_token') } kwargs['formdata'] = ImmutableMultiDict(form_params) super().__init__(**kwargs) self.selected_items.choices = [(option.name, option.friendly_name) for option in visible_options] self.selected_items.disabled_choices = [option.name for option in visible_options if not option.is_available]
class CERNAccessForm(RequestFormBase): regforms = IndicoSelectMultipleCheckboxField( _('Registration forms'), [DataRequired(_('At least one registration form has to be selected'))], widget=JinjaWidget('regform_list_widget.html', 'cern_access')) during_registration = BooleanField( _('Show during user registration'), widget=SwitchWidget(), description=_( "When enabled, users can request site access while registering " "and provide their additional personal data in the registration " "form. In any case, site access is only granted after a manager " "explicitly enables it for the registrants.")) during_registration_preselected = BooleanField( _('Preselect during user registration'), [HiddenUnless('during_registration')], widget=SwitchWidget(), description=_("Preselect the option to request site access during " "registration. Recommended if most registrants will " "need it.")) during_registration_required = BooleanField( _('Require during user registration'), [HiddenUnless('during_registration_preselected')], widget=SwitchWidget(), description=_("Require all users to provide data for site access. " "Registration without entering the data will not be " "possible.")) start_dt_override = IndicoDateTimeField( _('Start date override'), [Optional()], description=_("If set, CERN access will be granted starting at the " "specified date instead of the event's start date")) end_dt_override = IndicoDateTimeField( _('End date override'), [Optional(), LinkedDateTime('start_dt_override', not_equal=True)], description=_( "If set, CERN access will be granted until the specified date " "instead of the event's end date")) def __init__(self, *args, **kwargs): super(CERNAccessForm, self).__init__(*args, **kwargs) regforms = get_regforms(self.event) self._regform_map = {unicode(rf.id): rf for rf in regforms} self.regforms.choices = [(unicode(rf.id), rf.title) for rf in regforms] self.start_dt_override.default_time = self.event.start_dt_local.time() self.end_dt_override.default_time = self.event.end_dt_local.time() def validate_start_dt_override(self, field): if bool(self.start_dt_override.data) != bool( self.end_dt_override.data): raise ValidationError( _('You need to specify both date overrides or neither of them.' )) validate_end_dt_override = validate_start_dt_override
class ImportContentsForm(ImportSourceEventForm): selected_items = IndicoSelectMultipleCheckboxField(_('What to clone')) def __init__(self, source_event, target_event, set_defaults=False, **kwargs): cloners = EventCloner.get_cloners(source_event) visible_options = [ cloner for cloner in cloners if cloner.is_visible and not cloner.new_event_only ] conflicts = { cloner.name: cloner.get_conflicts(target_event) for cloner in cloners } cloners_with_conflicts = { name for name in conflicts if conflicts[name] } if set_defaults: form_params = { 'source_event_url': request.form.get('source_event_url', kwargs.pop('source_event_url', None)), 'selected_items': request.form.getlist('selected_items'), 'csrf_token': request.form.get('csrf_token') } kwargs['formdata'] = ImmutableMultiDict(form_params) super().__init__(**kwargs) self.selected_items.choices = [(option.name, option.friendly_name) for option in visible_options] # We disable all cloners that are not available, handle only cloning to new events, # have conflicts with target_event or any of their dependencies have conflicts with target_event disabled_choices = [] reasons = {} for option in visible_options: if not option.is_available: disabled_choices.append(option.name) reasons[option.name] = _('There is nothing to import') elif conflict := conflicts[option.name]: disabled_choices.append(option.name) reasons[option.name] = '\n'.join(conflict) elif cloners_with_conflicts & option.requires_deep: disabled_choices.append(option.name) reasons[option.name] = _( 'This option depends on other options which are unavailable' )
class ApplicationForm(IndicoForm): name = StringField(_('Name'), [DataRequired()]) description = TextAreaField(_('Description')) redirect_uris = RedirectURIField( _('Allowed authorization callback URLs'), [DataRequired()], description=_( 'More than one URL can be specified adding new lines. The ' 'redirect_uri sent by the OAuth client must use the same protocol ' "and host/port. If an entry contains a path, the redirect_uri's " 'path must start with this path.')) allowed_scopes = IndicoSelectMultipleCheckboxField( 'Allowed scopes', [DataRequired()], choices=sorted(SCOPES.items(), key=itemgetter(1)), description=_('Only scopes from this list may be requested by ' 'the app.')) is_enabled = BooleanField( _('Enabled'), widget=SwitchWidget(), description=_( 'If an application is not enabled, its OAuth tokens cannot be used and ' 'user cannot be prompted to authorize the application.')) allow_pkce_flow = BooleanField( _('Allow PKCE flow'), widget=SwitchWidget(), description=_( 'If enabled, the application can use the client-side PKCE flow which ' 'does not require the use of the Client Secret to get a token.')) is_trusted = BooleanField( _('Trusted'), widget=SwitchWidget(), description= _('Trusted applications will be granted authorization automatically and ' 'no intermediate page will be displayed during the authorization process.' )) def __init__(self, *args, **kwargs): self.application = kwargs.pop('application', None) super().__init__(*args, **kwargs) if self.application is not None: for field in self.application.system_app_type.enforced_data: # preserve existing value for disabled fields self[field].data = self[field].object_data def validate_name(self, field): query = OAuthApplication.query.filter( db.func.lower(OAuthApplication.name) == field.data.lower()) if self.application: query = query.filter(OAuthApplication.id != self.application.id) if query.has_rows(): raise ValidationError( _('There is already an application with this name'))
class PersonalTokenForm(IndicoForm): name = StringField(_('Name'), [DataRequired()], description=_("What's this token used for?")) scopes = IndicoSelectMultipleCheckboxField( 'Scopes', [DataRequired()], choices=sorted(SCOPES.items(), key=itemgetter(1)), description=_('Scopes define what kind of access the token has.')) def __init__(self, *args, **kwargs): self.user = kwargs.pop('user') self.token = kwargs.pop('token', None) super().__init__(*args, **kwargs) def validate_name(self, field): query = (self.user.query_personal_tokens().filter( db.func.lower(PersonalToken.name) == field.data.lower())) if self.token: query = query.filter(PersonalToken.id != self.token.id) if query.has_rows(): raise ValidationError(_('There is already a token with this name'))
class ImportContentsForm(ImportSourceEventForm): selected_items = IndicoSelectMultipleCheckboxField(_('What to clone')) def __init__(self, source_event, target_event, set_defaults=False, **kwargs): cloners = EventCloner.get_cloners(source_event) visible_options = [ cloner for cloner in cloners if cloner.is_visible and not cloner.new_event_only ] conflicts = { cloner.name: cloner.has_conflicts(target_event) for cloner in cloners } if set_defaults: form_params = { 'source_event_url': request.form.get('source_event_url', kwargs.pop('source_event_url', None)), 'selected_items': request.form.getlist('selected_items'), 'csrf_token': request.form.get('csrf_token') } kwargs['formdata'] = ImmutableMultiDict(form_params) super().__init__(**kwargs) self.selected_items.choices = [(option.name, option.friendly_name) for option in visible_options] # We disable all cloners that are not available, handle only cloning to new events, # have conflicts with target_event or any of their dependencies has conflicts with target_event self.selected_items.disabled_choices = [ option.name for option in visible_options if not option.is_available or conflicts[option.name] or any( conflicts[dep] for dep in option.requires) ]