Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose user blocking in the admin UI #4363

Merged
merged 8 commits into from Apr 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGES.rst
Expand Up @@ -60,6 +60,9 @@ Improvements
thanks :user:`giusedb` & :user:`omegak`)
- Add category navigation dialog on category display page (:issue:`4282`,
thanks :user:`omegak`)
- Add UI for admins to block/unblock users (:issue:`3243`)
- Show labels indicating whether a user is an admin, blocked or soft-deleted
(:issue:`4363`)

Bugfixes
^^^^^^^^
Expand Down
7 changes: 5 additions & 2 deletions indico/cli/user.py
Expand Up @@ -62,6 +62,8 @@ def _safe_lower(s):
help='Include deleted users in the results')
@click.option('--include-pending', '-P', is_flag=True,
help='Include pending users in the results')
@click.option('--include-blocked', '-B', is_flag=True,
help='Include blocked users in the results')
@click.option('--include-external', '-X', is_flag=True,
help='Also include external users (e.g. from LDAP). This is potentially very slow in substring mode')
@click.option('--include-system', '-S', is_flag=True,
Expand All @@ -70,12 +72,13 @@ def _safe_lower(s):
@click.option('--last-name', '-s', help='Last name of the user')
@click.option('--email', '-e', help='Email address of the user')
@click.option('--affiliation', '-a', help='Affiliation of the user')
def search(substring, include_deleted, include_pending, include_external, include_system, **criteria):
def search(substring, include_deleted, include_pending, include_blocked, include_external, include_system, **criteria):
"""Searches users matching some criteria"""
assert set(criteria.viewkeys()) == {'first_name', 'last_name', 'email', 'affiliation'}
criteria = {k: v for k, v in criteria.viewitems() if v is not None}
res = search_users(exact=(not substring), include_deleted=include_deleted, include_pending=include_pending,
external=include_external, allow_system_user=include_system, **criteria)
include_blocked=include_blocked, external=include_external,
allow_system_user=include_system, **criteria)
if not res:
print(cformat('%{yellow}No results found'))
return
Expand Down
48 changes: 37 additions & 11 deletions indico/modules/api/templates/user_profile.html
Expand Up @@ -12,15 +12,24 @@
{% if key and can_modify %}
<div class="i-box-buttons toolbar">
<div class="group">
<button type="button" class="i-button warning icon-plus" data-href="{{ url_for('.key_create') }}" data-method="post"
<button type="button"
class="ui orange small button"
data-href="{{ url_for('.key_create') }}"
data-method="post"
data-params='{"force": "1"}'
data-title="{% trans %}Create new API key{% endtrans %}"
data-confirm="{% trans %}Do you really want to create a new API key? Your old key will stop working immediately!{% endtrans %}">
data-confirm="{% trans %}Do you really want to create a new API key?
Your old key will stop working immediately!{% endtrans %}">
<i aria-hidden="true" class="icon plus"></i>
{%- trans %}Create new API key{% endtrans -%}
</button>
<button type="button" class="i-button danger icon-remove" data-href="{{ url_for('.key_delete') }}" data-method="post"
<button type="button"
class="ui negative small button"
data-href="{{ url_for('.key_delete') }}"
data-method="post"
data-title="{% trans %}Delete API key{% endtrans %}"
data-confirm="{% trans %}Do you really want to delete your API key?{% endtrans %}">
<i aria-hidden="true" class="icon trash alternate"></i>
{%- trans %}Delete API key{% endtrans -%}
</button>
</div>
Expand All @@ -36,7 +45,10 @@
{%- endtrans -%}
</p>

<button type="button" class="i-button highlight" data-href="{{ url_for('.key_create') }}" data-method="post">
<button type="button"
class="ui primary button"
data-href="{{ url_for('.key_create') }}"
data-method="post">
{%- trans %}Create API key{% endtrans -%}
</button>
{% else %}
Expand All @@ -45,7 +57,10 @@
<dd>
{{ key.token }}
{% if key.is_blocked %}
<i class="icon-warning warningText" title="{% trans %}Your API key has been blocked. Please contact an administrator for further details.{% endtrans %}"></i>
<i class="icon-warning warningText"
title="{% trans %}Your API key has been blocked.
Please contact an administrator for further details.{% endtrans %}">
</i>
{% endif %}
</dd>
{% if use_signatures %}
Expand All @@ -69,9 +84,13 @@
<dd>
{{ key.last_used_uri }}
{% if key.last_used_auth %}
<i class="icon-shield" title="{% trans %}Last request could access private data.{% endtrans %}"></i>
<i class="icon-shield"
title="{% trans %}Last request could access private data.{% endtrans %}">
</i>
{% else %}
<i class="icon-earth" title="{% trans %}Last request could only access public data.{% endtrans %}"></i>
<i class="icon-earth"
title="{% trans %}Last request could only access public data.{% endtrans %}">
</i>
{% endif %}
</dd>
{% endif %}
Expand Down Expand Up @@ -99,10 +118,12 @@
<div class="i-box-buttons toolbar">
<div class="group">
<button type="button"
class="i-button warning icon-remove"
class="ui negative small button"
data-href="{{ url_for('core.reset_signature_tokens') }}"
data-method="POST"
data-confirm="{% trans %}Are you sure you'd like to invalidate all your token-based links?{% endtrans %}">
data-confirm="{% trans %}Are you sure you'd like to invalidate all your
token-based links?{% endtrans %}">
<i aria-hidden="true" class="icon trash alternate"></i>
{%- trans %}Invalidate all links{% endtrans -%}
</button>
</div>
Expand All @@ -128,13 +149,18 @@
<div class="i-box-buttons toolbar">
<div class="group">
{% if key.is_blocked %}
<button type="button" class="i-button accept" data-href="{{ url_for('.key_block') }}"
<button type="button"
class="ui positive small button"
data-href="{{ url_for('.key_block') }}"
data-method="post">
{%- trans %}Unblock API key{% endtrans -%}
</button>
{% else %}
<button type="button" class="i-button warning icon-disable" data-href="{{ url_for('.key_block') }}"
<button type="button"
class="ui negative small button"
data-href="{{ url_for('.key_block') }}"
data-method="post">
<i aria-hidden="true" class="icon ban"></i>
{%- trans %}Block API key{% endtrans -%}
</button>
{% endif %}
Expand Down
42 changes: 21 additions & 21 deletions indico/modules/auth/templates/accounts.html
Expand Up @@ -20,9 +20,9 @@
{{ form_header(form, orientation='vertical', classes='no-block-padding') }}
{{ form_rows(form) }}
{% call form_footer(form) %}
<input class="i-button big highlight" type="submit"
<input class="ui primary button" type="submit"
value="{% trans %}Create account{% endtrans %}" data-disabled-until-change>
<a href="#" class="i-button big js-hide-form">
<a href="#" class="ui negative button js-hide-form">
{% trans %}Cancel{% endtrans %}
</a>
{% endcall %}
Expand All @@ -31,7 +31,7 @@
{{ form_header(form, orientation='vertical', classes='no-block-padding') }}
{{ form_rows(form) }}
{% call form_footer(form) %}
<input class="i-button big highlight" type="submit" value="{% trans %}Modify credentials{% endtrans %}" data-disabled-until-change>
<input class="ui primary button" type="submit" value="{% trans %}Modify credentials{% endtrans %}" data-disabled-until-change>
{% endcall %}
{% endif %}
{% if user.secondary_local_identities %}
Expand Down Expand Up @@ -70,7 +70,7 @@
</span>
</span>
</span>
<button class="i-button"
<button class="ui negative small button"
data-href="{{ url_for('.remove_account', identity) }}"
data-method="post"
data-title="{% trans %}Remove account{% endtrans %}"
Expand Down Expand Up @@ -99,35 +99,35 @@
<ul class="group-list with-buttons">
{% if user.external_identities %}
{% for identity in user.external_identities | sort(attribute='safe_last_login_dt', reverse=True) %}
<li>
<li class="flexrow f-a-center">
<span class="list-item-title">
{{ provider_titles[identity.provider] }}
</span>
<small>
({{ identity.identifier }})
</small>
<span>
<small>
({{ identity.identifier }})
</small>
</span>
<span class="right">
<span class="list-item-info">
<span>
<span class="label">
{% trans %}Last login:{% endtrans %}
</span>
<span class="content">
{% if identity.last_login_dt %}
{{ identity.last_login_dt | format_datetime('short') }}
{% else %}
{% trans %}Never{% endtrans %}
{% endif %}
</span>
<span class="label">
{% trans %}Last login:{% endtrans %}
</span>
<span class="content">
{% if identity.last_login_dt %}
{{ identity.last_login_dt | format_datetime('short') }}
{% else %}
{% trans %}Never{% endtrans %}
{% endif %}
</span>
</span>
{% if identity.id == session.login_identity %}
<button class="i-button" disabled
<button class="ui primary tiny button" disabled
title="{% trans %}The account used to log in cannot be unlinked{% endtrans %}">
{% trans %}Unlink{% endtrans %}
</button>
{% else %}
<button class="i-button right"
<button class="ui primary tiny button right"
data-href="{{ url_for('.remove_account', identity) }}"
data-method="post"
data-title="{% trans %}Unlink account{% endtrans %}"
Expand Down
5 changes: 2 additions & 3 deletions indico/modules/events/features/controllers.py
Expand Up @@ -17,7 +17,7 @@
from indico.modules.events.features.views import WPFeatures
from indico.modules.events.logs import EventLogKind, EventLogRealm
from indico.modules.events.management.controllers import RHManageEventBase
from indico.util.i18n import _, ngettext
from indico.util.i18n import ngettext
from indico.web.forms.base import FormDefaults, IndicoForm
from indico.web.forms.widgets import SwitchWidget
from indico.web.menu import render_sidemenu
Expand All @@ -37,8 +37,7 @@ def _make_form(self):
for name, feature in sorted(get_feature_definitions().iteritems(), key=lambda x: x[1].friendly_name):
if name in disallowed:
continue
field = BooleanField(feature.friendly_name, widget=SwitchWidget(on_label=_('On'), off_label=_('Off')),
description=feature.description)
field = BooleanField(feature.friendly_name, widget=SwitchWidget(), description=feature.description)
setattr(form_class, name, field)
defaults = {name: True for name in get_enabled_features(self.event)}
return form_class(csrf_enabled=False, obj=FormDefaults(defaults))
Expand Down
2 changes: 1 addition & 1 deletion indico/modules/events/layout/forms.py
Expand Up @@ -68,7 +68,7 @@ class ConferenceLayoutForm(LoggedLayoutForm):
description=_("Enable search within the event"))
show_nav_bar = BooleanField(_("Show navigation bar"), widget=SwitchWidget(),
description=_("Show the navigation bar at the top"))
show_banner = BooleanField(_("\"Now happening\""), widget=SwitchWidget(on_label=_("ON"), off_label=_("OFF")),
show_banner = BooleanField(_("\"Now happening\""), widget=SwitchWidget(),
description=_("Show a banner with the current entries from the timetable"))
show_social_badges = BooleanField(_("Show social badges"), widget=SwitchWidget())
name_format = IndicoEnumSelectField(_('Name format'), enum=NameFormat, none=_('Inherit from user preferences'),
Expand Down
Expand Up @@ -16,7 +16,7 @@
{{- sess.title -}}
</a>
</span>
<div class="group">
<div class="group f-self-no-shrink">
{% if sess.can_manage(session.user) %}
<a href="#" class="icon-edit" title="{% trans %}Edit session{% endtrans %}"
data-title="{% trans title=sess.title %}Edit session '{{ title }}'{% endtrans %}"
Expand Down
6 changes: 3 additions & 3 deletions indico/modules/oauth/templates/user_profile.html
Expand Up @@ -9,15 +9,15 @@
</div>
</div>
<div class="i-box-content">
<p>{% trans %}This is the list of applications your authorized to access your Indico data.{% endtrans %}</p>
<p>{% trans %}This is the list of applications you authorized to access your Indico data.{% endtrans %}</p>
<ul class="group-list with-buttons">
{% if not tokens %}
<li class="italic">
{%- trans %}No third party applications have been authorized.{% endtrans -%}
</li>
{% endif %}
{% for token in tokens|sort(attribute='application.name') %}
<li>
<li class="flexrow f-a-center">
<span class="list-item-title">{{ token.application.name }}</span>
<span class="right">
<span class="list-item-info">
Expand All @@ -30,7 +30,7 @@
{% endif %}
</span>
</span>
<button class="i-button"
<button class="ui negative small button"
data-href="{{ url_for('.user_token_revoke', token) }}"
data-method="POST"
data-confirm="{% trans app_name=token.application.name %}{{ app_name }} will no longer have access to your Indico data.<br>
Expand Down