Example #1
0
 def _principal_by_name(cls, name: str) -> Principal:
     query = bakery(
         lambda session: session.query(cls.factory).filter(
             cls.factory.name == bindparam("name")
         )
     )
     return query(DBSession()).params(name=name).one()
Example #2
0
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()

    metadata.create_all(engine, tables=tables)
    for populate in get_settings()['kotti.populators']:
        populate()
    commit()

    return DBSession()
Example #3
0
def content(connection, settings):
    """sets up some default content using Kotti's testing populator."""
    import transaction
    from kotti import DBSession
    from kotti import metadata
    from kotti.resources import get_root

    if connection.in_transaction():
        transaction.abort()
    DBSession().close()

    metadata.drop_all(connection.engine)
    transaction.begin()
    metadata.create_all(connection.engine)
    # to create the default content with the correct workflow state
    # the workflow must be initialized first;  please note that these
    # settings won't persist, though;  use the `workflow` fixture if needed
    from zope.configuration import xmlconfig
    import kotti

    xmlconfig.file("workflow.zcml", kotti, execute=True)
    for populate in settings["kotti.populators"]:
        populate()

    # We set the path here since it's required for some integration
    # tests, and because the 'content' fixture does not depend on
    # 'event' and therefore the event handlers aren't fired for root
    # otherwise:
    get_root().path = "/"
    transaction.commit()
Example #4
0
    def traverse(root, vpath_tuple):
        """
        :param root: The node where traversal should start
        :type root: :class:`kotti.resources.Node`

        :param vpath_tuple: Tuple of path segments to be traversed
        :type vpath_tuple: tuple

        :return: List of nodes, from root (excluded) to context (included).
                 Each node has its parent set already, so that no subsequent
                 queries will be be performed, e.g. when calling
                 ``lineage(context)``
        :rtype: list of :class:`kotti.resources.Node`
        """

        conditions = [
            (Node.path == root.path + '/'.join(vpath_tuple[:idx + 1]) + '/')
            for idx, item in enumerate(vpath_tuple)
        ]
        nodes = DBSession().query(Node)\
            .order_by(Node.path)\
            .filter(or_(*conditions))\
            .all()
        for i, node in enumerate(nodes):
            if i == 0:
                setattr(node, 'parent', root)
            else:
                setattr(node, 'parent', nodes[i - 1])

        return nodes
Example #5
0
File: env.py Project: geojeff/Kotti
def run_migrations_online():
    if DBSession.bind is None:
        raise ValueError(
            "\nYou must run Kotti's migration using the 'kotti-migrate' script"
            "\nand not through 'alembic' directly.")

    transaction.begin()
    connection = DBSession.connection()

    context.configure(
        connection=connection,
        target_metadata=metadata,
    )

    try:
        context.run_migrations()
        mark_changed(DBSession())
    except:
        traceback.print_exc()
        transaction.abort()
    else:
        transaction.commit()
    finally:
        #connection.close()
        pass
Example #6
0
def tnc_db_session(tnc_config, tnc_connection, request):
    from transaction import abort
    trans = tnc_connection.begin()          # begin a non-orm transaction
    request.addfinalizer(trans.rollback)
    request.addfinalizer(abort)
    from kotti import DBSession
    return DBSession()
Example #7
0
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)
Example #8
0
    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,
            }
Example #9
0
 def __getitem__(self, name):
     name = unicode(name)
     session = DBSession()
     try:
         return session.query(
             self.factory).filter(self.factory.name == name).one()
     except NoResultFound:
         raise KeyError(name)
Example #10
0
 def __delitem__(self, name):
     name = unicode(name)
     session = DBSession()
     try:
         principal = session.query(
             self.factory).filter(self.factory.name == name).one()
         session.delete(principal)
     except NoResultFound:
         raise KeyError(name)
Example #11
0
 def do_stamp(rev, context, revision=revision):
     current = context._current_rev()
     if revision is None:
         revision = context.script.get_current_head()
     elif revision == 'None':
         revision = None
     context._update_current_rev(current, revision)
     mark_changed(DBSession())
     return []
Example #12
0
def db_session(config, content, connection, request):
    """ returns a db session object and sets up a db transaction
        savepoint, which will be rolled back after the test.
    """
    from transaction import abort
    trans = connection.begin()  # begin a non-orm transaction
    request.addfinalizer(trans.rollback)
    request.addfinalizer(abort)
    from kotti import DBSession
    return DBSession()
Example #13
0
    def test_view_permitted_yes(self):
        from kotti import DBSession
        from kotti.resources import Node
        from kotti.resources import Document

        self.config.testing_securitypolicy(permissive=True)
        self.config.include('kotti.views.edit')
        root = DBSession().query(Node).get(1)
        request = DummyRequest()
        self.assertEquals(Document.type_info.addable(root, request), True)
Example #14
0
    def test_get_non_existing_paste_item(self):
        from kotti import DBSession
        from kotti.resources import Node
        from kotti.views.edit import get_paste_item

        root = DBSession().query(Node).get(1)
        request = DummyRequest()
        request.session['kotti.paste'] = (1701, 'copy')
        item = get_paste_item(root, request)
        self.assertEqual(item, None)
Example #15
0
    def root_id(self):
        """ Query for the one node without a parent and return its id.
        :result: The root node's id.
        :rtype: int
        """

        query = bakery(lambda session: session.query(Node).with_polymorphic(
            Node).add_columns(Node.id).enable_eagerloads(False).filter(
                Node.parent_id == None))

        return query(DBSession()).one().id
Example #16
0
def frontpage_view(context, request):
    session = DBSession()
    query = session.query(BlogEntry).order_by(BlogEntry.date.desc())
    items = query.all()[:3]
    items = [
        item for item in items if has_permission('view', item, request)
    ]
    return {
        'api': template_api(context, request),
        'items': items,
    }
Example #17
0
    def test_unique_constraint(self):
        from kotti import DBSession
        from kotti.resources import get_root
        from kotti.resources import Node

        # 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)
Example #18
0
    def do_stamp(rev, context, revision=revision):

        if revision is None:
            revision = context.script.get_current_head()
        elif revision == "None":
            revision = None

        context.stamp(env.script_dir, revision)

        mark_changed(DBSession())
        return []
Example #19
0
    def make(self, context=None, request=None, id=1, **kwargs):
        from kotti import DBSession
        from kotti.resources import Node
        from kotti.views.util import TemplateAPI

        if context is None:
            session = DBSession()
            context = session.query(Node).get(id)
        if request is None:
            request = DummyRequest()
        return TemplateAPI(context, request, **kwargs)
Example #20
0
def db_session(config, content, connection):
    """ returns a db session object and sets up a db transaction
        savepoint, which will be rolled back after the test.
    """

    import transaction
    trans = connection.begin()  # begin a non-orm transaction
    from kotti import DBSession
    yield DBSession()
    trans.rollback()
    transaction.abort()
Example #21
0
def get_paste_item(context, request):
    info = request.session.get('kotti.paste')
    if info:
        id, action = info
        item = DBSession().query(Node).get(id)
        if not item.type_info.addable(context, request):
            return
        if action == 'cut' and inside(context, item):
            return
        if context == item:
            return
        return item
Example #22
0
    def test_persistent_settings(self):
        from kotti import get_settings
        from kotti import get_version
        from kotti import DBSession
        from kotti.resources import Settings

        session = DBSession()
        [settings] = session.query(Settings).all()
        self.assertEqual(settings.data, {'kotti.db_version': get_version()})
        self.assertEqual(get_settings()['kotti.db_version'], get_version())
        settings.data['foo.bar'] = u'baz'
        self.assertEqual(get_settings()['foo.bar'], u'baz')
Example #23
0
    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']  # force a different code path
        self.assertTrue(
            root[u'child3', u'subchild33'] is root[u'child3'][u'subchild33'])
        self.assertTrue(root[(u'child3', u'subchild33')] is subchild33)
        self.assertTrue(root[(u'child3', u'subchild33')] is subchild33)
        self.assertRaises(KeyError, root.__getitem__, (u'child3', u'bad-name'))
        root.children  # force a different code path
        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)
Example #24
0
def set_groups(name, context, groups_to_set=()):
    """Set the list of groups for principal with given ``name`` and in
    given ``context``.
    """
    name = unicode(name)
    from kotti.resources import LocalGroup
    session = DBSession()
    session.query(LocalGroup).filter(LocalGroup.node_id == context.id).filter(
        LocalGroup.principal_name == name).delete()

    for group_name in groups_to_set:
        session.add(LocalGroup(context, name, unicode(group_name)))
Example #25
0
    def test_paste_non_existing_node(self):
        from kotti import DBSession
        from kotti.resources import Node
        from kotti.views.edit import paste_node

        root = DBSession().query(Node).get(1)
        request = DummyRequest()

        for index, action in enumerate(['copy', 'cut']):
            request.session['kotti.paste'] = (1701, 'copy')
            response = paste_node(root, request)
            self.assertEqual(response.status, '302 Found')
            self.assertEqual(len(request.session['_f_error']), index + 1)
Example #26
0
def view_calendar(context, request):

    kotti_calendar_resources.need()
    locale_name = get_locale_name(request)
    if locale_name in fullcalendar_locales:
        fullcalendar_locales[locale_name].need()
    else:  # pragma: no cover (safety belt only, should never happen)
        fullcalendar_locales["en"].need()

    session = DBSession()
    now = datetime.datetime.now()
    query = session.query(Event).filter(Event.parent_id == context.id)
    future = or_(Event.start > now, Event.end > now)
    upcoming = query.filter(future).order_by(Event.start).all()
    past = query.filter(Event.start < now).order_by(desc(Event.start)).all()
    upcoming = [event for event in upcoming if
                has_permission('view', event, request)]
    past = [event for event in past if
            has_permission('view', event, request)]

    fmt = '%Y-%m-%d %H:%M:%S'
    fullcalendar_events = []
    for event in (upcoming + past):
        json_event = {
            'title': event.title,
            'url': resource_url(event, request),
            'start': event.start.strftime(fmt),
            'allDay': event.all_day,
            }
        if event.end:
            json_event['end'] = event.end.strftime(fmt)
        fullcalendar_events.append(json_event)

    fullcalendar_options = {
        'header': {
            'left': 'prev,next today',
            'center': 'title',
            'right': 'month,agendaWeek,agendaDay'
        },
        'eventSources': context.feeds,
        'weekends': context.weekends,
        'events': fullcalendar_events,
        }

    return {
        'api': template_api(context, request),
        'upcoming_events': upcoming,
        'past_events': past,
        'fullcalendar_options': json.dumps(fullcalendar_options),
        }
Example #27
0
    def test_rename_to_empty_name(self):
        from kotti import DBSession
        from kotti.resources import Node
        from kotti.resources import Document
        from kotti.views.edit import rename_node

        root = DBSession().query(Node).get(1)
        child = root['child'] = Document(title=u"Child")
        request = DummyRequest()
        request.params['rename'] = u'on'
        request.params['name'] = u''
        request.params['title'] = u'foo'
        rename_node(child, request)
        self.assertEqual(request.session.pop_flash('error'),
                         [u'Name and title are required.'])
Example #28
0
    def __getitem__(self, path: Union[str, Iterable[str]]) -> "Node":
        db_session = DBSession()
        db_session._autoflush()

        # if not hasattr(path, '__iter__'):
        if isinstance(path, str):
            path = (path, )
        path = [p for p in path]

        # Optimization: don't query children if self._children already there:
        if "_children" in self.__dict__:
            rest = path[1:]
            try:
                [child] = filter(lambda ch: ch.name == path[0], self._children)
            except ValueError:
                raise KeyError(path)
            if rest:
                return child[rest]
            else:
                return child

        baked_query = bakery(lambda session: session.query(Node))

        if len(path) == 1:
            try:
                baked_query += lambda q: q.filter(
                    Node.name == bindparam("name"),
                    Node.parent_id == bindparam("parent_id"),
                )
                return (baked_query(db_session).params(
                    name=path[0], parent_id=self.id).one())
            except NoResultFound:
                raise KeyError(path)

        # We have a path with more than one element, so let's be a
        # little clever about fetching the requested node:
        nodes = Node.__table__
        conditions = [nodes.c.id == self.id]
        alias = nodes
        for name in path:
            alias, old_alias = nodes.alias(), alias
            conditions.append(alias.c.parent_id == old_alias.c.id)
            conditions.append(alias.c.name == name)
        expr = select([alias.c.id], and_(*conditions))
        row = db_session.execute(expr).fetchone()
        if row is None:
            raise KeyError(path)
        return baked_query(db_session).get(row.id)
Example #29
0
def principals_with_local_roles(context, inherit=True):
    """Return a list of principal names that have local roles in the
    context.
    """
    from resources import LocalGroup
    session = DBSession()
    principals = set()
    items = [context]
    if inherit:
        items = lineage(context)
    for item in items:
        principals.update(
            r[0] for r in session.query(LocalGroup.principal_name).filter(
                LocalGroup.node_id == item.id).group_by(
                    LocalGroup.principal_name).all()
            if not r[0].startswith('role:'))
    return list(principals)
Example #30
0
    def search(self, **kwargs):
        if not kwargs:
            return []

        filters = []
        for key, value in kwargs.items():
            col = getattr(self.factory, key)
            if '*' in value:
                value = value.replace('*', '%').lower()
                filters.append(func.lower(col).like(value))
            else:
                filters.append(col == value)

        session = DBSession()
        query = session.query(self.factory)
        query = query.filter(or_(*filters))
        return query