def create_from_data(cls, room, data, user, prebook=None, ignore_admin=False): """Creates a new reservation. :param room: The Room that's being booked. :param data: A dict containing the booking data, usually from a :class:`NewBookingConfirmForm` instance :param user: The :class:`.User` who creates the booking. :param prebook: Instead of determining the booking type from the user's permissions, always use the given mode. """ populate_fields = ('start_dt', 'end_dt', 'repeat_frequency', 'repeat_interval', 'room_id', 'contact_email', 'contact_phone', 'booking_reason', 'needs_assistance', 'uses_vc', 'needs_vc_assistance') if data['repeat_frequency'] == RepeatFrequency.NEVER and data[ 'start_dt'].date() != data['end_dt'].date(): raise ValueError('end_dt != start_dt for non-repeating booking') if prebook is None: prebook = not room.can_book(user, allow_admin=(not ignore_admin)) if prebook and not room.can_prebook( user, allow_admin=(not ignore_admin)): raise NoReportError(u'You cannot book this room') room.check_advance_days(data['end_dt'].date(), user) room.check_bookable_hours(data['start_dt'].time(), data['end_dt'].time(), user) reservation = cls() for field in populate_fields: if field in data: setattr(reservation, field, data[field]) reservation.room = room # if 'room_usage' is not specified, we'll take whatever is passed in 'booked_for_user' reservation.booked_for_user = data['booked_for_user'] if data.get( 'room_usage') != 'current_user' else user reservation.booked_for_name = reservation.booked_for_user.full_name reservation.state = ReservationState.pending if prebook else ReservationState.accepted reservation.created_by_user = user reservation.create_occurrences(True) if not any(occ.is_valid for occ in reservation.occurrences): raise NoReportError(_(u'Reservation has no valid occurrences')) db.session.flush() signals.rb.booking_created.send(reservation) notify_creation(reservation) return reservation
def _check_version(self, distribution, current_version=None): try: response = requests.get('https://pypi.org/pypi/{}/json'.format(distribution)) except requests.RequestException as exc: Logger.get('versioncheck').warning('Version check for %s failed: %s', distribution, exc) raise NoReportError.wrap_exc(ServiceUnavailable()) try: data = response.json() except ValueError: return None if current_version is None: try: current_version = get_distribution(distribution).version except DistributionNotFound: return None current_version = Version(current_version) if current_version.is_prerelease: # if we are on a prerelease, get the latest one even if it's also a prerelease latest_version = Version(data['info']['version']) else: # if we are stable, get the latest stable version versions = [v for v in map(Version, data['releases']) if not v.is_prerelease] latest_version = max(versions) if versions else None return {'current_version': unicode(current_version), 'latest_version': unicode(latest_version) if latest_version else None, 'outdated': (current_version < latest_version) if latest_version else False}
def _process(self): from_preview = request.args.get('from_preview') == '1' force_download = request.args.get('download') == '1' signals.attachments.attachment_accessed.send(self.attachment, user=session.user, from_preview=from_preview) if request.values.get('preview') == '1': if self.attachment.type != AttachmentType.file: raise BadRequest previewer = get_file_previewer(self.attachment.file) if not previewer: raise NoReportError.wrap_exc( BadRequest( _('There is no preview available for this file type. ' 'Please refresh the page.'))) preview_content = previewer.generate_content(self.attachment) return jsonify_template('attachments/preview.html', attachment=self.attachment, preview_content=preview_content) else: if self.attachment.type == AttachmentType.link: return redirect(self.attachment.link_url) else: return self.attachment.file.send(inline=not force_download)
def _check_version(self, distribution, current_version=None): try: response = requests.get('https://pypi.org/pypi/{}/json'.format(distribution)) except requests.RequestException as exc: Logger.get('versioncheck').warning('Version check for %s failed: %s', distribution, exc) raise NoReportError.wrap_exc(ServiceUnavailable()) try: data = response.json() except ValueError: return None if current_version is None: try: current_version = get_distribution(distribution).version except DistributionNotFound: return None current_version = Version(current_version) if current_version.is_prerelease: # if we are on a prerelease, get the latest one even if it's also a prerelease latest_version = Version(data['info']['version']) else: # if we are stable, get the latest stable version versions = [v for v in map(Version, data['releases']) if not v.is_prerelease] latest_version = max(versions) if versions else None return {'current_version': unicode(current_version), 'latest_version': unicode(latest_version) if latest_version else None, 'outdated': (current_version < latest_version) if latest_version else False}
def _entries(self): if self.session_block: # if we have a session block we reschedule the entries inside that block for entry in self.session_block.timetable_entry.children: # the block should only have entries on the same day if entry.start_dt.astimezone( self.event.tzinfo).date() != self.day: raise NoReportError.wrap_exc( BadRequest( _('This action cannot be completed because the event dates' ' have changed. Please reload the page and try again.' ))) yield entry elif self.session: # if we have a session we reschedule the blocks of that session on the day for block in self.session.blocks: if not block.timetable_entry: continue if block.timetable_entry.start_dt.astimezone( self.event.tzinfo).date() == self.day: yield block.timetable_entry else: # if we are on the top level we reschedule all top-level entries on the day query = (self.event.timetable_entries.filter( TimetableEntry.parent_id.is_(None), db.cast(TimetableEntry.start_dt.astimezone(self.event.tzinfo), db.Date) == self.day)) for entry in query: yield entry
def _check_access(self): cfa = self.event.cfa if session.user and not cfa.is_open and not cfa.can_submit_abstracts(session.user): raise NoReportError.wrap_exc(Forbidden(_('The Call for Abstracts is closed. ' 'Please contact the event organizer for further assistance.'))) elif not session.user or not cfa.can_submit_abstracts(session.user): raise Forbidden RHAbstractsBase._check_access(self)
def check_event_locked(rh, event, force=False): if (not getattr(rh, 'ALLOW_LOCKED', False) or force) and event.is_locked and request.method not in ('GET', 'HEAD'): raise NoReportError.wrap_exc( Forbidden( _('This event has been locked so no modifications are possible.' )))
def _check_access(self): cfa = self.event.cfa if session.user and not cfa.is_open and not cfa.can_submit_abstracts(session.user): raise NoReportError.wrap_exc(Forbidden(_('The Call for Abstracts is closed. ' 'Please contact the event organizer for further assistance.'))) elif not session.user or not cfa.can_submit_abstracts(session.user): raise Forbidden RHAbstractsBase._check_access(self)
def _checkParams(self, params): RHConferenceModifBase._checkParams(self, params) self.event = self._conf try: self.event_id = int(self.event.getId()) except ValueError: raise NoReportError( _('Room booking tools are not available for legacy events.'))
def _process_args(self): RHRoomBookingEventBase._process_args(self) RHRoomBookingNewBooking._process_args(self) assign = request.args.get('assign') if not assign or assign == 'nothing': self._assign_to = None elif assign == 'event': self._assign_to = self.event else: element, _, element_id = assign.partition('-') if element == 'session': self._assign_to = self.event.get_session(element_id) elif element == 'contribution': self._assign_to = self.event.get_contribution(element_id) else: raise NoReportError('Invalid assignment') if not self._assign_to: raise NoReportError('Invalid assignment')
def create_from_data(cls, room, data, user, prebook=None): """Creates a new reservation. :param room: The Room that's being booked. :param data: A dict containing the booking data, usually from a :class:`NewBookingConfirmForm` instance :param user: The :class:`Avatar` who creates the booking. :param prebook: Instead of determining the booking type from the user's permissions, always use the given mode. """ populate_fields = ('start_dt', 'end_dt', 'repeat_frequency', 'repeat_interval', 'room_id', 'booked_for_id', 'contact_email', 'contact_phone', 'booking_reason', 'used_equipment', 'needs_assistance', 'uses_vc', 'needs_vc_assistance') if data['repeat_frequency'] == RepeatFrequency.NEVER and data[ 'start_dt'].date() != data['end_dt'].date(): raise ValueError('end_dt != start_dt for non-repeating booking') if prebook is None: prebook = not room.can_be_booked(user) if prebook and not room.can_be_prebooked(user): raise NoReportError('You cannot book this room') room.check_advance_days(data['end_dt'].date(), user) room.check_bookable_hours(data['start_dt'].time(), data['end_dt'].time(), user) reservation = cls() for field in populate_fields: if field in data: setattr(reservation, field, data[field]) reservation.room = room reservation.booked_for_name = reservation.booked_for_user.getFullName() reservation.is_accepted = not prebook reservation.created_by_user = user reservation.create_occurrences(True) if not any(occ.is_valid for occ in reservation.occurrences): raise NoReportError(_('Reservation has no valid occurrences')) notify_creation(reservation) return reservation
def _process(self): if not self.registrations: raise NoReportError.wrap_exc(BadRequest(_("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)
def _process(self): pdf = RegistrantsListToPDF(self.event, reglist=self.registrations, display=self.export_config['regform_items'], static_items=self.export_config['static_item_ids']) try: data = pdf.getPDFBin() except Exception: if config.DEBUG: raise raise NoReportError(_("Text too large to generate a PDF with table style. " "Please try again generating with book style.")) return send_file('RegistrantsList.pdf', BytesIO(data), 'application/pdf')
def _check_access(self): cfa = self.event.cfa if session.user and not cfa.is_open and not cfa.can_submit_abstracts( session.user): raise NoReportError(_( 'The Call for Abstracts is closed. Please contact the event organizer for further ' 'assistance.'), http_status_code=403) elif not session.user or not cfa.can_submit_abstracts(session.user): raise Forbidden RHAbstractsBase._check_access(self)
def get_conflicting_occurrences(self): valid_occurrences = self.occurrences.filter(ReservationOccurrence.is_valid).all() if not valid_occurrences: raise NoReportError(_('Reservation has no valid occurrences')) colliding_occurrences = ReservationOccurrence.find_overlapping_with(self.room, valid_occurrences, self.id).all() conflicts = defaultdict(lambda: dict(confirmed=[], pending=[])) for occurrence in valid_occurrences: for colliding in colliding_occurrences: if occurrence.overlaps(colliding): key = 'confirmed' if colliding.reservation.is_accepted else 'pending' conflicts[occurrence][key].append(colliding) return conflicts
def check_advance_days(self, end_date, user=None, quiet=False): if not self.max_advance_days: return True if user and (rb_is_admin(user) or self.is_owned_by(user)): return True advance_days = (end_date - date.today()).days ok = advance_days < self.max_advance_days if quiet or ok: return ok else: msg = _(u'You cannot book this room more than {} days in advance') raise NoReportError(msg.format(self.max_advance_days))
def check_bookable_hours(self, start_time, end_time, user=None, quiet=False): if user and (rb_is_admin(user) or self.is_owned_by(user)): return True bookable_hours = self.bookable_hours.all() if not bookable_hours: return True for bt in bookable_hours: if bt.fits_period(start_time, end_time): return True if quiet: return False raise NoReportError(u'Room cannot be booked at this time')
def _process(self): if not self.registrations: raise NoReportError.wrap_exc(BadRequest(_("The selected registrants have been removed."))) registration = self.registrations[0] email_body = replace_placeholders('registration-email', request.form['body'], regform=self.regform, registration=registration) email_subject = replace_placeholders('registration-email', request.form['subject'], regform=self.regform, registration=registration) tpl = get_template_module('events/registration/emails/custom_email.html', email_subject=email_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)
def _sanitize(params, level, doNotSanitize=frozenset()): for i in params: if i in doNotSanitize: continue if isinstance(params, dict): param = params[i] else: param = i if isinstance(param, str): res = restrictedHTML(param, level) if res is not None: raise NoReportError(res) elif isinstance(param, list) or isinstance(param, dict): Sanitization._sanitize(param, level)
def _checkParams(self, params): RHAgreementManagerDetails._checkParams(self, params) if 'id' in request.view_args: self.agreement = Agreement.find_one(id=request.view_args['id']) if self._conf != self.agreement.event: raise NotFound if not self.agreement.pending: raise NoReportError(_("The agreement is already signed")) else: self.agreement = None identifier = request.args['identifier'] try: self.person = self.definition.get_people(self._conf)[identifier] except KeyError: raise NotFound
def _process_args(self): RHAgreementManagerDetails._process_args(self) if 'id' in request.view_args: self.agreement = Agreement.get_one(request.view_args['id']) if self.event != self.agreement.event: raise NotFound if not self.agreement.pending: raise NoReportError(_("The agreement is already signed")) else: self.agreement = None identifier = request.args['identifier'] try: self.person = self.definition.get_people(self.event)[identifier] except KeyError: raise NotFound
def _process(self): if self.registration.has_conflict(): raise NoReportError(_('Cannot reset this registration since there is another valid registration for the ' 'same user or email.')) if self.registration.state in (RegistrationState.complete, RegistrationState.unpaid): self.registration.update_state(approved=False) elif self.registration.state == RegistrationState.rejected: self.registration.rejection_reason = '' self.registration.update_state(rejected=False) elif self.registration.state == RegistrationState.withdrawn: self.registration.update_state(withdrawn=False) notify_registration_state_update(self.registration) else: raise BadRequest(_('The registration cannot be reset in its current state.')) self.registration.checked_in = False logger.info('Registration %r was reset by %r', self.registration, session.user) return jsonify_data(html=_render_registration_details(self.registration))
def _process(self): from_preview = request.args.get('from_preview') == '1' force_download = request.args.get('download') == '1' signals.attachments.attachment_accessed.send(self.attachment, user=session.user, from_preview=from_preview) if request.values.get('preview') == '1': if self.attachment.type != AttachmentType.file: raise BadRequest previewer = get_file_previewer(self.attachment.file) if not previewer: raise NoReportError.wrap_exc(BadRequest(_('There is no preview available for this file type. ' 'Please refresh the page.'))) preview_content = previewer.generate_content(self.attachment) return jsonify_template('attachments/preview.html', attachment=self.attachment, preview_content=preview_content) else: if self.attachment.type == AttachmentType.link: return redirect(self.attachment.link_url) else: return self.attachment.file.send(inline=not force_download)
def _redirect_if_insecure(): if not request.endpoint: return if ( request.blueprint == 'assets' or request.endpoint.endswith('.static') or request.endpoint in ('auth.logout', 'auth.accounts', 'core.contact', 'core.change_lang') ): return if 'insecure_password_error' not in session: return if request.method != 'GET': raise NoReportError.wrap_exc(Forbidden(_('You need to change your password'))) if request.is_xhr or request.is_json: return return redirect(url_for('auth.accounts'))
def _entries(self): if self.session_block: # if we have a session block we reschedule the entries inside that block for entry in self.session_block.timetable_entry.children: # the block should only have entries on the same day if entry.start_dt.astimezone(self.event.tzinfo).date() != self.day: raise NoReportError.wrap_exc(BadRequest(_('This action cannot be completed because the event dates' ' have changed. Please reload the page and try again.'))) yield entry elif self.session: # if we have a session we reschedule the blocks of that session on the day for block in self.session.blocks: if not block.timetable_entry: continue if block.timetable_entry.start_dt.astimezone(self.event.tzinfo).date() == self.day: yield block.timetable_entry else: # if we are on the top level we reschedule all top-level entries on the day query = (self.event.timetable_entries .filter(TimetableEntry.parent_id.is_(None), db.cast(TimetableEntry.start_dt.astimezone(self.event.tzinfo), db.Date) == self.day)) for entry in query: yield entry
def modify(self, data, user): """Modifies an existing reservation. :param data: A dict containing the booking data, usually from a :class:`ModifyBookingForm` instance :param user: The :class:`.User` who modifies the booking. """ populate_fields = ('start_dt', 'end_dt', 'repeat_frequency', 'repeat_interval', 'booked_for_user', 'booking_reason') # fields affecting occurrences occurrence_fields = {'start_dt', 'end_dt', 'repeat_frequency', 'repeat_interval'} # fields where date and time are compared separately date_time_fields = {'start_dt', 'end_dt'} # fields for the repetition repetition_fields = {'repeat_frequency', 'repeat_interval'} # pretty names for logging field_names = { 'start_dt/date': u"start date", 'end_dt/date': u"end date", 'start_dt/time': u"start time", 'end_dt/time': u"end time", 'repetition': u"booking type", 'booked_for_user': u"'Booked for' user", 'booking_reason': u"booking reason", } self.room.check_advance_days(data['end_dt'].date(), user) self.room.check_bookable_hours(data['start_dt'].time(), data['end_dt'].time(), user) changes = {} update_occurrences = False old_repetition = self.repetition for field in populate_fields: if field not in data: continue old = getattr(self, field) new = data[field] converter = unicode if old != new: # Booked for user updates the (redundant) name if field == 'booked_for_user': old = self.booked_for_name new = self.booked_for_name = data[field].full_name # Apply the change setattr(self, field, data[field]) # If any occurrence-related field changed we need to recreate the occurrences if field in occurrence_fields: update_occurrences = True # Record change for history entry if field in date_time_fields: # The date/time fields create separate entries for the date and time parts if old.date() != new.date(): changes[field + '/date'] = {'old': old.date(), 'new': new.date(), 'converter': format_date} if old.time() != new.time(): changes[field + '/time'] = {'old': old.time(), 'new': new.time(), 'converter': format_time} elif field in repetition_fields: # Repetition needs special handling since it consists of two fields but they are tied together # We simply update it whenever we encounter such a change; after the last change we end up with # the correct change data changes['repetition'] = {'old': old_repetition, 'new': self.repetition, 'converter': lambda x: RepeatMapping.get_message(*x)} else: changes[field] = {'old': old, 'new': new, 'converter': converter} if not changes: return False # Create a verbose log entry for the modification log = [u'Booking modified'] for field, change in changes.iteritems(): field_title = field_names.get(field, field) converter = change['converter'] old = to_unicode(converter(change['old'])) new = to_unicode(converter(change['new'])) if not old: log.append(u"The {} was set to '{}'".format(field_title, new)) elif not new: log.append(u"The {} was cleared".format(field_title)) else: log.append(u"The {} was changed from '{}' to '{}'".format(field_title, old, new)) self.edit_logs.append(ReservationEditLog(user_name=user.full_name, info=log)) # Recreate all occurrences if necessary if update_occurrences: cols = [col.name for col in ReservationOccurrence.__table__.columns if not col.primary_key and col.name not in {'start_dt', 'end_dt'}] old_occurrences = {occ.date: occ for occ in self.occurrences} self.occurrences.delete(synchronize_session='fetch') self.create_occurrences(True, user) db.session.flush() # Restore rejection data etc. for recreated occurrences for occurrence in self.occurrences: old_occurrence = old_occurrences.get(occurrence.date) # Copy data from old occurrence UNLESS the new one is invalid (e.g. because of collisions) # Otherwise we'd end up with valid occurrences ignoring collisions! if old_occurrence and occurrence.is_valid: for col in cols: setattr(occurrence, col, getattr(old_occurrence, col)) # Don't cause new notifications for the entire booking in case of daily repetition if self.repeat_frequency == RepeatFrequency.DAY and all(occ.notification_sent for occ in old_occurrences.itervalues()): for occurrence in self.occurrences: occurrence.notification_sent = True # Sanity check so we don't end up with an "empty" booking if not any(occ.is_valid for occ in self.occurrences): raise NoReportError(_(u'Reservation has no valid occurrences')) notify_modification(self, changes) return True
def test11(): from indico.core.errors import NoReportError raise NoReportError('we do not care about your error')
def check_event_locked(rh, event, force=False): if (not getattr(rh, 'ALLOW_LOCKED', False) or force) and event.is_locked and request.method not in ('GET', 'HEAD'): raise NoReportError.wrap_exc(Forbidden(_('This event has been locked so no modifications are possible.')))
def _checkParams(self): resv_id = request.view_args['resvID'] self._reservation = Reservation.get(resv_id) if not self._reservation: raise NoReportError('No booking with id: {}'.format(resv_id))
def _process_args(self): self._location = Location.get(int(request.form['location_id'])) if not self._location: raise NoReportError(u'No such location')
def _checkParams(self, params): RHAgreementManagerDetailsAgreementBase._checkParams(self, params) if self.agreement.state != AgreementState.accepted_on_behalf: raise NoReportError("The agreement was not accepted manually by an admin")
def _checkParams(self): self._location = Location.get(int(request.form['location_id'])) if not self._location: raise NoReportError(u'No such location')
def _process_args(self): RHAgreementManagerDetailsAgreementBase._process_args(self) if self.agreement.state != AgreementState.accepted_on_behalf: raise NoReportError("The agreement was not accepted manually by an admin")