예제 #1
0
def admin_log() -> str:
    form = LogForm()
    form.user.choices = [(0, _('all'))] + User.get_users_for_form()
    table = Table(['date', 'priority', 'type', 'message', 'user', 'info'],
                  order=[[0, 'desc']])
    logs = logger.get_system_logs(form.limit.data, form.priority.data,
                                  form.user.data)
    for row in logs:
        user = None
        if row['user_id']:
            try:
                user = link(User.get_by_id(row['user_id']))
            except AttributeError:  # pragma: no cover - user already deleted
                user = f"id {row['user_id']}"
        table.rows.append([
            format_datetime(row['created']),
            f"{row['priority']} {app.config['LOG_LEVELS'][row['priority']]}",
            row['type'], row['message'], user, row['info']
        ])
    return render_template(
        'admin/log.html',
        table=table,
        form=form,
        title=_('admin'),
        crumbs=[[_('admin'), f"{url_for('admin_index')}#tab-general"],
                _('system log')])
예제 #2
0
파일: user.py 프로젝트: nhmvienna/OpenAtlas
def user_activity(user_id: int = 0) -> str:
    form = ActivityForm()
    form.user.choices = [(0, _('all'))] + User.get_users_for_form()
    if form.validate_on_submit():
        activity = User.get_activities(int(form.limit.data),
                                       int(form.user.data), form.action.data)
    elif user_id:
        form.user.data = user_id
        activity = User.get_activities(100, user_id, 'all')
    else:
        activity = User.get_activities(100, 0, 'all')
    table = Table(['date', 'user', 'action', 'entity'], order=[[0, 'desc']])
    for row in activity:
        try:
            entity = link(Entity.get_by_id(row['entity_id']))
        except AttributeError:  # pragma: no cover - entity already deleted
            entity = f"id {row['entity_id']}"
        user = User.get_by_id(row['user_id'])
        table.rows.append([
            format_date(row['created']),
            link(user) if user else f"id {row['user_id']}",
            _(row['action']), entity
        ])
    return render_template('user/activity.html',
                           table=table,
                           form=form,
                           title=_('user'),
                           crumbs=[[_('admin'),
                                    url_for('admin_index')],
                                   _('activity')])
예제 #3
0
def note_set_private(id_: int) -> Union[str, Response]:
    if not is_authorized('manager'):
        abort(403)  # pragma: no cover
    note = User.get_note_by_id(id_)
    User.update_note(note['id'], note['text'], False)
    flash(_('note updated'), 'info')
    return redirect(f"{url_for('view', id_=note['entity_id'])}#tab-note")
예제 #4
0
def note_delete(id_: int) -> Response:
    note = User.get_note_by_id(id_)
    if not note['user_id'] == current_user.id:
        abort(403)  # pragma: no cover
    User.delete_note(note['id'])
    flash(_('note deleted'), 'info')
    return redirect(f"{url_for('view', id_=note['entity_id'])}#tab-note")
예제 #5
0
파일: user.py 프로젝트: nhmvienna/OpenAtlas
 def validate(self) -> bool:
     valid = FlaskForm.validate(self)
     username = ''
     user_email = ''
     if self.user_id:
         user = User.get_by_id(self.user_id)
         username = user.username
         user_email = user.email
     if username != self.username.data \
             and User.get_by_username(self.username.data):
         self.username.errors.append(_('error username exists'))
         valid = False
     if user_email != self.email.data and User.get_by_email(
             self.email.data):
         self.email.errors.append(_('error email exists'))
         valid = False
     if getattr(self, 'password'):
         if self.password.data != self.password2.data:
             self.password.errors.append(_('error passwords must match'))
             self.password2.errors.append(_('error passwords must match'))
             valid = False
         if len(self.password.data) < \
                 session['settings']['minimum_password_length']:
             self.password.errors.append(_('error password too short'))
             valid = False
     return valid
예제 #6
0
 def test_note(self) -> None:
     with app.app_context():
         with app.test_request_context():
             app.preprocess_request()  # type: ignore
             actor = Entity.insert('person', 'Ripley')
         rv = self.app.get(url_for('note_insert', entity_id=actor.id))
         assert b'Description' in rv.data
         rv = self.app.post(url_for('note_insert', entity_id=actor.id),
                            data={'description': 'A nice description'},
                            follow_redirects=True)
         assert b'Note added' in rv.data
         rv = self.app.get(url_for('overview'))
         assert b'A nice description' in rv.data
         with app.test_request_context():
             app.preprocess_request()  # type: ignore
             user = User.get_by_username('Alice')
             if user:
                 note_id = User.get_notes_by_user_id(user.id)[0]['id']
         rv = self.app.get(url_for('note_update', id_=note_id))
         assert b'A nice description' in rv.data
         rv = self.app.post(url_for('note_update', id_=note_id),
                            data={'description': 'A very nice description'},
                            follow_redirects=True)
         assert b'Note updated' in rv.data \
                and b'A very nice description' in rv.data
         rv = self.app.get(url_for('note_view', id_=note_id))
         assert b'A very nice description' in rv.data
         rv = self.app.get(url_for('note_set_private', id_=note_id),
                           follow_redirects=True)
         assert b'Note updated' in rv.data
         rv = self.app.get(url_for('note_delete', id_=note_id),
                           follow_redirects=True)
         assert b'Note deleted' in rv.data
예제 #7
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 = 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 = 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=session['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'))
예제 #8
0
def admin_newsletter() -> Union[str, Response]:
    class NewsLetterForm(FlaskForm):
        subject = StringField(
            '',
            [InputRequired()],
            render_kw={
                'placeholder': uc_first(_('subject')),
                'autofocus': True})
        body = TextAreaField(
            '',
            [InputRequired()],
            render_kw={'placeholder': uc_first(_('content'))})
        save = SubmitField(_('send'))

    form = NewsLetterForm()
    form.save.label.text = uc_first(_('send'))
    if form.validate_on_submit():  # pragma: no cover
        count = 0
        for user_id in request.form.getlist('recipient'):
            user = User.get_by_id(user_id)
            if user \
                    and user.settings['newsletter'] \
                    and user.active \
                    and user.email:
                code = User.generate_password()
                user.unsubscribe_code = code
                user.update()
                link_ = f"{request.scheme}://{request.headers['Host']}"
                link_ += url_for('index_unsubscribe', code=code)
                if send_mail(
                        form.subject.data,
                        f'{form.body.data}\n\n'
                        f'{_("To unsubscribe use the link below.")}\n\n'
                        f'{link_}',
                        user.email):
                    count += 1
        flash(f"{_('Newsletter send')}: {count}", 'info')
        return redirect(url_for('admin_index'))
    table = Table(['username', 'email', 'receiver'])
    for user in User.get_all():
        if user \
                and user.settings['newsletter'] \
                and user.active:  # pragma: no cover
            table.rows.append([
                user.username,
                user.email,
                f'<input value="{user.id}" name="recipient" type="checkbox" '
                f'checked="checked">'])
    return render_template(
        'admin/newsletter.html',
        form=form,
        table=table,
        title=_('newsletter'),
        crumbs=[
            [_('admin'), f"{url_for('admin_index')}#tab-user"],
            _('newsletter')])
예제 #9
0
 def get_log_for_advanced_view(entity_id: str) -> Dict[str, Any]:
     from openatlas.models.user import User
     data = Db.get_log_for_advanced_view(entity_id)
     return {
         'creator': User.get_by_id(data['creator_id']) if data['creator_id'] else None,
         'created': data['created'],
         'modifier': User.get_by_id(data['modifier_id']) if data['modifier_id'] else None,
         'modified': data['modified'],
         'project': Import.get_project_by_id(data['project_id']) if data['project_id'] else None,
         'importer': User.get_by_id(data['importer_id']) if data['importer_id'] else None,
         'origin_id': data['origin_id']}
예제 #10
0
def note_insert(entity_id: int) -> Union[str, Response]:
    entity = Entity.get_by_id(entity_id)
    form = build_form('note')
    if form.validate_on_submit():
        User.insert_note(entity_id, form.description.data, form.public.data)
        flash(_('note added'), 'info')
        return redirect(f"{url_for('view', id_=entity.id)}#tab-note")
    return render_template('display_form.html',
                           form=form,
                           entity=entity,
                           crumbs=[[
                               _(entity.class_.view),
                               url_for('index', view=entity.class_.view)
                           ], entity, f"+ {uc_first(_('note'))}"])
예제 #11
0
파일: user.py 프로젝트: nhmvienna/OpenAtlas
def user_insert() -> Union[str, Response]:
    form = UserForm()
    form.group.choices = get_groups()
    if not session['settings']['mail']:
        del form.send_info
    if form.validate_on_submit():
        user_id = User.insert(form)
        flash(_('user created'), 'info')
        if session['settings']['mail'] \
                and form.send_info.data:  # pragma: no cover
            subject = _('Your account information for %(sitename)s',
                        sitename=session['settings']['site_name'])
            body = _('Account information for %(username)s',
                     username=form.username.data) + \
                f" {_('at')} {request.scheme}://{request.headers['Host']}\n\n" \
                f"{uc_first(_('username'))}: {form.username.data}\n" \
                f"{uc_first(_('password'))}: {form.password.data}\n"
            if send_mail(subject, body, form.email.data, False):
                flash(
                    _('Sent account information mail to %(email)s.',
                      email=form.email.data), 'info')
            else:
                flash(
                    _('Failed to send account details to %(email)s.',
                      email=form.email.data), 'error')
        if hasattr(form, 'continue_') and form.continue_.data == 'yes':
            return redirect(url_for('user_insert'))
        return redirect(url_for('user_view', id_=user_id))
    return render_template(
        'user/insert.html',
        form=form,
        title=_('user'),
        crumbs=[[_('admin'), f"{url_for('admin_index')}#tab-user"],
                f"+ {uc_first(_('user'))}"])
예제 #12
0
def note_view(id_: int) -> str:
    note = User.get_note_by_id(id_)
    if not note['public'] and note['user_id'] != current_user.id:
        abort(403)  # pragma: no cover
    entity = Entity.get_by_id(note['entity_id'])
    buttons: list[str] = [manual('tools/notes')]
    if note['user_id'] == current_user.id:
        buttons += [
            button(_('edit'), url_for('note_update', id_=note['id'])),
            button(_('delete'), url_for('note_delete', id_=note['id']))
        ]
    elif is_authorized('manager'):  # pragma: no cover
        buttons += [
            button(_('set private'), url_for('note_set_private',
                                             id_=note['id']))
        ]
    tabs = {
        'info':
        Tab('info',
            buttons=buttons,
            content=f"<h1>{uc_first(_('note'))}</h1>{note['text']}")
    }
    return render_template('tabs.html',
                           tabs=tabs,
                           entity=entity,
                           crumbs=[[
                               _(entity.class_.view),
                               url_for('index', view=entity.class_.view)
                           ],
                                   link(entity),
                                   _('note')])
예제 #13
0
파일: user.py 프로젝트: nhmvienna/OpenAtlas
def user_update(id_: int) -> Union[str, Response]:
    user = User.get_by_id(id_)
    if user.group == 'admin' and current_user.group != 'admin':
        abort(403)  # pragma: no cover
    form = UserForm(obj=user)
    form.user_id = id_
    del form.password, form.password2, form.send_info
    del form.insert_and_continue, form.show_passwords
    form.group.choices = get_groups()
    if user and form.validate_on_submit():
        # Active is always true if current user to prevent self deactivation
        user.active = True if user.id == current_user.id else form.active.data
        user.real_name = form.real_name.data
        user.username = form.username.data
        user.email = form.email.data
        user.description = form.description.data
        user.group = form.group.data
        user.update()
        flash(_('info update'), 'info')
        return redirect(url_for('user_view', id_=id_))
    if user.id == current_user.id:
        del form.active
    return render_template(
        'display_form.html',
        form=form,
        title=user.username,
        manual_page='admin/user',
        crumbs=[[_('admin'), f"{url_for('admin_index')}#tab-user"], user,
                _('edit')])
예제 #14
0
파일: user.py 프로젝트: nhmvienna/OpenAtlas
def user_view(id_: int) -> str:
    user = User.get_by_id(id_)
    info = {
        _('username'):
        user.username,
        _('group'):
        user.group,
        _('full name'):
        user.real_name,
        _('email'):
        user.email
        if is_authorized('manager') or user.settings['show_email'] else '',
        _('language'):
        user.settings['language'],
        _('last login'):
        format_date(user.login_last_success),
        _('failed logins'):
        user.login_failed_count if is_authorized('manager') else ''
    }
    return render_template(
        'user/view.html',
        user=user,
        info=info,
        title=user.username,
        crumbs=[[_('admin'), f"{url_for('admin_index')}#tab-user"],
                user.username])
예제 #15
0
def reset_password() -> Union[str, Response]:
    if current_user.is_authenticated:  # Prevent password reset if logged in
        return redirect(url_for('overview'))
    form = PasswordResetForm()
    if form.validate_on_submit() \
            and session['settings']['mail']:  # pragma: no cover
        user = User.get_by_email(form.email.data)
        if not user:
            logger.log('info', 'password',
                       f'Password reset for non existing {form.email.data}')
            flash(_('error non existing email'), 'error')
        else:
            code = User.generate_password()
            user.password_reset_code = code
            user.password_reset_date = datetime.datetime.now()
            user.update()
            url = url_for('reset_confirm', code=code)
            link = f"{request.scheme}://{request.headers['Host']}{url}"
            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 += \
                f" {_('at')} {request.headers['Host']}\n\n" \
                f"{_('reset password link')}:\n\n" \
                f"{link}\n\n" \
                f"{_('The link is valid for')} " \
                f"{session['settings']['reset_confirm_hours']} {_('hours')}."
            email = form.email.data
            if send_mail(subject, body, form.email.data):
                flash(
                    _(
                        'A password reset confirmation mail was send '
                        'to %(email)s.',
                        email=email), 'info')
            else:
                flash(
                    _(
                        'Failed to send password reset confirmation mail '
                        'to %(email)s.',
                        email=email), 'error')
            return redirect(url_for('login'))
    return render_template('login/reset_password.html',
                           form=form,
                           crumbs=[[_('login'), url_for('login')],
                                   _('Forgot your password?')])
예제 #16
0
def note_update(id_: int) -> Union[str, Response]:
    note = User.get_note_by_id(id_)
    if not note['user_id'] == current_user.id:
        abort(403)  # pragma: no cover
    entity = Entity.get_by_id(note['entity_id'])
    form = build_form('note')
    if form.validate_on_submit():
        User.update_note(note['id'], form.description.data, form.public.data)
        flash(_('note updated'), 'info')
        return redirect(f"{url_for('view', id_=note['entity_id'])}#tab-note")
    form.save.label.text = _('save')
    form.description.data = note['text']
    form.public.data = note['public']
    return render_template('display_form.html',
                           form=form,
                           entity=entity,
                           crumbs=[[
                               _(entity.class_.view),
                               url_for('index', view=entity.class_.view)
                           ], entity,
                                   _('edit note')])
예제 #17
0
def index_unsubscribe(code: str) -> str:
    user = User.get_by_unsubscribe_code(code)
    text = _('unsubscribe link not valid')
    if user:  # pragma: no cover
        user.settings['newsletter'] = ''
        user.unsubscribe_code = ''
        user.update()
        user.remove_newsletter()
        text = _('You have successfully unsubscribed. '
                 'You can subscribe again in your Profile.')
    return render_template('index/unsubscribe.html',
                           text=text,
                           crumbs=[_('unsubscribe newsletter')])
예제 #18
0
def add_note_tab(entity: Entity) -> Tab:
    tab = Tab('note', entity=entity)
    for note in current_user.get_notes_by_entity_id(entity.id):
        data = [
            format_date(note['created']),
            uc_first(_('public'))
            if note['public'] else uc_first(_('private')),
            link(User.get_by_id(note['user_id'])),
            note['text'],
            f'<a href="{url_for("note_view", id_=note["id"])}">'
            f'{uc_first(_("view"))}</a>']
        tab.table.rows.append(data)
    return tab
예제 #19
0
def admin_newsletter() -> Union[str, Response]:
    form = NewsLetterForm()
    form.save.label.text = uc_first(_('send'))
    if form.validate_on_submit():  # pragma: no cover
        recipients = 0
        for user_id in (request.form.getlist('recipient')):
            user = User.get_by_id(user_id)
            if user and user.settings[
                    'newsletter'] and user.active and user.email:
                code = User.generate_password()
                user.unsubscribe_code = code
                user.update()
                link_ = request.scheme + '://' + request.headers['Host']
                link_ += url_for('index_unsubscribe', code=code)
                unsubscribe = '\n\n' + _(
                    'To unsubscribe use the link below.') + '\n\n' + link_
                if send_mail(form.subject.data, form.body.data + unsubscribe,
                             user.email):
                    recipients += 1
        flash(_('Newsletter send') + ': ' + str(recipients), 'info')
        return redirect(url_for('admin_index'))
    table = Table(['username', 'email', 'receiver'])
    for user in User.get_all():
        if user and user.settings[
                'newsletter'] and user.active:  # pragma: no cover
            table.rows.append([
                user.username, user.email,
                '<input value="{id}" name="recipient" type="checkbox" checked="checked">'
                .format(id=user.id)
            ])
    return render_template(
        'admin/newsletter.html',
        form=form,
        table=table,
        title=_('newsletter'),
        crumbs=[[_('admin'), url_for('admin_index') + '#tab-user'],
                _('newsletter')])
예제 #20
0
def login() -> Union[str, Response]:
    if current_user.is_authenticated:
        return redirect('/')
    form = LoginForm()
    if form.validate_on_submit():
        user = User.get_by_username(request.form['username'])
        if user and user.username:
            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('overview'))
                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',
                           title=_('login'),
                           crumbs=[_('login')],
                           form=form)
예제 #21
0
 def validate(self, extra_validators=None):
     valid = Form.validate(self)
     user = UserMapper.get_by_id(self.user_id) if self.user_id else User()
     if user.username != self.username.data and UserMapper.get_by_username(self.username.data):
         self.username.errors.append(str(_('error username exists')))
         valid = False
     if user.email != self.email.data and UserMapper.get_by_email(self.email.data):
         self.email.errors.append(str(_('error email exists')))
         valid = False
     if getattr(self, 'password'):
         if self.password.data != self.password2.data:
             self.password.errors.append(_('error passwords must match'))
             self.password2.errors.append(_('error passwords must match'))
             valid = False
         if len(self.password.data) < session['settings']['minimum_password_length']:
             self.password.errors.append(_('error password too short'))
             valid = False
     return valid
예제 #22
0
def note_view(id_: int) -> str:
    note = User.get_note_by_id(id_)
    if not note['public'] and note['user_id'] != current_user.id:
        abort(403)  # pragma: no cover
    entity = Entity.get_by_id(note['entity_id'])
    buttons: List[str] = []
    if note['user_id'] == current_user.id:
        buttons = [
            button(_('edit'), url_for('note_update', id_=note['id'])),
            button(_('delete'), url_for('note_delete', id_=note['id']))]
    elif is_authorized('manager'):  # pragma: no cover
        buttons = [button(_('set private'), url_for('note_set_private', id_=note['id']))]
    return render_template(
        'user/note.html',
        entity=entity,
        note=note,
        tabs={'info': Tab('info')},
        buttons=buttons,
        crumbs=[
            [_(entity.class_.view), url_for('index', view=entity.class_.view)],
            link(entity),
            _('note')])
예제 #23
0
파일: util.py 프로젝트: acdh-oeaw/OpenAtlas
def system_warnings(_context: str, _unneeded_string: str) -> str:
    if not is_authorized('manager'):
        return ''
    warnings = []
    if app.config['DATABASE_VERSION'] != g.settings['database_version']:
        warnings.append(
            f"Database version {app.config['DATABASE_VERSION']} is needed but "
            f"current version is {g.settings['database_version']}")
    for path in app.config['WRITABLE_DIRS']:
        if not os.access(path, os.W_OK):
            warnings.append(f"{uc_first(_('directory not writable'))}: "
                            f"{str(path).replace(app.root_path, '')}")
    if is_authorized('admin'):
        from openatlas.models.user import User
        user = User.get_by_username('OpenAtlas')
        if user and user.active:
            hash_ = hashpw('change_me_PLEASE!'.encode('utf-8'),
                           user.password.encode('utf-8'))
            if hash_ == user.password.encode('utf-8'):
                warnings.append(
                    "User OpenAtlas with default password is still active!")
    if warnings:
        return Markup(f'<p class="error">{"<br>".join(warnings)}<p>')
    return ''  # pragma: no cover
예제 #24
0
def overview() -> str:
    tabs = {
        'info':
        Tab('info'),
        'bookmarks':
        Tab('bookmarks', table=Table(['name', 'class', 'begin', 'end'])),
        'notes':
        Tab('notes',
            table=Table(
                ['date', _('visibility'), 'entity', 'class',
                 _('note')]))
    }
    tables = {
        'overview':
        Table(paging=False,
              defs=[{
                  'className': 'dt-body-right',
                  'targets': 1
              }]),
        'latest':
        Table(paging=False, order=[[0, 'desc']])
    }
    if current_user.is_authenticated and hasattr(current_user, 'bookmarks'):
        for entity_id in current_user.bookmarks:
            entity = Entity.get_by_id(entity_id)
            tabs['bookmarks'].table.rows.append([
                link(entity), entity.class_.label, entity.first, entity.last,
                bookmark_toggle(entity.id, True)
            ])
        for note in User.get_notes_by_user_id(current_user.id):
            entity = Entity.get_by_id(note['entity_id'])
            tabs['notes'].table.rows.append([
                format_date(note['created']),
                uc_first(_('public') if note['public'] else _('private')),
                link(entity), entity.class_.label, note['text'],
                f'<a href="{url_for("note_view", id_=note["id"])}">'
                f'{uc_first(_("view"))}</a>'
            ])
        for name, count in Entity.get_overview_counts().items():
            if count:
                url = url_for('index', view=g.class_view_mapping[name])
                if name == 'administrative_unit':
                    url = f"{url_for('node_index')}#menu-tab-places"
                elif name == 'type':
                    url = url_for('node_index')
                elif name == 'find':
                    url = url_for('index', view='artifact')
                elif name in [
                        'feature', 'human_remains', 'stratigraphic_unit',
                        'source_translation'
                ]:
                    url = ''
                tables['overview'].rows.append([
                    link(g.classes[name].label, url)
                    if url else g.classes[name].label,
                    format_number(count)
                ])
        for entity in Entity.get_latest(8):
            tables['latest'].rows.append([
                format_date(entity.created),
                link(entity), entity.class_.label, entity.first, entity.last,
                link(logger.get_log_for_advanced_view(entity.id)['creator'])
            ])
    tabs['info'].content = render_template('index/index.html',
                                           intro=get_translation('intro'),
                                           tables=tables)
    return render_template('tabs.html', tabs=tabs, crumbs=['overview'])
예제 #25
0
    def test_user(self) -> None:
        data = {
            'active': '',
            'username': '******',
            'email': '*****@*****.**',
            'password': '******',
            'password2': 'you_never_guess_this',
            'group': 'admin',
            'name': 'Ripley Weaver',
            'description': '',
            'send_info': ''
        }
        data2 = {
            'active': '',
            'username': '******',
            'email': '*****@*****.**',
            'password': '******',
            'password2': 'you_never_guess_this',
            'group': 'admin',
            'name': 'Newt',
            'continue_': 'yes',
            'send_info': ''
        }
        with app.app_context():  # type: ignore
            with app.test_request_context():
                app.preprocess_request()  # type: ignore
                logged_in_user = User.get_by_username('Alice')
                logged_in_user.remove_newsletter()
                if not logged_in_user:
                    abort(404)  # pragma: no cover
            rv = self.app.get(url_for('user_insert'))
            assert b'+ User' in rv.data
            rv = self.app.post(url_for('user_insert'), data=data)
            user_id = rv.location.split('/')[-1]
            data['password'] = '******'
            rv = self.app.post(url_for('user_insert'), data=data)
            assert b'match' in rv.data

            # Test insert with continue
            rv = self.app.post(url_for('user_insert'),
                               follow_redirects=True,
                               data=data2)
            assert b'Newt' not in rv.data

            rv = self.app.get(url_for('user_view', id_=user_id))
            assert b'Ripley' in rv.data
            rv = self.app.get(url_for('user_update', id_=logged_in_user.id))
            assert b'Alice' in rv.data
            data['description'] = 'The warrant officer'
            rv = self.app.post(url_for('user_update', id_=user_id),
                               data=data,
                               follow_redirects=True)
            assert b'The warrant officer' in rv.data
            rv = self.app.get(
                url_for('admin_index', action='delete_user', id_=user_id))
            assert b'User deleted' in rv.data

            # Test activity log
            data = {
                'name': 'test',
                'description': 'test'
            }  # insert a reference to show something
            self.app.post(url_for('insert', class_='bibliography'), data=data)
            rv = self.app.get(url_for('user_activity'))
            assert b'Activity' in rv.data
            rv = self.app.get(url_for('user_activity', user_id=user_id))
            assert b'Activity' in rv.data
            data = {'limit': 'all', 'action': 'all', 'user': '******'}
            rv = self.app.post(url_for('user_activity', data=data))
            assert b'Activity' in rv.data

            # Test missing permission
            self.app.get(url_for('logout'), follow_redirects=True)
            rv = self.app.get(url_for('user_insert'), follow_redirects=True)
            assert b'Forgot your password?' not in rv.data
            self.app.post('/login',
                          data={
                              'username': '******',
                              'password': '******'
                          })
            rv = self.app.get(url_for('user_insert'), follow_redirects=True)
            assert b'403 - Forbidden' in rv.data
예제 #26
0
def admin_index(action: Optional[str] = None,
                id_: Optional[int] = None) -> Union[str, Response]:
    if is_authorized('manager'):
        if id_ and action == 'delete_user':
            user = User.get_by_id(id_)
            if not user \
                    or user.id == current_user.id \
                    or (user.group == 'admin' and not is_authorized('admin')):
                abort(403)
            User.delete(id_)
            flash(_('user deleted'), 'info')
        elif action == 'remove_logo':
            Settings.set_logo()
            return redirect(f"{url_for('admin_index')}#tab-file")
    tables = {
        'user':
        Table([
            'username', 'name', 'group', 'email', 'newsletter', 'created',
            'last login', 'entities'
        ],
              defs=[{
                  'className': 'dt-body-right',
                  'targets': 7
              }]),
        'content':
        Table(['name'] + list(app.config['LANGUAGES']))
    }
    for user in User.get_all():
        count = User.get_created_entities_count(user.id)
        email = user.email \
            if is_authorized('manager') or user.settings['show_email'] else ''
        tables['user'].rows.append([
            link(user), user.real_name, user.group, email,
            _('yes') if user.settings['newsletter'] else '',
            format_date(user.created),
            format_date(user.login_last_success),
            format_number(count) if count else ''
        ])
    for item, languages in get_content().items():
        content = [uc_first(_(item))]
        for language in app.config['LANGUAGES']:
            content.append(sanitize(languages[language], 'text'))
        content.append(link(_('edit'), url_for('admin_content', item=item)))
        tables['content'].rows.append(content)
    form = None
    if is_authorized('admin'):
        form = TestMailForm()
        if form.validate_on_submit(
        ) and g.settings['mail']:  # pragma: no cover
            subject = _('Test mail from %(site_name)s',
                        site_name=g.settings['site_name'])
            body = _('This test mail was sent by %(username)s',
                     username=current_user.username)
            body += f" {_('at')} '{request.headers['Host']}"
            if send_mail(subject, body, form.receiver.data):
                flash(
                    _('A test mail was sent to %(email)s.',
                      email=form.receiver.data), 'info')
        else:
            form.receiver.data = current_user.email
    tabs = {
        'files':
        Tab(_('files'),
            buttons=[
                manual('entity/file'),
                button(_('edit'), url_for('admin_settings', category='files'))
                if is_authorized('manager') else '',
                button(_('list'), url_for('index', view='file')),
                button(_('file'), url_for('insert', class_='file'))
            ],
            content=render_template('admin/file.html',
                                    info=get_form_settings(FilesForm()),
                                    disk_space_info=get_disk_space_info())),
        'user':
        Tab(_('user'),
            table=tables['user'],
            buttons=[
                manual('admin/user'),
                button(_('activity'), url_for('user_activity')),
                button(_('newsletter'), url_for('admin_newsletter'))
                if is_authorized('manager') and g.settings['mail'] else '',
                button(_('user'), url_for('user_insert'))
                if is_authorized('manager') else ''
            ])
    }
    if is_authorized('admin'):
        tabs['general'] = Tab(
            'general',
            content=display_info(get_form_settings(GeneralForm())),
            buttons=[
                manual('admin/general'),
                button(_('edit'), url_for('admin_settings',
                                          category='general')),
                button(_('system log'), url_for('admin_log'))
            ])
        tabs['email'] = Tab(
            'email',
            content=display_info(get_form_settings(MailForm())),
            buttons=[
                manual('admin/mail'),
                button(_('edit'), url_for('admin_settings', category='mail'))
            ])
        if g.settings['mail']:
            tabs['email'].content += display_form(form)
    if is_authorized('manager'):
        tabs['modules'] = Tab(_('modules'),
                              content=f"""
                <h1>{_('Defaults for new user')}</h1>
                {display_info(get_form_settings(ModulesForm()))}""",
                              buttons=[
                                  manual('admin/modules'),
                                  button(
                                      _('edit'),
                                      url_for('admin_settings',
                                              category='modules'))
                              ])
        tabs['map'] = Tab('map',
                          content=display_info(get_form_settings(MapForm())),
                          buttons=[
                              manual('admin/map'),
                              button(_('edit'),
                                     url_for('admin_settings', category='map'))
                          ])
        tabs['content'] = Tab('content',
                              content=tables['content'].display(),
                              buttons=[manual('admin/content')])
    if is_authorized('contributor'):
        tabs['data'] = Tab('data',
                           content=render_template(
                               'admin/data.html',
                               imports=Import.get_all_projects(),
                               info=get_form_settings(ApiForm())))
    return render_template('tabs.html',
                           tabs=tabs,
                           title=_('admin'),
                           crumbs=[_('admin')])
예제 #27
0
def load_user(user_id: int) -> Optional[User]:
    return User.get_by_id(user_id, True)
예제 #28
0
def entity_view(id_: int) -> Union[str, Response]:
    if id_ in g.nodes:  # Nodes have their own view
        entity = g.nodes[id_]
        if not entity.root:
            if entity.class_.name == 'administrative_unit':
                tab_hash = '#menu-tab-places_collapse-'
            elif entity.standard:
                tab_hash = '#menu-tab-standard_collapse-'
            elif entity.value_type:
                tab_hash = '#menu-tab-value_collapse-'
            else:
                tab_hash = '#menu-tab-custom_collapse-'
            return redirect(f"{url_for('node_index')}{tab_hash}{id_}")
    elif id_ in g.reference_systems:
        entity = g.reference_systems[id_]
    else:
        entity = Entity.get_by_id(id_, nodes=True, aliases=True)
        if not entity.class_.view:
            flash(_("This entity can't be viewed directly."), 'error')
            abort(400)

    event_links = None  # Needed for actor
    overlays = None  # Needed for place
    tabs = {'info': Tab('info')}
    if isinstance(entity, Node):
        tabs['subs'] = Tab('subs', entity=entity)
        tabs['entities'] = Tab('entities', entity=entity)
        root = g.nodes[entity.root[-1]] if entity.root else None
        if root and root.value_type:  # pragma: no cover
            tabs['entities'].table.header = [
                _('name'), _('value'),
                _('class'), _('info')
            ]
        for item in entity.get_linked_entities(['P2', 'P89'],
                                               inverse=True,
                                               nodes=True):
            if item.class_.name in ['location', 'reference_system']:
                continue  # pragma: no cover
            if item.class_.name == 'object_location':  # pragma: no cover
                item = item.get_linked_entity_safe('P53', inverse=True)
            data = [link(item)]
            if root and root.value_type:  # pragma: no cover
                data.append(format_number(item.nodes[entity]))
            data.append(item.class_.label)
            data.append(item.description)
            tabs['entities'].table.rows.append(data)
        for sub_id in entity.subs:
            sub = g.nodes[sub_id]
            tabs['subs'].table.rows.append(
                [link(sub), sub.count, sub.description])
        if not tabs['entities'].table.rows:
            # If no entities available get links with this type_id
            tabs['entities'].table.header = [_('domain'), _('range')]
            for row in Link.get_entities_by_node(entity):
                tabs['entities'].table.rows.append([
                    link(Entity.get_by_id(row['domain_id'])),
                    link(Entity.get_by_id(row['range_id']))
                ])
    elif isinstance(entity, ReferenceSystem):
        for form_id, form in entity.get_forms().items():
            tabs[form['name']] = Tab(form['name'], entity=entity)
            tabs[form['name']].table = \
                Table([_('entity'), 'id', _('precision')])
        for link_ in entity.get_links('P67'):
            name = link_.description
            if entity.resolver_url:
                name = \
                    f'<a href="{entity.resolver_url + name}"' \
                    f' target="_blank" rel="noopener noreferrer">{name}</a>'
            tab_name = link_.range.class_.name
            tabs[tab_name].table.rows.append(
                [link(link_.range), name, link_.type.name])
        for form_id, form in entity.get_forms().items():
            tabs[form['name']].buttons = []
            if not tabs[form['name']].table.rows and is_authorized('manager'):
                tabs[form['name']].buttons = [
                    button(
                        _('remove'),
                        url_for('reference_system_remove_form',
                                system_id=entity.id,
                                form_id=form_id))
                ]
    elif entity.class_.view == 'actor':
        for name in [
                'source', 'event', 'relation', 'member_of', 'member',
                'artifact'
        ]:
            tabs[name] = Tab(name, entity=entity)
        event_links = entity.get_links(['P11', 'P14', 'P22', 'P23', 'P25'],
                                       True)
        for link_ in event_links:
            event = link_.domain
            places = event.get_linked_entities(['P7', 'P26', 'P27'])
            link_.object_ = None  # Needed for first/last appearance
            for place in places:
                object_ = place.get_linked_entity_safe('P53', True)
                entity.linked_places.append(object_)
                link_.object_ = object_
            first = link_.first
            if not link_.first and event.first:
                first = f'<span class="inactive">{event.first}</span>'
            last = link_.last
            if not link_.last and event.last:
                last = f'<span class="inactive">{event.last}</span>'
            data = [
                link(event), event.class_.label,
                _('moved') if link_.property.code == 'P25' else link(
                    link_.type), first, last, link_.description
            ]
            if link_.property.code == 'P25':
                data += ['']
            else:
                add_edit_link(
                    data,
                    url_for('involvement_update',
                            id_=link_.id,
                            origin_id=entity.id))
            add_remove_link(data, link_.domain.name, link_, entity, 'event')
            tabs['event'].table.rows.append(data)
        for link_ in entity.get_links('OA7') + entity.get_links('OA7', True):
            type_ = ''
            if entity.id == link_.domain.id:
                related = link_.range
                if link_.type:
                    type_ = link(link_.type.get_name_directed(),
                                 url_for('entity_view', id_=link_.type.id))
            else:
                related = link_.domain
                if link_.type:
                    type_ = link(link_.type.get_name_directed(True),
                                 url_for('entity_view', id_=link_.type.id))
            data = [
                type_,
                link(related), link_.first, link_.last, link_.description
            ]
            add_edit_link(
                data,
                url_for('relation_update', id_=link_.id, origin_id=entity.id))
            add_remove_link(data, related.name, link_, entity, 'relation')
            tabs['relation'].table.rows.append(data)
        for link_ in entity.get_links('P107', True):
            data = [
                link(link_.domain),
                link(link_.type), link_.first, link_.last, link_.description
            ]
            add_edit_link(
                data,
                url_for('member_update', id_=link_.id, origin_id=entity.id))
            add_remove_link(data, link_.domain.name, link_, entity,
                            'member-of')
            tabs['member_of'].table.rows.append(data)
        if entity.class_.name != 'group':
            del tabs['member']
        else:
            for link_ in entity.get_links('P107'):
                data = [
                    link(link_.range),
                    link(link_.type), link_.first, link_.last,
                    link_.description
                ]
                add_edit_link(
                    data,
                    url_for('member_update', id_=link_.id,
                            origin_id=entity.id))
                add_remove_link(data, link_.range.name, link_, entity,
                                'member')
                tabs['member'].table.rows.append(data)
        for link_ in entity.get_links('P52', True):
            data = [
                link(link_.domain), link_.domain.class_.label,
                link(link_.domain.standard_type), link_.domain.first,
                link_.domain.last, link_.domain.description
            ]
            tabs['artifact'].table.rows.append(data)
    elif entity.class_.view == 'artifact':
        tabs['source'] = Tab('source', entity=entity)
    elif entity.class_.view == 'event':
        for name in ['subs', 'source', 'actor']:
            tabs[name] = Tab(name, entity=entity)
        for sub_event in entity.get_linked_entities('P117',
                                                    inverse=True,
                                                    nodes=True):
            tabs['subs'].table.rows.append(get_base_table_data(sub_event))
        tabs['actor'].table.header.insert(5, _('activity'))  # Activity column
        for link_ in entity.get_links(['P11', 'P14', 'P22', 'P23']):
            first = link_.first
            if not link_.first and entity.first:
                first = f'<span class="inactive">{entity.first}</span>'
            last = link_.last
            if not link_.last and entity.last:
                last = f'<span class="inactive">{entity.last}</span>'
            data = [
                link(link_.range), link_.range.class_.label,
                link_.type.name if link_.type else '', first, last,
                g.properties[link_.property.code].name_inverse,
                link_.description
            ]
            add_edit_link(
                data,
                url_for('involvement_update',
                        id_=link_.id,
                        origin_id=entity.id))
            add_remove_link(data, link_.range.name, link_, entity, 'actor')
            tabs['actor'].table.rows.append(data)
        entity.linked_places = [
            location.get_linked_entity_safe('P53', True)
            for location in entity.get_linked_entities(['P7', 'P26', 'P27'])
        ]
    elif entity.class_.view == 'file':
        for name in [
                'source', 'event', 'actor', 'place', 'feature',
                'stratigraphic_unit', 'artifact', 'human_remains', 'reference',
                'type'
        ]:
            tabs[name] = Tab(name, entity=entity)
        entity.image_id = entity.id if get_file_path(entity.id) else None
        for link_ in entity.get_links('P67'):
            range_ = link_.range
            data = get_base_table_data(range_)
            add_remove_link(data, range_.name, link_, entity,
                            range_.class_.name)
            tabs[range_.class_.view].table.rows.append(data)
        for link_ in entity.get_links('P67', True):
            data = get_base_table_data(link_.domain)
            data.append(link_.description)
            add_edit_link(
                data,
                url_for('reference_link_update',
                        link_id=link_.id,
                        origin_id=entity.id))
            add_remove_link(data, link_.domain.name, link_, entity,
                            'reference')
            tabs['reference'].table.rows.append(data)
    elif entity.class_.view == 'place':
        tabs['source'] = Tab('source', entity=entity)
        if entity.class_.name == 'place':
            tabs['event'] = Tab('event', entity=entity)
        tabs['reference'] = Tab('reference', entity=entity)
        if entity.class_.name == 'place':
            tabs['actor'] = Tab('actor', entity=entity)
            tabs['feature'] = Tab('feature', entity=entity)
        elif entity.class_.name == 'feature':
            tabs['stratigraphic_unit'] = Tab('stratigraphic_unit',
                                             entity=entity)
        elif entity.class_.name == 'stratigraphic_unit':
            tabs['find'] = Tab('find', entity=entity)
            tabs['human_remains'] = Tab('human_remains', entity=entity)
        entity.location = entity.get_linked_entity_safe('P53', nodes=True)
        event_ids = []  # Keep track of inserted events to prevent doubles
        for event in entity.location.get_linked_entities(['P7', 'P26', 'P27'],
                                                         inverse=True):
            tabs['event'].table.rows.append(get_base_table_data(event))
            event_ids.append(event.id)
        for event in entity.get_linked_entities('P24', inverse=True):
            if event.id not in event_ids:  # Don't add again if already in table
                tabs['event'].table.rows.append(get_base_table_data(event))
        if 'actor' in tabs:
            for link_ in entity.location.get_links(['P74', 'OA8', 'OA9'],
                                                   inverse=True):
                actor = Entity.get_by_id(link_.domain.id)
                tabs['actor'].table.rows.append([
                    link(actor), g.properties[link_.property.code].name,
                    actor.class_.name, actor.first, actor.last,
                    actor.description
                ])
    elif entity.class_.view == 'reference':
        for name in [
                'source', 'event', 'actor', 'place', 'feature',
                'stratigraphic_unit', 'human_remains', 'artifact', 'file'
        ]:
            tabs[name] = Tab(name, entity=entity)
        for link_ in entity.get_links('P67'):
            range_ = link_.range
            data = get_base_table_data(range_)
            data.append(link_.description)
            add_edit_link(
                data,
                url_for('reference_link_update',
                        link_id=link_.id,
                        origin_id=entity.id))
            add_remove_link(data, range_.name, link_, entity,
                            range_.class_.name)
            tabs[range_.class_.view].table.rows.append(data)
    elif entity.class_.view == 'source':
        for name in [
                'actor', 'artifact', 'feature', 'event', 'human_remains',
                'place', 'stratigraphic_unit', 'text'
        ]:
            tabs[name] = Tab(name, entity=entity)
        for text in entity.get_linked_entities('P73', nodes=True):
            tabs['text'].table.rows.append([
                link(text),
                next(iter(text.nodes)).name if text.nodes else '',
                text.description
            ])
        for link_ in entity.get_links('P67'):
            range_ = link_.range
            data = get_base_table_data(range_)
            add_remove_link(data, range_.name, link_, entity,
                            range_.class_.name)
            tabs[range_.class_.view].table.rows.append(data)

    if entity.class_.view in [
            'actor', 'artifact', 'event', 'place', 'source', 'type'
    ]:
        if entity.class_.view != 'reference' and not isinstance(entity, Node):
            tabs['reference'] = Tab('reference', entity=entity)
        if entity.class_.view == 'artifact':
            tabs['event'] = Tab('event', entity=entity)
            for link_ in entity.get_links('P25', True):
                data = get_base_table_data(link_.domain)
                tabs['event'].table.rows.append(data)
        tabs['file'] = Tab('file', entity=entity)
        entity.image_id = entity.get_profile_image_id()
        if entity.class_.view == 'place' and is_authorized('editor') and \
                current_user.settings['module_map_overlay']:
            tabs['file'].table.header.append(uc_first(_('overlay')))
        for link_ in entity.get_links('P67', inverse=True):
            domain = link_.domain
            data = get_base_table_data(domain)
            if domain.class_.view == 'file':  # pragma: no cover
                extension = data[3]
                data.append(
                    get_profile_image_table_link(domain, entity, extension,
                                                 entity.image_id))
                if not entity.image_id \
                        and extension in app.config['DISPLAY_FILE_EXTENSIONS']:
                    entity.image_id = domain.id
                if entity.class_.view == 'place' \
                        and is_authorized('editor') \
                        and current_user.settings['module_map_overlay']:
                    overlays = Overlay.get_by_object(entity)
                    if extension in app.config['DISPLAY_FILE_EXTENSIONS']:
                        if domain.id in overlays:
                            add_edit_link(
                                data,
                                url_for('overlay_update',
                                        id_=overlays[domain.id].id))
                        else:
                            data.append(
                                link(
                                    _('link'),
                                    url_for('overlay_insert',
                                            image_id=domain.id,
                                            place_id=entity.id,
                                            link_id=link_.id)))
                    else:  # pragma: no cover
                        data.append('')
            if domain.class_.view not in ['source', 'file']:
                data.append(link_.description)
                add_edit_link(
                    data,
                    url_for('reference_link_update',
                            link_id=link_.id,
                            origin_id=entity.id))
                if domain.class_.view == 'reference_system':
                    entity.reference_systems.append(link_)
                    continue
            add_remove_link(data, domain.name, link_, entity,
                            domain.class_.view)
            tabs[domain.class_.view].table.rows.append(data)

    structure = None  # Needed for place
    gis_data = None  # Needed for place
    if entity.class_.view in ['artifact', 'place']:
        structure = get_structure(entity)
        if structure:
            for item in structure['subunits']:
                tabs[item.class_.name].table.rows.append(
                    get_base_table_data(item))
        gis_data = Gis.get_all([entity], structure)
        if gis_data['gisPointSelected'] == '[]' \
                and gis_data['gisPolygonSelected'] == '[]' \
                and gis_data['gisLineSelected'] == '[]' \
                and (not structure or not structure['super_id']):
            gis_data = {}

    if not gis_data:
        gis_data = Gis.get_all(entity.linked_places) \
            if entity.linked_places else None
    entity.info_data = get_entity_data(entity, event_links=event_links)
    tabs['note'] = Tab('note', entity=entity)
    for note in current_user.get_notes_by_entity_id(entity.id):
        data = [
            format_date(note['created']),
            uc_first(_('public'))
            if note['public'] else uc_first(_('private')),
            link(User.get_by_id(note['user_id'])), note['text'],
            f'<a href="{url_for("note_view", id_=note["id"])}">'
            f'{uc_first(_("view"))}</a>'
        ]
        tabs['note'].table.rows.append(data)
    if 'file' in tabs and current_user.settings['table_show_icons'] and \
            session['settings']['image_processing']:
        tabs['file'].table.header.insert(1, uc_first(_('icon')))
        for row in tabs['file'].table.rows:
            row.insert(
                1,
                file_preview(
                    int(row[0].replace('<a href="/entity/',
                                       '').split('"')[0])))
    tabs['info'].content = render_template(
        'entity/view.html',
        buttons=add_buttons(entity),
        entity=entity,
        gis_data=gis_data,
        structure=structure,  # Needed for place views
        overlays=overlays,  # Needed for place views
        title=entity.name)
    return render_template('tabs.html',
                           tabs=tabs,
                           gis_data=gis_data,
                           crumbs=add_crumbs(entity, structure),
                           entity=entity)
예제 #29
0
def admin_index(action: Optional[str] = None,
                id_: Optional[int] = None) -> Union[str, Response]:
    if is_authorized('manager'):
        if id_ and action == 'delete_user':
            user = User.get_by_id(id_)
            if not user \
                    or user.id == current_user.id \
                    or (user.group == 'admin' and not is_authorized('admin')):
                abort(403)  # pragma: no cover
            User.delete(id_)
            flash(_('user deleted'), 'info')
        elif action == 'remove_logo':
            Settings.set_logo()
            return redirect(url_for('admin_index') + '#tab-file')
    dirs = {
        'uploads':
        True if os.access(app.config['UPLOAD_DIR'], os.W_OK) else False,
        'export/sql':
        True if os.access(app.config['EXPORT_DIR'] /
                          'sql', os.W_OK) else False,
        'export/csv':
        True if os.access(app.config['EXPORT_DIR'] / 'csv', os.W_OK) else False
    }
    tables = {
        'user':
        Table([
            'username', 'name', 'group', 'email', 'newsletter', 'created',
            'last login', 'entities'
        ]),
        'content':
        Table(['name'] +
              [language for language in app.config['LANGUAGES'].keys()])
    }
    for user in User.get_all():
        count = User.get_created_entities_count(user.id)
        email = user.email if is_authorized(
            'manager') or user.settings['show_email'] else ''
        tables['user'].rows.append([
            link(user), user.real_name, user.group, email,
            _('yes') if user.settings['newsletter'] else '',
            format_date(user.created),
            format_date(user.login_last_success),
            format_number(count) if count else ''
        ])
    for item, languages in Content.get_content().items():
        content = [uc_first(_(item))]
        for language in app.config['LANGUAGES'].keys():
            content.append(sanitize(languages[language], 'text'))
        content.append(link(_('edit'), url_for('admin_content', item=item)))
        tables['content'].rows.append(content)
    form = None
    if is_authorized('admin'):
        form = TestMailForm()
        if form.validate_on_submit(
        ) and session['settings']['mail']:  # pragma: no cover
            subject = _('Test mail from %(site_name)s',
                        site_name=session['settings']['site_name'])
            body = _('This test mail was sent by %(username)s',
                     username=current_user.username)
            body += ' ' + _('at') + ' ' + request.headers['Host']
            if send_mail(subject, body, form.receiver.data):
                flash(
                    _('A test mail was sent to %(email)s.',
                      email=form.receiver.data), 'info')
        else:
            form.receiver.data = current_user.email
    return render_template('admin/index.html',
                           form=form,
                           tables=tables,
                           settings=session['settings'],
                           writeable_dirs=dirs,
                           disk_space_info=get_disk_space_info(),
                           imports=Import.get_all_projects(),
                           title=_('admin'),
                           crumbs=[_('admin')],
                           info={
                               'file': get_form_settings(FilesForm()),
                               'general': get_form_settings(GeneralForm()),
                               'mail': get_form_settings(MailForm()),
                               'map': get_form_settings(MapForm()),
                               'api': get_form_settings(ApiForm()),
                               'modules': get_form_settings(ModulesForm())
                           })
예제 #30
0
def ajax_bookmark() -> str:
    return jsonify(uc_first(User.toggle_bookmark(request.form['entity_id'])))