Exemplo n.º 1
0
 def _process(self):
     self.user.settings.set('suggest_categories', True)
     tz = session.tzinfo
     hours, minutes = timedelta_split(tz.utcoffset(datetime.now()))[:2]
     categories = get_related_categories(self.user)
     categories_events = []
     if categories:
         category_ids = {c['categ'].id for c in categories.itervalues()}
         today = now_utc(False).astimezone(tz).date()
         query = (Event.query
                  .filter(~Event.is_deleted,
                          Event.category_chain_overlaps(category_ids),
                          Event.start_dt.astimezone(session.tzinfo) >= today)
                  .options(joinedload('category').load_only('id', 'title'),
                           joinedload('series'),
                           subqueryload('acl_entries'),
                           load_only('id', 'category_id', 'start_dt', 'end_dt', 'title', 'access_key',
                                     'protection_mode', 'series_id', 'series_pos', 'series_count'))
                  .order_by(Event.start_dt, Event.id))
         categories_events = get_n_matching(query, 10, lambda x: x.can_access(self.user))
     from_dt = now_utc(False) - relativedelta(weeks=1, hour=0, minute=0, second=0)
     linked_events = [(event, {'management': bool(roles & self.management_roles),
                               'reviewing': bool(roles & self.reviewer_roles),
                               'attendance': bool(roles & self.attendance_roles)})
                      for event, roles in get_linked_events(self.user, from_dt, 10).iteritems()]
     return WPUser.render_template('dashboard.html', 'dashboard',
                                   offset='{:+03d}:{:02d}'.format(hours, minutes), user=self.user,
                                   categories=categories,
                                   categories_events=categories_events,
                                   suggested_categories=get_suggested_categories(self.user),
                                   linked_events=linked_events)
Exemplo n.º 2
0
 def _process(self):
     self.user.settings.set('suggest_categories', True)
     tz = session.tzinfo
     hours, minutes = timedelta_split(tz.utcoffset(datetime.now()))[:2]
     categories = get_related_categories(self.user)
     categories_events = []
     if categories:
         category_ids = {c['categ'].id for c in categories.itervalues()}
         today = now_utc(False).astimezone(tz).date()
         query = (Event.query
                  .filter(~Event.is_deleted,
                          Event.category_chain_overlaps(category_ids),
                          Event.start_dt.astimezone(session.tzinfo) >= today)
                  .options(joinedload('category').load_only('id', 'title'),
                           joinedload('series'),
                           subqueryload('acl_entries'),
                           load_only('id', 'category_id', 'start_dt', 'end_dt', 'title', 'access_key',
                                     'protection_mode', 'series_id', 'series_pos', 'series_count'))
                  .order_by(Event.start_dt, Event.id))
         categories_events = get_n_matching(query, 10, lambda x: x.can_access(self.user))
     from_dt = now_utc(False) - relativedelta(weeks=1, hour=0, minute=0, second=0)
     linked_events = [(event, {'management': bool(roles & self.management_roles),
                               'reviewing': bool(roles & self.reviewer_roles),
                               'attendance': bool(roles & self.attendance_roles)})
                      for event, roles in get_linked_events(self.user, from_dt, 10).iteritems()]
     return WPUser.render_template('dashboard.html', 'dashboard',
                                   offset='{:+03d}:{:02d}'.format(hours, minutes), user=self.user,
                                   categories=categories,
                                   categories_events=categories_events,
                                   suggested_categories=get_suggested_categories(self.user),
                                   linked_events=linked_events)
Exemplo n.º 3
0
 def _get_upcoming_event(self):
     query = (Event.query
              .filter(Event.is_visible_in(self.category.id),
                      Event.start_dt > now_utc(),
                      ~Event.is_deleted)
              .options(subqueryload('acl_entries'))
              .order_by(Event.start_dt, Event.id))
     res = get_n_matching(query, 1, lambda event: event.can_access(session.user))
     if res:
         return res[0]
Exemplo n.º 4
0
 def _get_upcoming_event(self):
     query = (Event.query
              .filter(Event.is_visible_in(self.category),
                      Event.start_dt > now_utc(),
                      ~Event.is_deleted)
              .options(subqueryload('acl_entries'))
              .order_by(Event.start_dt, Event.id))
     res = get_n_matching(query, 1, lambda event: event.can_access(session.user))
     if res:
         return res[0]
Exemplo n.º 5
0
def get_events_in_categories(category_ids, user, limit=10):
    """Get all the user-accessible events in a given set of categories."""
    tz = session.tzinfo
    today = now_utc(False).astimezone(tz).date()
    query = (Event.query.filter(
        ~Event.is_deleted, Event.category_chain_overlaps(category_ids),
        Event.start_dt.astimezone(session.tzinfo) >= today).options(
            joinedload('category').load_only('id', 'title'),
            joinedload('series'), subqueryload('acl_entries'),
            load_only('id', 'category_id', 'start_dt', 'end_dt', 'title',
                      'access_key', 'protection_mode', 'series_id',
                      'series_pos',
                      'series_count')).order_by(Event.start_dt, Event.id))
    return get_n_matching(query, limit, lambda x: x.can_access(user))
Exemplo n.º 6
0
    def _paginate(self, query, page, column, user, admin_override_enabled):
        reverse = False
        pagenav = {'prev': None, 'next': None}
        if not page:
            query = query.order_by(column.desc())
        elif page > 0:  # next page
            query = query.filter(column < page).order_by(column.desc())
            # since we asked for a next page we know that a previous page exists
            pagenav['prev'] = -(page - 1)
        elif page < 0:  # prev page
            query = query.filter(column > -page).order_by(column)
            # since we asked for a previous page we know that a next page exists
            pagenav['next'] = -(page - 1)
            reverse = True

        def _can_access(obj):
            return (obj.effective_protection_mode == ProtectionMode.public or
                    obj.can_access(user, allow_admin=admin_override_enabled))

        res = get_n_matching(query,
                             self.RESULTS_PER_PAGE + 1,
                             _can_access,
                             prefetch_factor=20)

        if len(res) > self.RESULTS_PER_PAGE:
            # we queried 1 more so we can see if there are more results available
            del res[self.RESULTS_PER_PAGE:]
            if reverse:
                pagenav['prev'] = -res[-1].id
            else:
                pagenav['next'] = res[-1].id

        if reverse:
            res.reverse()

        return res, pagenav
Exemplo n.º 7
0
    def _paginate(self, query, page, column, user, admin_override_enabled):
        reverse = False
        pagenav = {'prev': None, 'next': None}
        if not page:
            query = query.order_by(column.desc())
        elif page > 0:  # next page
            query = query.filter(column < page).order_by(column.desc())
            # since we asked for a next page we know that a previous page exists
            pagenav['prev'] = -(page - 1)
        elif page < 0:  # prev page
            query = query.filter(column > -page).order_by(column)
            # since we asked for a previous page we know that a next page exists
            pagenav['next'] = -(page - 1)
            reverse = True

        preloaded_categories = set()

        def _preload_categories(objs):
            nonlocal preloaded_categories
            obj_types = {type(o) for o in objs}
            assert len(obj_types) == 1
            obj_type = obj_types.pop()

            if obj_type == Event:
                chain_query = db.session.query(Event.category_chain).filter(
                    Event.id.in_(o.id for o in objs))
            elif obj_type == Category:
                chain_query = db.session.query(Category.chain_ids).filter(
                    Category.id.in_(o.id for o in objs))
            elif obj_type == Contribution:
                chain_query = (db.session.query(Event.category_chain).join(
                    Contribution.event).filter(
                        Contribution.id.in_(o.id for o in objs)))
            elif obj_type == Attachment:
                chain_query = (db.session.query(Event.category_chain).join(
                    Attachment.folder).join(AttachmentFolder.event).filter(
                        Attachment.id.in_(o.id for o in objs)))
            elif obj_type == EventNote:
                chain_query = (db.session.query(Event.category_chain).join(
                    EventNote.event).filter(
                        EventNote.id.in_(o.id for o in objs)))
            else:
                raise Exception(f'Unhandled object type: {obj_type}')
            category_ids = set(
                itertools.chain.from_iterable(id for id, in chain_query))
            query = (Category.query.filter(
                Category.id.in_(category_ids)).options(
                    load_only('id', 'parent_id', 'protection_mode')))
            Category.preload_relationships(
                query,
                'acl_entries',
                strategy=lambda rel: _apply_acl_entry_strategy(
                    subqueryload(rel), CategoryPrincipal))
            preloaded_categories |= set(query)

        def _can_access(obj, allow_effective_protection_mode=True):
            if isinstance(obj, (Category, Event, Session, Contribution)):
                # more efficient for events/categories/contribs since it avoids climbing up the chain
                protection_mode = (obj.effective_protection_mode
                                   if allow_effective_protection_mode else
                                   obj.protection_mode)
            elif isinstance(obj, Attachment):
                # attachments don't have it so we can only skip access checks if they
                # are public themselves
                protection_mode = obj.protection_mode
            elif isinstance(obj, EventNote):
                # notes inherit from their parent
                return _can_access(obj.object,
                                   allow_effective_protection_mode=False)
            elif isinstance(obj, SubContribution):
                # subcontributions inherit from their contribution
                return _can_access(obj.contribution,
                                   allow_effective_protection_mode=False)
            else:
                raise Exception(f'Unexpected object: {obj}')
            return (protection_mode == ProtectionMode.public or obj.can_access(
                user, allow_admin=admin_override_enabled))

        res = get_n_matching(query,
                             self.RESULTS_PER_PAGE + 1,
                             _can_access,
                             prefetch_factor=20,
                             preload_bulk=_preload_categories)

        if len(res) > self.RESULTS_PER_PAGE:
            # we queried 1 more so we can see if there are more results available
            del res[self.RESULTS_PER_PAGE:]
            if reverse:
                pagenav['prev'] = -res[-1].id
            else:
                pagenav['next'] = res[-1].id

        if reverse:
            res.reverse()

        return res, pagenav