def test_it(self): from kotti.views.view import view_node session = DBSession() root = session.query(Node).get(1) request = testing.DummyRequest() info = view_node(root, request) self.assertEqual(info['api'].context, root)
def populate(): """ Create the root node (:class:`~kotti.resources.Document`) and the 'about' subnode in the nodes tree if there are no nodes yet. """ lrm = LocalizerRequestMixin() lrm.registry = get_current_registry() lrm.locale_name = get_settings()['pyramid.default_locale_name'] localizer = lrm.localizer if DBSession.query(Node).count() == 0: localized_root_attrs = dict( [(k, localizer.translate(v)) for k, v in _ROOT_ATTRS.iteritems()]) root = Document(**localized_root_attrs) root.__acl__ = SITE_ACL DBSession.add(root) localized_about_attrs = dict( [(k, localizer.translate(v)) for k, v in _ABOUT_ATTRS.iteritems()]) root['about'] = Document(**localized_about_attrs) wf = get_workflow(root) if wf is not None: DBSession.flush() # Initializes workflow wf.transition_to_state(root, None, u'public') populate_users()
def test_order_of_addable_parents(self): from kotti.views.edit import add_node # The 'add_node' view sorts the 'possible_parents' returned by # 'addable_types' so that the parent comes first if the # context we're looking at does not have any children yet. session = DBSession() root = session.query(Node).get(1) request = testing.DummyRequest() with nodes_addable(): # The child Document does not contain any other Nodes, so it's # second in the 'possible_parents' list returned by 'node_add': child = root['child'] = Document(title=u"Child") info = add_node(child, request) first_parent, second_parent = info['possible_parents'] self.assertEqual(first_parent['node'], root) self.assertEqual(second_parent['node'], child) # Now we add a grandchild and see that this behaviour changes: child['grandchild'] = Document(title=u"Grandchild") info = add_node(child, request) first_parent, second_parent = info['possible_parents'] self.assertEqual(first_parent['node'], child) self.assertEqual(second_parent['node'], root)
def populate(): """ Create the root node (:class:`~kotti.resources.Document`) and the 'about' subnode in the nodes tree if there are no nodes yet. """ lrm = LocalizerRequestMixin() lrm.registry = get_current_registry() # noinspection PyPropertyAccess lrm.locale_name = get_settings()["pyramid.default_locale_name"] localizer = lrm.localizer if DBSession.query(Node.id).count() == 0: localized_root_attrs = { k: localizer.translate(v) for k, v in _ROOT_ATTRS.items() } root = Document(**localized_root_attrs) root.__acl__ = SITE_ACL DBSession.add(root) localized_about_attrs = { k: localizer.translate(v) for k, v in _ABOUT_ATTRS.items() } root["about"] = Document(**localized_about_attrs) wf = get_workflow(root) if wf is not None: DBSession.flush() # Initializes workflow wf.transition_to_state(root, None, "public") populate_users()
def _add_document_from_file(filename, name, parent, title, package='kotti', directory='populate-content', acl=None): body = unicode(resource_string(package, os.path.join(directory, filename))) node = Document(name=name, parent=parent, title=title, body=body) if acl is not None: node.__acl__ = acl DBSession.add(node) return node
def test_unique_constraint(self): session = DBSession() # Try to add two children with the same name to the root node: root = session.query(Node).get(1) session.add(Node(name=u'child1', parent=root)) session.add(Node(name=u'child1', parent=root)) self.assertRaises(IntegrityError, session.flush)
def populate(): if DBSession.query(Node).count() == 0: root = Document(**_ROOT_ATTRS) root.__acl__ = SITE_ACL DBSession.add(root) root['about'] = Document(**_ABOUT_ATTRS) populate_users()
def _make(self, context=None, id=1): from kotti.views.util import TemplateAPIEdit if context is None: session = DBSession() context = session.query(Node).get(id) request = testing.DummyRequest() return TemplateAPIEdit(context, request)
def populate_users(): principals = get_principals() if u'admin' not in principals: principals[u'admin'] = { 'name': u'admin', 'password': get_settings()['kotti.secret'], 'title': u"Administrator", 'groups': [u'role:admin'], } DBSession.flush() transaction.commit()
def test_single_choice(self): from kotti.views.edit import add_node # The view should redirect straight to the add form if there's # only one choice of parent and type: session = DBSession() root = session.query(Node).get(1) request = testing.DummyRequest() response = add_node(root, request) self.assertEqual(response.status, '302 Found') self.assertEqual(response.location, 'http://example.com/add_document')
def populate(): if DBSession.query(Node).count() == 0: root = Document(**_ROOT_ATTRS) root.__acl__ = SITE_ACL DBSession.add(root) root['about'] = Document(**_ABOUT_ATTRS) wf = get_workflow(root) if wf is not None: DBSession.flush() # Initializes workflow wf.transition_to_state(root, None, u'public') populate_users()
def upgrade(): from kotti.resources import DBSession from alembic.context import get_bind conn = get_bind() if conn.engine.dialect.name == 'mysql': update = "update nodes set path = concat(path, '/') where path not \ like '%/'" else: update = "update nodes set path = path || '/' where path not like '%/'" DBSession.execute(update)
def populate_root_document(): if DBSession.query(Node).count() == 0: root = Document(name=u'', title=u'Front Page') root.__acl__ = SITE_ACL root.default_view = 'front-page' DBSession.add(root) url = JOB_CONTAINERS['url'] root[url] = Document(title=u'Job Containers', owner=u'admin') set_groups(u'admin', root[url], set([u'role:owner'])) wf = get_workflow(root) if wf is not None: DBSession.flush() # Initializes workflow wf.transition_to_state(root, None, u'public')
def test_root_acl(self): session = DBSession() root = session.query(Node).get(1) # The root object has a persistent ACL set: self.assertEquals( root.__acl__, [ ('Allow', 'group:managers', security.ALL_PERMISSIONS), ('Allow', 'system.Authenticated', ('view',)), ('Allow', 'group:editors', ('add', 'edit')), ]) # Note how the last ACE is class-defined, that is, users in # the 'managers' group will have all permissions, always. # This is to prevent lock-out. self.assertEquals(root.__acl__[:-2], root._default_acl())
def _used_snippets(self, context, slot): snippets = DBSession.query(DocumentSlotToSnippet).filter( and_(DocumentSlotToSnippet.document_id == context.id, DocumentSlotToSnippet.slot_name == slot))\ .order_by(DocumentSlotToSnippet.position).all() return [{"snippet": "snippet-%d" % snippet.snippet_id} for snippet in snippets]
def downgrade(): from kotti import DBSession from kotti.resources import Node for node in DBSession.query(Node).with_polymorphic([Node]): # remove trailing '/' from all nodes but root if node.path != u'/': node.path = node.path[:-1]
def add_translation(context, request): """XXX: Check that we dont leak anything""" source_id = request.params['id'] source = DBSession.query(Content).get(int(source_id)) translation = context[source.__name__] = source.copy() api.link_translation(source, translation) return HTTPFound(location=request.resource_url(translation, 'edit'))
def upgrade(): from kotti.resources import DBSession from alembic.context import get_bind conn = get_bind() if conn.engine.dialect.name == 'mysql': update = "UPDATE nodes " \ "SET path = concat(path, '/') " \ "WHERE path NOT LIKE '%/'" else: update = "UPDATE nodes " \ "SET path = path || '/' " \ "WHERE path NOT LIKE '%/'" DBSession.execute(update)
def downgrade(): from kotti import DBSession from kotti.resources import Node for node in DBSession.query(Node).with_polymorphic([Node]): # remove trailing '/' from all nodes but root if node.path != '/': node.path = node.path[:-1]
def _used_snippets(self, context, slot): snippets = DBSession.query(DocumentSlotToSnippet).filter( and_(DocumentSlotToSnippet.document_id == context.id, DocumentSlotToSnippet.slot_name == slot))\ .order_by(DocumentSlotToSnippet.position).all() return [{ "snippet": "snippet-%d" % snippet.snippet_id } for snippet in snippets]
def populate(): """ Create the root node (Document) and the 'about' subnode in the nodes tree if there are no nodes yet. """ if DBSession.query(Node).count() == 0: root = Document(**_ROOT_ATTRS) root.__acl__ = SITE_ACL DBSession.add(root) root['about'] = Document(**_ABOUT_ATTRS) wf = get_workflow(root) if wf is not None: DBSession.flush() # Initializes workflow wf.transition_to_state(root, None, u'public') populate_users()
def test_multiple_types(self): from kotti.views.util import addable_types # Test a scenario where we may add multiple types to a folder: session = DBSession() root = session.query(Node).get(1) request = testing.DummyRequest() with nodes_addable(): # We should be able to add both Nodes and Documents now: possible_parents, possible_types = addable_types(root, request) self.assertEqual(len(possible_parents), 1) self.assertEqual(possible_parents[0]['factories'], [Document, Node]) document_info, node_info = possible_types self.assertEqual(document_info['factory'], Document) self.assertEqual(node_info['factory'], Node) self.assertEqual(document_info['nodes'], [root]) self.assertEqual(node_info['nodes'], [root])
def populate(): """ Create the root node (:class:`~kotti.resources.Document`) and the 'about' subnode in the nodes tree if there are no nodes yet. """ if DBSession.query(Node).count() == 0: root = Document(**_ROOT_ATTRS) root.__acl__ = SITE_ACL DBSession.add(root) root['about'] = Document(**_ABOUT_ATTRS) wf = get_workflow(root) if wf is not None: DBSession.flush() # Initializes workflow wf.transition_to_state(root, None, u'public') populate_users()
def test_set_and_get_acl(self): session = DBSession() root = session.query(Node).get(1) # The __acl__ attribute of Nodes allows ACEs to be retrieved # and set: del root.__acl__ self.assertRaises(AttributeError, root._get_acl) # When setting the ACL, we can also pass 3-tuples instead of # instances of ACE: root.__acl__ = [('Allow', 'system.Authenticated', ('edit',))] self.assertEquals( root.__acl__, [ ('Allow', 'group:managers', security.ALL_PERMISSIONS), ('Allow', 'system.Authenticated', ('edit',)) ]) root.__acl__ = [ ACE('Allow', 'system.Authenticated', ('view',)), ACE('Deny', 'system.Authenticated', ('view',)), ] self.assertEquals( root.__acl__, [ ('Allow', 'group:managers', security.ALL_PERMISSIONS), ('Allow', 'system.Authenticated', ('view',)), ('Deny', 'system.Authenticated', ('view',)), ]) # We can reorder the ACL: first, second = root.aces root.__acl__ = [second, first] self.assertEquals( root.__acl__, [ ('Allow', 'group:managers', security.ALL_PERMISSIONS), ('Deny', 'system.Authenticated', ('view',)), ('Allow', 'system.Authenticated', ('view',)), ]) self.assertEquals(root.aces, [second, first]) self.assertEquals((first.position, second.position), (1, 0)) root._del_acl() self.assertRaises(AttributeError, root._del_acl)
def get_source(content): """Given a translation target, this returns the translation source or None. If ``content`` is the source, this returns ``None``. """ translation = DBSession.query(Translation).filter_by( target_id=content.id).first() if translation is not None: return translation.source
def populate(): """ Create the root node (:class:`~kotti.resources.Document`) and the 'about' subnode in the nodes tree if there are no nodes yet. """ lrm = LocalizerRequestMixin() lrm.registry = get_current_registry() lrm.locale_name = get_settings()['pyramid.default_locale_name'] localizer = lrm.localizer if DBSession.query(Node.id).count() == 0: pkgdir = os.path.dirname(__file__) pagesdir = os.path.join(pkgdir, 'static/pages') #import pdb ; pdb.set_trace() root_filename = os.path.join(pagesdir, 'index.md') root_atts = make_markdown_attrs('', root_filename, title='Welcome to XYZZY', description='Home Page') root_atts['body'] = markdown.markdown(root_atts['body']) root = Document(**root_atts) root.__acl__ = SITE_ACL DBSession.add(root) webatts = make_markdown_attrs('webdesign', os.path.join( pagesdir, 'webdesign/index.md'), title='Web Design', description='Pages on Web Design') root['webdesign'] = MarkDownDocument(**webatts) wpages = ['history', 'development', 'stylesheets', 'javascript-components'] for wp in wpages: wpfn = os.path.join(pagesdir, 'webdesign/%s.md' % wp) wptitle = ' '.join([p.capitalize() for p in wp.split('-')]) wpatts = make_markdown_attrs(wp, wpfn, title=wptitle) root['webdesign'][wp] = MarkDownDocument(**wpatts) wf = get_workflow(root) if wf is not None: DBSession.flush() # Initializes workflow wf.transition_to_state(root, None, u'public') populate_users()
def autolink_language_root(event): context = event.object lr = DBSession.query(LanguageRoot).first() if lr is None: return source = api.get_source(lr) if source is None: source = lr api.link_translation(source, context)
def add_node(context, request): """This view's responsibility is to present the user with a form where they can choose between locations to add to, and types of nodes to add, and redirect to the actual add form based on this information. """ all_types = configuration['kotti.available_types'] if request.POST: what, where = request.POST['what'], request.POST['where'] session = DBSession() what = [t for t in all_types if t.type_info.name == what][0] where = session.query(Node).get(int(where)) location = resource_url( where, request, what.type_info.add_view) return HTTPFound(location=location) possible_parents, possible_types = addable_types(context, request) if len(possible_parents) == 1 and len(possible_parents[0]['factories']) == 1: # Redirect to the add form straight away if there's only one # choice of parents and addable types: parent = possible_parents[0] add_view = parent['factories'][0].type_info.add_view location = resource_url(parent['node'], request, add_view) return HTTPFound(location=location) # Swap first and second possible parents if there's no content in # 'possible_parents[0]' yet. This makes the parent then the # default choice in the form: api = TemplateAPIEdit(context, request) if not api.list_children() and len(possible_parents) > 1: possible_parents[0], possible_parents[1] = ( possible_parents[1], possible_parents[0]) return { 'api': api, 'possible_parents': possible_parents, 'possible_types': possible_types, }
def test_multiple_parents_and_types(self): from kotti.views.util import addable_types # A scenario where we can add multiple types to multiple folders: session = DBSession() root = session.query(Node).get(1) request = testing.DummyRequest() with nodes_addable(): # We should be able to add both to the child and to the parent: child = root['child'] = Document(title=u"Child") possible_parents, possible_types = addable_types(child, request) child_parent, root_parent = possible_parents self.assertEqual(child_parent['node'], child) self.assertEqual(root_parent['node'], root) self.assertEqual(child_parent['factories'], [Document, Node]) self.assertEqual(root_parent['factories'], [Document, Node]) document_info, node_info = possible_types self.assertEqual(document_info['factory'], Document) self.assertEqual(node_info['factory'], Node) self.assertEqual(document_info['nodes'], [child, root]) self.assertEqual(node_info['nodes'], [child, root])
def save_success(self, appstruct): appstruct.pop('csrf_token', None) context = self.request.context mapper = lambda snippet: ("snippet-%d" % snippet.id, snippet) view_name = self.context.default_view or "view" slots_names = [name for name, title in get_registered_slots(view_name)] for slot in context.slots: if slot.name in slots_names: snippets = self._available_snippets(context, slot.name) snippets = dict(map(mapper, snippets)) while slot.snippets: slot.snippets.pop() for snippet in appstruct[slot.name]: snippet_id = snippet['snippet'] if snippet_id in snippets: s = snippets[snippet_id] if s not in slot.snippets: slot.snippets.append(snippets[snippet_id]) del appstruct[slot.name] for slot_name in appstruct: snippets = self._available_snippets(context, slot_name) snippets = dict(map(mapper, snippets)) slot = DocumentSlot() slot.document = context slot.name = slot_name for snippet in appstruct[slot_name]: snippet_id = snippet['snippet'] if snippet_id in snippets: s = snippets[snippet_id] if s not in slot.snippets: slot.snippets.append(snippets[snippet_id]) for slot in context.slots: if slot.name not in slots_names: context.slots.remove(slot) DBSession.delete(slot) DBSession.flush() return HTTPFound(self.request.resource_url(context))
def get_translations(content): source = get_source(content) if source is None: source = content query = DBSession.query(Translation, Content).filter( Translation.source_id == source.id, Content.id == Translation.target_id, ) res = dict((content.language, content) for translation, content in query) res.pop(content.language, None) if source is not content: res[source.language] = source return res
def populate(): if DBSession.query(Node).count() == 0: root = Document(**_ROOT_ATTRS) root.__acl__ = SITE_ACL DBSession.add(root) root['about'] = Document(**_ABOUT_ATTRS) if DBSession.query(Settings).count() == 0: settings = Settings(data={'kotti.db_version': get_version()}) DBSession.add(settings) populate_users()
def populate(): nodecount = DBSession.query(Node).count() if nodecount == 0: p = _add_document_from_file( "home.html", u"", None, u"Welcome to Kotti!", acl=SITE_ACL) _add_document_from_file( "about.html", u"about", p, u"About") settingscount = DBSession.query(Settings).count() if settingscount == 0: settings = Settings(data={'kotti.db_version': get_version()}) DBSession.add(settings) populate_users() DBSession.flush() transaction.commit()
def test_container_methods(self): session = DBSession() # Test some of Node's container methods: root = session.query(Node).get(1) 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)
def _available_snippets(self, context, slot): snippets = DBSession.query(Snippet).all() return snippets
def upgrade(): from kotti.resources import DBSession DBSession.execute( "update nodes set path = path || '/' where path not like '%/'" )