diff --git a/src/backoffice/locale/de/LC_MESSAGES/django.po b/src/backoffice/locale/de/LC_MESSAGES/django.po
index e57363e86ff8f9d1f5b5d93e8bc7c8be4ce5cb7f..d7e394ca93b3a576c1441fa8cba3f3a4f16cbb2f 100644
--- a/src/backoffice/locale/de/LC_MESSAGES/django.po
+++ b/src/backoffice/locale/de/LC_MESSAGES/django.po
@@ -171,6 +171,9 @@ msgstr "Dieser Badge wird auch bei den Nutzern entfernt. Dies kann nicht rückg
 msgid "Badge__valid__Permanent__Redeem__tokens"
 msgstr "Aktive Redeem Tokens (Permanent, Map und Limited)"
 
+msgid "delete"
+msgstr "entfernen"
+
 msgid "Badge-new"
 msgstr "Neues Badge"
 
@@ -258,9 +261,6 @@ msgstr "bitte wählen"
 msgid "add"
 msgstr "hinzufügen"
 
-msgid "delete"
-msgstr "entfernen"
-
 msgid "assemblyedit_addlink"
 msgstr "Bezug zu anderer Assembly herstellen"
 
diff --git a/src/backoffice/locale/en/LC_MESSAGES/django.po b/src/backoffice/locale/en/LC_MESSAGES/django.po
index 7fad31971447260796ffb544bb069f2a10f7871b..0b4c88cbb30bbbc95e77c4b1afaada2cdb82dafb 100644
--- a/src/backoffice/locale/en/LC_MESSAGES/django.po
+++ b/src/backoffice/locale/en/LC_MESSAGES/django.po
@@ -171,6 +171,9 @@ msgstr "This badge will be removed from users as well. This cannot be undone. Ar
 msgid "Badge__valid__Permanent__Redeem__tokens"
 msgstr "Active Redeem Tokens (Permanent, Map und Limited)"
 
+msgid "delete"
+msgstr "delete"
+
 msgid "Badge-new"
 msgstr "new badge"
 
@@ -258,9 +261,6 @@ msgstr "please select"
 msgid "add"
 msgstr "add"
 
-msgid "delete"
-msgstr "delete"
-
 msgid "assemblyedit_addlink"
 msgstr "Associate with another assembly"
 
diff --git a/src/backoffice/templates/backoffice/user-block.html b/src/backoffice/templates/backoffice/user-block.html
index a558316489e1108fb18bde21460a7f7d2c8032a2..73be08b4bbd7c6028eb7d24777ed2cfe630da779 100644
--- a/src/backoffice/templates/backoffice/user-block.html
+++ b/src/backoffice/templates/backoffice/user-block.html
@@ -26,7 +26,7 @@
           {% endif %}
 
           {% if object.id != user.id %}
-          <button type="submit" class="btn btn-danger" disabled><strong>{{ object.username }}</strong> aus der Konferenz werfen</button>
+          <button type="submit" class="btn btn-danger"><strong>{{ object.username }}</strong> aus der Konferenz werfen</button>
           {% else %}
           <button type="submit" class="btn btn-danger" onclick="return confirm('virtuellen Selbstmord begehen?!')">eigenen Account (<strong>{{ object.username }}</strong>) aus der Konferenz werfen</button>
           {% endif %}
diff --git a/src/backoffice/templates/backoffice/user-detail.html b/src/backoffice/templates/backoffice/user-detail.html
index 936cb8929e3e11b416e5f30fbf9aeebd5d97da66..43af4c58667378f2c49a52d218e196d985320bdb 100644
--- a/src/backoffice/templates/backoffice/user-detail.html
+++ b/src/backoffice/templates/backoffice/user-detail.html
@@ -17,6 +17,16 @@
     {{ object.username }}
   </div>
   <div class="card-body">
+    {% if not object.is_active %}
+    <div class="alert alert-danger">
+      DISABLED USER
+    </div>
+    {% endif %}
+    {% if object.shadow_banned %}
+    <div class="alert alert-warning">
+      SHADOW BANNED
+    </div>
+    {% endif %}
     <form>
       <fieldset disabled>
         <div class="form-row">
@@ -93,7 +103,8 @@
     <div class="card">
       <div class="card-header">Actions</div>
       <div class="card-body text-center">
-        <p><a href="{% url 'backoffice:user-block' pk=object.pk %}" class="btn btn-default border-danger">{% if object.is_active %}🛑<br>block user{% else %}🛴<br>unblock user{% endif %}</a></p>
+        {% if can_block %}<p>{% if object.is_active %}<a href="{% url 'backoffice:user-block' pk=object.pk %}" class="btn btn-default border-danger">🛑<br>block user</a></p>{% endif %}{% endif %}
+        {% if can_rename %}<p><a href="{% url 'backoffice:user-rename' pk=object.pk %}" class="btn btn-default border-primary">🛴<br>rename user</a></p>{% endif %}
         <p><a href="javascript:alert('TODO')" class="btn btn-default border-primary">✉<br>message</a></p>
       </div>
     </div>
diff --git a/src/backoffice/templates/backoffice/user-list.html b/src/backoffice/templates/backoffice/user-list.html
index b33dd8341f8cf42a3b43e8c45a23afe8e71ccba9..82ca8ced68bc84f2bc341a2fdd6f1b76700fc324 100644
--- a/src/backoffice/templates/backoffice/user-list.html
+++ b/src/backoffice/templates/backoffice/user-list.html
@@ -5,9 +5,14 @@
 
 <div class="card">
   <div class="card-body">
+    search {{ usercount }} users:
     <form action="{% url 'backoffice:users' %}" method="POST" class="form-inline">{% csrf_token %}
       <input type="text" class="form-control" name="search" placeholder="username, displayname, ..." value="{{ search_term }}">
-      <button type="submit" class="btn btn-primary ml-2">🔍</button>
+
+      <button type="submit" class="btn btn-primary mx-2">🔍</button>
+
+      <input type="checkbox" id="idmyconf" name="myconf"{% if myconf %} checked{% endif %}>
+      <label for="idmyconf">limit to participants</label>
     </form>
   </div>
 </div>
@@ -29,7 +34,7 @@
     </thead>
     <tbody>
       {% for obj in object_list %}
-      <tr>
+      <tr{% if not obj.is_active %} style="text-decoration: line-through;"{% endif %}>
         <td>{% if obj.is_staff or obj.is_conference_staff %}<span title="staff">⚙</span>{% endif %}</td>
         <td>{% if obj.active_conference_angel %}<span title="angel">🧚</span>{% endif %}</td>
         <td><a href="{% url 'backoffice:user-detail' pk=obj.pk %}">{{ obj.username }}</a></td>
diff --git a/src/backoffice/templates/backoffice/user-rename.html b/src/backoffice/templates/backoffice/user-rename.html
new file mode 100644
index 0000000000000000000000000000000000000000..0b7b5dfa06b84e6624b3de2f2a4cff0fa0d4a2fb
--- /dev/null
+++ b/src/backoffice/templates/backoffice/user-rename.html
@@ -0,0 +1,31 @@
+{% extends 'backoffice/base.html' %}
+{% load i18n %}
+
+{% block content %}
+
+<div class="row">
+  <div class="col-md-10">
+    <div class="card border-primary">
+      <div class="card-header bg-primary">
+        <a href="{% url 'backoffice:user-detail' pk=object.pk %}" class="text-white"><< zurück</a>
+      </div>
+      <div class="card-body">
+        <form action="{% url 'backoffice:user-rename' pk=object.pk %}" method="POST" class="form">{% csrf_token %}
+          Username: <strong>{{ object.username }}</strong>
+
+          <div class="form-group">
+             <label for="idNewName">change to:</label>
+             <input type="text" id="idNewName" class="form-control" name="new_name" value="" placeholder="{{ object.username }}">
+          </div>
+
+          <button type="submit" class="btn btn-primary">Rename user</button>
+        </form>
+      </div>
+    </div>
+  </div>
+
+  <div class="col-md-2">
+    {% include 'backoffice/user-sidebar.html' %}
+  </div>
+</div>
+{% endblock %}
\ No newline at end of file
diff --git a/src/backoffice/urls.py b/src/backoffice/urls.py
index 6f7685c07cf6af000434e1d8e1ef4790e576bf0f..3e9495d1c85c39081aac17c3ade8f314403cdde2 100644
--- a/src/backoffice/urls.py
+++ b/src/backoffice/urls.py
@@ -75,6 +75,7 @@ urlpatterns = [
     path('users', users.UsersView.as_view(), name='users'),
     path('users/<int:pk>', users.UserView.as_view(), name='user-detail'),
     path('users/<int:pk>/block', users.UserBlockView.as_view(), name='user-block'),
+    path('users/<int:pk>/rename', users.UserRenameView.as_view(), name='user-rename'),
 
     path('set_language', misc.SetLanguageView.as_view(), name='set_language'),
 ]
diff --git a/src/backoffice/views/mixins.py b/src/backoffice/views/mixins.py
index 916c1e05b69d8c130095983449bc25dd1718eff4..63b691657dcac1782e28ef93af196a1d278da9d7 100644
--- a/src/backoffice/views/mixins.py
+++ b/src/backoffice/views/mixins.py
@@ -89,7 +89,7 @@ class ConferenceMixin(PermissionRequiredMixin):
             context.update({
                 'has_assemblies': self.is_assembly_team,
                 'has_pages': self.request.user.has_conference_staffpermission(self.conference, 'core.static_pages'),
-                'has_users': self.request.user.has_conference_staffpermission(self.conference, 'core.view_platformuser', 'core.block_platformuser'),
+                'has_users': self.request.user.has_conference_staffpermission(self.conference, 'core.platformusers', 'core.block_platformuser'),
             })
         else:
             context.update({
diff --git a/src/backoffice/views/users.py b/src/backoffice/views/users.py
index cc353f765824ad16ffa405cafaf655a5dbcda77e..3929b0a5a3922d4ed7a665101bc7f3a3aeb3ab11 100644
--- a/src/backoffice/views/users.py
+++ b/src/backoffice/views/users.py
@@ -1,13 +1,18 @@
 import logging
 
 from django.contrib import messages
+from django.contrib.sessions.exceptions import SuspiciousSession
+from django.contrib.sessions.models import Session
 from django.db.models import F
 from django.shortcuts import redirect, render
 from django.views.generic import DetailView, TemplateView
 
+from oauth2_provider.models import AccessToken
+
 from core.models.conference import ConferenceMember
 from core.models.users import PlatformUser
 
+
 from .mixins import ConferenceMixin
 
 
@@ -16,13 +21,19 @@ MAX_ROWS = 42
 
 
 class UsersView(ConferenceMixin, TemplateView):
-    permissions_required = ['core.view_platformuser']
+    permissions_required = ['core.platformusers']
     template_name = 'backoffice/user-list.html'
 
     def get_context_data(self, *args, **kwargs):
         ctx = super().get_context_data(*args, **kwargs)
         ctx['active_page'] = 'users'
         ctx['object_list'] = None
+        ctx['usercount'] = PlatformUser.objects.count()
+        ctx['myconf'] = self.request.method == 'GET' or 'myconf' in self.request.POST
+
+        ctx['can_block'] = self.request.user.has_conference_staffpermission(self.conference, 'core.block_platformuser')
+        ctx['can_rename'] = self.request.user.has_conference_staffpermission(self.conference, 'core.rename_platformuser')
+
         return ctx
 
     def post(self, *args, **kwargs):
@@ -31,7 +42,9 @@ class UsersView(ConferenceMixin, TemplateView):
             messages.error(self.request, 'Minimum 3 Zeichen!')
             return self.get(*args, **kwargs)
 
-        qs = PlatformUser.objects.filter(conferences__conference=self.conference, user_type=PlatformUser.Type.HUMAN)
+        qs = PlatformUser.objects.filter(user_type=PlatformUser.Type.HUMAN)
+        if 'myconf' in self.request.POST:
+            qs = qs.filter(conferences__conference=self.conference)
         qs = qs.annotate(is_conference_staff=F('conferences__is_staff'), active_conference_angel=F('conferences__active_angel'))
         qs = qs.filter(username__icontains=search_term)
         qs = qs.order_by('username')
@@ -51,7 +64,7 @@ class UsersView(ConferenceMixin, TemplateView):
 
 class UserView(ConferenceMixin, DetailView):
     model = PlatformUser
-    permissions_required = ['core.view_platformuser']
+    permissions_required = ['core.platformusers']
     template_name = 'backoffice/user-detail.html'
 
     def get_context_data(self, *args, **kwargs):
@@ -84,6 +97,72 @@ class UserBlockView(ConferenceMixin, DetailView):
         return ctx
 
     def post(self, *args, **kwargs):
-        obj = self.get_object()
-        messages.error(self.request, 'User blockieren ist noch nicht implementiert!')
-        return redirect('backoffice:user-detail', pk=obj.pk)
+        user = self.get_object()
+
+        user.is_active = False
+        user.save()
+        messages.success(self.request, 'User disabled: ' + user.username)
+        logger.warning('User "%s" was disabled by %s.', user.username, self.request.user)
+
+        log = []
+        deleted_access_tokens = 0
+        for token in AccessToken.objects.filter(user_id=user.id):
+            log.append(str(token.application))
+            token.delete()
+            deleted_access_tokens += 1
+
+        if deleted_access_tokens > 0:
+            messages.info(self.request, f'OAuth2 access token by {user.username} deleted for application(s):\n' + ',\n'.join(log))
+        else:
+            messages.info(self.request, f'No OAuth2 access tokens by {user.username} to be deleted.')
+
+        deleted_sessions = 0
+        for session in Session.objects.all():
+            try:
+                session_data = session.get_decoded()
+                if session_data.get('_auth_user_id') == str(user.pk) and session_data.get('_auth_user_backend') == 'django.contrib.auth.backends.ModelBackend':
+                    session.delete()
+                    deleted_sessions += 1
+
+            except SuspiciousSession:
+                # while we are at it, delete the errornous session, too
+                session.delete()
+
+        if deleted_sessions > 0:
+            messages.info(self.request, f'Deleted {deleted_sessions} sessions.')
+        else:
+            messages.info(self.request, 'No sessions to delete o.O')
+
+        return redirect('backoffice:user-detail', pk=user.pk)
+
+
+class UserRenameView(ConferenceMixin, DetailView):
+    model = PlatformUser
+    permissions_required = ['core.rename_platformuser']
+    template_name = 'backoffice/user-rename.html'
+
+    def get_context_data(self, *args, **kwargs):
+        ctx = super().get_context_data(*args, **kwargs)
+
+        ctx['active_page'] = 'users'
+
+        return ctx
+
+    def post(self, *args, **kwargs):
+        user = self.get_object()
+
+        new_name = self.request.POST.get('new_name', '').strip()
+        if new_name == '' or new_name == user.username:
+            return self.get(*args, **kwargs)
+
+        if PlatformUser.objects.filter(username=new_name):
+            messages.error(self.request, f'Username "{new_name}" exists, won\'t rename "{user.username}"!')
+            return self.get(*args, **kwargs)
+
+        old_name = user.username
+        user.username = new_name
+        user.save()
+        messages.success(self.request, f'Renamed user "{old_name}" to "{new_name}".')
+        logger.warning('Renamed user "%s" to "%s".', old_name, new_name)
+
+        return redirect('backoffice:user-detail', pk=user.pk)
diff --git a/src/core/migrations/0055_backoffice_users_perms.py b/src/core/migrations/0055_backoffice_users_perms.py
new file mode 100644
index 0000000000000000000000000000000000000000..e1db3877e2b43ebcca6113e08df6a5fe10033033
--- /dev/null
+++ b/src/core/migrations/0055_backoffice_users_perms.py
@@ -0,0 +1,17 @@
+# Generated by Django 3.1.3 on 2020-12-29 02:00
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0054_UserBadgeGrammar'),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name='conferencemember',
+            options={'permissions': [('assembly_team', 'ConferenceMember__permission-assembly_team'), ('static_pages', 'ConferenceMember__permission-static_pages'), ('platformusers', 'Orga: Users List'), ('rename_platformuser', 'Orga: Rename User'), ('block_platformuser', 'ConferenceMember__permission-block_platformuser'), ('change_conferencemember__active_angel', 'ConferenceMember__permission-change_conferencemember__active_angel'), ('view_platformuser__guardian', 'ConferenceMember__permission-view_platformuser__guardian')]},
+        ),
+    ]
diff --git a/src/core/models/conference.py b/src/core/models/conference.py
index 773a09b1e4a4e9d0fb5387147fdf9b95569c7885..5e2204e49f647c07a00e1f897efc4f36003d6fcd 100644
--- a/src/core/models/conference.py
+++ b/src/core/models/conference.py
@@ -33,6 +33,9 @@ class ConferenceMember(models.Model):
             ('static_pages', _('ConferenceMember__permission-static_pages')),
             # Access to static pages, can be further limited by configuring static_page_groups.
 
+            ('platformusers', 'Orga: Users List'),
+            ('rename_platformuser', 'Orga: Rename User'),
+
             ('block_platformuser', _('ConferenceMember__permission-block_platformuser')),
             # This is the right to block a misbehaving user.