def involvement_update(id_, origin_id):
    link_ = LinkMapper.get_by_id(id_)
    event = EntityMapper.get_by_id(link_.domain.id)
    actor = EntityMapper.get_by_id(link_.range.id)
    origin = event if origin_id == event.id else actor
    form = build_form(ActorForm, 'Involvement', link_, request)
    form.save.label.text = _('save')
    del form.actor, form.event, form.insert_and_continue
    form.activity.choices = [('P11', g.properties['P11'].name)]
    if event.class_.code in ['E7', 'E8', 'E12']:
        form.activity.choices.append(('P14', g.properties['P14'].name))
    if event.class_.code == 'E8':
        form.activity.choices.append(('P22', g.properties['P22'].name))
        form.activity.choices.append(('P23', g.properties['P23'].name))
    if form.validate_on_submit():
        g.cursor.execute('BEGIN')
        try:
            link_.delete()
            link_id = event.link(form.activity.data, actor, form.description.data)
            DateMapper.save_link_dates(link_id, form)
            NodeMapper.save_link_nodes(link_id, form)
            g.cursor.execute('COMMIT')
        except Exception as e:  # pragma: no cover
            g.cursor.execute('ROLLBACK')
            logger.log('error', 'database', 'transaction failed', e)
            flash(_('error transaction'), 'error')
        tab = 'actor' if origin.view_name == 'event' else 'event'
        return redirect(url_for(origin.view_name + '_view', id_=origin.id) + '#tab-' + tab)
    form.activity.data = link_.property.code
    form.description.data = link_.description
    link_.set_dates()
    form.populate_dates(link_)
    return render_template('involvement/update.html', origin=origin, form=form,
                           linked_object=event if origin_id != event.id else actor)
def relation_update(id_, origin_id):
    link_ = LinkMapper.get_by_id(id_)
    domain = EntityMapper.get_by_id(link_.domain.id)
    range_ = EntityMapper.get_by_id(link_.range.id)
    origin = range_ if origin_id == range_.id else domain
    related = range_ if origin_id == domain.id else domain
    form = build_form(RelationForm, 'Actor Actor Relation', link_, request)
    del form.actor, form.insert_and_continue, form.origin_id
    if form.validate_on_submit():
        g.cursor.execute('BEGIN')
        try:
            link_.delete()
            if form.inverse.data:
                link_id = related.link('OA7', origin, form.description.data)
            else:
                link_id = origin.link('OA7', related, form.description.data)
            DateMapper.save_link_dates(link_id, form)
            NodeMapper.save_link_nodes(link_id, form)
            g.cursor.execute('COMMIT')
            flash(_('info update'), 'info')
        except Exception as e:  # pragma: no cover
            g.cursor.execute('ROLLBACK')
            logger.log('error', 'database', 'transaction failed', e)
            flash(_('error transaction'), 'error')
        return redirect(url_for('actor_view', id_=origin.id) + '#tab-relation')
    if origin.id == range_.id:
        form.inverse.data = True
    form.save.label.text = _('save')
    link_.set_dates()
    form.populate_dates(link_)
    return render_template('relation/update.html', origin=origin, form=form, related=related)
Example #3
0
def hierarchy_update(id_: int) -> str:
    root = g.nodes[id_]
    if root.system:
        abort(403)
    form = build_form(HierarchyForm, 'hierarchy', root)  # type: HierarchyForm
    form.forms.choices = NodeMapper.get_form_choices(root)
    if root.value_type:
        del form.multiple
    elif root.multiple:
        form.multiple.render_kw = {'disabled': 'disabled'}
    if form.validate_on_submit():
        if form.name.data != root.name and NodeMapper.get_nodes(form.name.data):
            flash(_('error name exists'), 'error')
            return redirect(url_for('node_index') + '#tab-' + str(root.id))
        save(form, root)
        flash(_('info update'), 'info')
        return redirect(url_for('node_index') + '#tab-' + str(root.id))
    form.multiple = root.multiple
    table = Table(['form', 'count'], paging=False)
    for form_id, form_ in root.forms.items():
        url = url_for('hierarchy_remove_form', id_=root.id, remove_id=form_id)
        link = '<a href="' + url + '">' + uc_first(_('remove')) + '</a>'
        count = NodeMapper.get_form_count(root, form_id)
        table.rows.append([form_['name'], format_number(count) if count else link])
    return render_template('hierarchy/update.html', node=root, form=form, table=table,
                           forms=[form.id for form in form.forms])
Example #4
0
def relation_insert(origin_id):
    origin = EntityMapper.get_by_id(origin_id)
    form = build_form(RelationForm, 'Actor Actor Relation')
    form.origin_id.data = origin.id
    if form.validate_on_submit():
        g.cursor.execute('BEGIN')
        try:
            for actor_id in ast.literal_eval(form.actor.data):
                if form.inverse.data:
                    link_id = LinkMapper.insert(actor_id, 'OA7', origin.id,
                                                form.description.data)
                else:
                    link_id = origin.link('OA7', actor_id,
                                          form.description.data)
                DateMapper.save_link_dates(link_id, form)
                NodeMapper.save_link_nodes(link_id, form)
            g.cursor.execute('COMMIT')
            flash(_('entity created'), 'info')
        except Exception as e:  # pragma: no cover
            g.cursor.execute('ROLLBACK')
            logger.log('error', 'database', 'transaction failed', e)
            flash(_('error transaction'), 'error')
        if form.continue_.data == 'yes':
            return redirect(url_for('relation_insert', origin_id=origin_id))
        return redirect(url_for('actor_view', id_=origin.id) + '#tab-relation')
    return render_template('relation/insert.html', origin=origin, form=form)
Example #5
0
def member_update(id_, origin_id):
    link_ = LinkMapper.get_by_id(id_)
    domain = EntityMapper.get_by_id(link_.domain.id)
    range_ = EntityMapper.get_by_id(link_.range.id)
    origin = range_ if origin_id == range_.id else domain
    related = range_ if origin_id == domain.id else domain
    form = build_form(MemberForm, 'Member', link_, request)
    del form.actor, form.group, form.insert_and_continue
    if form.validate_on_submit():
        g.cursor.execute('BEGIN')
        try:
            link_.delete()
            link_id = domain.link('P107', range_, form.description.data)
            DateMapper.save_link_dates(link_id, form)
            NodeMapper.save_link_nodes(link_id, form)
            g.cursor.execute('COMMIT')
        except Exception as e:  # pragma: no cover
            g.cursor.execute('ROLLBACK')
            logger.log('error', 'database', 'transaction failed', e)
            flash(_('error transaction'), 'error')
        tab = '#tab-member-of' if origin.id == range_.id else '#tab-member'
        return redirect(url_for('actor_view', id_=origin.id) + tab)
    form.save.label.text = _('save')
    link_.set_dates()
    form.populate_dates(link_)
    return render_template('member/update.html',
                           origin=origin,
                           form=form,
                           related=related)
Example #6
0
def relation_update(id_, origin_id):
    link_ = LinkMapper.get_by_id(id_)
    domain = EntityMapper.get_by_id(link_.domain.id)
    range_ = EntityMapper.get_by_id(link_.range.id)
    origin = range_ if origin_id == range_.id else domain
    related = range_ if origin_id == domain.id else domain
    form = build_form(RelationForm, 'Actor Actor Relation', link_, request)
    del form.actor, form.insert_and_continue, form.origin_id
    if form.validate_on_submit():
        g.cursor.execute('BEGIN')
        try:
            link_.delete()
            if form.inverse.data:
                link_id = related.link('OA7', origin, form.description.data)
            else:
                link_id = origin.link('OA7', related, form.description.data)
            DateMapper.save_link_dates(link_id, form)
            NodeMapper.save_link_nodes(link_id, form)
            g.cursor.execute('COMMIT')
            flash(_('info update'), 'info')
        except Exception as e:  # pragma: no cover
            g.cursor.execute('ROLLBACK')
            logger.log('error', 'database', 'transaction failed', e)
            flash(_('error transaction'), 'error')
        return redirect(url_for('actor_view', id_=origin.id) + '#tab-relation')
    if origin.id == range_.id:
        form.inverse.data = True
    form.save.label.text = _('save')
    link_.set_dates()
    form.populate_dates(link_)
    return render_template('relation/update.html',
                           origin=origin,
                           form=form,
                           related=related)
def member_update(id_, origin_id):
    link_ = LinkMapper.get_by_id(id_)
    domain = EntityMapper.get_by_id(link_.domain.id)
    range_ = EntityMapper.get_by_id(link_.range.id)
    origin = range_ if origin_id == range_.id else domain
    form = build_form(MemberForm, 'Member', link_, request)
    del form.actor, form.group, form.insert_and_continue
    if form.validate_on_submit():
        g.cursor.execute('BEGIN')
        try:
            link_.delete()
            link_id = domain.link('P107', range_, form.description.data)
            DateMapper.save_link_dates(link_id, form)
            NodeMapper.save_link_nodes(link_id, form)
            g.cursor.execute('COMMIT')
        except Exception as e:  # pragma: no cover
            g.cursor.execute('ROLLBACK')
            logger.log('error', 'database', 'transaction failed', e)
            flash(_('error transaction'), 'error')
        tab = '#tab-member-of' if origin.id == range_.id else '#tab-member'
        return redirect(url_for('actor_view', id_=origin.id) + tab)
    form.save.label.text = _('save')
    link_.set_dates()
    form.populate_dates(link_)
    related = range_ if origin_id == domain.id else domain
    return render_template('member/update.html', origin=origin, form=form, related=related)
def hierarchy_update(id_):
    root = g.nodes[id_]
    if root.system:
        abort(403)
    form = build_form(HierarchyForm, 'hierarchy', root)
    form.forms.choices = NodeMapper.get_form_choices(root)
    if root.value_type:
        del form.multiple
    elif root.multiple:
        form.multiple.render_kw = {'disabled': 'disabled'}
    if form.validate_on_submit():
        if form.name.data != root.name and NodeMapper.get_nodes(form.name.data):
            flash(_('error name exists'), 'error')
            return redirect(url_for('node_index') + '#tab-' + str(root.id))
        save(form, root)
        flash(_('info update'), 'info')
        return redirect(url_for('node_index') + '#tab-' + str(root.id))
    form.multiple = root.multiple
    table = {'id': 'used_forms', 'show_pager': False, 'data': [], 'sort': 'sortList: [[0, 0]]',
             'header': ['form', 'count']}
    for form_id, form_ in root.forms.items():
        url = url_for('hierarchy_remove_form', id_=root.id, remove_id=form_id)
        link = '<a href="' + url + '">' + uc_first(_('remove')) + '</a>'
        count = NodeMapper.get_form_count(root, form_id)
        table['data'].append([form_['name'], format_number(count) if count else link])
    return render_template('hierarchy/update.html', node=root, form=form, table=table,
                           forms=[form.id for form in form.forms])
    def test_node(self):
        with app.app_context():
            self.login()
            with app.test_request_context():
                app.preprocess_request()
                actor_node = NodeMapper.get_hierarchy_by_name('Actor Actor Relation')
                sex_node = NodeMapper.get_hierarchy_by_name('Sex')
            rv = self.app.get(url_for('node_index'))
            assert b'Actor Actor Relation' in rv.data
            rv = self.app.get(url_for('node_insert', root_id=actor_node.id, super_id=actor_node.id))
            assert b'Actor Actor Relation' in rv.data
            rv = self.app.post(
                url_for('node_insert', root_id=actor_node.id), data={'name_search': 'new'})
            assert b'Inverse' in rv.data
            data = {
                'name': 'My secret node',
                'name_inverse': 'Do I look inverse?',
                'description': 'Very important!'}
            rv = self.app.post(url_for('node_insert', root_id=actor_node.id), data=data)
            node_id = rv.location.split('/')[-1].replace('node#tab-', '')
            rv = self.app.get(url_for('node_update', id_=node_id))
            assert b'My secret node' in rv.data and b'Super' in rv.data
            self.app.post(url_for('node_insert', root_id=sex_node.id), data=data)
            rv = self.app.post(
                url_for('node_update', id_=node_id), data=data, follow_redirects=True)
            assert b'Changes have been saved.' in rv.data

            # Test insert an continue
            data['continue_'] = 'yes'
            rv = self.app.post(
                url_for('node_insert', root_id=actor_node.id), data=data, follow_redirects=True)
            assert b'An entry has been created' in rv.data
            data['continue_'] = ''

            # Test forbidden system node
            rv = self.app.post(
                url_for('node_update', id_=actor_node.id), data=data, follow_redirects=True)
            assert b'Forbidden' in rv.data

            # Test update with self as root
            data[str(actor_node.id)] = node_id
            rv = self.app.post(
                url_for('node_update', id_=node_id), data=data, follow_redirects=True)
            assert b'Type can&#39;t have itself as super.' in rv.data

            # Test update with a child as root
            rv = self.app.post(url_for('node_insert', root_id=actor_node.id), data=data)
            child_node_id = rv.location.split('/')[-1].replace('node#tab-', '')
            data[str(actor_node.id)] = child_node_id
            rv = self.app.post(
                url_for('node_update', id_=node_id), data=data, follow_redirects=True)
            assert b'Type can&#39;t have a sub as super.' in rv.data

            # Test delete system node
            rv = self.app.get(url_for('node_delete', id_=actor_node.id), follow_redirects=True)
            assert b'Forbidden' in rv.data
            rv = self.app.get(url_for('node_delete', id_=child_node_id), follow_redirects=True)
            assert b'The entry has been deleted.' in rv.data
Example #10
0
def hierarchy_remove_form(id_: int, remove_id: int) -> str:
    root = g.nodes[id_]
    if NodeMapper.get_form_count(root, remove_id):
        abort(403)  # pragma: no cover
    try:
        NodeMapper.remove_form_from_hierarchy(root, remove_id)
        flash(_('info update'), 'info')
    except Exception as e:  # pragma: no cover
        logger.log('error', 'database', 'remove form from hierarchy failed', e)
        flash(_('error database'), 'error')
    return redirect(url_for('hierarchy_update', id_=id_))
def hierarchy_remove_form(id_, remove_id):
    root = g.nodes[id_]
    if NodeMapper.get_form_count(root, remove_id):
        abort(403)  # pragma: no cover
    try:
        NodeMapper.remove_form_from_hierarchy(root, remove_id)
        flash(_('info update'), 'info')
    except Exception as e:  # pragma: no cover
        logger.log('error', 'database', 'remove form from hierarchy failed', e)
        flash(_('error database'), 'error')
    return redirect(url_for('hierarchy_update', id_=id_))
def hierarchy_insert(param):
    form = build_form(HierarchyForm, 'hierarchy')
    form.forms.choices = NodeMapper.get_form_choices()
    if param == 'value':
        del form.multiple
    if form.validate_on_submit():
        if NodeMapper.get_nodes(form.name.data):
            flash(_('error name exists'), 'error')
            return render_template('hierarchy/insert.html', form=form)
        node = save(form, value_type=True if param == 'value' else False)
        flash(_('entity created'), 'info')
        return redirect(url_for('node_index') + '#tab-' + str(node.id))
    return render_template('hierarchy/insert.html', form=form, param=param)
Example #13
0
def hierarchy_insert(param: str) -> str:
    form = build_form(HierarchyForm, 'hierarchy')  # type: HierarchyForm
    form.forms.choices = NodeMapper.get_form_choices()
    if param == 'value':
        del form.multiple
    if form.validate_on_submit():
        if NodeMapper.get_nodes(form.name.data):
            flash(_('error name exists'), 'error')
            return render_template('hierarchy/insert.html', form=form)
        node = save(form, value_type=True if param == 'value' else False)
        flash(_('entity created'), 'info')
        return redirect(url_for('node_index') + '#tab-' + str(node.id))
    return render_template('hierarchy/insert.html', form=form, param=param)
Example #14
0
 def __call__(self, field, **kwargs):
     from openatlas.models.node import NodeMapper
     selection = ''
     selected_ids = []
     if field.data:
         field.data = field.data[0] if isinstance(field.data, list) else field.data
         selection = g.nodes[int(field.data)].name
         selected_ids.append(g.nodes[int(field.data)].id)
     try:
         hierarchy_id = int(field.id)
     except ValueError:
         hierarchy_id = NodeMapper.get_hierarchy_by_name(uc_first(field.id)).id
     root = g.nodes[hierarchy_id]
     html = """
         <input id="{name}-button" name="{name}-button" type="text"
             class="table-select {required}" onfocus="this.blur()"
             readonly="readonly" value="{selection}" placeholder="{change_label}" />
         <a id="{name}-clear" {clear_style} class="button"
             onclick="clearSelect('{name}');">{clear_label}</a>
         <div id="{name}-overlay" class="overlay">
             <div id="{name}-dialog" class="overlay-container">
                 <input class="tree-filter" id="{name}-tree-search" placeholder="Filter" />
                 <div id="{name}-tree"></div>
             </div>
         </div>
         <script>
             $(document).ready(function () {{
                 createOverlay("{name}","{title}",false,);
                 $("#{name}-tree").jstree({{
                     "core" : {{"check_callback" : true, 'data':[{tree_data}]}},
                     "search": {{"case_insensitive": true, "show_only_matches": true}},
                     "plugins" : ["search"],
                 }});
                 $("#{name}-tree").on("select_node.jstree", function (e, data) {{
                     selectFromTree("{name}", data.node.id, data.node.text);
                 }});
                 $("#{name}-tree-search").keyup(function() {{
                     $("#{name}-tree").jstree("search", $(this).val());
                 }});
             }});
         </script>""".format(
         name=field.id,
         title=root.name,
         change_label=uc_first(_('change')),
         clear_label=uc_first(_('clear')),
         selection=selection,
         tree_data=NodeMapper.get_tree_data(hierarchy_id, selected_ids),
         clear_style='' if selection else ' style="display: none;" ',
         required=' required' if field.flags.required else '')
     return super(TreeSelect, self).__call__(field, **kwargs) + html
def node_move_entities(id_):
    node = g.nodes[id_]
    root = g.nodes[node.root[-1]]
    if root.value_type:  # pragma: no cover
        abort(403)
    form = build_move_form(MoveForm, node)
    if form.validate_on_submit():
        g.cursor.execute('BEGIN')
        NodeMapper.move_entities(node, getattr(form, str(root.id)).data, form.selection.data)
        g.cursor.execute('COMMIT')
        flash('Entities where updated', 'success')
        return redirect(url_for('node_index') + '#tab-' + str(root.id))
    getattr(form, str(root.id)).data = node.id
    return render_template('types/move.html', node=node, root=root, form=form)
Example #16
0
    def test_hierarchy(self):
        with app.app_context():
            self.login()
            rv = self.app.get(url_for('hierarchy_insert', param='custom'))
            assert b'+ Custom' in rv.data
            data = {'name': 'Geronimo', 'multiple': True, 'description': 'Very important!'}
            rv = self.app.post(url_for('hierarchy_insert', param='custom'), data=data)
            hierarchy_id = rv.location.split('/')[-1].replace('types#tab-', '')
            rv = self.app.get(url_for('hierarchy_update', id_=hierarchy_id))
            assert b'Geronimo' in rv.data
            rv = self.app.post(
                url_for('hierarchy_update', id_=hierarchy_id), data=data, follow_redirects=True)
            assert b'Changes have been saved.' in rv.data
            data['name'] = 'Actor Actor Relation'
            rv = self.app.post(
                url_for('hierarchy_update', id_=hierarchy_id), data=data, follow_redirects=True)
            assert b'The name is already in use' in rv.data
            rv = self.app.post(url_for('hierarchy_delete', id_=hierarchy_id), follow_redirects=True)
            assert b'deleted' in rv.data

            # Test checks
            actor_node = NodeMapper.get_hierarchy_by_name('Actor Actor Relation')
            rv = self.app.get(url_for('hierarchy_update', id_=actor_node.id), follow_redirects=True)
            assert b'Forbidden' in rv.data
            rv = self.app.get(url_for('hierarchy_delete', id_=actor_node.id), follow_redirects=True)
            assert b'Forbidden' in rv.data
            rv = self.app.post(url_for('hierarchy_insert', param='custom'), data=data)
            assert b'The name is already in use' in rv.data
Example #17
0
def before_request():
    debug_model['div sql'] = 0
    from openatlas.models.classObject import ClassMapper
    from openatlas.models.node import NodeMapper
    from openatlas.models.property import PropertyMapper
    from openatlas.models.settings import SettingsMapper
    if request.path.startswith('/static'):  # pragma: no cover
        return  # Only needed if not running with apache and static alias
    debug_model['current'] = time.time()
    g.db = connect()
    g.cursor = g.db.cursor(cursor_factory=psycopg2.extras.NamedTupleCursor)
    g.classes = ClassMapper.get_all()
    g.properties = PropertyMapper.get_all()
    g.nodes = NodeMapper.get_all_nodes()
    session['settings'] = SettingsMapper.get_settings()
    session['language'] = get_locale()
    # Set max file upload in MB
    app.config['MAX_CONTENT_LENGTH'] = session['settings']['file_upload_max_size'] * 1024 * 1024
    debug_model['by codes'] = 0
    debug_model['by id'] = 0
    debug_model['link sql'] = 0
    debug_model['user'] = 0
    debug_model['model'] = time.time() - debug_model['current']
    debug_model['current'] = time.time()

    # Workaround overlay maps for Thanados until #978 is implemented
    session['settings']['overlay_hack'] = False
    if session['settings']['site_name'] == 'Thanados':
        session['settings']['overlay_hack'] = True  # pragma: no cover
Example #18
0
 def check_single_type_duplicates() -> list:
     # Find entities with multiple types attached which should be single
     from openatlas.models.node import NodeMapper
     from openatlas.models.entity import EntityMapper
     data = []
     for id_, node in g.nodes.items():
         if not node.root and not node.multiple and not node.value_type:
             node_ids = NodeMapper.get_all_sub_ids(node)
             if node_ids:
                 sql = """
                     SELECT domain_id FROM model.link
                     WHERE property_code = 'P2' AND range_id IN %(node_ids)s
                     GROUP BY domain_id HAVING COUNT(*) > 1;"""
                 g.cursor.execute(sql, {'node_ids': tuple(node_ids)})
                 debug_model['link sql'] += 1
                 for row in g.cursor.fetchall():
                     offending_nodes = []
                     entity = EntityMapper.get_by_id(row.domain_id, nodes=True)
                     for entity_node in entity.nodes:
                         if g.nodes[entity_node.root[-1]].id == node.id:
                             url = url_for('admin_delete_single_type_duplicate',
                                           entity_id=entity.id, node_id=entity_node.id)
                             offending_nodes.append(
                                 '<a href="' + url + '">' + uc_first(_('remove')) + '</a> ' +
                                 entity_node.name)
                     data.append([link(entity), entity.class_.name,
                                  link(g.nodes[id_]), '<br />'.join(offending_nodes)])
     return data
Example #19
0
 def check_single_type_duplicates() -> list:
     # Find entities with multiple types attached which should be single
     from openatlas.models.node import NodeMapper
     from openatlas.models.entity import EntityMapper
     data = []
     for id_, node in g.nodes.items():
         if not node.root and not node.multiple and not node.value_type:
             node_ids = NodeMapper.get_all_sub_ids(node)
             if node_ids:
                 sql = """
                     SELECT domain_id FROM model.link
                     WHERE property_code = 'P2' AND range_id IN %(node_ids)s
                     GROUP BY domain_id HAVING COUNT(*) > 1;"""
                 g.execute(sql, {'node_ids': tuple(node_ids)})
                 for row in g.cursor.fetchall():
                     offending_nodes = []
                     entity = EntityMapper.get_by_id(row.domain_id,
                                                     nodes=True)
                     for entity_node in entity.nodes:
                         if g.nodes[entity_node.root[-1]].id == node.id:
                             url = url_for(
                                 'admin_delete_single_type_duplicate',
                                 entity_id=entity.id,
                                 node_id=entity_node.id)
                             offending_nodes.append('<a href="' + url +
                                                    '">' +
                                                    uc_first(_('remove')) +
                                                    '</a> ' +
                                                    entity_node.name)
                     data.append([
                         link(entity), entity.class_.name,
                         link(g.nodes[id_]), '<br />'.join(offending_nodes)
                     ])
     return data
Example #20
0
def before_request():
    from openatlas.models.classObject import ClassMapper
    from openatlas.models.node import NodeMapper
    from openatlas.models.property import PropertyMapper
    from openatlas.models.settings import SettingsMapper
    if request.path.startswith('/static'):  # pragma: no cover
        return  # only needed if not running with apache and static alias
    debug_model['current'] = time.time()
    g.db = connect()
    g.cursor = g.db.cursor(cursor_factory=psycopg2.extras.NamedTupleCursor)
    g.classes = ClassMapper.get_all()
    g.properties = PropertyMapper.get_all()
    g.nodes = NodeMapper.get_all_nodes()
    session['settings'] = SettingsMapper.get_settings()
    session['language'] = get_locale()
    # Set max file upload in MB
    app.config['MAX_CONTENT_LENGTH'] = session['settings'][
        'file_upload_max_size'] * 1024 * 1024
    debug_model['by codes'] = 0
    debug_model['by id'] = 0
    debug_model['by ids'] = 0
    debug_model['linked'] = 0
    debug_model['user'] = 0
    debug_model['div sql'] = 0
    debug_model['model'] = time.time() - debug_model['current']
    debug_model['current'] = time.time()
Example #21
0
def node_move_entities(id_: int) -> str:
    node = g.nodes[id_]
    root = g.nodes[node.root[-1]]
    if root.value_type:  # pragma: no cover
        abort(403)
    form = build_move_form(MoveForm, node)
    if form.validate_on_submit():
        g.cursor.execute('BEGIN')
        NodeMapper.move_entities(node,
                                 getattr(form, str(root.id)).data,
                                 form.checkbox_values.data)
        g.cursor.execute('COMMIT')
        flash('Entities where updated', 'success')
        return redirect(url_for('node_index') + '#tab-' + str(root.id))
    form.save.label.text = uc_first(_('move'))
    getattr(form, str(root.id)).data = node.id
    return render_template('types/move.html', node=node, root=root, form=form)
Example #22
0
def build_form(form,
               form_name,
               entity=None,
               request_origin=None,
               entity2=None):
    """ The entity parameter can also be a link."""
    # Add custom fields
    custom_list = []

    def add_value_type_fields(subs) -> None:
        for sub_id in subs:
            sub = g.nodes[sub_id]
            setattr(form, str(sub.id), ValueFloatField(sub.name, [Optional()]))
            add_value_type_fields(sub.subs)

    for id_, node in NodeMapper.get_nodes_for_form(form_name).items():
        custom_list.append(id_)
        setattr(
            form, str(id_),
            TreeMultiField(str(id_)) if node.multiple else TreeField(str(id_)))
        if node.value_type:
            add_value_type_fields(node.subs)

    form_instance = form(obj=entity)

    # Delete custom fields except the ones specified for the form
    delete_list = [
    ]  # Can't delete fields in the loop so creating a list for later deletion
    for field in form_instance:
        if type(field) in (TreeField, TreeMultiField) and int(
                field.id) not in custom_list:
            delete_list.append(field.id)
    for item in delete_list:
        delattr(form_instance, item)

    # Set field data if available and only if it's a GET request
    if entity and request_origin and request_origin.method == 'GET':
        # Important to use isinstance instead type check, because can be a sub type (e.g. ActorForm)
        if isinstance(form_instance, DateForm):
            form_instance.populate_dates(entity)
        nodes = entity.nodes
        if entity2:
            nodes.update(entity2.nodes)
        if hasattr(form, 'opened'):
            form_instance.opened.data = time.time()
        node_data = {}  # type: dict
        for node, node_value in nodes.items():
            root = g.nodes[node.root[-1]] if node.root else node
            if root.id not in node_data:
                node_data[root.id] = []
            node_data[root.id].append(node.id)
            if root.value_type:
                getattr(form_instance, str(node.id)).data = node_value
        for root_id, nodes in node_data.items():
            if hasattr(form_instance, str(root_id)):
                getattr(form_instance, str(root_id)).data = nodes
    return form_instance
def save(form, node=None, value_type=False):
    g.cursor.execute('BEGIN')
    try:
        if not node:
            node = NodeMapper.insert('E55', sanitize(form.name.data, 'node'))
            NodeMapper.insert_hierarchy(node, form, value_type)
        else:
            node = g.nodes[node.id]
            NodeMapper.update_hierarchy(node, form)
        node.name = sanitize(form.name.data, 'node')
        node.description = form.description.data
        node.update()
        g.cursor.execute('COMMIT')
    except Exception as e:  # pragma: no cover
        g.cursor.execute('ROLLBACK')
        logger.log('error', 'database', 'transaction failed', e)
        flash(_('error transaction'), 'error')
    return node
Example #24
0
def save(form, node=None, value_type: Optional[bool] = False):
    g.cursor.execute('BEGIN')
    try:
        if not node:
            node = NodeMapper.insert('E55', sanitize(form.name.data, 'node'))
            NodeMapper.insert_hierarchy(node, form, value_type)
        else:
            node = g.nodes[node.id]
            NodeMapper.update_hierarchy(node, form)
        node.name = sanitize(form.name.data, 'node')
        node.description = form.description.data
        node.update()
        g.cursor.execute('COMMIT')
    except Exception as e:  # pragma: no cover
        g.cursor.execute('ROLLBACK')
        logger.log('error', 'database', 'transaction failed', e)
        flash(_('error transaction'), 'error')
    return node
def build_form(form: Any,
               form_name: str,
               selected_object: Union[Entity, Link, None] = None,
               request_origin: Optional_Type[Request] = None,
               entity2: Optional_Type[Entity] = None) -> Any:
    def add_value_type_fields(subs: List[int]) -> None:
        for sub_id in subs:
            sub = g.nodes[sub_id]
            setattr(form, str(sub.id), ValueFloatField(sub.name, [Optional()]))
            add_value_type_fields(sub.subs)

    # Add custom fields
    custom_list = []
    for id_, node in NodeMapper.get_nodes_for_form(form_name).items():
        custom_list.append(id_)
        setattr(
            form, str(id_),
            TreeMultiField(str(id_)) if node.multiple else TreeField(str(id_)))
        if node.value_type:
            add_value_type_fields(node.subs)
    form_instance = form(obj=selected_object)

    # Delete custom fields except the ones specified for the form
    delete_list = [
    ]  # Can't delete fields in the loop so creating a list for later deletion
    for field in form_instance:
        if type(field) in (TreeField, TreeMultiField) and int(
                field.id) not in custom_list:
            delete_list.append(field.id)
    for item in delete_list:
        delattr(form_instance, item)

    # Set field data if available and only if it's a GET request
    if selected_object and request_origin and request_origin.method == 'GET':
        from openatlas.forms.date import DateForm
        # Important to use isinstance instead type check, because can be a sub type (e.g. ActorForm)
        if isinstance(form_instance, DateForm):
            form_instance.populate_dates(selected_object)
        nodes = selected_object.nodes
        if isinstance(entity2, Entity):
            nodes.update(entity2.nodes)  # type: ignore
        if hasattr(form, 'opened'):
            form_instance.opened.data = time.time()
        node_data: Dict[int, List[int]] = {}
        for node, node_value in nodes.items():  # type: ignore
            root = g.nodes[node.root[-1]] if node.root else node
            if root.id not in node_data:
                node_data[root.id] = []
            node_data[root.id].append(node.id)
            if root.value_type:
                getattr(form_instance, str(node.id)).data = node_value
        for root_id, nodes_ in node_data.items():
            if hasattr(form_instance, str(root_id)):
                getattr(form_instance, str(root_id)).data = nodes_
    return form_instance
Example #26
0
def involvement_insert(origin_id):
    origin = EntityMapper.get_by_id(origin_id)
    view_name = get_view_name(origin)
    form = build_form(ActorForm, 'Involvement')
    if view_name == 'event':
        del form.event
    else:
        del form.actor
    form.activity.choices = [('P11', g.properties['P11'].name_inverse)]
    if origin.class_.code in ['E7', 'E8', 'E12']:
        form.activity.choices.append(('P14', g.properties['P14'].name_inverse))
    if origin.class_.code == 'E8':
        form.activity.choices.append(('P22', g.properties['P22'].name_inverse))
        form.activity.choices.append(('P23', g.properties['P23'].name_inverse))
    if form.validate_on_submit():
        g.cursor.execute('BEGIN')
        try:
            if view_name == 'event':
                for actor_id in ast.literal_eval(form.actor.data):
                    link_id = origin.link(form.activity.data, actor_id,
                                          form.description.data)
                    DateMapper.save_link_dates(link_id, form)
                    NodeMapper.save_link_nodes(link_id, form)
            else:
                for event_id in ast.literal_eval(form.event.data):
                    link_id = LinkMapper.insert(event_id, form.activity.data,
                                                origin.id,
                                                form.description.data)
                    DateMapper.save_link_dates(link_id, form)
                    NodeMapper.save_link_nodes(link_id, form)
            g.cursor.execute('COMMIT')
            flash(_('entity created'), 'info')
        except Exception as e:  # pragma: no cover
            g.cursor.execute('ROLLBACK')
            logger.log('error', 'database', 'transaction failed', e)
            flash(_('error transaction'), 'error')
        if form.continue_.data == 'yes':
            return redirect(url_for('involvement_insert', origin_id=origin_id))
        tab = 'actor' if view_name == 'event' else 'event'
        return redirect(
            url_for(view_name + '_view', id_=origin.id) + '#tab-' + tab)
    return render_template('involvement/insert.html', origin=origin, form=form)
 def __call__(self, field: TreeField, **kwargs: Any) -> TreeSelect:
     from openatlas.models.node import NodeMapper
     selection = ''
     selected_ids = []
     if field.data:
         field.data = field.data[0] if type(
             field.data) is list else field.data
         selection = g.nodes[int(field.data)].name
         selected_ids.append(g.nodes[int(field.data)].id)
     html = """
         <input id="{name}-button" name="{name}-button" type="text"
             class="table-select {required}" onfocus="this.blur()"
             readonly="readonly" value="{selection}" placeholder="{change_label}">
         <a id="{name}-clear" {clear_style} class="button"
             onclick="clearSelect('{name}');">{clear_label}</a>
         <div id="{name}-overlay" class="overlay">
             <div id="{name}-dialog" class="overlay-container">
                 <input class="tree-filter" id="{name}-tree-search" placeholder="{filter}">
                 <div id="{name}-tree"></div>
             </div>
         </div>
         <script>
             $(document).ready(function () {{
                 createOverlay("{name}","{title}",false,);
                 $("#{name}-tree").jstree({{
                     "core" : {{"check_callback" : true, 'data':[{tree_data}]}},
                     "search": {{"case_insensitive": true, "show_only_matches": true}},
                     "plugins" : ["search"],
                 }});
                 $("#{name}-tree").on("select_node.jstree", function (e, data) {{
                     selectFromTree("{name}", data.node.id, data.node.text);
                 }});
                 $("#{name}-tree-search").keyup(function() {{
                     if (this.value.length >= {min_chars}) {{
                         $("#{name}-tree").jstree("search", $(this).val());
                     }}
                     else if (this.value.length == 0) {{
                         $("#{name}-tree").jstree("search", $(this).val());
                         $("#{name}-tree").jstree(true).show_all();
                     }}                        
                 }});
             }});
         </script>""".format(
         filter=uc_first(_('type to search')),
         min_chars=session['settings']['minimum_jstree_search'],
         name=field.id,
         title=g.nodes[int(field.id)].name,
         change_label=uc_first(_('change')),
         clear_label=uc_first(_('clear')),
         selection=selection,
         tree_data=NodeMapper.get_tree_data(int(field.id), selected_ids),
         clear_style='' if selection else ' style="display: none;" ',
         required=' required' if field.flags.required else '')
     return super(TreeSelect, self).__call__(field, **kwargs) + html
Example #28
0
    def test_hierarchy(self):
        with app.app_context():
            self.login()

            # Custom types
            data = {
                'name': 'Geronimo',
                'forms': [1, 2, 4, 5, 6],
                'multiple': True,
                'description': 'Very important!'}
            rv = self.app.post(url_for('hierarchy_insert', param='custom'), data=data)
            hierarchy_id = rv.location.split('/')[-1].replace('types#tab-', '')
            rv = self.app.get(url_for('hierarchy_update', id_=hierarchy_id))
            assert b'Geronimo' in rv.data
            data['forms'] = [3]
            rv = self.app.post(
                url_for('hierarchy_update', id_=hierarchy_id), data=data, follow_redirects=True)
            assert b'Changes have been saved.' in rv.data

            rv = self.app.get(url_for('hierarchy_insert', param='custom'))
            assert b'+ Custom' in rv.data

            data = {'name': 'My secret node', 'description': 'Very important!'}
            rv = self.app.post(url_for('node_insert', root_id=hierarchy_id), data=data)
            node_id = rv.location.split('/')[-1].replace('types#tab-', '')
            rv = self.app.get(url_for('hierarchy_remove_form', id_=hierarchy_id, remove_id=2),
                              follow_redirects=True)
            assert b'Changes have been saved.' in rv.data
            self.app.get(url_for('node_delete', id_=node_id))

            data['name'] = 'Actor Actor Relation'
            rv = self.app.post(
                url_for('hierarchy_update', id_=hierarchy_id), data=data, follow_redirects=True)
            assert b'The name is already in use' in rv.data
            rv = self.app.post(url_for('hierarchy_delete', id_=hierarchy_id), follow_redirects=True)
            assert b'deleted' in rv.data

            # Value types
            rv = self.app.get(url_for('hierarchy_insert', param='value'))
            assert b'+ Value' in rv.data
            data2 = {'name': 'A valued value type', 'forms': [1], 'description': ''}
            rv = self.app.post(url_for('hierarchy_insert', param='value'), data=data2)
            custom_hierarchy_id = rv.location.split('/')[-1].replace('types#tab-', '')
            rv = self.app.get(url_for('hierarchy_update', id_=custom_hierarchy_id))
            assert b'valued' in rv.data

            # Test checks
            actor_node = NodeMapper.get_hierarchy_by_name('Actor Actor Relation')
            rv = self.app.get(url_for('hierarchy_update', id_=actor_node.id), follow_redirects=True)
            assert b'Forbidden' in rv.data
            rv = self.app.get(url_for('hierarchy_delete', id_=actor_node.id), follow_redirects=True)
            assert b'Forbidden' in rv.data
            rv = self.app.post(url_for('hierarchy_insert', param='custom'), data=data)
            assert b'The name is already in use' in rv.data
    def test_involvement(self):
        with app.app_context():
            self.login()
            with app.test_request_context():
                app.preprocess_request()
                actor_id = EntityMapper.insert('E21', 'Captain Miller').id
                event_id = EntityMapper.insert('E8', 'Event Horizon').id
                involvement_id = NodeMapper.get_hierarchy_by_name(
                    'Involvement').id

            # add involvement
            rv = self.app.get(url_for('involvement_insert',
                                      origin_id=actor_id))
            assert b'Involvement' in rv.data
            data = {
                'event': '[' + str(event_id) + ']',
                'activity': 'P11',
                involvement_id: involvement_id
            }
            rv = self.app.post(url_for('involvement_insert',
                                       origin_id=actor_id),
                               data=data,
                               follow_redirects=True)
            assert b'Event Horizon' in rv.data
            data = {
                'actor': '[' + str(actor_id) + ']',
                'continue_': 'yes',
                'activity': 'P22'
            }
            rv = self.app.post(url_for('involvement_insert',
                                       origin_id=event_id),
                               data=data,
                               follow_redirects=True)
            assert b'Event Horizon' in rv.data
            self.app.get(url_for('event_view', id_=event_id))

            # update involvement
            with app.test_request_context():
                app.preprocess_request()
                link_id = LinkMapper.get_links(event_id, 'P22')[0].id
            rv = self.app.get(
                url_for('involvement_update', id_=link_id, origin_id=event_id))
            assert b'Captain' in rv.data
            rv = self.app.post(url_for('involvement_update',
                                       id_=link_id,
                                       origin_id=actor_id),
                               data={
                                   'description':
                                   'Infinite Space - Infinite Terror',
                                   'activity': 'P23'
                               },
                               follow_redirects=True)
            assert b'Infinite Space - Infinite Terror' in rv.data
            self.app.get(url_for('event_view', id_=event_id))
Example #30
0
    def test_node(self):
        with app.app_context():
            self.login()
            with app.test_request_context():
                app.preprocess_request()
                actor_node = NodeMapper.get_hierarchy_by_name('Actor Actor Relation')
                sex_node = NodeMapper.get_hierarchy_by_name('Sex')
            rv = self.app.get(url_for('node_index'))
            assert b'Actor Actor Relation' in rv.data
            rv = self.app.post(
                url_for('node_insert', root_id=actor_node.id), data={'name_search': 'new'})
            assert b'Inverse' in rv.data
            data = {
                'name': 'My secret node',
                'name_inverse': 'Do I look inverse?',
                'description': 'Very important!'}
            rv = self.app.post(url_for('node_insert', root_id=actor_node.id), data=data)
            node_id = rv.location.split('/')[-1].replace('node#tab-', '')
            rv = self.app.get(url_for('node_update', id_=node_id))
            assert b'My secret node' in rv.data and b'Super' in rv.data
            self.app.post(url_for('node_insert', root_id=sex_node.id), data=data)
            rv = self.app.post(
                url_for('node_update', id_=node_id), data=data, follow_redirects=True)
            assert b'Changes have been saved.' in rv.data

            # Test forbidden system node
            rv = self.app.post(
                url_for('node_update', id_=actor_node.id), data=data, follow_redirects=True)
            assert b'Forbidden' in rv.data

            # Test update with self as root
            data[str(actor_node.id)] = node_id
            rv = self.app.post(
                url_for('node_update', id_=node_id), data=data, follow_redirects=True)
            assert b'super' in rv.data

            # Test delete system node
            rv = self.app.get(url_for('node_delete', id_=actor_node.id), follow_redirects=True)
            assert b'Forbidden' in rv.data
            rv = self.app.get(url_for('node_delete', id_=node_id), follow_redirects=True)
            assert b'The entry has been deleted.' in rv.data
Example #31
0
def involvement_update(id_, origin_id):
    link_ = LinkMapper.get_by_id(id_)
    event = EntityMapper.get_by_id(link_.domain.id)
    actor = EntityMapper.get_by_id(link_.range.id)
    origin = event if origin_id == event.id else actor
    form = build_form(ActorForm, 'Involvement', link_, request)
    form.save.label.text = _('save')
    del form.actor, form.event, form.insert_and_continue
    form.activity.choices = [('P11', g.properties['P11'].name)]
    if event.class_.code in ['E7', 'E8', 'E12']:
        form.activity.choices.append(('P14', g.properties['P14'].name))
    if event.class_.code == 'E8':
        form.activity.choices.append(('P22', g.properties['P22'].name))
        form.activity.choices.append(('P23', g.properties['P23'].name))
    if form.validate_on_submit():
        g.cursor.execute('BEGIN')
        try:
            link_.delete()
            link_id = event.link(form.activity.data, actor,
                                 form.description.data)
            DateMapper.save_link_dates(link_id, form)
            NodeMapper.save_link_nodes(link_id, form)
            g.cursor.execute('COMMIT')
        except Exception as e:  # pragma: no cover
            g.cursor.execute('ROLLBACK')
            logger.log('error', 'database', 'transaction failed', e)
            flash(_('error transaction'), 'error')
        view_name = get_view_name(origin)
        tab = 'actor' if view_name == 'event' else 'event'
        return redirect(
            url_for(view_name + '_view', id_=origin.id) + '#tab-' + tab)
    form.activity.data = link_.property.code
    form.description.data = link_.description
    link_.set_dates()
    form.populate_dates(link_)
    return render_template(
        'involvement/update.html',
        origin=origin,
        form=form,
        linked_object=event if origin_id != event.id else actor)
def member_insert(origin_id):
    origin = EntityMapper.get_by_id(origin_id)
    form = build_form(MemberForm, 'Member')
    del form.group
    form.origin_id.data = origin.id
    if form.validate_on_submit():
        g.cursor.execute('BEGIN')
        try:
            for actor in EntityMapper.get_by_ids(ast.literal_eval(form.actor.data)):
                link_id = origin.link('P107', actor, form.description.data)
                DateMapper.save_link_dates(link_id, form)
                NodeMapper.save_link_nodes(link_id, form)
            g.cursor.execute('COMMIT')
            flash(_('entity created'), 'info')
        except Exception as e:  # pragma: no cover
            g.cursor.execute('ROLLBACK')
            logger.log('error', 'database', 'transaction failed', e)
            flash(_('error transaction'), 'error')
        if form.continue_.data == 'yes':
            return redirect(url_for('member_insert', origin_id=origin_id))
        return redirect(url_for('actor_view', id_=origin.id) + '#tab-member')
    return render_template('member/insert.html', origin=origin, form=form)
Example #33
0
def hierarchy_update(id_):
    node = g.nodes[id_]
    if node.system:
        abort(403)
    form = build_form(HierarchyForm, 'hierarchy', node)
    form.forms.choices = NodeMapper.get_form_choices()
    if node.value_type:
        del form.multiple
    elif node.multiple:
        form.multiple.render_kw = {'disabled': 'disabled'}
    if form.validate_on_submit():
        if form.name.data != node.name and NodeMapper.get_nodes(form.name.data):
            flash(_('error name exists'), 'error')
            return redirect(url_for('node_index') + '#tab-' + str(node.id))
        save(form, node)
        flash(_('info update'), 'info')
        return redirect(url_for('node_index') + '#tab-' + str(node.id))
    form.multiple = node.multiple
    return render_template(
        'hierarchy/update.html',
        node=node,
        form=form,
        forms=[form.id for form in form.forms])
def involvement_insert(origin_id):
    origin = EntityMapper.get_by_id(origin_id)
    form = build_form(ActorForm, 'Involvement')
    if origin.view_name == 'event':
        del form.event
    else:
        del form.actor
    form.activity.choices = [('P11', g.properties['P11'].name_inverse)]
    if origin.class_.code in ['E7', 'E8', 'E12']:
        form.activity.choices.append(('P14', g.properties['P14'].name_inverse))
    if origin.class_.code == 'E8':
        form.activity.choices.append(('P22', g.properties['P22'].name_inverse))
        form.activity.choices.append(('P23', g.properties['P23'].name_inverse))
    if form.validate_on_submit():
        g.cursor.execute('BEGIN')
        try:
            if origin.view_name == 'event':
                for actor in EntityMapper.get_by_ids(ast.literal_eval(form.actor.data)):
                    link_id = origin.link(form.activity.data, actor, form.description.data)
                    DateMapper.save_link_dates(link_id, form)
                    NodeMapper.save_link_nodes(link_id, form)
            else:
                for event in EntityMapper.get_by_ids(ast.literal_eval(form.event.data)):
                    link_id = event.link(form.activity.data, origin, form.description.data)
                    DateMapper.save_link_dates(link_id, form)
                    NodeMapper.save_link_nodes(link_id, form)
            g.cursor.execute('COMMIT')
            flash(_('entity created'), 'info')
        except Exception as e:  # pragma: no cover
            g.cursor.execute('ROLLBACK')
            logger.log('error', 'database', 'transaction failed', e)
            flash(_('error transaction'), 'error')
        if form.continue_.data == 'yes':
            return redirect(url_for('involvement_insert', origin_id=origin_id))
        tab = 'actor' if origin.view_name == 'event' else 'event'
        return redirect(url_for(origin.view_name + '_view', id_=origin.id) + '#tab-' + tab)
    return render_template('involvement/insert.html', origin=origin, form=form)
Example #35
0
def save(form, node=None, root=None):
    g.cursor.execute('BEGIN')
    try:
        if node:
            log_action = 'update'
            root = g.nodes[node.root[-1]] if node.root else None
            super_ = g.nodes[node.root[0]] if node.root else None
        else:
            log_action = 'insert'
            node = NodeMapper.insert(root.class_.code, form.name.data)
            super_ = 'new'
        new_super_id = getattr(form, str(root.id)).data
        new_super = g.nodes[int(new_super_id)] if new_super_id else g.nodes[
            root.id]
        if new_super.id == node.id:
            flash(_('error node self as super'), 'error')
            return
        if new_super.root and node.id in new_super.root:
            flash(_('error node sub as super'), 'error')
            return
        node.name = form.name.data
        if root.directional and form.name_inverse.data.strip():
            node.name += ' (' + form.name_inverse.data.strip() + ')'
        if not root.directional:
            node.name = node.name.replace('(', '').replace(')', '')
        node.description = form.description.data if form.description else form.unit.data
        node.update()

        # Update super if changed and node is not a root node
        if super_ and (super_ == 'new' or super_.id != new_super_id):
            property_code = 'P127' if node.class_.code == 'E55' else 'P89'
            node.delete_links(property_code)
            node.link(property_code, new_super)
        g.cursor.execute('COMMIT')
        url = url_for('node_view', id_=node.id)
        if form.continue_.data == 'yes':
            url = url_for('node_insert',
                          root_id=root.id,
                          super_id=new_super_id if new_super_id else None)
        logger.log_user(node.id, log_action)
        flash(
            _('entity created')
            if log_action == 'insert' else _('info update'), 'info')
    except Exception as e:  # pragma: no cover
        g.cursor.execute('ROLLBACK')
        logger.log('error', 'database', 'transaction failed', e)
        flash(_('error transaction'), 'error')
        url = url_for('node_index')
    return url
Example #36
0
def admin_orphans() -> str:
    header = ['name', 'class', 'type', 'system type', 'created', 'updated', 'description']
    tables = {'orphans': Table(header),
              'unlinked': Table(header),
              'missing_files': Table(header),
              'circular': Table(['entity']),
              'nodes': Table(['name', 'root']),
              'orphaned_files': Table(['name', 'size', 'date', 'ext'])}
    tables['circular'].rows = [[link(entity)] for entity in EntityMapper.get_circular()]
    for entity in EntityMapper.get_orphans():
        name = 'unlinked' if entity.class_.code in app.config['CODE_CLASS'].keys() else 'orphans'
        tables[name].rows.append([link(entity),
                                  link(entity.class_),
                                  entity.print_base_type(),
                                  entity.system_type,
                                  format_date(entity.created),
                                  format_date(entity.modified),
                                  truncate_string(entity.description)])
    for node in NodeMapper.get_orphans():
        tables['nodes'].rows.append([link(node), link(g.nodes[node.root[-1]])])

    # Get orphaned file entities (no corresponding file)
    file_ids = []
    for entity in EntityMapper.get_by_system_type('file', nodes=True):
        file_ids.append(str(entity.id))
        if not get_file_path(entity):
            tables['missing_files'].rows.append([link(entity),
                                                 link(entity.class_),
                                                 entity.print_base_type(),
                                                 entity.system_type,
                                                 format_date(entity.created),
                                                 format_date(entity.modified),
                                                 truncate_string(entity.description)])

    # Get orphaned files (no corresponding entity)
    for file in os.scandir(app.config['UPLOAD_FOLDER_PATH']):
        name = file.name
        if name != '.gitignore' and splitext(file.name)[0] not in file_ids:
            confirm = ' onclick="return confirm(\'' + _('Delete %(name)s?', name=name) + '\')"'
            tables['orphaned_files'].rows.append([
                name,
                convert_size(file.stat().st_size),
                format_date(datetime.datetime.utcfromtimestamp(file.stat().st_ctime)),
                splitext(name)[1],
                '<a href="' + url_for('download_file', filename=name) + '">' + uc_first(
                    _('download')) + '</a>',
                '<a href="' + url_for('admin_file_delete', filename=name) + '" ' +
                confirm + '>' + uc_first(_('delete')) + '</a>'])
    return render_template('admin/orphans.html', tables=tables)
Example #37
0
def build_form(form, form_name, entity=None, request_origin=None, entity2=None) -> Form:
    """ The entity parameter can also be a link."""
    # Add custom fields
    custom_list = []

    def add_value_type_fields(subs) -> None:
        for sub_id in subs:
            sub = g.nodes[sub_id]
            setattr(form, str(sub.id), ValueFloatField(sub.name, [Optional()]))
            add_value_type_fields(sub.subs)

    for id_, node in NodeMapper.get_nodes_for_form(form_name).items():
        custom_list.append(id_)
        setattr(form, str(id_), TreeMultiField(str(id_)) if node.multiple else TreeField(str(id_)))
        if node.value_type:
            add_value_type_fields(node.subs)

    form_instance = form(obj=entity)

    # Delete custom fields except the ones specified for the form
    delete_list = []  # Can't delete fields in the loop so creating a list for later deletion
    for field in form_instance:
        if type(field) in (TreeField, TreeMultiField) and int(field.id) not in custom_list:
            delete_list.append(field.id)
    for item in delete_list:
        delattr(form_instance, item)

    # Set field data if available and only if it's a GET request
    if entity and request_origin and request_origin.method == 'GET':
        # Important to use isinstance instead type check, because can be a sub type (e.g. ActorForm)
        if isinstance(form_instance, DateForm):
            form_instance.populate_dates(entity)
        nodes = entity.nodes
        if entity2:
            nodes.update(entity2.nodes)
        if hasattr(form, 'opened'):
            form_instance.opened.data = time.time()
        node_data = {}  # type: dict
        for node, node_value in nodes.items():
            root = g.nodes[node.root[-1]] if node.root else node
            if root.id not in node_data:
                node_data[root.id] = []
            node_data[root.id].append(node.id)
            if root.value_type:
                getattr(form_instance, str(node.id)).data = node_value
        for root_id, nodes in node_data.items():
            if hasattr(form_instance, str(root_id)):
                getattr(form_instance, str(root_id)).data = nodes
    return form_instance
 def __call__(self, field, **kwargs):
     from openatlas.models.node import NodeMapper
     selection = ''
     selected_ids = []
     if field.data:
         field.data = field.data[0] if type(field.data) is list else field.data
         selection = g.nodes[int(field.data)].name
         selected_ids.append(g.nodes[int(field.data)].id)
     html = """
         <input id="{name}-button" name="{name}-button" type="text"
             class="table-select {required}" onfocus="this.blur()"
             readonly="readonly" value="{selection}" placeholder="{change_label}" />
         <a id="{name}-clear" {clear_style} class="button"
             onclick="clearSelect('{name}');">{clear_label}</a>
         <div id="{name}-overlay" class="overlay">
             <div id="{name}-dialog" class="overlay-container">
                 <input class="tree-filter" id="{name}-tree-search" placeholder="{filter}" />
                 <div id="{name}-tree"></div>
             </div>
         </div>
         <script>
             $(document).ready(function () {{
                 createOverlay("{name}","{title}",false,);
                 $("#{name}-tree").jstree({{
                     "core" : {{"check_callback" : true, 'data':[{tree_data}]}},
                     "search": {{"case_insensitive": true, "show_only_matches": true}},
                     "plugins" : ["search"],
                 }});
                 $("#{name}-tree").on("select_node.jstree", function (e, data) {{
                     selectFromTree("{name}", data.node.id, data.node.text);
                 }});
                 $("#{name}-tree-search").keyup(function() {{
                     if (this.value.length >= {min_chars}) {{
                         $("#{name}-tree").jstree("search", $(this).val());
                     }}
                 }});
             }});
         </script>""".format(
         filter=uc_first(_('type to search')),
         min_chars=session['settings']['minimum_jstree_search'],
         name=field.id,
         title=g.nodes[int(field.id)].name,
         change_label=uc_first(_('change')),
         clear_label=uc_first(_('clear')),
         selection=selection,
         tree_data=NodeMapper.get_tree_data(int(field.id), selected_ids),
         clear_style='' if selection else ' style="display: none;" ',
         required=' required' if field.flags.required else '')
     return super(TreeSelect, self).__call__(field, **kwargs) + html
 def __call__(self, field: TreeField, **kwargs: Any) -> TreeMultiSelect:
     selection = ''
     selected_ids = []
     root = g.nodes[int(field.id)]
     if field.data:
         # Somehow field.data can be a string after a failed form validation, so fix that below
         field.data = ast.literal_eval(
             field.data) if type(field.data) is str else field.data
         for entity_id in field.data:
             selected_ids.append(entity_id)
             selection += g.nodes[entity_id].name + '<br>'
     html = """
         <span id="{name}-button" class="button">{change_label}</span>
         <div id="{name}-selection" style="text-align:left;">{selection}</div>
         <div id="{name}-overlay" class="overlay">
            <div id="{name}-dialog" class="overlay-container">
                <input class="tree-filter" id="{name}-tree-search" placeholder="{filter}">
                <div id="{name}-tree"></div>
            </div>
         </div>
         <script>
             createOverlay("{name}", "{title}", true, "tree");
             $("#{name}-tree").jstree({{
                 "core" : {{ "check_callback" : true, 'data':[{tree_data}] }},
                 "search": {{"case_insensitive": true, "show_only_matches": true}},
                 "plugins": ["search", "checkbox"],
                 "checkbox": {{"three_state": false}}
             }});
             $("#{name}-tree-search").keyup(function(){{
                 if (this.value.length >= {min_chars}) {{
                     $("#{name}-tree").jstree("search", $(this).val());
                 }}
                 else if (this.value.length == 0) {{
                     $("#{name}-tree").jstree("search", $(this).val());
                     $("#{name}-tree").jstree(true).show_all();
                 }}
             }});
         </script>""".format(
         filter=uc_first(_('type to search')),
         min_chars=session['settings']['minimum_jstree_search'],
         name=field.id,
         title=root.name,
         selection=selection,
         change_label=uc_first(_('change')),
         tree_data=NodeMapper.get_tree_data(int(field.id), selected_ids))
     return super(TreeMultiSelect, self).__call__(field, **kwargs) + html
def save(form, node=None, root=None):
    g.cursor.execute('BEGIN')
    try:
        if node:
            log_action = 'update'
            root = g.nodes[node.root[-1]] if node.root else None
            super_ = g.nodes[node.root[0]] if node.root else None
        else:
            log_action = 'insert'
            node = NodeMapper.insert(root.class_.code, form.name.data)
            super_ = 'new'
        new_super_id = getattr(form, str(root.id)).data
        new_super = g.nodes[int(new_super_id)] if new_super_id else g.nodes[root.id]
        if new_super.id == node.id:
            flash(_('error node self as super'), 'error')
            return
        if new_super.root and node.id in new_super.root:
            flash(_('error node sub as super'), 'error')
            return
        node.name = form.name.data
        if root.directional and form.name_inverse.data.strip():
            node.name += ' (' + form.name_inverse.data.strip() + ')'
        if not root.directional:
            node.name = node.name.replace('(', '').replace(')', '')
        node.description = form.description.data
        node.update()

        # Update super if changed and node is not a root node
        if super_ and (super_ == 'new' or super_.id != new_super_id):
            property_code = 'P127' if node.class_.code == 'E55' else 'P89'
            node.delete_links(property_code)
            node.link(property_code, new_super)
        g.cursor.execute('COMMIT')
        url = url_for('node_view', id_=node.id)
        if form.continue_.data == 'yes':
            url = url_for('node_insert', root_id=root.id,
                          super_id=new_super_id if new_super_id else None)
        logger.log_user(node.id, log_action)
        flash(_('entity created') if log_action == 'insert' else _('info update'), 'info')
    except Exception as e:  # pragma: no cover
        g.cursor.execute('ROLLBACK')
        logger.log('error', 'database', 'transaction failed', e)
        flash(_('error transaction'), 'error')
        url = url_for('node_index')
    return url
Example #41
0
 def print_base_type(self):
     from openatlas.models.node import NodeMapper
     if not self.view_name or self.view_name == 'actor':  # actors have no base type
         return ''
     root_name = self.view_name.title()
     if self.view_name == 'reference':
         root_name = self.system_type.title()
     elif self.view_name == 'file':
         root_name = 'License'
     elif self.view_name == 'place':
         root_name = uc_first(self.system_type)
         if self.system_type == 'stratigraphic unit':
             root_name = 'Stratigraphic Unit'
     root_id = NodeMapper.get_hierarchy_by_name(root_name).id
     for node in self.nodes:
         if node.root and node.root[-1] == root_id:
             return node.name
     return ''
 def delete_orphans(parameter: str) -> int:
     from openatlas.models.node import NodeMapper
     class_codes = tuple(app.config['CODE_CLASS'].keys())
     if parameter == 'orphans':
         class_codes = class_codes + ('E55', )
         sql_where = EntityMapper.sql_orphan + " AND e.class_code NOT IN %(class_codes)s"
     elif parameter == 'unlinked':
         sql_where = EntityMapper.sql_orphan + " AND e.class_code IN %(class_codes)s"
     elif parameter == 'types':
         count = 0
         for node in NodeMapper.get_node_orphans():
             node.delete()
             count += 1
         return count
     else:
         return 0
     sql = 'DELETE FROM model.entity WHERE id IN (' + sql_where + ');'
     g.execute(sql, {'class_codes': class_codes})
     return g.cursor.rowcount
Example #43
0
 def print_base_type(self):
     from openatlas.models.node import NodeMapper
     view_name = get_view_name(self)
     if not view_name or view_name == 'actor':  # actors have no base type
         return ''
     root_name = view_name.title()
     if view_name == 'reference':
         root_name = self.system_type.title()
     elif view_name == 'file':
         root_name = 'License'
     elif view_name == 'place':
         root_name = uc_first(self.system_type)
         if self.system_type == 'stratigraphic unit':
             root_name = 'Stratigraphic Unit'
     root_id = NodeMapper.get_hierarchy_by_name(root_name).id
     for node in self.nodes:
         if node.root and node.root[-1] == root_id:
             return node.name
     return ''
    def test_involvement(self):
        with app.app_context():
            self.login()
            rv = self.app.post(url_for('event_insert', code='E8'),
                               data={
                                    'name': 'Event Horizon',
                                    'date_begin_year': '1949',
                                    'date_begin_month': '10',
                                    'date_begin_day': '8',
                                    'date_end_year': '1951'})
            event_id = int(rv.location.split('/')[-1])
            with app.test_request_context():
                app.preprocess_request()
                actor_id = EntityMapper.insert('E21', 'Captain Miller').id
                involvement_id = NodeMapper.get_hierarchy_by_name('Involvement').id

            # Add involvement
            rv = self.app.get(url_for('involvement_insert', origin_id=actor_id))
            assert b'Involvement' in rv.data
            data = {'event': '[' + str(event_id) + ']', 'activity': 'P11',
                    involvement_id: involvement_id}
            rv = self.app.post(url_for('involvement_insert', origin_id=actor_id), data=data,
                               follow_redirects=True)
            assert b'Event Horizon' in rv.data
            data = {'actor': '[' + str(actor_id) + ']', 'continue_': 'yes', 'activity': 'P22'}
            rv = self.app.post(url_for('involvement_insert', origin_id=event_id), data=data,
                               follow_redirects=True)
            assert b'Event Horizon' in rv.data
            self.app.get(url_for('event_view', id_=event_id))

            # Update involvement
            with app.test_request_context():
                app.preprocess_request()
                link_id = LinkMapper.get_links(event_id, 'P22')[0].id
            rv = self.app.get(url_for('involvement_update', id_=link_id, origin_id=event_id))
            assert b'Captain' in rv.data
            rv = self.app.post(
                url_for('involvement_update', id_=link_id, origin_id=actor_id),
                data={'description': 'Infinite Space - Infinite Terror', 'activity': 'P23'},
                follow_redirects=True)
            assert b'Infinite Space - Infinite Terror' in rv.data
            self.app.get(url_for('event_view', id_=event_id))
Example #45
0
def tree_select(name):
    html = """
        <div id="{name}-tree"></div>
        <script>
            $(document).ready(function () {{
                $("#{name}-tree").jstree({{
                    "search": {{ "case_insensitive": true, "show_only_matches": true }},
                    "plugins" : ["core", "html_data", "search"],
                    "core":{{ "data":[{tree}] }}
                }});
                $("#{name}-tree-search").keyup(function() {{
                    $("#{name}-tree").jstree("search", $(this).val());
                }});
                $("#{name}-tree").on("select_node.jstree", function (e, data) {{
                    document.location.href = data.node.original.href;
                }});
            }});
        </script>""".format(name=sanitize(name),
                            tree=walk_tree(NodeMapper.get_nodes(name)))
    return html
Example #46
0
 def delete_orphans(parameter) -> int:
     from openatlas.models.node import NodeMapper
     class_codes = tuple(app.config['CODE_CLASS'].keys())
     if parameter == 'orphans':
         class_codes = class_codes + ('E55',)
         sql_where = EntityMapper.sql_orphan + " AND e.class_code NOT IN %(class_codes)s"
     elif parameter == 'unlinked':
         sql_where = EntityMapper.sql_orphan + " AND e.class_code IN %(class_codes)s"
     elif parameter == 'types':
         count = 0
         for node in NodeMapper.get_orphans():
             EntityMapper.delete(node)
             count += 1
         return count
     else:
         return 0
     sql = 'DELETE FROM model.entity WHERE id IN (' + sql_where + ');'
     g.cursor.execute(sql, {'class_codes': class_codes})
     debug_model['div sql'] += 1
     return g.cursor.rowcount
 def __call__(self, field, **kwargs):
     selection = ''
     selected_ids = []
     root = g.nodes[int(field.id)]
     if field.data:
         # Somehow field.data can be a string after a failed form validation, so fix that below
         field.data = ast.literal_eval(field.data) if type(field.data) is str else field.data
         for entity_id in field.data:
             selected_ids.append(entity_id)
             selection += g.nodes[entity_id].name + '<br />'
     html = """
         <span id="{name}-button" class="button">{change_label}</span>
         <div id="{name}-selection" style="text-align:left;">{selection}</div>
         <div id="{name}-overlay" class="overlay">
            <div id="{name}-dialog" class="overlay-container">
                <input class="tree-filter" id="{name}-tree-search" placeholder="{filter}" />
                <div id="{name}-tree"></div>
            </div>
         </div>
         <script>
             createOverlay("{name}", "{title}", true, "tree");
             $("#{name}-tree").jstree({{
                 "core" : {{ "check_callback" : true, 'data':[{tree_data}] }},
                 "search": {{"case_insensitive": true, "show_only_matches": true}},
                 "plugins": ["search", "checkbox"],
                 "checkbox": {{"three_state": false}}
             }});
             $("#{name}-tree-search").keyup(function(){{
                 if (this.value.length >= {min_chars}) {{
                     $("#{name}-tree").jstree("search", $(this).val());
                 }}
             }});
         </script>""".format(
         filter=uc_first(_('type to search')),
         min_chars=session['settings']['minimum_jstree_search'],
         name=field.id,
         title=root.name,
         selection=selection,
         change_label=uc_first(_('change')),
         tree_data=NodeMapper.get_tree_data(int(field.id), selected_ids))
     return super(TreeMultiSelect, self).__call__(field, **kwargs) + html
def tree_select(name):
    html = """
        <div id="{name}-tree"></div>
        <script>
            $(document).ready(function () {{
                $("#{name}-tree").jstree({{
                    "search": {{ "case_insensitive": true, "show_only_matches": true }},
                    "plugins" : ["core", "html_data", "search"],
                    "core":{{ "data":[{tree}] }}
                }});
                $("#{name}-tree").on("select_node.jstree", function (e, data) {{
                    document.location.href = data.node.original.href;
                }});
                $("#{name}-tree-search").keyup(function() {{
                    if (this.value.length >= {min_chars}) {{
                        $("#{name}-tree").jstree("search", $(this).val());
                    }}
                }});
            }});
        </script>""".format(min_chars=session['settings']['minimum_jstree_search'],
                            name=sanitize(name), tree=walk_tree(NodeMapper.get_nodes(name)))
    return html
 def print_base_type(self) -> str:
     from openatlas.models.node import NodeMapper
     if not self.view_name or self.view_name == 'actor':  # actors have no base type
         return ''
     root_name = self.view_name.title()
     if self.view_name == 'reference':
         root_name = self.system_type.title()
         if root_name == 'External Reference Geonames':
             root_name = 'External Reference'
     elif self.view_name == 'file':
         root_name = 'License'
     elif self.view_name == 'place':
         root_name = uc_first(self.system_type)
         if self.system_type == 'stratigraphic unit':
             root_name = 'Stratigraphic Unit'
     elif self.class_.code == 'E84':
         root_name = 'Information Carrier'
     root_id = NodeMapper.get_hierarchy_by_name(root_name).id
     for node in self.nodes:
         if node.root and node.root[-1] == root_id:
             return node.name
     return ''
Example #50
0
 def __call__(self, field, **kwargs):
     selection = ''
     selected_ids = []
     root = g.nodes[int(field.id)]
     if field.data:
         if isinstance(field.data, str):
             field.data = ast.literal_eval(field.data)
         for entity_id in field.data:
             entity = g.nodes[entity_id]
             selected_ids.append(entity.id)
     html = """
         <span id="{name}-button" class="button">{change_label}</span>
         <div id="{name}-selection" style="text-align:left;">{selection}</div>
         <div id="{name}-overlay" class="overlay">
            <div id="{name}-dialog" class="overlay-container">
                <input class="tree-filter" id="{name}-tree-search" placeholder="Filter" />
                <div id="{name}-tree"></div>
            </div>
         </div>
         <script>
             createOverlay("{name}", "{title}", true, "tree");
             $("#{name}-tree").jstree({{
                 "core" : {{ "check_callback" : true, 'data':[{tree_data}] }},
                 "search": {{"case_insensitive": true, "show_only_matches": true}},
                 "plugins": ["search", "checkbox"],
                 "checkbox": {{"three_state": false}}
             }});
             $("#{name}-tree-search").keyup(function(){{
                 $("#{name}-tree").jstree("search", $(this).val());
             }});
         </script>""".format(
         name=field.id,
         title=root.name,
         selection=selection,
         change_label=uc_first(_('change')),
         tree_data=NodeMapper.get_tree_data(int(field.id), selected_ids))
     return super(TreeMultiSelect, self).__call__(field, **kwargs) + html
    def test_place(self):
        with app.app_context():
            self.login()
            rv = self.app.get(url_for('place_insert'))
            assert b'+ Place' in rv.data
            with app.test_request_context():
                app.preprocess_request()
                unit_node = NodeMapper.get_hierarchy_by_name('Administrative Unit')
                unit_sub1 = g.nodes[unit_node.subs[0]]
                unit_sub2 = g.nodes[unit_node.subs[1]]
                reference_id = EntityMapper.insert('E31', 'Ancient Books', 'edition').id
                place_node = NodeMapper.get_hierarchy_by_name('Place')
                source_id = EntityMapper.insert('E33', 'Tha source').id
            data = {'name': 'Asgard', 'alias-0': 'Valhöll',
                    unit_node.id: '[' + str(unit_sub1.id) + ',' + str(unit_sub2.id) + ']'}
            rv = self.app.post(url_for('place_insert', origin_id=reference_id), data=data,
                               follow_redirects=True)
            assert b'Asgard' in rv.data
            gis_points = """[{"type":"Feature", "geometry":{"type":"Point", "coordinates":[9,17]},
                    "properties":{"name":"Valhalla","description":"","shapeType":"centerpoint"}}]"""
            data['gis_points'] = gis_points
            data['gis_polygons'] = """[{"geometry":{
                "coordinates":[[[9.75307425847859,17.8111792731339],
                [9.75315472474904,17.8110005175436],[9.75333711496205,17.8110873417098],
                [9.75307425847859,17.8111792731339]]],"type":"Polygon"},
                "properties":{"count":4,"description":"","id":8,"name":"",
                "objectDescription":"","objectId":185,"shapeType":"Shape",
                "siteType":"Settlement","title":""},"type":"Feature"}]"""
            data[place_node.id] = place_node.subs
            data['continue_'] = 'yes'
            rv = self.app.post(
                url_for('place_insert', origin_id=source_id), data=data, follow_redirects=True)
            assert b'Tha source' in rv.data

            with app.test_request_context():
                app.preprocess_request()
                places = EntityMapper.get_by_codes('place')
                place_id = places[0].id
                place2 = places[1]
                location = place2.get_linked_entity('P53')
                actor = EntityMapper.insert('E21', 'Milla Jovovich')
                actor.link('P74', location)
            assert b'Tha source' in rv.data
            rv = self.app.get(url_for('place_index'))
            assert b'Asgard' in rv.data
            rv = self.app.get(url_for('place_update', id_=place_id))
            assert b'Valhalla' in rv.data
            data['continue_'] = ''
            data['alias-1'] = 'Val-hall'
            rv = self.app.post(
                url_for('place_update', id_=place_id), data=data, follow_redirects=True)
            assert b'Val-hall' in rv.data
            with app.test_request_context():
                app.preprocess_request()
                event = EntityMapper.insert('E8', 'Valhalla rising')
                event.link('P7', location)
                event.link('P24', location)
            rv = self.app.get(url_for('place_view', id_=place2.id))
            assert rv.data and b'Valhalla rising' in rv.data

            # Test invalid geom
            data['gis_polygons'] = """[{"type": "Feature", "geometry":
                {"type": "Polygon", "coordinates": [
                [[298.9893436362036, -5.888919049309554], [299.00444983737543, -5.9138487869408545],
                 [299.00650977389887, -5.893358673645309], [298.9848804404028, -5.9070188333813585],
                 [298.9893436362036, -5.888919049309554]]]},
                "properties": {"name": "", "description": "", "shapeType": "shape"}}]"""
            rv = self.app.post(
                url_for('place_insert', origin_id=source_id), data=data, follow_redirects=True)
            assert b'An invalid geometry was entered' in rv.data

            # Place types
            rv = self.app.get(url_for('node_move_entities', id_=unit_sub1.id))
            assert b'Asgard' in rv.data

            # Test move entities of multiple node if link to new node exists
            rv = self.app.post(url_for('node_move_entities', id_=unit_sub1.id),
                               data={unit_node.id: unit_sub2.id, 'selection': location.id},
                               follow_redirects=True)
            assert b'Entities where updated' in rv.data

            # Test move entities of multiple node if link to new node doesn't exists
            rv = self.app.post(url_for('node_move_entities', id_=unit_sub2.id),
                               data={unit_node.id: unit_sub1.id, 'selection': location.id},
                               follow_redirects=True)
            assert b'Entities where updated' in rv.data

            # Subunits
            with app.app_context():
                self.app.get(url_for('place_insert', origin_id=place_id))
                rv = self.app.post(url_for('place_insert', origin_id=place_id),
                                   data={'name': "It's not a bug, it's a feature!"})
                feat_id = rv.location.split('/')[-1]
                self.app.get(url_for('place_insert', origin_id=feat_id))
                self.app.get(url_for('place_update', id_=feat_id))
                self.app.post(url_for('place_update', id_=feat_id),
                              data={'name': "It's not a bug, it's a feature!"})
                rv = self.app.post(url_for('place_insert', origin_id=feat_id),
                                   data={'name':  "I'm a stratigraphic unit"})
                stratigraphic_id = rv.location.split('/')[-1]
                self.app.get(url_for('place_insert', origin_id=stratigraphic_id))
                self.app.get(url_for('place_update', id_=stratigraphic_id))
                self.app.post(url_for('place_update', id_=stratigraphic_id),
                              data={'name': "I'm a stratigraphic unit"})
                dimension_node_id = NodeMapper.get_hierarchy_by_name('Dimensions').subs[0]
                data = {'name': 'You never find me', str(dimension_node_id): '50'}
                rv = self.app.post(url_for('place_insert', origin_id=stratigraphic_id), data=data)
                find_id = rv.location.split('/')[-1]
                self.app.get(url_for('place_update', id_=find_id))
                self.app.post(url_for('place_update', id_=find_id), data=data)
            rv = self.app.get(url_for('place_view', id_=feat_id))
            assert b'not a bug' in rv.data
            rv = self.app.get(url_for('place_view', id_=stratigraphic_id))
            assert b'a stratigraphic unit' in rv.data
            rv = self.app.get(url_for('place_view', id_=find_id))
            assert b'You never' in rv.data
            rv = self.app.get(url_for('place_delete', id_=place_id), follow_redirects=True)
            assert b'not possible if subunits' in rv.data
            rv = self.app.get(url_for('place_delete', id_=find_id), follow_redirects=True)
            assert b'The entry has been deleted.' in rv.data
            rv = self.app.get(url_for('place_delete', id_=place2.id), follow_redirects=True)
            assert b'The entry has been deleted.' in rv.data
 def save_nodes(self, form: FlaskForm) -> None:
     from openatlas.models.node import NodeMapper
     NodeMapper.save_entity_nodes(self, form)
    def test_relation(self):
        with app.app_context():
            self.login()
            with app.test_request_context():
                app.preprocess_request()
                actor_id = EntityMapper.insert('E21', 'Connor MacLeod').id
                related_id = EntityMapper.insert('E21', 'The Kurgan').id

            # Add relationship
            rv = self.app.get(url_for('relation_insert', origin_id=actor_id))
            assert b'Actor Actor Relation' in rv.data
            relation_id = NodeMapper.get_hierarchy_by_name('Actor Actor Relation').id
            relation_sub_id = g.nodes[relation_id].subs[0]
            data = {
                'actor': '[' + str(related_id) + ']',
                relation_id: relation_sub_id,
                'inverse': None,
                'date_begin_year': '-1949',
                'date_begin_month': '10',
                'date_begin_day': '8',
                'date_begin_year2': '-1948',
                'date_end_year': '2049',
                'date_end_year2': '2050'}
            rv = self.app.post(
                url_for('relation_insert', origin_id=actor_id), data=data, follow_redirects=True)
            assert b'The Kurgan' in rv.data
            rv = self.app.get(url_for('node_view', id_=relation_sub_id))
            assert b'Connor' in rv.data
            data['continue_'] = 'yes'
            data['inverse'] = True
            rv = self.app.post(
                url_for('relation_insert', origin_id=actor_id), data=data, follow_redirects=True)
            assert b'The Kurgan' in rv.data
            rv = self.app.get(url_for('actor_view', id_=actor_id))
            assert b'The Kurgan' in rv.data

            rv = self.app.post(
                url_for('relation_insert', origin_id=related_id), data=data, follow_redirects=True)
            assert b"Can't link to itself." in rv.data

            # Relation types
            rv = self.app.get(url_for('node_move_entities', id_=relation_sub_id))
            assert b'The Kurgan' in rv.data

            # Update relationship
            with app.test_request_context():
                app.preprocess_request()
                link_id = LinkMapper.get_links(actor_id, 'OA7')[0].id
                link_id2 = LinkMapper.get_links(actor_id, 'OA7', True)[0].id
            rv = self.app.get(url_for('relation_update', id_=link_id, origin_id=related_id))
            assert b'Connor' in rv.data
            rv = self.app.post(
                url_for('relation_update', id_=link_id, origin_id=actor_id),
                data={'description': 'There can be only one!', 'inverse': True},
                follow_redirects=True)
            assert b'only one' in rv.data
            rv = self.app.post(
                url_for('relation_update', id_=link_id2, origin_id=actor_id),
                data={'description': 'There can be only one!', 'inverse': None},
                follow_redirects=True)
            assert b'only one' in rv.data
Example #54
0
 def get_all(objects=None):
     all_ = {'point': [], 'linestring': [], 'polygon': []}
     selected = {'point': [], 'linestring': [], 'polygon': [], 'polygon_point': []}
     # Workaround to include GIS features of a subunit which would be otherwise omitted
     subunit_selected_id = 0
     if objects:
         if type(objects) is not list:
             if objects.system_type in ['feature', 'finds', 'stratigraphic unit']:
                 subunit_selected_id = objects.id
             objects = [objects]
     else:
         objects = []
     object_ids = [x.id for x in objects]
     polygon_point_sql = \
         'public.ST_AsGeoJSON(public.ST_PointOnSurface(polygon.geom)) AS polygon_point, '
     for shape in ['point', 'polygon', 'linestring']:
         sql = """
             SELECT
                 object.id AS object_id,
                 {shape}.id,
                 {shape}.name,
                 {shape}.description,
                 {shape}.type,
                 public.ST_AsGeoJSON({shape}.geom) AS geojson, {polygon_point_sql}
                 object.name AS object_name,
                 object.description AS object_desc,
                 string_agg(CAST(t.range_id AS text), ',') AS types
             FROM model.entity place
             JOIN model.link l ON place.id = l.range_id
             JOIN model.entity object ON l.domain_id = object.id
             JOIN gis.{shape} {shape} ON place.id = {shape}.entity_id
             LEFT JOIN model.link t ON object.id = t.domain_id AND t.property_code = 'P2'
             WHERE place.class_code = 'E53'
                 AND l.property_code = 'P53'
                 AND (object.system_type = 'place' OR object.id = {subunit_selected_id})
             GROUP BY object.id, {shape}.id;""".format(
             shape=shape, subunit_selected_id=subunit_selected_id,
             polygon_point_sql=polygon_point_sql if shape == 'polygon' else '')
         g.cursor.execute(sql)
         debug_model['div sql'] += 1
         place_type_root_id = NodeMapper.get_hierarchy_by_name('Place').id
         for row in g.cursor.fetchall():
             description = row.description.replace('"', '\"') if row.description else ''
             object_desc = row.object_desc.replace('"', '\"') if row.object_desc else ''
             item = {'type': 'Feature',
                     'geometry': json.loads(row.geojson),
                     'properties': {
                         'objectId': row.object_id,
                         'objectName': row.object_name.replace('"', '\"'),
                         'objectDescription': object_desc,
                         'id': row.id,
                         'name': row.name.replace('"', '\"') if row.name else '',
                         'description': description,
                         'shapeType': row.type}}
             if hasattr(row, 'types') and row.types:
                 nodes_list = ast.literal_eval('[' + row.types + ']')
                 for node_id in list(set(nodes_list)):
                     node = g.nodes[node_id]
                     if node.root and node.root[-1] == place_type_root_id:
                         item['properties']['objectType'] = node.name.replace('"', '\"')
                         break
             if row.object_id in object_ids:
                 selected[shape].append(item)
             else:
                 all_[shape].append(item)
             if hasattr(row, 'polygon_point'):
                 polygon_point_item = dict(item)  # make a copy to prevent overriding geometry
                 polygon_point_item['geometry'] = json.loads(row.polygon_point)
                 if row.object_id in object_ids:
                     selected['polygon_point'].append(polygon_point_item)
                 else:
                     all_['point'].append(polygon_point_item)
     return {'gisPointAll': json.dumps(all_['point']),
             'gisPointSelected': json.dumps(selected['point']),
             'gisLineAll': json.dumps(all_['linestring']),
             'gisLineSelected': json.dumps(selected['linestring']),
             'gisPolygonAll': json.dumps(all_['polygon']),
             'gisPolygonSelected': json.dumps(selected['polygon']),
             'gisPolygonPointSelected': json.dumps(selected['polygon_point'])}
    def test_actor(self):
        with app.app_context():
            self.login()
            rv = self.app.get(url_for('actor_index'))
            assert b'No entries' in rv.data

            # Create entities for actor
            rv = self.app.post(url_for('place_insert'), data={'name': 'Nostromos'})
            residence_id = rv.location.split('/')[-1]
            with app.test_request_context():
                app.preprocess_request()
                sex_node = NodeMapper.get_hierarchy_by_name('Sex')
                sex_node_sub_1 = g.nodes[sex_node.subs[0]]
                sex_node_sub_2 = g.nodes[sex_node.subs[1]]
                event_id = EntityMapper.insert('E8', 'Event Horizon').id
                source_id = EntityMapper.insert('E33', 'Tha source').id

            # Actor insert
            rv = self.app.get(url_for('actor_insert', code='E21'))
            assert b'+ Person' in rv.data
            self.app.get(url_for('actor_insert', code='E21', origin_id=residence_id))
            data = {
                sex_node.id: sex_node_sub_1.id,
                'name': 'Sigourney Weaver',
                'alias-1': 'Ripley',
                'residence': residence_id,
                'appears_first': residence_id,
                'appears_last': residence_id,
                'description': 'Susan Alexandra Weaver is an American actress.',
                'date_begin_year': '-1949',
                'date_begin_month': '10',
                'date_begin_day': '8',
                'date_begin_year2': '-1948',
                'date_end_year': '2049',
                'date_end_year2': '2050',
                'date_birth': True,
                'date_death': True}
            rv = self.app.post(
                url_for('actor_insert', code='E21', origin_id=residence_id), data=data)
            actor_id = rv.location.split('/')[-1]

            # Test actor nodes
            rv = self.app.get(url_for('node_view', id_=sex_node_sub_1.id))
            assert b'Susan' in rv.data
            rv = self.app.get(url_for('node_move_entities', id_=sex_node_sub_1.id))
            assert b'Sigourney' in rv.data
            rv = self.app.post(url_for('node_move_entities', id_=sex_node_sub_1.id),
                               data={sex_node.id: sex_node_sub_2.id, 'selection': [actor_id]},
                               follow_redirects=True)
            assert b'Entities where updated' in rv.data
            rv = self.app.post(url_for('node_move_entities', id_=sex_node_sub_2.id),
                               data={sex_node.id: '', 'selection': [actor_id]},
                               follow_redirects=True)
            assert b'Entities where updated' in rv.data
            self.app.post(url_for('actor_insert', code='E21', origin_id=actor_id), data=data)
            self.app.post(url_for('actor_insert', code='E21', origin_id=event_id), data=data)
            self.app.post(url_for('actor_insert', code='E21', origin_id=source_id), data=data)
            rv = self.app.post(url_for('reference_insert', code='reference'), data={'name': 'Book'})
            reference_id = rv.location.split('/')[-1]
            rv = self.app.post(
                url_for('actor_insert', code='E21', origin_id=reference_id),
                data=data, follow_redirects=True)
            assert b'An entry has been created' in rv.data
            data['continue_'] = 'yes'
            rv = self.app.post(
                url_for('actor_insert', code='E21'), data=data, follow_redirects=True)
            assert b'An entry has been created' in rv.data
            rv = self.app.get(url_for('actor_index'))
            assert b'Sigourney Weaver' in rv.data

            # Actor update
            rv = self.app.get(url_for('actor_update', id_=actor_id))
            assert b'American actress' in rv.data
            data['name'] = 'Susan Alexandra Weaver'
            data['date_end_year'] = ''
            data['date_begin_year2'] = '1950'
            data['date_begin_day'] = ''
            rv = self.app.post(
                url_for('actor_update', id_=actor_id), data=data, follow_redirects=True)
            assert b'Susan Alexandra Weaver' in rv.data
            rv = self.app.post(
                url_for('ajax_bookmark'), data={'entity_id': actor_id}, follow_redirects=True)
            assert b'Remove bookmark' in rv.data
            rv = self.app.get('/')
            assert b'Weaver' in rv.data
            rv = self.app.post(
                url_for('ajax_bookmark'), data={'entity_id': actor_id}, follow_redirects=True)
            assert b'Bookmark' in rv.data
            rv = self.app.get(url_for('link_delete', origin_id=actor_id, id_=666),
                              follow_redirects=True)
            assert b'removed'in rv.data

            # Actor delete
            rv = self.app.get(url_for('actor_delete', id_=actor_id), follow_redirects=True)
            assert b'The entry has been deleted.' in rv.data
Example #56
0
 def save_nodes(self, form):
     from openatlas.models.node import NodeMapper
     NodeMapper.save_entity_nodes(self, form)