def create_all_tables(db, verbose=False, add_initial_data=True): """Create all tables and required initial objects""" from indico.modules.categories import Category from indico.modules.designer import TemplateType from indico.modules.designer.models.templates import DesignerTemplate from indico.modules.oauth.models.applications import OAuthApplication, SystemAppType from indico.modules.users import User if verbose: print(cformat('%{green}Creating tables')) db.create_all() if add_initial_data: if verbose: print(cformat('%{green}Creating system user')) db.session.add(User(id=0, is_system=True, first_name='Indico', last_name='System')) if verbose: print(cformat('%{green}Creating root category')) cat = Category(id=0, title='Home', protection_mode=ProtectionMode.public) db.session.add(cat) db.session.flush() if verbose: print(cformat('%{green}Creating default ticket template for root category ')) dt = DesignerTemplate(category_id=0, title='Default ticket', type=TemplateType.badge, data=DEFAULT_TEMPLATE_DATA, is_system_template=True) cat.default_ticket_template = dt db.session.add(dt) if verbose: print(cformat('%{green}Creating system oauth apps')) for sat in SystemAppType: if sat != SystemAppType.none: db.session.add(OAuthApplication(system_app_type=sat, **sat.default_data)) db.session.commit()
def _process_args(self): if 'confId' in request.view_args: self.obj = Event.get_one(request.view_args['confId'], is_deleted=False) self.obj_type = 'event' elif 'category_id' in request.view_args: self.obj = Category.get_one(request.view_args['category_id'], is_deleted=False) self.obj_type = 'category' if not self.obj.is_root else None else: self.obj = Category.get_root() self.obj_type = None
def _get_event_own_visibility_horizon(self, event): if self.visibility.data is None: # unlimited return Category.get_root() elif self.visibility.data == 0: # invisible return None else: return event.category.nth_parent(self.visibility.data - 1)
def category_cleanup(): from indico.modules.events import Event cfg = Config.getInstance() janitor_user = User.get_one(cfg.getJanitorUserId()) logger.debug("Checking whether any categories should be cleaned up") for categ_id, days in cfg.getCategoryCleanup().iteritems(): try: category = Category.get(int(categ_id), is_deleted=False) except KeyError: logger.warning("Category %s does not exist!", categ_id) continue now = now_utc() to_delete = Event.query.with_parent(category).filter(Event.created_dt < (now - timedelta(days=days))).all() if not to_delete: continue logger.info("Category %s: %s events were created more than %s days ago and will be deleted", categ_id, len(to_delete), days) for i, event in enumerate(to_delete, 1): logger.info("Deleting %s", event) event.as_legacy.delete(user=janitor_user) if i % 100 == 0: db.session.commit() DBMgr.getInstance().commit() db.session.commit() DBMgr.getInstance().commit()
def _default_category(self): try: category_id = int(request.args['category_id']) except (ValueError, KeyError): return self.root_category if self.single_category else None else: return Category.get(category_id, is_deleted=False)
def _mappers_configured(): event_alias = db.aliased(Event) # Event.category_chain -- the category ids of the event, starting # with the root category down to the event's immediate parent. cte = Category.get_tree_cte() query = select([cte.c.path]).where(cte.c.id == Event.category_id).correlate_except(cte) Event.category_chain = column_property(query, deferred=True) # Event.effective_protection_mode -- the effective protection mode # (public/protected) of the event, even if it's inheriting it from its # parent category query = (select([db.case({ProtectionMode.inheriting.value: Category.effective_protection_mode}, else_=Event.protection_mode, value=Event.protection_mode)]) .where(Category.id == Event.category_id)) Event.effective_protection_mode = column_property(query, deferred=True) # Event.series_pos -- the position of the event in its series subquery = (select([event_alias.id, db.func.row_number().over(order_by=(event_alias.start_dt, event_alias.id)).label('pos')]) .where((event_alias.series_id == Event.series_id) & ~event_alias.is_deleted) .correlate(Event) .alias()) query = select([subquery.c.pos]).where(subquery.c.id == Event.id).correlate_except(subquery) Event.series_pos = column_property(query, group='series', deferred=True) # Event.series_count -- the number of events in the event's series query = (db.select([db.func.count(event_alias.id)]) .where((event_alias.series_id == Event.series_id) & ~event_alias.is_deleted) .correlate_except(event_alias)) Event.series_count = column_property(query, group='series', deferred=True)
def is_visible_in(cls, category_id): """ Create a filter that checks whether the event is visible in the specified category. """ cte = Category.get_visible_categories_cte(category_id) return (db.exists(db.select([1])) .where(db.and_(cte.c.id == Event.category_id, db.or_(Event.visibility.is_(None), Event.visibility > cte.c.level))))
def process_formdata(self, valuelist): from indico.modules.categories import Category if valuelist: try: category_id = int(json.loads(valuelist[0])['id']) except KeyError: self.data = None else: self.data = Category.get(category_id, is_deleted=False)
def category_family(create_category, db): grandpa = Category.get_root() dad = create_category(1, title='Dad', parent=grandpa) son = create_category(2, title='Son', parent=dad) sibling = create_category(3, title='Sibling', parent=dad) db.session.add(son) db.session.flush() return grandpa, dad, son, sibling
def _process(self): query = (Category.query .filter(Category.title_matches(request.args['term']), ~Category.is_deleted) .options(undefer('chain_titles')) .order_by(Category.title)) results = [{ 'title': category.title, 'path': category.chain_titles[1:-1], 'url': unicode(category.url) } for category in query.limit(7)] return jsonify(success=True, results=results, count=query.count())
def _process(self): db.session.delete(self.template) root = Category.get_root() if not root.default_ticket_template: # if we deleted the root category's default template, pick # a system template as the new default (this always exists) system_template = DesignerTemplate.find_first(DesignerTemplate.is_system_template, DesignerTemplate.type == TemplateType.badge) root.default_ticket_template = system_template db.session.flush() flash(_('The template has been deleted'), 'success') return jsonify_data(html=_render_template_list(self.target, event=self.event_or_none))
def category_chain_overlaps(cls, category_ids): """ Create a filter that checks whether the event has any of the provided category ids in its parent chain. :param category_ids: A list of category ids or a single category id """ from indico.modules.categories import Category if not isinstance(category_ids, (list, tuple, set)): category_ids = [category_ids] cte = Category.get_tree_cte() return (cte.c.id == Event.category_id) & cte.c.path.overlap(category_ids)
def test_excluded_categories(mocker, monkeypatch, db, create_category): """Test if category exclusions work.""" plugin = mocker.patch('indico_livesync.plugin.LiveSyncPlugin') plugin.settings.get.return_value = [{'id': 2}, {'id': 3}] categories = {} with db.session.no_autoflush: for cat_id in xrange(6): category = (create_category(cat_id, title=str(cat_id), protection_mode=0, parent=categories[CATEGORY_PARENTS[cat_id]]) if cat_id else Category.get_root()) categories[cat_id] = category db.session.add(category) db.session.flush() db.session.flush() for cat in categories.viewvalues(): db = mocker.patch('indico_livesync.models.queue.db') LiveSyncQueueEntry.create({ChangeType.created}, obj_ref(cat), excluded_categories=get_excluded_categories()) assert db.session.add.called == (cat.id not in {2, 3, 4, 5})
def test_effective_protection_mode(db): def _cat(id_, protection_mode=ProtectionMode.inheriting, children=None): return Category(id=id_, title='cat-{}'.format(id_), protection_mode=protection_mode, children=children or []) root = Category.get_root() root.protection_mode = ProtectionMode.protected root.children = [ _cat(1), _cat(2, ProtectionMode.public, children=[ _cat(3, children=[ _cat(4, ProtectionMode.inheriting), _cat(5, ProtectionMode.public), _cat(6, ProtectionMode.protected), ]), _cat(7, ProtectionMode.protected, children=[ _cat(8, ProtectionMode.inheriting), _cat(9, ProtectionMode.public), _cat(10, ProtectionMode.protected), ]), _cat(11) ]) ] db.session.add(root) db.session.flush() data = {c.id: c.effective_protection_mode for c in Category.query.options(undefer('effective_protection_mode'))} assert data == { 0: ProtectionMode.protected, 1: ProtectionMode.protected, 2: ProtectionMode.public, 3: ProtectionMode.public, 4: ProtectionMode.public, 5: ProtectionMode.public, 6: ProtectionMode.protected, 7: ProtectionMode.protected, 8: ProtectionMode.protected, 9: ProtectionMode.public, 10: ProtectionMode.protected, 11: ProtectionMode.public }
def _checkParams(self): RHUserBase._checkParams(self) self.category = Category.get_one(request.view_args['category_id'])
def serialize_categories_ical(category_ids, user, event_filter=True, event_filter_fn=None, update_query=None): """Export the events in a category to iCal :param category_ids: Category IDs to export :param user: The user who needs to be able to access the events :param event_filter: A SQLalchemy criterion to restrict which events will be returned. Usually something involving the start/end date of the event. :param event_filter_fn: A callable that determines which events to include (after querying) :param update_query: A callable that can update the query used to retrieve the events. Must return the updated query object. """ own_room_strategy = joinedload('own_room') own_room_strategy.load_only('building', 'floor', 'number', 'verbose_name') own_room_strategy.lazyload('owner') own_venue_strategy = joinedload('own_venue').load_only('name') query = (Event.query .filter(Event.category_chain_overlaps(category_ids), ~Event.is_deleted, event_filter) .options(load_only('id', 'category_id', 'start_dt', 'end_dt', 'title', 'description', 'own_venue_name', 'own_room_name', 'protection_mode', 'access_key'), subqueryload('acl_entries'), joinedload('person_links'), own_room_strategy, own_venue_strategy) .order_by(Event.start_dt)) if update_query: query = update_query(query) it = iter(query) if event_filter_fn: it = ifilter(event_filter_fn, it) events = list(it) # make sure the parent categories are in sqlalchemy's identity cache. # this avoids query spam from `protection_parent` lookups _parent_categs = (Category._get_chain_query(Category.id.in_({e.category_id for e in events})) .options(load_only('id', 'parent_id', 'protection_mode'), joinedload('acl_entries')) .all()) cal = ical.Calendar() cal.add('version', '2.0') cal.add('prodid', '-//CERN//INDICO//EN') now = now_utc(False) for event in events: if not event.can_access(user): continue location = ('{} ({})'.format(event.room_name, event.venue_name) if event.venue_name and event.room_name else (event.venue_name or event.room_name)) cal_event = ical.Event() cal_event.add('uid', u'indico-event-{}@{}'.format(event.id, url_parse(config.BASE_URL).host)) cal_event.add('dtstamp', now) cal_event.add('dtstart', event.start_dt) cal_event.add('dtend', event.end_dt) cal_event.add('url', event.external_url) cal_event.add('summary', event.title) cal_event.add('location', location) description = [] if event.person_links: speakers = [u'{} ({})'.format(x.full_name, x.affiliation) if x.affiliation else x.full_name for x in event.person_links] description.append(u'Speakers: {}'.format(u', '.join(speakers))) if event.description: desc_text = unicode(event.description) or u'<p/>' # get rid of RichMarkup try: description.append(unicode(html.fromstring(desc_text).text_content())) except ParserError: # this happens e.g. if desc_text contains only a html comment pass description.append(event.external_url) cal_event.add('description', u'\n'.join(description)) cal.add_component(cal_event) return BytesIO(cal.to_ical())
def _create_category(id_=None, **kwargs): kwargs.setdefault('title', u'cat#{}'.format(id_) if id_ is not None else u'dummy') kwargs.setdefault('timezone', 'UTC') if 'parent' not in kwargs: kwargs['parent'] = Category.get_root() return Category(id=id_, acl_entries=set(), **kwargs)
def _process_args(self): self.event_type = EventType[request.view_args['event_type']] self.root_category = Category.get_root() self.single_category = not self.root_category.children
def _process_args(self): RHUserBase._process_args(self) self.category = Category.get_one(request.view_args['category_id']) self.suggestion = self.user.suggested_categories.filter_by(category=self.category).first()