def test_copy_local_groups(self): from kotti import DBSession from kotti.resources import get_root from kotti.security import principals_with_local_roles from kotti.security import set_groups self.test_principals_with_local_roles() root = get_root() child = root[u'child'] self.assertEqual( set(principals_with_local_roles(child)), set(['bob', 'group:bobsgroup', 'group:franksgroup']) ) # We make a copy of 'child', and we expect the local roles set # on 'child' to not be copied over: child2 = root['child2'] = child.copy() DBSession.flush() self.assertEqual( set(principals_with_local_roles(child2)), set([u'bob', u'group:franksgroup']), ) self.assertEqual(len(principals_with_local_roles(child)), 3) # When we now change the local roles of 'child', the copy is # unaffected: set_groups('group:bobsgroup', child, []) self.assertEqual(len(principals_with_local_roles(child)), 2) self.assertEqual(len(principals_with_local_roles(child2)), 2)
def default_search_content(search_term, request=None): searchstring = u'%%%s%%' % search_term # generic_filter can be applied to all Node (and subclassed) objects generic_filter = or_(Content.name.like(searchstring), Content.title.like(searchstring), Content.description.like(searchstring)) results = DBSession.query(Content).filter(generic_filter).all() # specific result contain objects matching additional criteria # but must not match the generic criteria (because these objects # are already in the generic_results) document_results = DBSession.query(Document).filter( and_(Document.body.like(searchstring), not_(generic_filter))) for results_set in [content_with_tags([searchstring]), document_results.all()]: [results.append(c) for c in results_set if not c in results] result_dicts = [] for result in results: if has_permission('view', result, request): result_dicts.append(dict( name=result.name, title=result.title, description=result.description, path=request.resource_path(result))) return result_dicts
def initialize_sql(engine, drop_all=False): DBSession.registry.clear() DBSession.configure(bind=engine) metadata.bind = engine if drop_all or os.environ.get('KOTTI_TEST_DB_STRING'): metadata.reflect() metadata.drop_all(engine) # Allow users of Kotti to cherry pick the tables that they want to use: settings = _resolve_dotted(get_settings()) tables = settings['kotti.use_tables'].strip() or None if tables: tables = [metadata.tables[name] for name in tables.split()] _adjust_for_engine(engine) # Allow migrations to set the 'head' stamp in case the database is # initialized freshly: if not engine.table_names(): stamp_heads() metadata.create_all(engine, tables=tables) if os.environ.get('KOTTI_DISABLE_POPULATORS', '0') not in TRUE_VALUES: for populate in settings['kotti.populators']: populate() commit() return DBSession
def test_groups_from_users(self): from kotti import DBSession from kotti.resources import get_root from kotti.resources import Node from kotti.security import list_groups from kotti.security import set_groups self.make_bob() root = get_root() child = root[u'child'] = Node() DBSession.flush() self.assertEqual(list_groups('bob', root), ['group:bobsgroup']) set_groups('group:bobsgroup', root, ['role:editor']) set_groups('role:editor', child, ['group:foogroup']) self.assertEqual( set(list_groups('bob', root)), set(['group:bobsgroup', 'role:editor']) ) self.assertEqual( set(list_groups('bob', child)), set(['group:bobsgroup', 'role:editor', 'group:foogroup']) )
def initialize_sql(engine, drop_all=False): DBSession.registry.clear() DBSession.configure(bind=engine) metadata.bind = engine if drop_all or os.environ.get('KOTTI_TEST_DB_STRING'): metadata.reflect() metadata.drop_all(engine) # Allow users of Kotti to cherry pick the tables that they want to use: settings = get_current_registry().settings tables = settings['kotti.use_tables'].strip() or None if tables: if 'settings' not in tables: tables += ' settings' tables = [metadata.tables[name] for name in tables.split()] if engine.dialect.name == 'mysql': # pragma: no cover from sqlalchemy.dialects.mysql.base import LONGBLOB File.__table__.c.data.type = LONGBLOB() metadata.create_all(engine, tables=tables) for populate in get_settings()['kotti.populators']: populate() commit() return DBSession()
def delete_nodes(self): """ Delete nodes view. Renders either a view to delete multiple nodes or delete the selected nodes and get back to the referrer of the request. :result: Either a redirect response or a dictionary passed to the template for rendering. :rtype: pyramid.httpexceptions.HTTPFound or dict """ if 'delete_nodes' in self.request.POST: ids = self.request.POST.getall('children-to-delete') if not ids: self.flash(_(u"Nothing was deleted."), 'info') for id in ids: item = DBSession.query(Node).get(id) self.flash(_(u'${title} was deleted.', mapping=dict(title=item.title)), 'success') del self.context[item.name] return self.back('@@contents') if 'cancel' in self.request.POST: self.flash(_(u'No changes were made.'), 'info') return self.back('@@contents') ids = self._selected_children(add_context=False) items = [] if ids is not None: items = DBSession.query(Node).filter(Node.id.in_(ids)).\ order_by(Node.position).all() return {'items': items, 'states': _states(self.context, self.request)}
def view_meetups(request): if 'delete' in request.POST: todel = request.POST.getall('meetupcheck') for mid in todel: # print 'mid:%s, len mid:%d'% ( mid, len(mid) ) meetup = DBSession.query(Act).filter_by(id=int(mid)).first() if meetup is not None : # print meetup if len(meetup.parts) != 0: request.session.flash(u"活动'%s..'由于已经有人报名不能删除!" % meetup.title[:10], 'danger') else: meetup.status = Act.STATUS_DELETED request.session.flash(u"活动'%s..'已成功删除!" % meetup.title[:10], 'success') DBSession.flush() # DBSession.commit() return view_meetup_entry()
def view_review(context, request): jquery.need() contextbody = jinja2.Markup(context.body) user = get_user(request) if request.POST : if user is None: request.session.flash(u"请先登陆..","info") came_from = request.url return HTTPFound("/login?came_from=%s" % came_from) if 'submit' in request.POST: comment_content = request.params.get("review-comment-input") comment = Comment() comment.type = comment.TYPE_MEETUP_REVIEW comment.user_id = user.id comment.document_id = context.id # ACTION!!!: There is a SQL injection risk here! should be prevented comment.content = comment_content DBSession.add( comment) DBSession.flush() return wrap_user2(request, {'context':context, 'contextbody': contextbody, 'comments_count': len(context.comments) })
def initialize_sql(engine, drop_all=False): DBSession.registry.clear() DBSession.configure(bind=engine) metadata.bind = engine if drop_all or os.environ.get('KOTTI_TEST_DB_STRING'): metadata.reflect() metadata.drop_all(engine) # Allow users of Kotti to cherry pick the tables that they want to use: settings = get_current_registry().settings tables = settings['kotti.use_tables'].strip() or None if tables: tables = [metadata.tables[name] for name in tables.split()] if engine.dialect.name == 'mysql': # pragma: no cover from sqlalchemy.dialects.mysql.base import LONGBLOB File.__table__.c.data.type = LONGBLOB() # Allow migrations to set the 'head' stamp in case the database is # initialized freshly: if not engine.table_names(): stamp_heads() metadata.create_all(engine, tables=tables) if os.environ.get('KOTTI_DISABLE_POPULATORS', '0') not in ('1', 'y'): for populate in get_settings()['kotti.populators']: populate() commit() return DBSession
def paste_node(context, request): session = DBSession() id, action = request.session['kotti.paste'] item = session.query(Node).get(id) if item is not None: if action == 'cut': if not has_permission('edit', item, request): raise Forbidden() item.__parent__.children.remove(item) context.children.append(item) del request.session['kotti.paste'] elif action == 'copy': copy = item.copy() name = copy.name if not name: # for root name = copy.title name = title_to_name(name, blacklist=context.keys()) copy.name = name context.children.append(copy) request.session.flash(_(u'${title} pasted.', mapping=dict(title=item.title)), 'success') else: request.session.flash(_(u'Could not paste node. It does not exist anymore.'), 'error') if not request.is_xhr: location = resource_url(context, request) return HTTPFound(location=location)
def add_some_groups(): session = DBSession() root = get_root() child = root[u'child'] = Node() grandchild = child[u'grandchild'] = Node() session.flush() # root: # bob -> group:bobsgroup # frank -> group:franksgroup # group:franksgroup -> role:editor # child: # group:bobsgroup -> group:franksgroup # grandchild: # group:franksgroup -> role:admin # group:franksgroup -> group:bobsgroup # bob and frank are a site-wide members of their respective groups: set_groups('bob', root, ['group:bobsgroup']) set_groups('frank', root, ['group:franksgroup']) # franksgroup has a site-wide editor role: set_groups('group:franksgroup', root, ['role:editor']) # bobsgroup is part of franksgroup on the child level: set_groups('group:bobsgroup', child, ['group:franksgroup']) # franksgroup has the admin role on the grandchild. # and finally, to test recursion, we make franksgroup part of # bobsgroup on the grandchild level: set_groups('group:franksgroup', grandchild, ['role:owner', 'group:bobsgroup'])
def test_unique_constraint(self): # Try to add two children with the same name to the root node: session = DBSession() root = get_root() session.add(Node(name=u'child1', parent=root)) session.add(Node(name=u'child1', parent=root)) self.assertRaises(IntegrityError, session.flush)
def view(self): session = DBSession() query = session.query(SoftwareProject).filter( SoftwareProject.parent_id == self.context.id) items = query.all() # [TODO] Are these calls too expensive? [item.refresh_pypi() for item in items] [item.refresh_github() for item in items] [item.refresh_bitbucket() for item in items] if self.context.sort_order_is_ascending: items = sorted(items, key=lambda x: x.date) else: items = sorted(items, key=lambda x: x.date, reverse=True) page = self.request.params.get('page', 1) settings = collection_settings() if settings['use_batching']: items = Batch.fromPagenumber(items, pagesize=settings['pagesize'], pagenumber=int(page)) return { 'api': template_api(self.context, self.request), 'macros': get_renderer('templates/macros.pt').implementation(), 'items': items, 'settings': settings, }
def __getitem__(self, name): log.debug( sys._getframe().f_code.co_name ) log.debug(type(name)) log.debug(name) name = unicode(name) try: principal = DBSession.query( self.stub_factory).filter( self.stub_factory.name == name).one() log.debug('principal found :: id={} name={} email={}'.format( principal.id, principal.name, principal.email)) return principal except NoResultFound: try: account = DBSession.query( self.factory).filter( self.factory.email == self.__name2email(name)).one() log.debug('account found id={} email={}'.format( account.id, account.email)) principal = DBSession.query( self.stub_factory).filter( self.stub_factory.id == account.id).one() log.debug('principal found :: id={} name={} email={}'.format( principal.id, principal.name, principal.email)) return principal except NoResultFound: log.error('KeyError') raise KeyError(name)
def resume_view(context, request): jquery.need() user = get_user(request) if not user: raise UserNotFount() if "add_resume" in request.POST: title = request.POST['resume_title'] if title.strip() != '': resume = resources.Resume(title=title, user=user) #DBSession.add(resume) #DBSession.flush() #return HTTPFound(location='/resume_edit2/%d' % resume.id) elif "operator" in request.POST: ops = request.POST['operator'] print ops if ops == 'del_resume': id = request.POST['operator_id'] resume = DBSession.query(resources.Resume).get(id) if resume and resume.user_id == user.id: DBSession.delete(resume) return wrap_user(request,{ 'resumes':user.resumes, 'pcs':user.position_items, })
def test_inherit(self): from kotti import DBSession from kotti.resources import get_root from kotti.resources import Node from kotti.security import list_groups from kotti.security import list_groups_raw from kotti.security import set_groups root = get_root() child = root[u'child'] = Node() DBSession.flush() self.assertEqual(list_groups('bob', child), []) set_groups('bob', root, ['role:editor']) self.assertEqual(list_groups('bob', child), ['role:editor']) # Groups from the child are added: set_groups('bob', child, ['group:somegroup']) self.assertEqual( set(list_groups('bob', child)), set(['group:somegroup', 'role:editor']) ) # We can ask to list only those groups that are defined locally: self.assertEqual( list_groups_raw(u'bob', child), set(['group:somegroup']))
def create( self, content: Union[bytes, FieldStorage], filename: Optional[str] = None, content_type: Optional[str] = None, ) -> str: """Saves a new file and returns the file id :param content: can either be ``bytes``, another ``file object`` or a :class:`cgi.FieldStorage`. When ``filename`` and ``content_type`` parameters are not provided they are deducted from the content itself. :param filename: filename for this file :type filename: string :param content_type: Mimetype of this file :type content_type: string :return: the unique ``file_id`` associated to this file :rtype: string """ new_file_id = str(uuid.uuid1()) content, filename, content_type = self.fileinfo(content, filename, content_type) if hasattr(content, "read"): content = content.read() fstore = DBStoredFile( data=content, file_id=new_file_id, filename=filename, content_type=content_type, ) DBSession.add(fstore) return new_file_id
def _get_product(self, sku, subsku): """return tuple product & variation""" product = DBSession.query( VendoProduct).filter_by(sku=sku).one() variation = DBSession.query( VendoProductVariation).filter_by(sub_sku=subsku).one() return product, variation
def upgrade(): sa.orm.events.MapperEvents._clear() # avoids filedepot magic from depot.manager import DepotManager from depot.fields.upload import UploadedFile from depot.fields.sqlalchemy import UploadedFileField from kotti import DBSession, metadata from kotti.resources import File t = sa.Table("files", metadata) t.c.data.type = sa.LargeBinary() dn = DepotManager.get_default() for obj in DBSession.query(File): uploaded_file = UploadedFile({"depot_name": dn, "files": []}) uploaded_file._thaw() uploaded_file.process_content(obj.data, filename=obj.filename, content_type=obj.mimetype) stored_file = DepotManager.get().get(uploaded_file["file_id"]) obj.data = uploaded_file.encode() stored_file.last_modified = obj.modification_date log.info( "Migrated {} bytes for File with pk {} to {}/{}".format(len(obj.data), obj.id, dn, uploaded_file["file_id"]) ) DBSession.flush() if DBSession.get_bind().name != "sqlite": # not supported by sqlite op.alter_column("files", "data", type_=UploadedFileField())
def __setitem__(self, name: str, principal: Union[Principal, dict]) -> None: name = name if isinstance(principal, dict): principal = self.factory(**principal) DBSession.add(principal)
def fruit_categories_bunch(cls, order_by, how_many=10): # fruit_categories contain fruits ret = [] fruits = DBSession.query(Fruit).all() for r in DBSession.query(FruitCategory).all(): ret.append(cls.make_record(r, fruits)) return ret
def __delitem__(self, name): name = unicode(name) try: principal = self._principal_by_name(name) DBSession.delete(principal) except NoResultFound: raise KeyError(name)
def paste_nodes(self): """ Paste nodes view. Paste formerly copied or cutted nodes into the current context. Note that a cutted node can not be pasted into itself. :result: Redirect response to the referrer of the request. :rtype: pyramid.httpexceptions.HTTPFound """ ids, action = self.request.session["kotti.paste"] for count, id in enumerate(ids): item = DBSession.query(Node).get(id) if item is not None: if action == "cut": if not self.request.has_permission("edit", item): raise Forbidden() item.__parent__.children.remove(item) item.name = title_to_name(item.name, blacklist=self.context.keys()) self.context[item.name] = item if count is len(ids) - 1: del self.request.session["kotti.paste"] elif action == "copy": copy = item.copy() name = copy.name if not name: # for root name = copy.title name = title_to_name(name, blacklist=self.context.keys()) copy.name = name self.context[name] = copy self.flash( _("${title} was pasted.", mapping=dict(title=item.title)), "success" ) else: self.flash(_("Could not paste node. It no longer exists."), "error") DBSession.flush() if not self.request.is_xhr: return self.back()
def fruit_category(self, cls, id_wanted): r = DBSession.query(FruitCategory).filter_by(id=id_wanted).first() if r is not None: fruits = DBSession.query(Fruit).all() return self.make_record(r, fruits) else: return None
def delete_nodes(self): """ Delete nodes view. Renders either a view to delete multiple nodes or delete the selected nodes and get back to the referrer of the request. :result: Either a redirect response or a dictionary passed to the template for rendering. :rtype: pyramid.httpexceptions.HTTPFound or dict """ if "delete_nodes" in self.request.POST: ids = self.request.POST.getall("children-to-delete") if not ids: self.request.session.flash(_(u"Nothing deleted."), "info") for id in ids: item = DBSession.query(Node).get(id) self.request.session.flash(_(u"${title} deleted.", mapping=dict(title=item.title)), "success") del self.context[item.name] return self.back("@@contents") if "cancel" in self.request.POST: self.request.session.flash(_(u"No changes made."), "info") return self.back("@@contents") ids = self._selected_children(add_context=False) items = [] if ids is not None: items = DBSession.query(Node).filter(Node.id.in_(ids)).order_by(Node.position).all() return {"items": items, "states": _states(self.context, self.request)}
def rename_nodes(self): """ Rename nodes view. Renders either a view to change the titles and names for multiple nodes or handle the changes and get back to the referrer of the request. :result: Either a redirect response or a dictionary passed to the template for rendering. :rtype: pyramid.httpexceptions.HTTPFound or dict """ if "rename_nodes" in self.request.POST: ids = self.request.POST.getall("children-to-rename") for id in ids: item = DBSession.query(Node).get(id) name = self.request.POST[id + "-name"] title = self.request.POST[id + "-title"] if not name or not title: self.request.session.flash(_(u"Name and title are required."), "error") location = resource_url(self.context, self.request) + "@@rename_nodes" return HTTPFound(location=location) else: item.name = title_to_name(name, blacklist=self.context.keys()) item.title = title self.request.session.flash(_(u"Your changes have been saved."), "success") return self.back("@@contents") if "cancel" in self.request.POST: self.request.session.flash(_(u"No changes made."), "info") return self.back("@@contents") ids = self._selected_children(add_context=False) items = [] if ids is not None: items = DBSession.query(Node).filter(Node.id.in_(ids)).all() return {"items": items}
def __delitem__(self, name: str) -> None: name = name try: principal = self._principal_by_name(name) DBSession.delete(principal) except NoResultFound: raise KeyError(name)
def order_node(context, request): P = request.POST if 'order-up' in P or 'order-down' in P: up, down = P.get('order-up'), P.get('order-down') child = DBSession.query(Node).get(int(down or up)) if up is not None: mod = -1 else: # pragma: no cover mod = 1 index = context.children.index(child) context.children.pop(index) context.children.insert(index + mod, child) request.session.flash(_(u'${title} moved.', mapping=dict(title=child.title)), 'success') if not request.is_xhr: return HTTPFound(location=request.url) elif 'toggle-visibility' in P: child = DBSession.query(Node).get(int(P['toggle-visibility'])) child.in_navigation ^= True mapping = dict(title=child.title) if child.in_navigation: msg = _(u'${title} is now visible in the navigation.', mapping=mapping) else: msg = _(u'${title} is no longer visible in the navigation.', mapping=mapping) request.session.flash(msg, 'success') if not request.is_xhr: return HTTPFound(location=request.url) return {}
def save_success(self, appstruct): appstruct.pop('csrf_token', None) DBSession.add( self.add(**appstruct) ) self.request.session.flash(self.success_message, 'success') location = self.success_url return HTTPFound(location=location)
def test_principals_with_local_roles(self): from kotti import DBSession from kotti.resources import get_root from kotti.resources import Node from kotti.security import map_principals_with_local_roles from kotti.security import principals_with_local_roles from kotti.security import set_groups root = get_root() child = root[u'child'] = Node() DBSession.flush() self.assertEqual(principals_with_local_roles(root), []) self.assertEqual(principals_with_local_roles(child), []) self.assertEqual(map_principals_with_local_roles(root), []) self.assertEqual(map_principals_with_local_roles(child), []) set_groups('group:bobsgroup', child, ['role:editor']) set_groups('bob', root, ['group:bobsgroup']) set_groups('group:franksgroup', root, ['role:editor']) self.assertEqual( set(principals_with_local_roles(child)), set(['bob', 'group:bobsgroup', 'group:franksgroup']) ) self.assertEqual( set(principals_with_local_roles(child, inherit=False)), set(['group:bobsgroup']) ) self.assertEqual( set(principals_with_local_roles(root)), set(['bob', 'group:franksgroup']) )
def iterkeys(self): for (principal_name, ) in DBSession.query(self.factory.name): yield principal_name
def _before_update(mapper, connection, target): session = DBSession.object_session(target) if session.is_modified(target, include_collections=False): notify(ObjectUpdate(target, get_current_request()))
def test_container_methods(self, db_session): from kotti import DBSession from kotti.resources import get_root from kotti.resources import Node # Test some of Node's container methods: root = get_root() assert root.keys() == [] child1 = Node(name=u'child1', parent=root) DBSession.add(child1) assert root.keys() == [u'child1'] assert root[u'child1'] == child1 del root[u'child1'] assert root.keys() == [] # When we delete a parent node, all its child nodes will be # released as well: root[u'child2'] = Node() root[u'child2'][u'subchild'] = Node() assert (DBSession.query(Node).filter( Node.name == u'subchild').count() == 1) del root[u'child2'] assert (DBSession.query(Node).filter( Node.name == u'subchild').count() == 0) # We can pass a tuple as the key to more efficiently reach # down to child objects: root[u'child3'] = Node() subchild33 = Node(name=u'subchild33', parent=root[u'child3']) DBSession.add(subchild33) del root.__dict__['_children'] # force a different code path assert root[u'child3', u'subchild33'] is root[u'child3'][u'subchild33'] assert root[(u'child3', u'subchild33')] is subchild33 assert root[(u'child3', u'subchild33')] is subchild33 with raises(KeyError): root[u'child3', u'bad-name'] root.children # force a different code path with raises(KeyError): root[u'child3', u'bad-name'] del root[u'child3'] # Overwriting an existing Node is an error; first delete manually! child4 = Node(name=u'child4', parent=root) DBSession.add(child4) assert root.keys() == [u'child4'] child44 = Node(name=u'child4') DBSession.add(child44) root[u'child4'] = child44 with raises(SQLAlchemyError): DBSession.flush()
def upgrade(): from depot.manager import DepotManager from depot.fields.upload import UploadedFile from sqlalchemy import bindparam, Unicode, Column from kotti import DBSession, metadata files = sa.Table('files', metadata) files.c.data.type = sa.LargeBinary() # this restores to old column type dn = DepotManager.get_default() _saved = [] def process(thing): id, data, filename, mimetype = thing uploaded_file = UploadedFile({'depot_name': dn, 'files': []}) # noinspection PyProtectedMember uploaded_file._thaw() uploaded_file.process_content( data, filename=filename, content_type=mimetype) _saved.append({'nodeid': id, 'data': uploaded_file.encode()}) log.info(f"Saved data for node id {id}") query = DBSession.query( files.c.id, files.c.data, files.c.filename, files.c.mimetype ).order_by(files.c.id).yield_per(10) window_size = 10 window_idx = 0 log.info("Starting migration of blob data") now = time.time() while True: start, stop = window_size * window_idx, window_size * (window_idx + 1) things = query.slice(start, stop).all() if things is None: break for thing in things: process(thing) if len(things) < window_size: break window_idx += 1 log.info("Files written on disk, saving information to DB") op.drop_column('files', 'data') op.add_column('files', Column('data', Unicode(4096))) files.c.data.type = Unicode(4096) update = files.update().where(files.c.id == bindparam('nodeid')).\ values({files.c.data: bindparam('data')}) def chunks(l, n): for i in range(0, len(l), n): yield l[i:i + n] for cdata in chunks(_saved, 10): DBSession.execute(update, cdata) log.info("Blob migration completed in {} seconds".format( int(time.time() - now)))
def reset_content_owner(event): """Reset the owner of the content from the deleted owner.""" contents = DBSession.query(Content).filter( Content.owner == event.object.name).all() for content in contents: content.owner = None
def delete_orphaned_tags(event): DBSession.query(Tag).filter(~Tag.content_tags.any()).delete( synchronize_session=False)
def expire(event): DBSession.flush() DBSession.expire_all()
def sitemap(request): nodes = DBSession.query(Content).with_polymorphic(Content) request.response.content_type = "text/xml" return {'nodes': nodes}
def activities(self): row_size_per_page = 15 cur_page = 1 total_rows = DBSession.query(func.count(Activity.id)).scalar() total_page_num = int( math.ceil(float(total_rows) / float(row_size_per_page))) location = '/activities' param = 'page' if self.request.params.keys(): cur_page = int(self.request.params.values()[0]) def get_date(d): return d.strftime('%Y-%m-%d %H:%M') if d else '' def pagination_data(): end = total_page_num + 1 data = [] for x in range(1, end): data.append({ 'val': x, 'url': '%s?%s=%d' % (location, param, x) }) return data return { 'headers': [{ 'key': 'owner', 'label': _(u'Owner'), 'structure': False }, { 'key': 'start_dt', 'label': _(u'Start Date'), 'structure': False }, { 'key': 'end_dt', 'label': _(u'End Date'), 'structure': False }, { 'key': 'summary', 'label': _(u'Summary'), 'structure': True }, { 'key': 'issues', 'label': _(u'Issues'), 'structure': True }, { 'key': 'engagement', 'label': _(u'Engagement'), 'structure': False }], 'data': [{ 'url': self.request.resource_url(i), 'start_dt': get_date(i.start_dt), 'end_dt': get_date(i.end_dt), 'owner': i.owner, 'summary': i.summary, 'issues': i.issues, 'engagement': i.engagement.title } for i in DBSession.query(Activity).order_by( desc(Activity.start_dt)).slice( row_size_per_page * (cur_page - 1), row_size_per_page * (cur_page)).all()], 'pagination': pagination_data(), 'navigation': { 'cur_page': cur_page, 'total_page': total_page_num, 'prev': '%s?%s=%d' % (location, param, cur_page - 1), 'next': '%s?%s=%d' % (location, param, cur_page + 1) } }
def __setitem__(self, name, principal): name = unicode(name) if isinstance(principal, dict): principal = self.factory(**principal) DBSession.add(principal)
def _principal_by_name(cls, name): query = bakery(lambda session: session.query(cls.factory).filter( cls.factory.name == bindparam('name'))) return query(DBSession()).params(name=name).one()
def test_works_with_auth(self): from kotti import DBSession from kotti.resources import get_root from kotti.resources import Node from kotti.security import get_principals from kotti.security import list_groups_callback from kotti.security import set_groups root = get_root() child = root[u'child'] = Node() DBSession.flush() request = DummyRequest() auth = CallbackAuthenticationPolicy() auth.unauthenticated_userid = lambda *args: 'bob' auth.callback = list_groups_callback request.context = root self.assertEqual( # user doesn't exist yet auth.effective_principals(request), ['system.Everyone']) get_principals()[u'bob'] = dict(name=u'bob') self.assertEqual(auth.effective_principals(request), ['system.Everyone', 'system.Authenticated', 'bob']) # Define that bob belongs to bobsgroup on the root level: set_groups('bob', root, ['group:bobsgroup']) request.context = child self.assertEqual( set(auth.effective_principals(request)), set([ 'system.Everyone', 'system.Authenticated', 'bob', 'group:bobsgroup' ])) # define that bob belongs to franksgroup in the user db: get_principals()[u'bob'].groups = [u'group:franksgroup'] set_groups('group:franksgroup', child, ['group:anothergroup']) self.assertEqual( set(auth.effective_principals(request)), set([ 'system.Everyone', 'system.Authenticated', 'bob', 'group:bobsgroup', 'group:franksgroup', 'group:anothergroup', ])) # And lastly test that circular group defintions are not a # problem here either: get_principals()[u'group:franksgroup'] = dict( name=u'group:franksgroup', title=u"Frank's group", groups=[u'group:funnygroup', u'group:bobsgroup'], ) self.assertEqual( set(auth.effective_principals(request)), set([ 'system.Everyone', 'system.Authenticated', 'bob', 'group:bobsgroup', 'group:franksgroup', 'group:anothergroup', 'group:funnygroup', ]))
def test_container_methods(self): from kotti import DBSession from kotti.resources import get_root from kotti.resources import Node session = DBSession() # Test some of Node's container methods: root = get_root() self.assertEquals(root.keys(), []) child1 = Node(name=u'child1', parent=root) session.add(child1) self.assertEquals(root.keys(), [u'child1']) self.assertEquals(root[u'child1'], child1) del root[u'child1'] self.assertEquals(root.keys(), []) # When we delete a parent node, all its child nodes will be # released as well: root[u'child2'] = Node() root[u'child2'][u'subchild'] = Node() self.assertEquals( session.query(Node).filter(Node.name == u'subchild').count(), 1) del root[u'child2'] self.assertEquals( session.query(Node).filter(Node.name == u'subchild').count(), 0) # We can pass a tuple as the key to more efficiently reach # down to child objects: root[u'child3'] = Node() subchild33 = Node(name=u'subchild33', parent=root[u'child3']) session.add(subchild33) del root.__dict__['_children'] self.assertTrue( root[u'child3', u'subchild33'] is root[u'child3'][u'subchild33']) self.assertTrue(root[(u'child3', u'subchild33')] is subchild33) self.assertRaises(KeyError, root.__getitem__, (u'child3', u'bad-name')) del root[u'child3'] # Overwriting an existing Node is an error; first delete manually! child4 = Node(name=u'child4', parent=root) session.add(child4) self.assertEquals(root.keys(), [u'child4']) child44 = Node(name=u'child4') session.add(child44) root[u'child4'] = child44 self.assertRaises(SQLAlchemyError, session.flush)
def content_with_tags(tag_terms): return DBSession.query(Content).join(TagsToContents).join(Tag).filter( or_(*[Tag.title.like(tag_term) for tag_term in tag_terms])).all()
def __delitem__(self, key: str) -> None: node = self[key] self.children.remove(node) DBSession.delete(node)
def __delitem__(self, key): node = self[unicode(key)] self.children.remove(node) DBSession.delete(node)
def clear(self) -> None: DBSession.query(Node).filter(Node.parent == self).delete()