def reset_password():
    if current_user.is_authenticated:  # Prevent password reset if already logged in
        return redirect(url_for('index'))
    form = PasswordResetForm()
    if form.validate_on_submit() and session['settings']['mail']:  # pragma: no cover
        user = UserMapper.get_by_email(form.email.data)
        if not user:
            logger.log('info', 'password', 'Password reset for non existing ' + form.email.data)
            flash(_('error non existing email'), 'error')
        else:
            code = UserMapper.generate_password()
            user.password_reset_code = code
            user.password_reset_date = datetime.datetime.now()
            user.update()
            link = request.scheme + '://' + request.headers['Host']
            link += url_for('reset_confirm', code=code)
            subject = _('Password reset request for %(site_name)s',
                        site_name=session['settings']['site_name'])
            body = _('We received a password reset request for %(username)s',
                     username=user.username)
            body += ' ' + _('at') + ' '
            body += request.headers['Host'] + '\n\n' + _('reset password link') + ':\n\n'
            body += link + '\n\n' + _('The link is valid for') + ' '
            body += str(session['settings']['reset_confirm_hours']) + ' ' + _('hours') + '.'
            if send_mail(subject, body, form.email.data):
                flash(_('A password reset confirmation mail was send to %(email)s.',
                        email=form.email.data), 'info')
            else:
                flash(_('Failed to send password reset confirmation mail to %(email)s.',
                        email=form.email.data), 'error')
            return redirect(url_for('login'))
    return render_template('login/reset_password.html', form=form)
Example #2
0
def relation_insert(origin_id: int) -> Union[str, Response]:
    origin = Entity.get_by_id(origin_id)
    form = build_form('actor_actor_relation')
    form.relation_origin_id.data = origin.id
    if form.validate_on_submit():
        Transaction.begin()
        try:
            for actor in Entity.get_by_ids(ast.literal_eval(form.actor.data)):
                if form.inverse.data:
                    link_ = Link.get_by_id(
                        actor.link('OA7', origin, form.description.data)[0])
                else:
                    link_ = Link.get_by_id(
                        origin.link('OA7', actor, form.description.data)[0])
                link_.set_dates(form)
                link_.type = get_link_type(form)
                link_.update()
            Transaction.commit()
            flash(_('entity created'), 'info')
        except Exception as e:  # pragma: no cover
            Transaction.rollback()
            logger.log('error', 'database', 'transaction failed', e)
            flash(_('error transaction'), 'error')
        if hasattr(form, 'continue_') and form.continue_.data == 'yes':
            return redirect(url_for('relation_insert', origin_id=origin_id))
        return redirect(
            url_for('entity_view', id_=origin.id) + '#tab-relation')
    return render_template(
        'display_form.html',
        form=form,
        title=_('relation'),
        crumbs=[[_('actor'), url_for('index', view='actor')], origin,
                '+ ' + uc_first(_('relation'))])
Example #3
0
def export_csv() -> str:
    path = app.config['EXPORT_FOLDER_PATH'] + '/csv'
    writeable = True if os.access(path, os.W_OK) else False
    form = ExportCsvForm()
    if form.validate_on_submit() and writeable:
        Export.export_csv(form)
        logger.log('info', 'database', 'CSV export')
        flash(_('data was exported as CSV'), 'info')
        return redirect(url_for('export_csv'))
    table = Table(['name', 'size'], order='[[0, "desc"]]')
    for file in [
            f for f in os.listdir(path)
            if os.path.isfile(os.path.join(path, f))
    ]:
        name = basename(file)
        if name == '.gitignore':
            continue
        link = '<a href="{url}">{label}</a>'.format(url=url_for('download_csv',
                                                                filename=name),
                                                    label=uc_first(
                                                        _('download')))
        data = [name, convert_size(os.path.getsize(path + '/' + name)), link]
        if is_authorized('admin') and writeable:
            confirm = ' onclick="return confirm(\'' + _('Delete %(name)s?',
                                                        name=name) + '\')"'
            delete = '<a href="' + url_for('delete_csv', filename=name)
            delete += '" ' + confirm + '>' + uc_first(_('delete')) + '</a>'
            data.append(delete)
        table.rows.append(data)
    return render_template('export/export_csv.html',
                           form=form,
                           table=table,
                           writeable=writeable)
def reset_confirm(code):  # pragma: no cover
    user = UserMapper.get_by_reset_code(code)
    if not user:
        logger.log('info', 'auth', 'unknown reset code')
        flash(_('invalid password reset confirmation code'), 'error')
        abort(404)
    hours = session['settings']['reset_confirm_hours']
    if datetime.datetime.now() > user.password_reset_date + datetime.timedelta(hours=hours):
        logger.log('info', 'auth', 'reset code expired')
        flash(_('This reset confirmation code has expired.'), 'error')
        abort(404)
    password = UserMapper.generate_password()
    user.password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
    user.password_reset_code = None
    user.password_reset_date = None
    user.login_failed_count = 0
    user.update()
    subject = _('New password for %(sitename)s', sitename=session['settings']['site_name'])
    body = _('New password for %(username)s', username=user.username) + ' '
    body += _('at') + ' ' + request.scheme + '://' + request.headers['Host'] + ':\n\n'
    body += uc_first(_('username')) + ': ' + user.username + '\n'
    body += uc_first(_('password')) + ': ' + password + '\n'
    if send_mail(subject, body, user.email, False):
        flash(_('Send new password mail to %(email)s.', email=user.email), 'info')
    else:
        flash(_('Failed to send password mail to %(email)s.', email=user.email), 'error')
    return redirect(url_for('login'))
Example #5
0
def delete_entity(id_: int) -> Optional[str]:
    url = None
    entity = Entity.get_by_id(id_)
    if not is_authorized(entity.class_.write_access):
        abort(403)  # pragma: no cover
    if isinstance(entity, ReferenceSystem):
        if entity.system:
            abort(403)
        if entity.forms:
            flash(_('Deletion not possible if forms are attached'), 'error')
            return url_for('entity_view', id_=id_)
    if entity.class_.view in ['artifact', 'place']:
        if entity.get_linked_entities('P46'):
            flash(_('Deletion not possible if subunits exists'), 'error')
            return url_for('entity_view', id_=id_)
        parent = None \
            if entity.class_.name == 'place' \
            else entity.get_linked_entity('P46', True)
        entity.delete()
        logger.log_user(id_, 'delete')
        flash(_('entity deleted'), 'info')
        if parent:
            tab = f"#tab-{entity.class_.name.replace('_', '-')}"
            url = url_for('entity_view', id_=parent.id) + tab
    else:
        Entity.delete_(id_)
        logger.log_user(id_, 'delete')
        flash(_('entity deleted'), 'info')
        if entity.class_.name == 'file':
            try:
                delete_files(id_)
            except Exception as e:  # pragma: no cover
                logger.log('error', 'file', 'file deletion failed', e)
                flash(_('error file delete'), 'error')
    return url
Example #6
0
def member_insert(origin_id: int) -> str:
    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_ = LinkMapper.get_by_id(
                    origin.link('P107', actor, form.description.data))
                link_.set_dates(form)
                link_.type = get_link_type(form)
                link_.update()
            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 #7
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)
Example #8
0
def admin_settings(category: str) -> Union[str, Response]:
    if category in ['general', 'mail'] and not is_authorized('admin'):
        abort(403)  # pragma: no cover
    form = getattr(importlib.import_module('openatlas.forms.setting'),
                   uc_first(category) + 'Form')()  # Get forms dynamically
    if form.validate_on_submit():
        Transaction.begin()
        try:
            Settings.update(form)
            logger.log('info', 'settings', 'Settings updated')
            Transaction.commit()
            flash(_('info update'), 'info')
        except Exception as e:  # pragma: no cover
            Transaction.rollback()
            logger.log('error', 'database', 'transaction failed', e)
            flash(_('error transaction'), 'error')
        tab = 'data' if category == 'api' else category
        tab = 'email' if category == 'mail' else tab
        return redirect(url_for('admin_index') + '#tab-' + tab)
    set_form_settings(form)
    return render_template('display_form.html',
                           form=form,
                           manual_page='admin/' + category,
                           title=_('admin'),
                           crumbs=[[
                               _('admin'),
                               url_for('admin_index') + '#tab-' +
                               ('data' if category == 'api' else category)
                           ],
                                   _(category)])
Example #9
0
def admin_file_delete(filename: str) -> Response:  # pragma: no cover
    if filename != 'all':  # Delete one file
        try:
            (app.config['UPLOAD_DIR'] / filename).unlink()
            flash(f"{filename} {_('was deleted')}", 'info')
        except Exception as e:
            logger.log('error', 'file', f'deletion of {filename} failed', e)
            flash(_('error file delete'), 'error')
        return redirect(f"{url_for('admin_orphans')}#tab-orphaned-files")

    if is_authorized('admin'):  # Delete all files with no corresponding entity
        entity_file_ids = [entity.id for entity in Entity.get_by_class('file')]
        for file in app.config['UPLOAD_DIR'].iterdir():
            if file.name != '.gitignore' and int(
                    file.stem) not in entity_file_ids:
                try:
                    (app.config['UPLOAD_DIR'] / file.name).unlink()
                except Exception as e:
                    logger.log(
                        'error',
                        'file',
                        f'deletion of {file.name} failed',
                        e)
                    flash(_('error file delete'), 'error')
    return redirect(f"{url_for('admin_orphans')}#tab-orphaned-files")
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)
Example #11
0
def save(form, source=None, origin=None):
    g.cursor.execute('BEGIN')
    try:
        log_action = 'update'
        if not source:
            source = EntityMapper.insert('E33', form.name.data, 'source content')
            log_action = 'insert'
        source.name = form.name.data
        source.description = form.description.data
        source.update()
        source.save_nodes(form)
        url = url_for('source_view', id_=source.id)
        if origin:
            url = url_for(get_view_name(origin) + '_view', id_=origin.id) + '#tab-source'
            if get_view_name(origin) == 'reference':
                link_ = origin.link('P67', source)
                url = url_for('reference_link_update', link_id=link_, origin_id=origin)
            elif get_view_name(origin) == 'file':
                origin.link('P67', source)
            else:
                source.link('P67', origin)
        g.cursor.execute('COMMIT')
        if form.continue_.data == 'yes':
            url = url_for('source_insert', origin_id=origin.id if origin else None)
        logger.log_user(source.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('source_insert', origin_id=origin.id if origin else None)
    return url
Example #12
0
def save(form, reference=None, code: Optional[str] = None, origin=None) -> str:
    g.cursor.execute('BEGIN')
    log_action = 'update'
    try:
        if not reference:
            log_action = 'insert'
            system_type = code.replace('_', ' ')
            reference = EntityMapper.insert('E31', form.name.data, system_type)
        reference.name = form.name.data
        reference.description = form.description.data
        reference.update()
        reference.save_nodes(form)
        url = url_for('reference_view', id_=reference.id)
        if origin:
            link_id = reference.link('P67', origin)
            url = url_for('reference_link_update',
                          link_id=link_id,
                          origin_id=origin.id)
        if form.continue_.data == 'yes' and code:
            url = url_for('reference_insert', code=code)
        g.cursor.execute('COMMIT')
        logger.log_user(reference.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('reference_index')
    return url
def save(form, reference=None, code=None, origin=None):
    g.cursor.execute('BEGIN')
    log_action = 'update'
    try:
        if not reference:
            log_action = 'insert'
            class_code = 'E84' if code == 'carrier' else 'E31'
            system_type = 'information carrier' if code == 'carrier' else code
            reference = EntityMapper.insert(class_code, form.name.data, system_type)
        reference.name = form.name.data
        reference.description = form.description.data
        reference.update()
        reference.save_nodes(form)
        url = url_for('reference_view', id_=reference.id)
        if origin:
            link_id = reference.link('P67', origin)
            url = url_for('reference_link_update', link_id=link_id, origin_id=origin.id)
        if form.continue_.data == 'yes' and code:
            url = url_for('reference_insert', code=code)
        g.cursor.execute('COMMIT')
        logger.log_user(reference.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('reference_index')
    return url
Example #14
0
def insert_files(form: FlaskForm,
                 origin: Optional[Entity] = None) -> Union[str, Response]:
    filenames = []
    url = url_for('index', view=g.classes['file'].view)
    try:
        Transaction.begin()
        entity_name = form.name.data.strip()
        for count, file in enumerate(form.file.data):
            entity = Entity.insert('file', file.filename)
            url = get_redirect_url(form, entity, origin)
            # Add 'a' to prevent emtpy temporary filename, has no side effects
            filename = secure_filename(f'a{file.filename}')
            new_name = f"{entity.id}.{filename.rsplit('.', 1)[1].lower()}"
            file.save(str(app.config['UPLOAD_DIR'] / new_name))
            filenames.append(new_name)
            if g.settings['image_processing']:
                resize_image(new_name)
            if len(form.file.data) > 1:
                form.name.data = f'{entity_name}_{str(count + 1).zfill(2)}'
                if origin:
                    url = f"{url_for('view', id_=origin.id)}#tab-file"
            entity.update(process_form_data(form, entity, origin))
            logger.log_user(entity.id, 'insert')
        Transaction.commit()
        flash(_('entity created'), 'info')
    except Exception as e:  # pragma: no cover
        Transaction.rollback()
        for filename in filenames:
            (app.config['UPLOAD_DIR'] / filename).unlink()
        logger.log('error', 'database', 'transaction failed', e)
        flash(_('error transaction'), 'error')
        url = url_for('index', view=g.classes['file'].view)
    return url
Example #15
0
def save(form, object_=None) -> str:
    g.cursor.execute('BEGIN')
    log_action = 'update'
    try:
        if not object_:
            log_action = 'insert'
            object_ = EntityMapper.insert('E84', form.name.data,
                                          'information carrier')
        object_.name = form.name.data
        object_.description = form.description.data
        object_.update()
        object_.save_nodes(form)
        url = url_for('object_view', id_=object_.id)
        url = url_for('object_insert') if form.continue_.data == 'yes' else url
        g.cursor.execute('COMMIT')
        logger.log_user(object_.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('object_index')
    return url
Example #16
0
def settings_update():
    form = SettingsForm()
    if form.validate_on_submit():
        g.cursor.execute('BEGIN')
        try:
            SettingsMapper.update(form)
            logger.log('info', 'settings', 'Settings updated')
            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('settings_index'))
    for field in SettingsMapper.fields:
        if field.startswith('file_'):
            continue
        if field in ['mail_recipients_feedback']:
            getattr(form, field).data = ';'.join(session['settings'][field])
        elif field in ['default_table_rows', 'log_level']:
            getattr(form, field).data = int(session['settings'][field])
        else:
            getattr(form, field).data = session['settings'][field]
    return render_template('settings/update.html',
                           form=form,
                           settings=session['settings'])
def save(form, source=None, origin=None):
    g.cursor.execute('BEGIN')
    log_action = 'update'
    try:
        if not source:
            source = EntityMapper.insert('E33', form.name.data, 'source content')
            log_action = 'insert'
        source.name = form.name.data
        source.description = form.description.data
        source.update()
        source.save_nodes(form)
        url = url_for('source_view', id_=source.id)
        if origin:
            url = url_for(origin.view_name + '_view', id_=origin.id) + '#tab-source'
            if origin.view_name == 'reference':
                link_ = origin.link('P67', source)
                url = url_for('reference_link_update', link_id=link_, origin_id=origin)
            elif origin.view_name == 'file':
                origin.link('P67', source)
            else:
                source.link('P67', origin)
        g.cursor.execute('COMMIT')
        if form.continue_.data == 'yes':
            url = url_for('source_insert', origin_id=origin.id if origin else None)
        logger.log_user(source.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('source_insert', origin_id=origin.id if origin else None)
    return url
 def __init__(self, row):
     if not row:
         logger.log('error', 'model', 'invalid id')
         abort(418)
     self.id = row.id
     self.nodes = dict()
     if hasattr(row, 'nodes') and row.nodes:
         for node in row.nodes:
             self.nodes[g.nodes[node['f1']]] = node['f2']  # f1 = node id, f2 = value
     self.name = row.name
     self.root = None
     self.description = row.description if row.description else ''
     self.system_type = row.system_type
     self.created = row.created
     self.modified = row.modified
     self.first = int(row.first) if hasattr(row, 'first') and row.first else None
     self.last = int(row.last) if hasattr(row, 'last') and row.last else None
     self.class_ = g.classes[row.class_code]
     self.dates = {}
     self.view_name = None  # view_name is used to build urls
     if self.system_type == 'file':
         self.view_name = 'file'
     elif self.class_.code in app.config['CODE_CLASS']:
         self.view_name = app.config['CODE_CLASS'][self.class_.code]
     self.table_name = self.view_name  # table_name is used to build tables
     if self.view_name == 'place':
         self.table_name = self.system_type.replace(' ', '-')
 def insert(code: str,
            name: str,
            system_type: Optional[str] = None,
            description: Optional[str] = None) -> Entity:
     from openatlas.util.util import sanitize
     from openatlas import logger
     if not name:  # pragma: no cover
         logger.log('error', 'database', 'Insert entity without name')
         abort(422)
     sql = """
         INSERT INTO model.entity (name, system_type, class_code, description)
         VALUES (%(name)s, %(system_type)s, %(code)s, %(description)s)
         RETURNING id;"""
     params = {
         'name':
         str(name).strip(),
         'code':
         code,
         'system_type':
         system_type.strip() if system_type else None,
         'description':
         sanitize(description, 'description') if description else None
     }
     g.execute(sql, params)
     return EntityMapper.get_by_id(g.cursor.fetchone()[0])
Example #20
0
def relation_update(link_: Link, domain: Entity, range_: Entity,
                    origin: Entity) -> Union[str, Response]:
    origin = range_ if origin.id == range_.id else domain
    related = range_ if origin.id == domain.id else domain
    form = build_form('actor_actor_relation', link_)
    if form.validate_on_submit():
        Transaction.begin()
        try:
            link_.delete()
            if form.inverse.data:
                link_ = Link.get_by_id(
                    related.link('OA7', origin, form.description.data)[0])
            else:
                link_ = Link.get_by_id(
                    origin.link('OA7', related, form.description.data)[0])
            link_.set_dates(process_form_dates(form))
            link_.type = get_link_type(form)
            link_.update()
            Transaction.commit()
            flash(_('info update'), 'info')
        except Exception as e:  # pragma: no cover
            Transaction.rollback()
            logger.log('error', 'database', 'transaction failed', e)
            flash(_('error transaction'), 'error')
        return redirect(f"{url_for('view', id_=origin.id)}#tab-relation")
    if origin.id == range_.id:
        form.inverse.data = True
    return render_template(
        'display_form.html',
        form=form,
        title=_('relation'),
        crumbs=[[_('actor'), url_for('index', view='actor')], origin, related,
                _('edit')])
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)
Example #22
0
def member_update(id_: int, origin_id: int) -> Union[str, Response]:
    link_ = Link.get_by_id(id_)
    domain = Entity.get_by_id(link_.domain.id)
    range_ = Entity.get_by_id(link_.range.id)
    origin = range_ if origin_id == range_.id else domain
    form = build_form('actor_function', link_)
    if form.validate_on_submit():
        Transaction.begin()
        try:
            link_.delete()
            link_ = Link.get_by_id(
                domain.link('P107', range_, form.description.data)[0])
            link_.set_dates(process_form_dates(form))
            link_.type = get_link_type(form)
            link_.update()
            Transaction.commit()
        except Exception as e:  # pragma: no cover
            Transaction.rollback()
            logger.log('error', 'database', 'transaction failed', e)
            flash(_('error transaction'), 'error')
        return redirect(
            f"{url_for('view', id_=origin.id)}"
            f"#tab-member{'-of' if origin.id == range_.id else ''}")
    form.save.label.text = _('save')
    related = range_ if origin_id == domain.id else domain
    return render_template(
        'display_form.html',
        form=form,
        crumbs=[[_('actor'), url_for('index', view='actor')], origin, related,
                _('edit')])
Example #23
0
def profile_settings(category: str) -> Union[str, Response]:
    if category not in ['profile', 'display'] and not is_authorized('contributor'):
        abort(403)  # pragma: no cover
    form = getattr(
        importlib.import_module('openatlas.forms.setting'),
        uc_first(category) + 'Form')()
    if form.validate_on_submit():
        for field in form:
            if field.type in ['CSRFTokenField', 'HiddenField', 'SubmitField']:
                continue
            if field.name == 'name':
                current_user.real_name = field.data
            elif field.name == 'email':
                current_user.email = field.data
            else:
                current_user.settings[field.name] = field.data
        Transaction.begin()
        try:
            current_user.update()
            current_user.update_settings(form)
            Transaction.commit()
            session['language'] = current_user.settings['language']
            flash(_('info update'), 'info')
        except Exception as e:  # pragma: no cover
            Transaction.rollback()
            logger.log('error', 'database', 'transaction failed', e)
            flash(_('error transaction'), 'error')
        return redirect(url_for('profile_index') + '#tab-' + category)
    set_form_settings(form, True)
    return render_template(
        'display_form.html',
        form=form,
        manual_page='profile',
        title=_('profile'),
        crumbs=[[_('profile'), url_for('profile_index') + '#tab-' + category], _(category)])
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 #25
0
def reset_confirm(code: str) -> Response:  # pragma: no cover
    user = User.get_by_reset_code(code)
    if not user or not user.username or not user.email:
        logger.log('info', 'auth', 'unknown reset code')
        flash(_('invalid password reset confirmation code'), 'error')
        abort(404)
    hours = g.settings['reset_confirm_hours']
    if datetime.datetime.now() > \
            user.password_reset_date + datetime.timedelta(hours=hours):
        logger.log('info', 'auth', 'reset code expired')
        flash(_('This reset confirmation code has expired.'), 'error')
        abort(404)
    password = User.generate_password()
    user.password = bcrypt.hashpw(password.encode('utf-8'),
                                  bcrypt.gensalt()).decode('utf-8')
    user.password_reset_code = None
    user.password_reset_date = None
    user.login_failed_count = 0
    user.update()
    subject = \
        _('New password for %(sitename)s', sitename=g.settings['site_name'])
    body = _('New password for %(username)s', username=user.username) + ' '
    body += f"{_('at')} {request.scheme}://{request.headers['Host']}:\n\n"
    body += f"{uc_first(_('username'))}: {user.username}\n"
    body += f"{uc_first(_('password'))}: {password}\n"
    if send_mail(subject, body, user.email, False):
        flash(_('A new password was sent to %(email)s.', email=user.email),
              'info')
    else:
        flash(
            _('Failed to send password mail to %(email)s.', email=user.email),
            'error')
    return redirect(url_for('login'))
Example #26
0
def reset_confirm(code: str) -> str:  # pragma: no cover
    user = UserMapper.get_by_reset_code(code)
    if not user:
        logger.log('info', 'auth', 'unknown reset code')
        flash(_('invalid password reset confirmation code'), 'error')
        abort(404)
    hours = session['settings']['reset_confirm_hours']
    if datetime.datetime.now() > user.password_reset_date + datetime.timedelta(
            hours=hours):
        logger.log('info', 'auth', 'reset code expired')
        flash(_('This reset confirmation code has expired.'), 'error')
        abort(404)
    password = UserMapper.generate_password()
    user.password = bcrypt.hashpw(password.encode('utf-8'),
                                  bcrypt.gensalt()).decode('utf-8')
    user.password_reset_code = None
    user.password_reset_date = None
    user.login_failed_count = 0
    user.update()
    subject = _('New password for %(sitename)s',
                sitename=session['settings']['site_name'])
    body = _('New password for %(username)s', username=user.username) + ' '
    body += _('at') + ' ' + request.scheme + '://' + request.headers[
        'Host'] + ':\n\n'
    body += uc_first(_('username')) + ': ' + user.username + '\n'
    body += uc_first(_('password')) + ': ' + password + '\n'
    if send_mail(subject, body, user.email, False):
        flash(_('Send new password mail to %(email)s.', email=user.email),
              'info')
    else:
        flash(
            _('Failed to send password mail to %(email)s.', email=user.email),
            'error')
    return redirect(url_for('login'))
Example #27
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)
def export_sql():
    path = app.config['EXPORT_FOLDER_PATH'] + '/sql'
    writeable = True if os.access(path, os.W_OK) else False
    form = ExportSqlForm()
    if form.validate_on_submit() and writeable:
        if Export.export_sql():
            logger.log('info', 'database', 'SQL export')
            flash(_('data was exported as SQL'), 'info')
        else:  # pragma: no cover
            logger.log('error', 'database', 'SQL export failed')
            flash(_('SQL export failed'), 'error')
        return redirect(url_for('export_sql'))
    table = {'id': 'sql', 'header': ['name', 'size'], 'data': [],
             'sort': 'sortList: [[0, 1]],headers: {0: { sorter: "text" }}'}
    for file in [f for f in os.listdir(path) if os.path.isfile(os.path.join(path, f))]:
        name = basename(file)
        if name == '.gitignore':
            continue
        url = url_for('download_sql', filename=name)
        data = [name, convert_size(os.path.getsize(path + '/' + name)),
                '<a href="' + url + '">' + uc_first(_('download')) + '</a>']
        if is_authorized('admin') and writeable:
            confirm = ' onclick="return confirm(\'' + _('Delete %(name)s?', name=name) + '\')"'
            delete = '<a href="' + url_for('delete_sql', filename=name)
            delete += '" ' + confirm + '>' + uc_first(_('delete')) + '</a>'
            data.append(delete)
        table['data'].append(data)
    return render_template('export/export_sql.html', form=form, table=table, writeable=writeable)
Example #29
0
def admin_check_link_duplicates(delete: Optional[str] = None) -> str:
    if delete:
        delete_count = str(LinkMapper.delete_link_duplicates())
        logger.log('info', 'admin', 'Deleted duplicate links: ' + delete_count)
        flash(_('deleted links') + ': ' + delete_count, 'info')
        return redirect(url_for('admin_check_link_duplicates'))
    table = Table(['domain', 'range', 'property_code', 'description', 'type_id', 'begin_from',
                   'begin_to', 'begin_comment', 'end_from', 'end_to', 'end_comment', 'count'])

    for result in LinkMapper.check_link_duplicates():
        table.rows.append([link(EntityMapper.get_by_id(result.domain_id)),
                           link(EntityMapper.get_by_id(result.range_id)),
                           link(g.properties[result.property_code]),
                           truncate_string(result.description),
                           link(g.nodes[result.type_id]) if result.type_id else '',
                           format_date(result.begin_from),
                           format_date(result.begin_to),
                           truncate_string(result.begin_comment),
                           format_date(result.end_from),
                           format_date(result.end_to),
                           truncate_string(result.end_comment),
                           result.count])
    duplicates = False
    if table.rows:
        duplicates = True
    else:  # If no exact duplicates where found check if single types are used multiple times
        table = Table(['entity', 'class', 'base type', 'incorrect multiple types'],
                      rows=LinkMapper.check_single_type_duplicates())
    return render_template('admin/check_link_duplicates.html', table=table, duplicates=duplicates)
Example #30
0
def admin_file_delete(filename: str) -> str:  # pragma: no cover
    if filename != 'all':
        try:
            os.remove(app.config['UPLOAD_FOLDER_PATH'] + '/' + filename)
            flash(filename + ' ' + _('was deleted'), 'info')
        except Exception as e:
            logger.log('error', 'file', 'deletion of ' + filename + ' failed', e)
            flash(_('error file delete'), 'error')
        return redirect(url_for('admin_orphans') + '#tab-orphaned-files')

    if is_authorized('admin'):
        # Get all files with entities
        file_ids = [str(entity.id) for entity in EntityMapper.get_by_system_type('file')]

        # Get orphaned files (no corresponding entity)
        path = app.config['UPLOAD_FOLDER_PATH']
        for file in [f for f in os.listdir(path) if os.path.isfile(os.path.join(path, f))]:
            filename = basename(file)
            if filename != '.gitignore' and splitext(filename)[0] not in file_ids:
                try:
                    os.remove(app.config['UPLOAD_FOLDER_PATH'] + '/' + filename)
                except Exception as e:
                    logger.log('error', 'file', 'deletion of ' + filename + ' failed', e)
                    flash(_('error file delete'), 'error')
    return redirect(url_for('admin_orphans') + '#tab-orphaned-files')
Example #31
0
 def insert(entity: Entity,
            property_code: str,
            range_: Union[Entity, list[Entity]],
            description: Optional[str] = None,
            inverse: bool = False,
            type_id: Optional[int] = None) -> list[int]:
     property_ = g.properties[property_code]
     entities = range_ if isinstance(range_, list) else [range_]
     new_link_ids = []
     for linked_entity in entities:
         domain = linked_entity if inverse else entity
         range_ = entity if inverse else linked_entity
         domain_error = True
         range_error = True
         if property_.find_object('domain_class_code',
                                  domain.class_.cidoc_class.code):
             domain_error = False
         if property_.find_object('range_class_code',
                                  range_.class_.cidoc_class.code):
             range_error = False
         if domain_error or range_error:  # pragma: no cover
             text = \
                 f"invalid CIDOC link {domain.class_.cidoc_class.code}" \
                 f" > {property_code} > {range_.class_.cidoc_class.code}"
             logger.log('error', 'model', text)
             abort(400, text)
         id_ = Db.insert({
             'property_code': property_code,
             'domain_id': domain.id,
             'range_id': range_.id,
             'description': description,
             'type_id': type_id
         })
         new_link_ids.append(id_)
     return new_link_ids
def export_csv():
    path = app.config['EXPORT_FOLDER_PATH'] + '/csv'
    writeable = True if os.access(path, os.W_OK) else False
    form = ExportCsvForm()
    if form.validate_on_submit() and writeable:
        Export.export_csv(form)
        logger.log('info', 'database', 'CSV export')
        flash(_('data was exported as CSV'), 'info')
        return redirect(url_for('export_csv'))
    table = {'id': 'csv', 'header': ['name', 'size'], 'data': [],
             'sort': 'sortList: [[0, 1]],headers: {0: { sorter: "text" }}'}
    for file in [f for f in os.listdir(path) if os.path.isfile(os.path.join(path, f))]:
        name = basename(file)
        if name == '.gitignore':
            continue
        link = '<a href="{url}">{label}</a>'.format(url=url_for('download_csv', filename=name),
                                                    label=uc_first(_('download')))
        data = [name, convert_size(os.path.getsize(path + '/' + name)), link]
        if is_authorized('admin') and writeable:
            confirm = ' onclick="return confirm(\'' + _('Delete %(name)s?', name=name) + '\')"'
            delete = '<a href="' + url_for('delete_csv', filename=name)
            delete += '" ' + confirm + '>' + uc_first(_('delete')) + '</a>'
            data.append(delete)
        table['data'].append(data)
    return render_template('export/export_csv.html', form=form, table=table, writeable=writeable)
Example #33
0
def sql_execute() -> str:
    file_data = get_backup_file_data()
    response = ''
    form = SqlForm()
    if form.validate_on_submit() and not file_data['backup_too_old']:
        Transaction.begin()
        try:
            g.cursor.execute(form.statement.data)
            response = f'<p>Rows affected: {g.cursor.rowcount}</p>'
            try:
                response += f'<p>{g.cursor.fetchall()}</p>'
            except Exception:  # pragma: no cover
                pass  # Assuming no SELECT statement so returning rowcount
            Transaction.commit()
            flash(_('SQL executed'), 'info')
            logger.log('info', 'database', 'SQL executed', form.statement.data)
        except Exception as e:
            Transaction.rollback()
            logger.log('error', 'database', 'transaction failed', e)
            response = str(e)
            flash(_('error transaction'), 'error')
    return render_template(
        'sql/execute.html',
        form=form,
        response=response,
        file_data=file_data,
        title=_('SQL'),
        crumbs=[[_('admin'), f"{url_for('admin_index')}#tab-data"],
                [_('SQL'), url_for('sql_index')],
                _('execute')])
Example #34
0
def hierarchy_insert(category: str) -> Union[str, Response]:
    form = build_form('hierarchy', code=category)
    form.classes.choices = Type.get_class_choices()
    if form.validate_on_submit():
        if Type.check_hierarchy_exists(form.name.data):
            flash(_('error name exists'), 'error')
            return render_template('display_form.html', form=form)
        try:
            Transaction.begin()
            type_ = Entity.insert('type', sanitize(form.name.data))
            Type.insert_hierarchy(
                type_,  # type: ignore
                category,
                form.classes.data,
                is_multiple(form, category))
            type_.update(process_form_data(form, type_))
            Transaction.commit()
        except Exception as e:  # pragma: no cover
            Transaction.rollback()
            logger.log('error', 'database', 'transaction failed', e)
            flash(_('error transaction'), 'error')
            abort(418)
        flash(_('entity created'), 'info')
        return redirect(f"{url_for('type_index')}#menu-tab-{category}")
    return render_template(
        'display_form.html',
        form=form,
        manual_page='entity/type',
        title=_('types'),
        crumbs=[
            [_('types'), url_for('type_index')],
            f'+ {uc_first(_(category))}'])
Example #35
0
def was_modified(form: FlaskForm, entity: Entity) -> bool:  # pragma: no cover
    if not entity.modified or not form.opened.data:
        return False
    if entity.modified < datetime.fromtimestamp(float(form.opened.data)):
        return False
    logger.log('info', 'multi user', 'Multi user overwrite prevented.')
    return True
Example #36
0
def save(form: FlaskForm,
         entity: Optional[Entity] = None,
         class_: Optional[str] = None,
         origin: Optional[Entity] = None) -> Union[str, Response]:
    if class_ == 'file' and not entity:
        return insert_file(form, origin)
    Transaction.begin()
    action = 'update'
    try:
        if not entity:
            action = 'insert'
            entity = insert_entity(form, class_, origin)
        if isinstance(entity, ReferenceSystem):
            entity.name = entity.name \
                if hasattr(entity, 'system') and entity.system \
                else form.name.data
            entity.description = form.description.data
            entity.website_url = form.website_url.data \
                if form.website_url.data else None
            entity.resolver_url = form.resolver_url.data \
                if form.resolver_url.data else None
            entity.placeholder = form.placeholder.data \
                if form.placeholder.data else None
            entity.update_system(form)
            if hasattr(form, 'forms'):
                entity.add_forms(form)
        else:
            entity.update(form)
            class_ = entity.class_.name
        update_links(entity, form, action, origin)
        url = link_and_get_redirect_url(form, entity, class_, origin)
        logger.log_user(entity.id, action)
        Transaction.commit()
        flash(
            _('entity created') if action == 'insert' else _('info update'),
            'info')
    except InvalidGeomException as e:  # pragma: no cover
        Transaction.rollback()
        logger.log('error', 'database',
                   'transaction failed because of invalid geom', e)
        flash(_('Invalid geom entered'), 'error')
        if action == 'update' and entity:
            url = url_for('update',
                          id_=entity.id,
                          origin_id=origin.id if origin else None)
        else:
            url = url_for('index', view=g.classes[class_].view)
    except Exception as e:  # pragma: no cover
        Transaction.rollback()
        logger.log('error', 'database', 'transaction failed', e)
        flash(_('error transaction'), 'error')
        if action == 'update' and entity:
            url = url_for('update',
                          id_=entity.id,
                          origin_id=origin.id if origin else None)
        else:
            url = url_for('index', view=g.classes[class_].view)
            if class_ in ['administrative_unit', 'type']:
                url = url_for('node_index')
    return url
Example #37
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 #38
0
def create_folder(folder: Path) -> bool:
    try:
        folder.mkdir()
        return True
    except OSError as e:  # pragma: no cover
        logger.log('info', 'image processing', 'failed to create a folder', e)
        return False
Example #39
0
 def get_linked_entity(entity_param, code, inverse=False):
     result = LinkMapper.get_linked_entities(entity_param, code, inverse)
     if len(result) > 1:  # pragma: no cover
         logger.log('error', 'model', 'multiple linked entities found for ' + code)
         flash(_('error multiple linked entities found'), 'error')
         return
     if result:
         return result[0]
Example #40
0
def reference_system_remove_form(system_id: int, form_id: int) -> Response:
    try:
        g.reference_systems[system_id].remove_form(form_id)
        flash(_('info update'), 'info')
    except Exception as e:  # pragma: no cover
        logger.log('error', 'database', 'remove form failed', e)
        flash(_('error database'), 'error')
    return redirect(url_for('entity_view', id_=system_id))
Example #41
0
def profile_update() -> str:
    form = ProfileForm()
    user = current_user
    if form.validate_on_submit():
        user.real_name = form.name.data
        user.email = form.email.data
        user.settings['show_email'] = form.show_email.data
        user.settings['newsletter'] = form.newsletter.data
        user.settings['language'] = form.language.data
        user.settings['table_rows'] = form.table_rows.data
        user.settings['module_geonames'] = form.module_geonames.data
        user.settings['module_map_overlay'] = form.module_map_overlay.data
        user.settings['module_notes'] = form.module_notes.data
        user.settings['max_zoom'] = form.max_zoom.data
        user.settings[
            'table_show_aliases'] = 'True' if form.table_show_aliases.data == 'on' else 'False'
        user.settings['layout'] = form.layout.data
        g.cursor.execute('BEGIN')
        try:
            user.update()
            user.update_settings()
            g.cursor.execute('COMMIT')
            session['language'] = form.language.data
            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('profile_index'))
    form.name.data = current_user.real_name
    form.name.label.text = uc_first(_('full name'))
    form.email.data = current_user.email
    form.email.label.text = uc_first(_('email'))
    form.show_email.data = current_user.settings['show_email']
    form.show_email.label.text = uc_first(_('show email'))
    form.newsletter.data = current_user.settings['newsletter']
    form.newsletter.label.text = uc_first(_('newsletter'))
    language = user.settings['language'] if user.settings[
        'language'] else session['language']
    form.language.data = language
    form.language.label.text = uc_first(_('language'))
    form.table_rows.data = user.settings['table_rows']
    form.table_rows.label.text = uc_first(_('table rows'))
    form.table_show_aliases.data = 'on' if user.settings[
        'table_show_aliases'] else 'off'
    form.table_show_aliases.label.text = uc_first(_('show aliases in tables'))
    form.layout.data = user.settings['layout']
    form.layout.label.text = uc_first(_('layout'))
    form.max_zoom.data = user.settings['max_zoom']
    form.max_zoom.label.text = uc_first(_('max map zoom'))
    form.module_geonames.data = user.settings['module_geonames']
    form.module_geonames.label.text = 'GeoNames'
    form.module_map_overlay.data = user.settings['module_map_overlay']
    form.module_map_overlay.label.text = uc_first(_('map overlay'))
    form.module_notes.data = user.settings['module_notes']
    form.module_notes.label.text = uc_first(_('notes'))
    form.save.label.text = uc_first(_('save'))
    return render_template('profile/update.html', form=form)
def delete_sql(filename):
    try:
        os.remove(app.config['EXPORT_FOLDER_PATH'] + '/sql/' + filename)
        logger.log('info', 'file', 'SQL file deleted')
        flash(_('file deleted'), 'info')
    except Exception as e:  # pragma: no cover
        logger.log('error', 'file', 'SQL file deletion failed', e)
        flash(_('error file delete'), 'error')
    return redirect(url_for('export_sql'))
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 save(form, actor=None, code=None, origin=None):
    g.cursor.execute('BEGIN')
    try:
        log_action = 'update'
        if actor:
            actor.delete_links(['P74', 'OA8', 'OA9'])
            for alias in actor.get_linked_entities('P131'):
                alias.delete()
        else:
            actor = EntityMapper.insert(code, form.name.data)
            log_action = 'insert'
        actor.name = form.name.data
        actor.description = form.description.data
        actor.update()
        actor.save_dates(form)
        actor.save_nodes(form)
        url = url_for('actor_view', id_=actor.id)
        if form.residence.data:
            object_ = EntityMapper.get_by_id(form.residence.data)
            actor.link('P74', object_.get_linked_entity('P53'))
        if form.appears_first.data:
            object_ = EntityMapper.get_by_id(form.appears_first.data)
            actor.link('OA8', object_.get_linked_entity('P53'))
        if form.appears_last.data:
            object_ = EntityMapper.get_by_id(form.appears_last.data)
            actor.link('OA9', object_.get_linked_entity('P53'))
        for alias in form.alias.data:
            if alias.strip():  # Check if it isn't empty
                actor.link('P131', EntityMapper.insert('E82', alias))
        if origin:
            if origin.view_name == 'reference':
                link_id = origin.link('P67', actor)
                url = url_for('reference_link_update', link_id=link_id, origin_id=origin.id)
            elif origin.view_name == 'source':
                origin.link('P67', actor)
                url = url_for('source_view', id_=origin.id) + '#tab-actor'
            elif origin.view_name == 'event':
                link_id = origin.link('P11', actor)
                url = url_for('involvement_update', id_=link_id, origin_id=origin.id)
            elif origin.view_name == 'actor':
                link_id = origin.link('OA7', actor)
                url = url_for('relation_update', id_=link_id, origin_id=origin.id)
        if form.continue_.data == 'yes' and code:
            url = url_for('actor_insert', code=code)
        logger.log_user(actor.id, log_action)
        g.cursor.execute('COMMIT')
        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')
        return redirect(url_for('actor_index'))
    return url
Example #45
0
 def insert(code, name, system_type=None, description=None):
     if not name:  # pragma: no cover
         logger.log('error', 'database', 'Insert entity without name and date')
         return
     sql = """
         INSERT INTO model.entity (name, system_type, class_code, description)
         VALUES (%(name)s, %(system_type)s, %(code)s, %(description)s)
         RETURNING id;"""
     params = {'name': name.strip(), 'code': code,
               'system_type': system_type.strip() if system_type else None,
               'description': description.strip() if description else None}
     g.cursor.execute(sql, params)
     debug_model['div sql'] += 1
     return EntityMapper.get_by_id(g.cursor.fetchone()[0])
def source_add(origin_id):
    """ Link an entity to source coming from the entity."""
    origin = EntityMapper.get_by_id(origin_id)
    if request.method == 'POST':
        g.cursor.execute('BEGIN')
        try:
            for entity in EntityMapper.get_by_ids(request.form.getlist('values')):
                entity.link('P67', origin)
            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 redirect(url_for(origin.view_name + '_view', id_=origin.id) + '#tab-source')
    form = build_table_form('source', origin.get_linked_entities('P67', True))
    return render_template('source/add.html', origin=origin, form=form)
def save(form, event=None, code=None, origin=None):
    g.cursor.execute('BEGIN')
    try:
        log_action = 'insert'
        if event:
            log_action = 'update'
            event.delete_links(['P117', 'P7', 'P24'])
        else:
            event = EntityMapper.insert(code, form.name.data)
        event.name = form.name.data
        event.description = form.description.data
        event.update()
        event.save_dates(form)
        event.save_nodes(form)
        if form.event.data:
            entity = EntityMapper.get_by_id(form.event.data)
            event.link('P117', entity)
        if form.place.data:
            place = LinkMapper.get_linked_entity(int(form.place.data), 'P53')
            event.link('P7', place)
        if event.class_.code == 'E8' and form.given_place.data:  # Link place for acquisition
            places = [EntityMapper.get_by_id(i) for i in ast.literal_eval(form.given_place.data)]
            event.link('P24', places)
        url = url_for('event_view', id_=event.id)
        if origin:
            url = url_for(origin.view_name + '_view', id_=origin.id) + '#tab-event'
            if origin.view_name == 'reference':
                link_id = origin.link('P67', event)
                url = url_for('reference_link_update', link_id=link_id, origin_id=origin.id)
            elif origin.view_name == 'source':
                origin.link('P67', event)
            elif origin.view_name == 'actor':
                link_id = event.link('P11', origin)
                url = url_for('involvement_update', id_=link_id, origin_id=origin.id)
            elif origin.view_name == 'file':
                origin.link('P67', event)
        if form.continue_.data == 'yes':
            url = url_for('event_insert', code=code, origin_id=origin.id if origin else None)
        g.cursor.execute('COMMIT')
        logger.log_user(event.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('event_index')
    return url
Example #48
0
 def __init__(self, row) -> None:
     if not row:
         logger.log('error', 'model', 'invalid id')
         abort(418)
     self.id = row.id
     self.nodes = {}  # type: Dict
     if hasattr(row, 'nodes') and row.nodes:
         for node in row.nodes:
             self.nodes[g.nodes[node['f1']]] = node['f2']  # f1 = node id, f2 = value
     self.aliases = {}  # type: Dict
     if hasattr(row, 'aliases') and row.aliases:
         for alias in row.aliases:
             self.aliases[alias['f1']] = alias['f2']  # f1 = alias id, f2 = alias name
         self.aliases = OrderedDict(sorted(self.aliases.items(), key=lambda kv: (kv[1], kv[0])))
     self.name = row.name
     self.root = None  # type: Optional[list]
     self.description = row.description if row.description else ''
     self.system_type = row.system_type
     self.created = row.created
     self.modified = row.modified
     self.begin_from = None
     self.begin_to = None
     self.begin_comment = None
     self.end_from = None
     self.end_to = None
     self.end_comment = None
     self.origin_id = None  # type: Optional[int]
     if hasattr(row, 'begin_from'):
         self.begin_from = DateMapper.timestamp_to_datetime64(row.begin_from)
         self.begin_to = DateMapper.timestamp_to_datetime64(row.begin_to)
         self.begin_comment = row.begin_comment
         self.end_from = DateMapper.timestamp_to_datetime64(row.end_from)
         self.end_to = DateMapper.timestamp_to_datetime64(row.end_to)
         self.end_comment = row.end_comment
         self.first = DateForm.format_date(self.begin_from, 'year') if self.begin_from else None
         self.last = DateForm.format_date(self.end_from, 'year') if self.end_from else None
         self.last = DateForm.format_date(self.end_to, 'year') if self.end_to else self.last
     self.class_ = g.classes[row.class_code]
     self.view_name = None  # view_name is used to build urls
     self.external_references = []  # type: list
     if self.system_type == 'file':
         self.view_name = 'file'
     elif self.class_.code in app.config['CODE_CLASS']:
         self.view_name = app.config['CODE_CLASS'][self.class_.code]
     self.table_name = self.view_name  # table_name is used to build tables
     if self.view_name == 'place':
         self.table_name = self.system_type.replace(' ', '-')
 def insert(code, name, system_type=None, description=None, date=None):
     if not name and not date:  # pragma: no cover
         logger.log('error', 'database', 'Insert entity without name and date')
         return  # Something went wrong so don't insert
     sql = """
         INSERT INTO model.entity (name, system_type, class_code, description, value_timestamp)
         VALUES (%(name)s, %(system_type)s, %(code)s, %(description)s, %(value_timestamp)s)
         RETURNING id;"""
     params = {
         'name': name.strip(),
         'code': code,
         'system_type': system_type.strip() if system_type else None,
         'description': description.strip() if description else None,
         'value_timestamp':  DateMapper.datetime64_to_timestamp(date) if date else None}
     g.cursor.execute(sql, params)
     debug_model['div sql'] += 1
     return EntityMapper.get_by_id(g.cursor.fetchone()[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
        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
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 #52
0
 def insert(entity,
            property_code: str,
            linked_entities,
            description: Optional[str] = None,
            inverse: Optional[bool] = False):
     from openatlas.models.entity import Entity, EntityMapper
     # linked_entities can be an entity, an entity id or a list of them
     if not entity or not linked_entities:  # pragma: no cover
         return
     property_ = g.properties[property_code]
     try:
         linked_entities = ast.literal_eval(linked_entities)
     except (SyntaxError, ValueError):
         pass
     linked_entities = linked_entities if type(linked_entities) is list else [linked_entities]
     if type(linked_entities[0]) is not Entity:
         linked_entities = EntityMapper.get_by_ids(linked_entities)
     result = None
     for linked_entity in linked_entities:
         domain = linked_entity if inverse else entity
         range_ = entity if inverse else linked_entity
         domain_error = True
         range_error = True
         if property_.find_object('domain_class_code', g.classes[domain.class_.code].code):
             domain_error = False
         if property_.find_object('range_class_code', g.classes[range_.class_.code].code):
             range_error = False
         if domain_error or range_error:
             text = _('error link') + ': ' + g.classes[domain.class_.code].code + ' > '
             text += property_code + ' > ' + g.classes[range_.class_.code].code
             logger.log('error', 'model', text)
             flash(text, 'error')
             continue
         sql = """
             INSERT INTO model.link (property_code, domain_id, range_id, description)
             VALUES (%(property_code)s, %(domain_id)s, %(range_id)s, %(description)s)
             RETURNING id;"""
         # Todo: build only one sql and get execution out of loop
         g.cursor.execute(sql, {'property_code': property_code, 'domain_id': domain.id,
                                'range_id': range_.id, 'description': description})
         debug_model['link sql'] += 1
         result = g.cursor.fetchone()[0]
     return result
 def update_content(name, form):
     g.cursor.execute('BEGIN')
     try:
         for language in app.config['LANGUAGES'].keys():
             sql = 'DELETE FROM web.i18n WHERE name = %(name)s AND language = %(language)s'
             g.cursor.execute(sql, {'name': name, 'language': language})
             debug_model['div sql'] += 1
             sql = """
                 INSERT INTO web.i18n (name, language, text)
                 VALUES (%(name)s, %(language)s, %(text)s);"""
             g.cursor.execute(sql, {
                 'name': name,
                 'language': language,
                 'text': form.__getattribute__(language).data.strip()})
             debug_model['div sql'] += 1
             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')
Example #54
0
 def __init__(self, row):
     if not row:
         logger.log('error', 'model', 'invalid id')
         abort(418)
     self.id = row.id
     self.nodes = dict()
     if hasattr(row, 'nodes') and row.nodes:
         for node in row.nodes:
             self.nodes[g.nodes[node['f1']]] = node['f2']  # f1 = node id, f2 = value
     self.name = row.name
     self.root = None
     self.description = row.description if row.description else ''
     self.system_type = row.system_type
     self.created = row.created
     self.modified = row.modified
     self.begin_from = None
     self.begin_to = None
     self.begin_comment = None
     self.end_from = None
     self.end_to = None
     self.end_comment = None
     if hasattr(row, 'begin_from'):
         self.begin_from = DateMapper.timestamp_to_datetime64(row.begin_from)
         self.begin_to = DateMapper.timestamp_to_datetime64(row.begin_to)
         self.begin_comment = row.begin_comment
         self.end_from = DateMapper.timestamp_to_datetime64(row.end_from)
         self.end_to = DateMapper.timestamp_to_datetime64(row.end_to)
         self.end_comment = row.end_comment
         self.first = DateForm.format_date(self.begin_from, 'year') if self.begin_from else None
         self.last = DateForm.format_date(self.end_from, 'year') if self.end_from else None
         self.last = DateForm.format_date(self.end_to, 'year') if self.end_to else self.last
     self.class_ = g.classes[row.class_code]
     self.view_name = None  # view_name is used to build urls
     self.external_references = []  # Used in view info tab for display
     if self.system_type == 'file':
         self.view_name = 'file'
     elif self.class_.code in app.config['CODE_CLASS']:
         self.view_name = app.config['CODE_CLASS'][self.class_.code]
     self.table_name = self.view_name  # table_name is used to build tables
     if self.view_name == 'place':
         self.table_name = self.system_type.replace(' ', '-')
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)
def profile_update():
    form = ProfileForm()
    if form.validate_on_submit():
        current_user.real_name = form.name.data
        current_user.email = form.email.data
        current_user.settings['show_email'] = form.show_email.data
        current_user.settings['newsletter'] = form.newsletter.data
        g.cursor.execute('BEGIN')
        try:
            current_user.update()
            current_user.update_settings()
            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('profile_index'))
    form.name.data = current_user.real_name
    form.email.data = current_user.email
    form.show_email.data = current_user.settings['show_email']
    form.newsletter.data = current_user.settings['newsletter']
    return render_template('profile/update.html', form=form)
def login():
    if current_user.is_authenticated:
        return redirect('/')
    form = LoginForm()
    if form.validate_on_submit():
        user = UserMapper.get_by_username(request.form['username'])
        if user:
            if user.login_attempts_exceeded():
                logger.log('notice', 'auth', 'Login attempts exceeded: ' + user.username)
                flash(_('error login attempts exceeded'), 'error')
                return render_template('login/index.html', form=form)
            hash_ = hashpw(request.form['password'].encode('utf-8'), user.password.encode('utf-8'))
            if hash_ == user.password.encode('utf-8'):
                if user.active:
                    login_user(user)
                    session['login_previous_success'] = user.login_last_success
                    session['login_previous_failures'] = user.login_failed_count
                    if user.settings['language']:
                        session['language'] = user.settings['language']
                    user.login_last_success = datetime.datetime.now()
                    user.login_failed_count = 0
                    user.update()
                    logger.log('info', 'auth', 'Login of ' + user.username)
                    return redirect(request.args.get('next') or url_for('index'))
                else:
                    logger.log('notice', 'auth', 'Inactive login try ' + user.username)
                    flash(_('error inactive'), 'error')
            else:
                logger.log('notice', 'auth', 'Wrong password: '******'error wrong password'), 'error')
        else:
            logger.log('notice', 'auth', 'Wrong username: '******'username'])
            flash(_('error username'), 'error')
    return render_template('login/index.html', form=form)
def profile_index():
    user = current_user
    data = {'info': [
        (_('username'), user.username),
        (_('full name'), user.real_name),
        (_('email'), user.email),
        (_('show email'), uc_first(_('on')) if user.settings['show_email'] else uc_first(_('off'))),
        (_('newsletter'), uc_first(_('on')) if user.settings['newsletter'] else uc_first(_('off')))
    ]}
    form = DisplayForm()
    if form.validate_on_submit():
        user.settings['language'] = form.language.data
        user.settings['theme'] = form.theme.data
        user.settings['table_rows'] = form.table_rows.data
        user.settings['layout'] = form.layout.data
        g.cursor.execute('BEGIN')
        try:
            user.update_settings()
            g.cursor.execute('COMMIT')
            session['language'] = form.language.data
            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('profile_index'))

    form.language.data = user.settings['language']
    form.theme.data = user.settings['theme']
    form.table_rows.data = user.settings['table_rows']
    form.layout.data = user.settings['layout']
    data['display'] = [
        (form.language.label, form.language),
        (str(form.table_rows.label) +
            display_tooltip(form.table_rows.description), form.table_rows),
        (str(form.layout.label) + display_tooltip(form.layout.description), form.layout)]
    return render_template('profile/index.html', data=data, form=form)
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)
def import_data(project_id, class_code):
    project = ImportMapper.get_project_by_id(project_id)
    form = ImportForm()
    table = None
    imported = False
    messages = {'error': [], 'warn': []}
    if form.validate_on_submit():
        file_ = request.files['file']
        file_path = app.config['IMPORT_FOLDER_PATH'] + '/' + secure_filename(file_.filename)
        columns = {'allowed': ['name', 'id', 'description'], 'valid': [], 'invalid': []}
        try:
            file_.save(file_path)
            if file_path.rsplit('.', 1)[1].lower() in ['xls', 'xlsx']:
                df = pd.read_excel(file_path, keep_default_na=False)
            else:
                df = pd.read_csv(file_path, keep_default_na=False)
            headers = list(df.columns.values)
            if 'name' not in headers:  # pragma: no cover
                messages['error'].append(_('missing name column'))
                raise Exception()
            for item in headers:  # pragma: no cover
                if item not in columns['allowed']:
                    columns['invalid'].append(item)
                    del df[item]
            if columns['invalid']:  # pragma: no cover
                messages['warn'].append(_('invalid columns') + ': ' + ','.join(columns['invalid']))
            headers = list(df.columns.values)  # Read cleaned headers again
            table_data = []
            checked_data = []
            origin_ids = []
            names = []
            missing_name_count = 0
            for index, row in df.iterrows():
                if not row['name']:  # pragma: no cover
                    missing_name_count += 1
                    continue
                table_row = []
                checked_row = {}
                for item in headers:
                    table_row.append(row[item])
                    checked_row[item] = row[item]
                    if item == 'name' and form.duplicate.data:
                        names.append(row['name'].lower())
                    if item == 'id' and row[item]:
                        origin_ids.append(str(row['id']))
                table_data.append(table_row)
                checked_data.append(checked_row)
            table = {'id': 'import', 'header': headers, 'data': table_data}

            # Checking for data inconsistency
            if missing_name_count:  # pragma: no cover
                messages['warn'].append(_('empty names') + ': ' + str(missing_name_count))
            doubles = [item for item, count in collections.Counter(origin_ids).items() if count > 1]
            if doubles:  # pragma: no cover
                messages['error'].append(_('double IDs in import') + ': ' + ', '.join(doubles))
            existing = ImportMapper.check_origin_ids(project, origin_ids) if origin_ids else None
            if existing:
                messages['error'].append(_('IDs already in database') + ': ' + ', '.join(existing))
            if form.duplicate.data:  # Check for possible duplicates
                duplicates = ImportMapper.check_duplicates(class_code, names)
                if duplicates:  # pragma: no cover
                    messages['warn'].append(_('possible duplicates') + ': ' + ', '.join(duplicates))
            if messages['error']:
                raise Exception()
        except Exception as e:  # pragma: no cover
            flash(_('error at import'), 'error')
            return render_template('import/import_data.html', project=project, form=form,
                                   class_code=class_code, messages=messages)

        if not form.preview.data and checked_data:
            g.cursor.execute('BEGIN')
            try:
                ImportMapper.import_data(project, class_code, checked_data)
                g.cursor.execute('COMMIT')
                logger.log('info', 'import', 'import: ' + str(len(checked_data)))
                flash(_('import of') + ': ' + str(len(checked_data)), 'info')
                imported = True
            except Exception as e:  # pragma: no cover
                g.cursor.execute('ROLLBACK')
                logger.log('error', 'import', 'import failed', e)
                flash(_('error transaction'), 'error')
    return render_template('import/import_data.html', project=project, form=form,
                           class_code=class_code, table=table, imported=imported, messages=messages)