def rb_merge_users(new_id, old_id): """Updates RB data after an Avatar merge :param new_id: Target user :param old_id: Source user (being deleted in the merge) """ from indico.modules.rb import settings as rb_settings from indico.modules.rb.models.blocking_principals import BlockingPrincipal from indico.modules.rb.models.blockings import Blocking from indico.modules.rb.models.reservations import Reservation from indico.modules.rb.models.rooms import Room old_user = User.get(int(old_id)) new_user = User.get(int(new_id)) for bp in BlockingPrincipal.find(): if bp.principal == old_user: bp.principal = new_user Blocking.find(created_by_id=old_id).update({'created_by_id': new_id}) Reservation.find(created_by_id=old_id).update({'created_by_id': new_id}) Reservation.find(booked_for_id=old_id).update({'booked_for_id': new_id}) Room.find(owner_id=old_id).update({'owner_id': new_id}) for key in ('authorized_principals', 'admin_principals'): principals = rb_settings.get(key) principals = principals_merge_users(principals, new_id, old_id) rb_settings.set(key, principals)
def _build_digest_window_filter(): if datetime.now().hour >= rb_settings.get('notification_hour'): # Both today and delayed digests return Room.is_in_digest_window() else: # Delayed digests only return Room.is_in_digest_window(exclude_first_day=True)
def _build_notification_window_filter(): if datetime.now().hour >= rb_settings.get('notification_hour'): # Both today and delayed notifications return ReservationOccurrence.is_in_notification_window() else: # Delayed notifications only return ReservationOccurrence.is_in_notification_window(exclude_first_day=True)
def roombooking_occurrences_digest(): if not Config.getInstance().getIsRoomBookingActive(): logger.info('Digest not sent because room booking is disabled') return if not rb_settings.get('notifications_enabled'): logger.info('Digest not sent because notifications are globally disabled') return digest_start = round_up_month(date.today(), from_day=2) digest_end = get_month_end(digest_start) occurrences = ReservationOccurrence.find( Room.notifications_enabled, Reservation.is_accepted, Reservation.repeat_frequency == RepeatFrequency.WEEK, ReservationOccurrence.is_valid, ReservationOccurrence.start_dt >= digest_start, ReservationOccurrence.start_dt <= digest_end, ~ReservationOccurrence.notification_sent, _build_digest_window_filter(), _join=[Reservation, Room] ) digests = defaultdict(list) for occurrence in occurrences: digests[occurrence.reservation].append(occurrence) try: for reservation, occurrences in digests.iteritems(): notify_reservation_digest(reservation, occurrences) for occurrence in occurrences: occurrence.notification_sent = True finally: db.session.commit()
def roombooking_occurrences(): if not Config.getInstance().getIsRoomBookingActive(): logger.info('Notifications not sent because room booking is disabled') return if not rb_settings.get('notifications_enabled'): logger.info('Notifications not sent because they are globally disabled') return occurrences = ReservationOccurrence.find( Room.notifications_enabled, Reservation.is_accepted, Reservation.repeat_frequency != RepeatFrequency.WEEK, ReservationOccurrence.is_valid, ReservationOccurrence.start_dt >= datetime.now(), ~ReservationOccurrence.notification_sent, _build_notification_window_filter(), _join=[Reservation, Room] ) try: for occ in occurrences: notify_upcoming_occurrence(occ) occ.notification_sent = True if occ.reservation.repeat_frequency == RepeatFrequency.DAY: occ.reservation.occurrences.update({'notification_sent': True}) finally: db.session.commit()
def rb_is_admin(user): """Checks if the user is a room booking admin""" from indico.modules.rb import settings as rb_settings if user.user.is_admin: return True principals = retrieve_principals(rb_settings.get('admin_principals')) return any(principal.containsUser(user) for principal in principals)
def create_user(db): """Returns a callable which lets you create dummy users""" _users = set() def _create_user(id_, name=u'Pig', surname=u'Guinea', rb_admin=False, email=None, groups=None): user = User.get(id_) if user: return user.as_avatar user = User() user.id = id_ user.first_name = name user.last_name = surname user.email = email or u'{}@example.com'.format(id_) user.local_groups = {g.group for g in (groups or ())} db.session.add(user) db.session.flush() if rb_admin: rb_settings.set('admin_principals', rb_settings.get('admin_principals') + [user.as_principal]) db.session.flush() _users.add(user) avatar = user.as_avatar avatar.email = user.email return avatar yield _create_user admins = set(map(tuple, rb_settings.get('admin_principals'))) for user in _users: admins.discard(user.as_principal) db.session.delete(user) rb_settings.set('admin_principals', list(admins))
def _getBody(self, params): reservation = params["reservation"] params["endpoints"] = self.endpoints params["assistance_emails"] = rb_settings.get("assistance_emails") params["vc_equipment"] = ", ".join(eq.name for eq in reservation.get_vc_equipment()) params["repetition"] = RepeatMapping.get_message(*reservation.repetition) params["edit_logs"] = reservation.edit_logs.order_by(ReservationEditLog.timestamp.desc()).all() params["excluded_days"] = reservation.find_excluded_days().all() return WTemplated("RoomBookingDetails").getHTML(params)
def _build_notification_before_days_filter(notification_before_days): days_until_occurrence = cast(ReservationOccurrence.start_dt, Date) - cast(func.now(), Date) notification_before_days = func.coalesce(Room.notification_before_days, notification_before_days) if datetime.now().hour >= settings.get('notification_hour', 6): # Notify of today and delayed occurrences (happening in N or less days) return days_until_occurrence <= notification_before_days else: # Notify only of delayed occurrences (happening in less than N days) return days_until_occurrence < notification_before_days
def is_in_digest_window(self, exclude_first_day=False): from indico.modules.rb import settings as rb_settings digest_start = round_up_month(date.today(), from_day=2) days_until_next_digest = (digest_start - date.today()).days digest_window = self.notification_before_days or rb_settings.get('notification_before_days') if exclude_first_day: return days_until_next_digest < digest_window else: return days_until_next_digest <= digest_window
def is_in_digest_window(self, exclude_first_day=False): from indico.modules.rb import settings as rb_settings digest_start = round_up_month(date.today(), from_day=2) days_until_next_digest = cast(digest_start, Date) - cast(func.now(), Date) digest_window = func.coalesce(self.notification_before_days, rb_settings.get('notification_before_days')) if exclude_first_day: return days_until_next_digest < digest_window else: return days_until_next_digest <= digest_window
def compose_email_to_vc_support(self, **mail_params): from indico.modules.rb import settings as rb_settings if self.reservation.is_accepted and self.reservation.uses_vc: to_list = rb_settings.get('vc_support_emails') if to_list: subject = self._get_email_subject(**mail_params) body = self._make_body(mail_params, reservation=self.reservation) return make_email(to_list=to_list, subject=subject, body=body)
def _getBody(self, params): reservation = params['reservation'] params['endpoints'] = self.endpoints params['assistance_emails'] = rb_settings.get('assistance_emails') params['vc_equipment'] = ', '.join(eq.name for eq in reservation.get_vc_equipment()) params['repetition'] = RepeatMapping.get_message(*reservation.repetition) params['edit_logs'] = reservation.edit_logs.order_by(ReservationEditLog.timestamp.desc()).all() params['excluded_days'] = reservation.find_excluded_days().all() return WTemplated('RoomBookingDetails').getHTML(params)
def rb_check_user_access(user): """Checks if the user has access to the room booking system""" from indico.modules.rb import settings if user.isRBAdmin(): return True principals = retrieve_principals(settings.get('authorized_principals', [])) if not principals: # everyone has access return True return any(principal.containsUser(user) for principal in principals)
def compose_email_to_assistance(self, **mail_params): from indico.modules.rb import settings as rb_settings if self.reservation.room.notification_for_assistance: if self.reservation.needs_assistance or mail_params.get('assistance_cancelled'): to_list = rb_settings.get('assistance_emails') if to_list: subject = self._get_email_subject(**mail_params) body = self._make_body(mail_params, reservation=self.reservation) return make_email(to_list=to_list, subject=subject, body=body)
def is_in_notification_window(self, exclude_first_day=False): from indico.modules.rb import settings as rb_settings from indico.modules.rb.models.rooms import Room in_the_past = cast(self.start_dt, Date) < cast(func.now(), Date) days_until_occurrence = cast(self.start_dt, Date) - cast(func.now(), Date) notification_window = func.coalesce(Room.notification_before_days, rb_settings.get('notification_before_days', 1)) if exclude_first_day: return (days_until_occurrence < notification_window) & ~in_the_past else: return (days_until_occurrence <= notification_window) & ~in_the_past
def is_in_notification_window(self, exclude_first_day=False): from indico.modules.rb import settings as rb_settings if self.start_dt.date() < date.today(): return False days_until_occurrence = (self.start_dt.date() - date.today()).days notification_window = (self.reservation.room.notification_before_days or rb_settings.get('notification_before_days', 1)) if exclude_first_day: return days_until_occurrence < notification_window else: return days_until_occurrence <= notification_window
def is_in_digest_window(self, exclude_first_day=False): from indico.modules.rb import settings as rb_settings digest_start = round_up_month(date.today(), from_day=2) days_until_next_digest = cast(digest_start, Date) - cast( func.now(), Date) digest_window = func.coalesce( self.notification_before_days, rb_settings.get('notification_before_days')) if exclude_first_day: return days_until_next_digest < digest_window else: return days_until_next_digest <= digest_window
def _getBody(self, params): reservation = params['reservation'] params['endpoints'] = self.endpoints params['assistance_emails'] = rb_settings.get('assistance_emails') params['vc_equipment'] = ', '.join( eq.name for eq in reservation.get_vc_equipment()) params['repetition'] = RepeatMapping.get_message( *reservation.repetition) params['edit_logs'] = reservation.edit_logs.order_by( ReservationEditLog.timestamp.desc()).all() params['excluded_days'] = reservation.find_excluded_days().all() return WTemplated('RoomBookingDetails').getHTML(params)
def is_in_notification_window(self, exclude_first_day=False): from indico.modules.rb import settings as rb_settings from indico.modules.rb.models.rooms import Room in_the_past = cast(self.start_dt, Date) < cast(func.now(), Date) days_until_occurrence = cast(self.start_dt, Date) - cast( func.now(), Date) notification_window = func.coalesce( Room.notification_before_days, rb_settings.get('notification_before_days', 1)) if exclude_first_day: return (days_until_occurrence < notification_window) & ~in_the_past else: return (days_until_occurrence <= notification_window) & ~in_the_past
def compose_email_to_assistance(self, **mail_params): from indico.modules.rb import settings as rb_settings if self.reservation.room.notification_for_assistance: if self.reservation.needs_assistance or mail_params.get( 'assistance_cancelled'): to_list = rb_settings.get('assistance_emails') if to_list: subject = self._get_email_subject(**mail_params) body = self._make_body(mail_params, reservation=self.reservation) return make_email(to_list=to_list, subject=subject, body=body)
def run(self): occurrences = ReservationOccurrence.find( Reservation.is_accepted, ~ReservationOccurrence.notification_sent, ReservationOccurrence.is_valid, ReservationOccurrence.start_dt >= func.now(), _build_notification_before_days_filter(settings.get('notification_before_days', 0)), _join=[Reservation, Room] ) for occ in occurrences: occ.notification_sent = True if occ.reservation.repeat_frequency == RepeatFrequency.DAY: occ.reservation.occurrences.update({'notification_sent': True}) notify_upcoming_occurrence(occ)
def _getBody(self, params): params['endpoints'] = self.endpoints calendar = RoomBookingCalendarWidget( params['occurrences'], params['start_dt'], params['end_dt'], candidates=params['candidates'], specific_room=params['room'], repeat_frequency=params['repeat_frequency'], repeat_interval=params['repeat_interval']) params['calendar'] = calendar.render(show_navbar=False, details_in_new_tab=True) params['serializable_room'] = Room.get( params['room'].id).to_serializable('__public_exhaustive__') params['booking_limit'] = rb_settings.get('booking_limit') return WTemplated('RoomBookingBookingForm').getHTML(params)
def run(self): occurrences = ReservationOccurrence.find( Reservation.is_accepted, ~ReservationOccurrence.notification_sent, ReservationOccurrence.is_valid, ReservationOccurrence.start_dt >= func.now(), _build_notification_before_days_filter( settings.get('notification_before_days', 0)), _join=[Reservation, Room]) try: for occ in occurrences: notify_upcoming_occurrence(occ) occ.notification_sent = True if occ.reservation.repeat_frequency == RepeatFrequency.DAY: occ.reservation.occurrences.update( {'notification_sent': True}) finally: db.session.commit()
def _process(self): room = self._reservation.room form = ModifyBookingForm(obj=self._reservation, old_start_dt=self._reservation.start_dt, old_end_dt=self._reservation.end_dt) form.used_equipment.query = room.find_available_vc_equipment() if not room.notification_for_assistance and not self._reservation.needs_assistance: del form.needs_assistance invalid_form = form.is_submitted() and not form.validate() if invalid_form: occurrences = {} candidates = {} conflicts = {} pre_conflicts = {} else: occurrences, candidates = self._get_all_occurrences([room.id], form, reservation_id=self._reservation.id) conflicts, pre_conflicts = self._get_all_conflicts(room, form, self._reservation.id) if form.validate_on_submit() and not form.submit_check.data: try: booking_limit_days = room.booking_limit_days or rb_settings.get('booking_limit') if not self._validate_room_booking_limit(form, booking_limit_days): msg = (_(u'Bookings for the room "{}" may not be longer than {} days') .format(room.name, booking_limit_days)) return jsonify(success=False, url=url_for('rooms.roomBooking-modifyBookingForm', self._reservation), msg=msg) self._reservation.modify(form.data, session.user) flash(_(u'Booking updated'), 'success') except NoReportError as e: db.session.rollback() return jsonify(success=False, msg=unicode(e)) return jsonify(success=True, url=self._get_success_url()) elif invalid_form and not form.submit_check.data and request.is_xhr: return jsonify(success=False, msg='\n'.join(form.error_list)) return self._get_view(form=form, room=room, rooms=Room.find_all(), occurrences=occurrences, candidates=candidates, conflicts=conflicts, pre_conflicts=pre_conflicts, start_dt=form.start_dt.data, end_dt=form.end_dt.data, only_conflicts=False, repeat_frequency=form.repeat_frequency.data, repeat_interval=form.repeat_interval.data, reservation=self._reservation, can_override=room.can_be_overridden(session.user)).display()
def _create_user(id_, name=u'Pig', surname=u'Guinea', rb_admin=False, email=None, groups=None): user = User.get(id_) if user: return user.as_avatar user = User() user.id = id_ user.first_name = name user.last_name = surname user.email = email or u'{}@example.com'.format(id_) user.local_groups = {g.group for g in (groups or ())} db.session.add(user) db.session.flush() if rb_admin: rb_settings.set('admin_principals', rb_settings.get('admin_principals') + [user.as_principal]) db.session.flush() _users.add(user) avatar = user.as_avatar avatar.email = user.email return avatar
def _process(self): room = self._room rooms = Room.find_all() form = self._make_form() if form.is_submitted() and not form.validate(): occurrences = {} candidates = {} conflicts = {} pre_conflicts = {} only_conflicts = False else: occurrences, candidates = self._get_all_occurrences([self._room.id], form) conflicts, pre_conflicts = self._get_all_conflicts(self._room, form) candidate_days = {occ.date for candidate in candidates.itervalues() for occ in candidate} conflicting_days = {occ.date for occ in conflicts.iterkeys()} only_conflicts = candidate_days <= conflicting_days if form.validate_on_submit() and not form.submit_check.data: booking_limit_days = room.booking_limit_days or rb_settings.get('booking_limit') if not self._validate_room_booking_limit(form, booking_limit_days): msg = (_(u'Bookings for the room "{}" may not be longer than {} days') .format(room.name, booking_limit_days)) return jsonify(success=False, url=url_for('rooms.room_book', room), msg=msg) return self._create_booking_response(form, room) can_override = room.can_be_overridden(session.user) return self._get_view(form=form, room=room, rooms=rooms, occurrences=occurrences, candidates=candidates, conflicts=conflicts, only_conflicts=only_conflicts, pre_conflicts=pre_conflicts, start_dt=form.start_dt.data, end_dt=form.end_dt.data, repeat_frequency=form.repeat_frequency.data, repeat_interval=form.repeat_interval.data, can_override=can_override, past_date=not form.is_submitted() and self.past_date, date_changed=not form.is_submitted() and self.date_changed).display()
def rb_merge_users(new_id, old_id): """Updates RB data after an Avatar merge :param new_id: Target user :param old_id: Source user (being deleted in the merge) """ from indico.modules.rb import settings from indico.modules.rb.models.blocking_principals import BlockingPrincipal from indico.modules.rb.models.blockings import Blocking from indico.modules.rb.models.reservations import Reservation from indico.modules.rb.models.rooms import Room BlockingPrincipal.find(entity_type='Avatar', entity_id=old_id).update({'entity_id': new_id}) Blocking.find(created_by_id=old_id).update({'created_by_id': new_id}) Reservation.find(created_by_id=old_id).update({'created_by_id': new_id}) Reservation.find(booked_for_id=old_id).update({'booked_for_id': new_id}) Room.find(owner_id=old_id).update({'owner_id': new_id}) for key in ('authorized_principals', 'admin_principals'): principals = settings.get(key, []) principals = principals_merge_users(principals, new_id, old_id) settings.set(key, principals)
def _getBody(self, params): params['serializable_rooms'] = _get_serializable_rooms( [r.id for r in params['rooms']]) params['booking_limit'] = rb_settings.get('booking_limit') return WTemplated('RoomBookingNewBookingSelectRoom').getHTML(params)