diff --git a/api/funkwhale_api/federation/models.py b/api/funkwhale_api/federation/models.py
index ad88422e4f97f5259277c9b40617e43f9361be08..35b15b6678f5537da7a6f8d2b0f0c8d12c5100d5 100644
--- a/api/funkwhale_api/federation/models.py
+++ b/api/funkwhale_api/federation/models.py
@@ -61,16 +61,6 @@ class ActorQuerySet(models.QuerySet):
 
         return qs
 
-    def with_outbox_activities_count(self):
-        return self.annotate(
-            outbox_activities_count=models.Count("outbox_activities", distinct=True)
-        )
-
-    def with_followers_count(self):
-        return self.annotate(
-            followers_count=models.Count("received_follows", distinct=True)
-        )
-
     def with_uploads_count(self):
         return self.annotate(
             uploads_count=models.Count("libraries__uploads", distinct=True)
@@ -86,7 +76,9 @@ class DomainQuerySet(models.QuerySet):
 
     def with_outbox_activities_count(self):
         return self.annotate(
-            outbox_activities_count=models.Count("actors__outbox_activities", distinct=True)
+            outbox_activities_count=models.Count(
+                "actors__outbox_activities", distinct=True
+            )
         )
 
 
@@ -186,10 +178,10 @@ class Actor(models.Model):
 
     @property
     def full_username(self):
-        return "{}@{}".format(self.preferred_username, self.domain)
+        return "{}@{}".format(self.preferred_username, self.domain_id)
 
     def __str__(self):
-        return "{}@{}".format(self.preferred_username, self.domain)
+        return "{}@{}".format(self.preferred_username, self.domain_id)
 
     @property
     def is_local(self):
@@ -217,6 +209,35 @@ class Actor(models.Model):
         data["total"] = sum(data.values())
         return data
 
+    def get_stats(self):
+        from funkwhale_api.music import models as music_models
+
+        data = Actor.objects.filter(pk=self.pk).aggregate(
+            outbox_activities=models.Count("outbox_activities", distinct=True),
+            libraries=models.Count("libraries", distinct=True),
+            received_library_follows=models.Count(
+                "libraries__received_follows", distinct=True
+            ),
+            emitted_library_follows=models.Count("library_follows", distinct=True),
+        )
+        data["artists"] = music_models.Artist.objects.filter(
+            from_activity__actor=self.pk
+        ).count()
+        data["albums"] = music_models.Album.objects.filter(
+            from_activity__actor=self.pk
+        ).count()
+        data["tracks"] = music_models.Track.objects.filter(
+            from_activity__actor=self.pk
+        ).count()
+
+        uploads = music_models.Upload.objects.filter(library__actor=self.pk)
+        data["uploads"] = uploads.count()
+        data["media_total_size"] = uploads.aggregate(v=models.Sum("size"))["v"] or 0
+        data["media_downloaded_size"] = (
+            uploads.with_file().aggregate(v=models.Sum("size"))["v"] or 0
+        )
+        return data
+
 
 class InboxItem(models.Model):
     """
diff --git a/api/funkwhale_api/manage/filters.py b/api/funkwhale_api/manage/filters.py
index dfb901924fe7d2d9b112585891f8636a161cd985..51648298a1ad92e96289ffbb08c5de3d57c52333 100644
--- a/api/funkwhale_api/manage/filters.py
+++ b/api/funkwhale_api/manage/filters.py
@@ -37,10 +37,15 @@ class ManageActorFilterSet(filters.FilterSet):
             search_fields={
                 "name": {"to": "name"},
                 "username": {"to": "preferred_username"},
+                "email": {"to": "user__email"},
                 "bio": {"to": "summary"},
                 "type": {"to": "type"},
             },
-            filter_fields={"domain": {"to": "domain_id__iexact"}},
+            filter_fields={
+                "domain": {"to": "domain__name__iexact"},
+                "username": {"to": "preferred_username__iexact"},
+                "email": {"to": "user__email__iexact"},
+            },
         )
     )
     local = filters.BooleanFilter(name="_", method="filter_local")
diff --git a/api/funkwhale_api/manage/serializers.py b/api/funkwhale_api/manage/serializers.py
index 3b06fb84850bd581c87ebe78dffb3b7433f0f83e..76d0cf05fc49fb789e10385ad8dd4cb3f3e719e1 100644
--- a/api/funkwhale_api/manage/serializers.py
+++ b/api/funkwhale_api/manage/serializers.py
@@ -116,6 +116,7 @@ class ManageUserSerializer(serializers.ModelSerializer):
             "permissions",
             "privacy_level",
             "upload_quota",
+            "full_username",
         )
         read_only_fields = [
             "id",
@@ -194,9 +195,8 @@ class ManageDomainSerializer(serializers.ModelSerializer):
 
 
 class ManageActorSerializer(serializers.ModelSerializer):
-    outbox_activities_count = serializers.SerializerMethodField()
     uploads_count = serializers.SerializerMethodField()
-    followers_count = serializers.SerializerMethodField()
+    user = ManageUserSerializer()
 
     class Meta:
         model = federation_models.Actor
@@ -205,6 +205,7 @@ class ManageActorSerializer(serializers.ModelSerializer):
             "url",
             "fid",
             "preferred_username",
+            "full_username",
             "domain",
             "name",
             "summary",
@@ -215,16 +216,9 @@ class ManageActorSerializer(serializers.ModelSerializer):
             "outbox_url",
             "shared_inbox_url",
             "manually_approves_followers",
-            "outbox_activities_count",
             "uploads_count",
-            "followers_count",
+            "user",
         ]
 
     def get_uploads_count(self, o):
         return getattr(o, "uploads_count", 0)
-
-    def get_followers_count(self, o):
-        return getattr(o, "followers_count", 0)
-
-    def get_outbox_activities_count(self, o):
-        return getattr(o, "outbox_activities_count", 0)
diff --git a/api/funkwhale_api/manage/views.py b/api/funkwhale_api/manage/views.py
index ddd4fe571479ba2fd48e7c410381ec9f0103b9b2..0697c6c14e3609fc32c508807312d47913e11407 100644
--- a/api/funkwhale_api/manage/views.py
+++ b/api/funkwhale_api/manage/views.py
@@ -138,10 +138,9 @@ class ManageActorViewSet(
     lookup_value_regex = r"([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+)"
     queryset = (
         federation_models.Actor.objects.all()
-        .with_outbox_activities_count()
-        .with_followers_count()
         .with_uploads_count()
         .order_by("-creation_date")
+        .select_related("user")
     )
     serializer_class = serializers.ManageActorSerializer
     filter_class = filters.ManageActorFilterSet
@@ -155,7 +154,6 @@ class ManageActorViewSet(
         "creation_date",
         "last_fetch_date",
         "uploads_count",
-        "followers_count",
         "outbox_activities_count",
     ]
 
diff --git a/api/funkwhale_api/users/models.py b/api/funkwhale_api/users/models.py
index 07bb4bae4c23ceb83033bdf434f619fa3e400572..79650301e9e68acb01b32c754a249e46b3d30102 100644
--- a/api/funkwhale_api/users/models.py
+++ b/api/funkwhale_api/users/models.py
@@ -204,6 +204,9 @@ class User(AbstractUser):
 
         return ["user.{}.{}".format(self.pk, g) for g in groups]
 
+    def full_username(self):
+        return "{}@{}".format(self.username, settings.FEDERATION_HOSTNAME)
+
 
 def generate_code(length=10):
     return "".join(
diff --git a/api/tests/federation/test_models.py b/api/tests/federation/test_models.py
index 2936750484a1642edc2ab0c0c84f12c39208e8c0..f59293b6780b32531fb71d43a8d923486e37ea92 100644
--- a/api/tests/federation/test_models.py
+++ b/api/tests/federation/test_models.py
@@ -97,3 +97,22 @@ def test_domain_stats(factories):
     domain = factories["federation.Domain"]()
 
     assert domain.get_stats() == expected
+
+
+def test_actor_stats(factories):
+    expected = {
+        "libraries": 0,
+        "tracks": 0,
+        "albums": 0,
+        "uploads": 0,
+        "artists": 0,
+        "outbox_activities": 0,
+        "received_library_follows": 0,
+        "emitted_library_follows": 0,
+        "media_total_size": 0,
+        "media_downloaded_size": 0,
+    }
+
+    actor = factories["federation.Actor"]()
+
+    assert actor.get_stats() == expected
diff --git a/api/tests/manage/test_serializers.py b/api/tests/manage/test_serializers.py
index 83d49cd66a84b1ec46518bb59bd7efe9cce94aa3..803820b489350fcbf795abb424bace0f3e3b614c 100644
--- a/api/tests/manage/test_serializers.py
+++ b/api/tests/manage/test_serializers.py
@@ -55,16 +55,12 @@ def test_manage_domain_serializer(factories, now):
 
 def test_manage_actor_serializer(factories, now):
     actor = factories["federation.Actor"]()
-    setattr(actor, "outbox_activities_count", 23)
-    setattr(actor, "followers_count", 42)
     setattr(actor, "uploads_count", 66)
     expected = {
         "id": actor.id,
         "name": actor.name,
         "creation_date": actor.creation_date.isoformat().split("+")[0] + "Z",
         "last_fetch_date": actor.last_fetch_date.isoformat().split("+")[0] + "Z",
-        "outbox_activities_count": 23,
-        "followers_count": 42,
         "uploads_count": 66,
         "fid": actor.fid,
         "url": actor.url,
@@ -76,6 +72,8 @@ def test_manage_actor_serializer(factories, now):
         "summary": actor.summary,
         "preferred_username": actor.preferred_username,
         "manually_approves_followers": actor.manually_approves_followers,
+        "full_username": actor.full_username,
+        "user": None,
     }
     s = serializers.ManageActorSerializer(actor)
 
diff --git a/front/src/Embed.vue b/front/src/Embed.vue
index fdd3406faa00fe42fc78aeec5dac2d34de5c4b2f..7987b054a44213976944251afe7c152e7043ad82 100644
--- a/front/src/Embed.vue
+++ b/front/src/Embed.vue
@@ -247,7 +247,6 @@ export default {
         self.isLoading = false;
       }).catch(error => {
         if (error.response) {
-          console.log(error.response)
           if (error.response.status === 404) {
             self.error = 'server_not_found'
           }
@@ -274,7 +273,6 @@ export default {
         self.isLoading = false;
       }).catch(error => {
         if (error.response) {
-          console.log(error.response)
           if (error.response.status === 404) {
             self.error = 'server_not_found'
           }
diff --git a/front/src/components/manage/moderation/AccountsTable.vue b/front/src/components/manage/moderation/AccountsTable.vue
new file mode 100644
index 0000000000000000000000000000000000000000..8750b4ec97a0497f7033446857cda80055bad63c
--- /dev/null
+++ b/front/src/components/manage/moderation/AccountsTable.vue
@@ -0,0 +1,205 @@
+<template>
+  <div>
+    <div class="ui inline form">
+      <div class="fields">
+        <div class="ui six wide field">
+          <label><translate>Search</translate></label>
+          <form @submit.prevent="search.query = $refs.search.value">
+            <input ref="search" type="text" :value="search.query" :placeholder="labels.searchPlaceholder" />
+          </form>
+        </div>
+        <div class="field">
+          <label><translate>Ordering</translate></label>
+          <select class="ui dropdown" v-model="ordering">
+            <option v-for="option in orderingOptions" :value="option[0]">
+              {{ sharedLabels.filters[option[1]] }}
+            </option>
+          </select>
+        </div>
+        <div class="field">
+          <label><translate>Ordering direction</translate></label>
+          <select class="ui dropdown" v-model="orderingDirection">
+            <option value="+"><translate>Ascending</translate></option>
+            <option value="-"><translate>Descending</translate></option>
+          </select>
+        </div>
+      </div>
+      </div>
+    <div class="dimmable">
+      <div v-if="isLoading" class="ui active inverted dimmer">
+          <div class="ui loader"></div>
+      </div>
+      <action-table
+        v-if="result"
+        @action-launched="fetchData"
+        :objects-data="result"
+        :actions="actions"
+        :filters="actionFilters">
+        <template slot="header-cells">
+          <th><translate>Name</translate></th>
+          <th><translate>Domain</translate></th>
+          <th><translate>Uploads</translate></th>
+          <th><translate>First seen</translate></th>
+          <th><translate>Last seen</translate></th>
+        </template>
+        <template slot="row-cells" slot-scope="scope">
+          <td>
+            <router-link :to="{name: 'manage.moderation.accounts.detail', params: {id: scope.obj.full_username }}">{{ scope.obj.preferred_username }}</router-link>
+          </td>
+          <td>
+            <template v-if="!scope.obj.user">
+              <router-link :to="{name: 'manage.moderation.domains.detail', params: {id: scope.obj.domain }}">
+                <i class="wrench icon"></i>
+              </router-link>
+              <span role="button" class="discrete link" @click="addSearchToken('domain', scope.obj.domain)" :title="scope.obj.domain">{{ scope.obj.domain }}</span>
+            </template>
+            <span role="button" v-else class="ui tiny teal icon link label" @click="addSearchToken('domain', scope.obj.domain)">
+              <i class="home icon"></i>
+              <translate>Local account</translate>
+            </span>
+          </td>
+          <td>
+            {{ scope.obj.uploads_count }}
+          </td>
+          <td>
+            <human-date :date="scope.obj.creation_date"></human-date>
+          </td>
+          <td>
+            <human-date v-if="scope.obj.last_fetch_date" :date="scope.obj.last_fetch_date"></human-date>
+          </td>
+        </template>
+      </action-table>
+    </div>
+    <div>
+      <pagination
+        v-if="result && result.count > paginateBy"
+        @page-changed="selectPage"
+        :compact="true"
+        :current="page"
+        :paginate-by="paginateBy"
+        :total="result.count"
+        ></pagination>
+
+      <span v-if="result && result.results.length > 0">
+        <translate
+          :translate-params="{start: ((page-1) * paginateBy) + 1, end: ((page-1) * paginateBy) + result.results.length, total: result.count}">
+          Showing results %{ start }-%{ end } on %{ total }
+        </translate>
+      </span>
+    </div>
+  </div>
+</template>
+
+<script>
+import axios from 'axios'
+import _ from '@/lodash'
+import time from '@/utils/time'
+import {normalizeQuery, parseTokens} from '@/search'
+import Pagination from '@/components/Pagination'
+import ActionTable from '@/components/common/ActionTable'
+import OrderingMixin from '@/components/mixins/Ordering'
+import TranslationsMixin from '@/components/mixins/Translations'
+import SmartSearchMixin from '@/components/mixins/SmartSearch'
+
+
+export default {
+  mixins: [OrderingMixin, TranslationsMixin, SmartSearchMixin],
+  props: {
+    filters: {type: Object, required: false},
+  },
+  components: {
+    Pagination,
+    ActionTable
+  },
+  data () {
+    let defaultOrdering = this.getOrderingFromString(this.defaultOrdering || '-creation_date')
+    return {
+      time,
+      isLoading: false,
+      result: null,
+      page: 1,
+      paginateBy: 50,
+      search: {
+        query: this.defaultQuery,
+        tokens: parseTokens(normalizeQuery(this.defaultQuery))
+      },
+      orderingDirection: defaultOrdering.direction || '+',
+      ordering: defaultOrdering.field,
+      orderingOptions: [
+        ['creation_date', 'first_seen'],
+        ["last_fetch_date", "last_seen"],
+        ["preferred_username", "username"],
+        ["domain", "domain"],
+        ["uploads_count", "uploads"],
+      ]
+    }
+  },
+  created () {
+    this.fetchData()
+  },
+  methods: {
+    fetchData () {
+      let params = _.merge({
+        'page': this.page,
+        'page_size': this.paginateBy,
+        'q': this.search.query,
+        'ordering': this.getOrderingAsString()
+      }, this.filters)
+      let self = this
+      self.isLoading = true
+      self.checked = []
+      axios.get('/manage/accounts/', {params: params}).then((response) => {
+        self.result = response.data
+        self.isLoading = false
+      }, error => {
+        self.isLoading = false
+        self.errors = error.backendErrors
+      })
+    },
+    selectPage: function (page) {
+      this.page = page
+    }
+  },
+  computed: {
+    labels () {
+      return {
+        searchPlaceholder: this.$gettext('Search by domain, username, bio...')
+      }
+    },
+    actionFilters () {
+      var currentFilters = {
+        q: this.search.query
+      }
+      if (this.filters) {
+        return _.merge(currentFilters, this.filters)
+      } else {
+        return currentFilters
+      }
+    },
+    actions () {
+      return [
+        // {
+        //   name: 'delete',
+        //   label: this.$gettext('Delete'),
+        //   isDangerous: true
+        // }
+      ]
+    }
+  },
+  watch: {
+    search (newValue) {
+      this.page = 1
+      this.fetchData()
+    },
+    page () {
+      this.fetchData()
+    },
+    ordering () {
+      this.fetchData()
+    },
+    orderingDirection () {
+      this.fetchData()
+    }
+  }
+}
+</script>
diff --git a/front/src/components/manage/users/UsersTable.vue b/front/src/components/manage/users/UsersTable.vue
index 33b2433cb5c4b1f6917d151a9d972421d024edab..974ca392d9bea3fc59c92a07aa28e5dc1288e50e 100644
--- a/front/src/components/manage/users/UsersTable.vue
+++ b/front/src/components/manage/users/UsersTable.vue
@@ -45,7 +45,7 @@
         </template>
         <template slot="row-cells" slot-scope="scope">
           <td>
-            <router-link :to="{name: 'manage.users.users.detail', params: {id: scope.obj.id }}">{{ scope.obj.username }}</router-link>
+            <router-link :to="{name: 'manage.moderation.accounts.detail', params: {id: scope.obj.full_username }}">{{ scope.obj.username }}</router-link>
           </td>
           <td>
             <span>{{ scope.obj.email }}</span>
@@ -168,17 +168,13 @@ export default {
     },
     permissions () {
       return [
-        {
-          'code': 'upload',
-          'label': this.$gettext('Upload')
-        },
         {
           'code': 'library',
           'label': this.$gettext('Library')
         },
         {
-          'code': 'federation',
-          'label': this.$gettext('Federation')
+          'code': 'moderation',
+          'label': this.$gettext('Moderation')
         },
         {
           'code': 'settings',
diff --git a/front/src/components/mixins/SmartSearch.vue b/front/src/components/mixins/SmartSearch.vue
index 170436b7a1ca3a540b3c2fe19582c60b6db26c5c..8b03becbbd8e7fb7b3bd38eaa673d9b01615a728 100644
--- a/front/src/components/mixins/SmartSearch.vue
+++ b/front/src/components/mixins/SmartSearch.vue
@@ -4,7 +4,8 @@ import {normalizeQuery, parseTokens, compileTokens} from '@/search'
 
 export default {
   props: {
-    defaultQuery: {type: String, default: '', required: false},
+    defaultQuery: {type: String, required: false},
+    updateUrl: {type: Boolean, required: false, default: false},
   },
   methods: {
     getTokenValue (key, fallback) {
@@ -47,6 +48,15 @@ export default {
         this.search.query = compileTokens(newValue)
         this.page = 1
         this.fetchData()
+        if (this.updateUrl) {
+          let params = {}
+          if (this.search.query) {
+            params.q = this.search.query
+          }
+          this.$router.replace({
+            query: params
+          })
+        }
       },
       deep: true
     },
diff --git a/front/src/components/mixins/Translations.vue b/front/src/components/mixins/Translations.vue
index c982c9ad7ffedea54bae8664569166ad8e705c09..9d237c9161bb14fb26339f18de51399ac924ac11 100644
--- a/front/src/components/mixins/Translations.vue
+++ b/front/src/components/mixins/Translations.vue
@@ -16,6 +16,7 @@ export default {
         filters: {
           creation_date: this.$gettext('Creation date'),
           first_seen: this.$gettext('First seen date'),
+          last_seen: this.$gettext('Last seen date'),
           accessed_date: this.$gettext('Accessed date'),
           modification_date: this.$gettext('Modification date'),
           imported_date: this.$gettext('Imported date'),
@@ -31,8 +32,11 @@ export default {
           date_joined: this.$gettext('Sign-up date'),
           last_activity: this.$gettext('Last activity'),
           username: this.$gettext('Username'),
+          domain: this.$gettext('Domain'),
           users: this.$gettext('Users'),
           received_messages: this.$gettext('Received messages'),
+          uploads: this.$gettext('Uploads'),
+          followers: this.$gettext('Followers'),
         }
       }
     }
diff --git a/front/src/router/index.js b/front/src/router/index.js
index 9d4b46917afa5a12cc1efedd5b2c175de9e8bee4..492cbd6171c3e71b7e1626f410103311cb603bec 100644
--- a/front/src/router/index.js
+++ b/front/src/router/index.js
@@ -27,12 +27,13 @@ import AdminSettings from '@/views/admin/Settings'
 import AdminLibraryBase from '@/views/admin/library/Base'
 import AdminLibraryFilesList from '@/views/admin/library/FilesList'
 import AdminUsersBase from '@/views/admin/users/Base'
-import AdminUsersDetail from '@/views/admin/users/UsersDetail'
 import AdminUsersList from '@/views/admin/users/UsersList'
 import AdminInvitationsList from '@/views/admin/users/InvitationsList'
 import AdminModerationBase from '@/views/admin/moderation/Base'
 import AdminDomainsList from '@/views/admin/moderation/DomainsList'
 import AdminDomainsDetail from '@/views/admin/moderation/DomainsDetail'
+import AdminAccountsList from '@/views/admin/moderation/AccountsList'
+import AdminAccountsDetail from '@/views/admin/moderation/AccountsDetail'
 import ContentBase from '@/views/content/Base'
 import ContentHome from '@/views/content/Home'
 import LibrariesHome from '@/views/content/libraries/Home'
@@ -214,12 +215,6 @@ export default new Router({
           name: 'manage.users.users.list',
           component: AdminUsersList
         },
-        {
-          path: 'users/:id',
-          name: 'manage.users.users.detail',
-          component: AdminUsersDetail,
-          props: true
-        },
         {
           path: 'invitations',
           name: 'manage.users.invitations.list',
@@ -241,6 +236,23 @@ export default new Router({
           name: 'manage.moderation.domains.detail',
           component: AdminDomainsDetail,
           props: true
+        },
+        {
+          path: 'accounts',
+          name: 'manage.moderation.accounts.list',
+          component: AdminAccountsList,
+          props: (route) => {
+            return {
+              defaultQuery: route.query.q,
+
+            }
+          }
+        },
+        {
+          path: 'accounts/:id',
+          name: 'manage.moderation.accounts.detail',
+          component: AdminAccountsDetail,
+          props: true
         }
       ]
     },
diff --git a/front/src/views/admin/moderation/AccountsDetail.vue b/front/src/views/admin/moderation/AccountsDetail.vue
new file mode 100644
index 0000000000000000000000000000000000000000..abed7baad28b92dd5fac2b72e2947c90504edd11
--- /dev/null
+++ b/front/src/views/admin/moderation/AccountsDetail.vue
@@ -0,0 +1,426 @@
+<template>
+  <main>
+    <div v-if="isLoading" class="ui vertical segment">
+      <div :class="['ui', 'centered', 'active', 'inline', 'loader']"></div>
+    </div>
+    <template v-if="object">
+      <section :class="['ui', 'head', 'vertical', 'stripe', 'segment']" v-title="object.full_username">
+        <div class="segment-content">
+          <h2 class="ui header">
+            <i class="circular inverted user icon"></i>
+            <div class="content">
+              {{ object.full_username }}
+              <div class="sub header">
+                <template v-if="object.user">
+                  <span class="ui tiny teal icon label">
+                    <i class="home icon"></i>
+                    <translate>Local account</translate>
+                  </span>
+                  &nbsp;
+                </template>
+                <a :href="object.url || object.fid" target="_blank" rel="noopener noreferrer">
+                  <translate>Open profile</translate>&nbsp;
+                  <i class="external icon"></i>
+                </a>
+              </div>
+            </div>
+          </h2>
+        </div>
+      </section>
+      <div class="ui vertical stripe segment">
+        <div class="ui stackable three column grid">
+          <div class="column">
+            <section>
+              <h3 class="ui header">
+                <i class="info icon"></i>
+                <div class="content">
+                  <translate>Account data</translate>
+                </div>
+              </h3>
+              <table class="ui very basic table">
+                <tbody>
+                  <tr>
+                    <td>
+                      <translate>Username</translate>
+                    </td>
+                    <td>
+                      {{ object.preferred_username }}
+                    </td>
+                  </tr>
+                  <tr v-if="!object.user">
+                    <td>
+                      <translate>Domain</translate>
+                    </td>
+                    <td>
+                      <router-link :to="{name: 'manage.moderation.domains.detail', params: {id: object.domain }}">
+                        {{ object.domain }}
+                      </router-link>
+                    </td>
+                  </tr>
+                  <tr>
+                    <td>
+                      <translate>Display name</translate>
+                    </td>
+                    <td>
+                      {{ object.name }}
+                    </td>
+                  </tr>
+                  <tr v-if="object.user">
+                    <td>
+                      <translate>Email address</translate>
+                    </td>
+                    <td>
+                      {{ object.user.email }}
+                    </td>
+                  </tr>
+                  <tr v-if="object.user">
+                    <td>
+                      <translate>Login status</translate>
+                    </td>
+                    <td>
+                      <div class="ui toggle checkbox" v-if="object.user.username != $store.state.auth.profile.username">
+                        <input
+                          @change="updateUser('is_active')"
+                          v-model="object.user.is_active" type="checkbox">
+                        <label>
+                          <translate v-if="object.user.is_active" key="1">Enabled</translate>
+                          <translate v-else key="2">Disabled</translate>
+                        </label>
+                      </div>
+                      <translate v-else-if="object.user.is_active" key="1">Enabled</translate>
+                      <translate v-else key="2">Disabled</translate>
+                    </td>
+                  </tr>
+                  <tr v-if="object.user">
+                    <td>
+                      <translate>Permissions</translate>
+                    </td>
+                    <td>
+                      <select
+                        @change="updateUser('permissions')"
+                        v-model="permissions"
+                        multiple
+                        class="ui search selection dropdown">
+                        <option v-for="p in allPermissions" :value="p.code">{{ p.label }}</option>
+                      </select>
+                    </td>
+                  </tr>
+                  <tr>
+                    <td>
+                      <translate>Type</translate>
+                    </td>
+                    <td>
+                      {{ object.type }}
+                    </td>
+                  </tr>
+                  <tr v-if="!object.user">
+                    <td>
+                      <translate>First seen</translate>
+                    </td>
+                    <td>
+                      <human-date :date="object.creation_date"></human-date>
+                    </td>
+                  </tr>
+                  <tr v-if="!object.user">
+                    <td>
+                      <translate>Last checked</translate>
+                    </td>
+                    <td>
+                      <human-date v-if="object.last_fetch_date" :date="object.last_fetch_date"></human-date>
+                      <translate v-else>N/A</translate>
+                    </td>
+                  </tr>
+                  <tr v-if="object.user">
+                    <td>
+                      <translate>Sign-up date</translate>
+                    </td>
+                    <td>
+                      <human-date :date="object.user.date_joined"></human-date>
+                    </td>
+                  </tr>
+                  <tr v-if="object.user">
+                    <td>
+                      <translate>Last activity</translate>
+                    </td>
+                    <td>
+                      <human-date :date="object.user.last_activity"></human-date>
+                    </td>
+                  </tr>
+                </tbody>
+              </table>
+            </section>
+          </div>
+          <div class="column">
+            <section>
+              <h3 class="ui header">
+                <i class="feed icon"></i>
+                <div class="content">
+                  <translate>Activity</translate>&nbsp;
+                  <span :data-tooltip="labels.statsWarning"><i class="question circle icon"></i></span>
+
+                </div>
+              </h3>
+              <div v-if="isLoadingStats" class="ui placeholder">
+                <div class="full line"></div>
+                <div class="short line"></div>
+                <div class="medium line"></div>
+                <div class="long line"></div>
+              </div>
+              <table v-else class="ui very basic table">
+                <tbody>
+                  <tr>
+                    <td>
+                      <translate>Emitted messages</translate>
+                    </td>
+                    <td>
+                      {{ stats.outbox_activities}}
+                    </td>
+                  </tr>
+                  <tr>
+                    <td>
+                      <translate>Received library follows</translate>
+                    </td>
+                    <td>
+                      {{ stats.received_library_follows}}
+                    </td>
+                  </tr>
+                  <tr>
+                    <td>
+                      <translate>Emitted library follows</translate>
+                    </td>
+                    <td>
+                      {{ stats.emitted_library_follows}}
+                    </td>
+                  </tr>
+                </tbody>
+              </table>
+            </section>
+          </div>
+          <div class="column">
+            <section>
+              <h3 class="ui header">
+                <i class="music icon"></i>
+                <div class="content">
+                  <translate>Audio content</translate>&nbsp;
+                  <span :data-tooltip="labels.statsWarning"><i class="question circle icon"></i></span>
+
+                </div>
+              </h3>
+              <div v-if="isLoadingStats" class="ui placeholder">
+                <div class="full line"></div>
+                <div class="short line"></div>
+                <div class="medium line"></div>
+                <div class="long line"></div>
+              </div>
+              <table v-else class="ui very basic table">
+                <tbody>
+
+                  <tr v-if="!object.user">
+                    <td>
+                      <translate>Cached size</translate>
+                    </td>
+                    <td>
+                      {{ stats.media_downloaded_size | humanSize }}
+                    </td>
+                  </tr>
+                  <tr v-if="object.user">
+                    <td>
+                      <translate>Upload quota</translate>
+                      <span :data-tooltip="labels.uploadQuota"><i class="question circle icon"></i></span>
+                    </td>
+                    <td>
+                      <div class="ui right labeled input">
+                        <input
+                          class="ui input"
+                          @change="updateUser('upload_quota', true)"
+                          v-model.number="object.user.upload_quota"
+                          step="100"
+                          type="number" />
+                        <div class="ui basic label">
+                          <translate>MB</translate>
+                        </div>
+                      </div>
+                    </td>
+                  </tr>
+                  <tr>
+                    <td>
+                      <translate>Total size</translate>
+                    </td>
+                    <td>
+                      {{ stats.media_total_size | humanSize }}
+                    </td>
+                  </tr>
+
+                  <tr>
+                    <td>
+                      <translate>Libraries</translate>
+                    </td>
+                    <td>
+                      {{ stats.libraries }}
+                    </td>
+                  </tr>
+                  <tr>
+                    <td>
+                      <translate>Uploads</translate>
+                    </td>
+                    <td>
+                      {{ stats.uploads }}
+                    </td>
+                  </tr>
+                  <tr>
+                    <td>
+                      <translate>Artists</translate>
+                    </td>
+                    <td>
+                      {{ stats.artists }}
+                    </td>
+                  </tr>
+                  <tr>
+                    <td>
+                      <translate>Albums</translate>
+                    </td>
+                    <td>
+                      {{ stats.albums}}
+                    </td>
+                  </tr>
+                  <tr>
+                    <td>
+                      <translate>Tracks</translate>
+                    </td>
+                    <td>
+                      {{ stats.tracks }}
+                    </td>
+                  </tr>
+                </tbody>
+              </table>
+
+            </section>
+          </div>
+        </div>
+      </div>
+
+    </template>
+  </main>
+</template>
+
+<script>
+import axios from "axios"
+import logger from "@/logging"
+import lodash from '@/lodash'
+import $ from "jquery"
+
+export default {
+  props: ["id"],
+  data() {
+    return {
+      lodash,
+      isLoading: true,
+      isLoadingStats: false,
+      object: null,
+      stats: null,
+      permissions: [],
+    }
+  },
+  created() {
+    this.fetchData()
+    this.fetchStats()
+  },
+  methods: {
+    fetchData() {
+      var self = this
+      this.isLoading = true
+      let url = "manage/accounts/" + this.id + "/"
+      axios.get(url).then(response => {
+        self.object = response.data
+        self.isLoading = false
+        if (response.data.user) {
+          self.allPermissions.forEach(p => {
+            if (self.object.user.permissions[p.code]) {
+              self.permissions.push(p.code)
+            }
+          })
+        }
+      })
+    },
+    fetchStats() {
+      var self = this
+      this.isLoadingStats = true
+      let url = "manage/accounts/" + this.id + "/stats/"
+      axios.get(url).then(response => {
+        self.stats = response.data
+        self.isLoadingStats = false
+      })
+    },
+    refreshNodeInfo (data) {
+      this.object.nodeinfo = data
+      this.object.nodeinfo_fetch_date = new Date()
+    },
+
+    updateUser(attr, toNull) {
+      let newValue = this.object.user[attr]
+      if (toNull && !newValue) {
+        newValue = null
+      }
+      let params = {}
+      if (attr === "permissions") {
+        params["permissions"] = {}
+        this.allPermissions.forEach(p => {
+          params["permissions"][p.code] = this.permissions.indexOf(p.code) > -1
+        })
+      } else {
+        params[attr] = newValue
+      }
+      axios.patch(`manage/users/users/${this.object.user.id}/`, params).then(
+        response => {
+          logger.default.info(
+            `${attr} was updated succcessfully to ${newValue}`
+          )
+        },
+        error => {
+          logger.default.error(
+            `Error while setting ${attr} to ${newValue}`,
+            error
+          )
+        }
+      )
+    }
+  },
+  computed: {
+    labels() {
+      return {
+        statsWarning: this.$gettext("Statistics are computed from known activity and content on your instance, and do not reflect general activity for this account"),
+        uploadQuota: this.$gettext(
+          "Determine how much content the user can upload. Leave empty to use the default value of the instance."
+        ),
+      }
+    },
+    allPermissions() {
+      return [
+        {
+          code: "library",
+          label: this.$gettext("Library")
+        },
+        {
+          code: "moderation",
+          label: this.$gettext("Moderation")
+        },
+        {
+          code: "settings",
+          label: this.$gettext("Settings")
+        }
+      ]
+    }
+  },
+  watch: {
+    object () {
+      this.$nextTick(() => {
+        $(this.$el).find("select.dropdown").dropdown()
+      })
+    }
+  }
+}
+</script>
+
+<!-- Add "scoped" attribute to limit CSS to this component only -->
+<style scoped>
+</style>
diff --git a/front/src/views/admin/moderation/AccountsList.vue b/front/src/views/admin/moderation/AccountsList.vue
new file mode 100644
index 0000000000000000000000000000000000000000..877c96c5ee548615fdfb4720c07a4e6b5c8af211
--- /dev/null
+++ b/front/src/views/admin/moderation/AccountsList.vue
@@ -0,0 +1,33 @@
+<template>
+  <main v-title="labels.accounts">
+    <section class="ui vertical stripe segment">
+      <h2 class="ui header"><translate>Accounts</translate></h2>
+      <div class="ui hidden divider"></div>
+      <accounts-table :update-url="true" :default-query="defaultQuery"></accounts-table>
+    </section>
+  </main>
+</template>
+
+<script>
+import AccountsTable from "@/components/manage/moderation/AccountsTable"
+
+export default {
+  components: {
+    AccountsTable
+  },
+  props: {
+    defaultQuery: {type: String, required: false},
+  },
+  computed: {
+    labels() {
+      return {
+        accounts: this.$gettext("Accounts")
+      }
+    }
+  }
+}
+</script>
+
+<!-- Add "scoped" attribute to limit CSS to this component only -->
+<style scoped>
+</style>
diff --git a/front/src/views/admin/moderation/Base.vue b/front/src/views/admin/moderation/Base.vue
index d4487339d3f41bb665e67c7034fdf974f7a72095..e0bf6c1adcd41f3df44526fde5bcbf8ecbb9ce4a 100644
--- a/front/src/views/admin/moderation/Base.vue
+++ b/front/src/views/admin/moderation/Base.vue
@@ -1,9 +1,13 @@
 <template>
-  <div class="main pusher"  v-title="labels.manageDomains">
+  <div class="main pusher"  v-title="labels.moderation">
     <nav class="ui secondary pointing menu" role="navigation" :aria-label="labels.secondaryMenu">
       <router-link
         class="ui item"
         :to="{name: 'manage.moderation.domains.list'}"><translate>Domains</translate></router-link>
+      <router-link
+        class="ui item"
+        :to="{name: 'manage.moderation.accounts.list'}"><translate>Accounts</translate></router-link>
+
     </nav>
     <router-view :key="$route.fullPath"></router-view>
   </div>
@@ -14,7 +18,7 @@ export default {
   computed: {
     labels() {
       return {
-        manageDomains: this.$gettext("Manage domains"),
+        moderation: this.$gettext("Moderation"),
         secondaryMenu: this.$gettext("Secondary menu")
       }
     }
diff --git a/front/src/views/admin/moderation/DomainsDetail.vue b/front/src/views/admin/moderation/DomainsDetail.vue
index 71007a45604ee0e40235d385ca54d94b3115b298..1adb1c3055b063e21669ec97d276a047b277b9ae 100644
--- a/front/src/views/admin/moderation/DomainsDetail.vue
+++ b/front/src/views/admin/moderation/DomainsDetail.vue
@@ -115,7 +115,11 @@
                 <tbody>
                   <tr>
                     <td>
-                      <translate>Known users</translate>
+                      <router-link
+                        :to="{name: 'manage.moderation.accounts.list', query: {q: 'domain:' + object.name }}">
+                        <translate>Known accounts</translate>
+                        </router-link>
+
                     </td>
                     <td>
                       {{ stats.actors }}
@@ -169,58 +173,58 @@
                 <tbody>
                   <tr>
                     <td>
-                      <translate>Artists</translate>
+                      <translate>Cached size</translate>
                     </td>
                     <td>
-                      {{ stats.artists }}
+                      {{ stats.media_downloaded_size | humanSize }}
                     </td>
                   </tr>
                   <tr>
                     <td>
-                      <translate>Albums</translate>
+                      <translate>Total size</translate>
                     </td>
                     <td>
-                      {{ stats.albums}}
+                      {{ stats.media_total_size | humanSize }}
                     </td>
                   </tr>
                   <tr>
                     <td>
-                      <translate>Tracks</translate>
+                      <translate>Libraries</translate>
                     </td>
                     <td>
-                      {{ stats.tracks }}
+                      {{ stats.libraries }}
                     </td>
                   </tr>
                   <tr>
                     <td>
-                      <translate>Libraries</translate>
+                      <translate>Uploads</translate>
                     </td>
                     <td>
-                      {{ stats.libraries }}
+                      {{ stats.uploads }}
                     </td>
                   </tr>
                   <tr>
                     <td>
-                      <translate>Uploads</translate>
+                      <translate>Artists</translate>
                     </td>
                     <td>
-                      {{ stats.uploads }}
+                      {{ stats.artists }}
                     </td>
                   </tr>
                   <tr>
                     <td>
-                      <translate>Cached size</translate>
+                      <translate>Albums</translate>
                     </td>
                     <td>
-                      {{ stats.media_downloaded_size | humanSize }}
+                      {{ stats.albums}}
                     </td>
                   </tr>
                   <tr>
                     <td>
-                      <translate>Total size</translate>
+                      <translate>Tracks</translate>
                     </td>
                     <td>
-                      {{ stats.media_total_size | humanSize }}
+                      {{ stats.tracks }}
                     </td>
                   </tr>
                 </tbody>
diff --git a/front/src/views/admin/users/UsersDetail.vue b/front/src/views/admin/users/UsersDetail.vue
deleted file mode 100644
index 7eaafb6cb761989d87779c20c546ac75094aa842..0000000000000000000000000000000000000000
--- a/front/src/views/admin/users/UsersDetail.vue
+++ /dev/null
@@ -1,216 +0,0 @@
-<template>
-  <main>
-    <div v-if="isLoading" class="ui vertical segment">
-      <div :class="['ui', 'centered', 'active', 'inline', 'loader']"></div>
-    </div>
-    <template v-if="object">
-      <section :class="['ui', 'head', 'vertical', 'center', 'aligned', 'stripe', 'segment']" v-title="object.username">
-        <div class="segment-content">
-          <h2 class="ui center aligned icon header">
-            <i class="circular inverted user red icon"></i>
-            <div class="content">
-              @{{ object.username }}
-            </div>
-          </h2>
-        </div>
-        <div class="ui hidden divider"></div>
-        <div class="ui one column centered grid">
-          <table class="ui collapsing very basic table">
-            <tbody>
-              <tr>
-                <td>
-                  <translate>Name</translate>
-                </td>
-                <td>
-                  {{ object.name }}
-                </td>
-              </tr>
-              <tr>
-                <td>
-                  <translate>Email address</translate>
-                </td>
-                <td>
-                  {{ object.email }}
-                </td>
-              </tr>
-              <tr>
-                <td>
-                  <translate>Sign-up</translate>
-                </td>
-                <td>
-                  <human-date :date="object.date_joined"></human-date>
-                </td>
-              </tr>
-              <tr>
-                <td>
-                  <translate>Last activity</translate>
-                </td>
-                <td>
-                  <human-date v-if="object.last_activity" :date="object.last_activity"></human-date>
-                  <template v-else><translate>N/A</translate></template>
-                </td>
-              </tr>
-              <tr>
-                <td>
-                  <translate>Account active</translate>
-                  <span :data-tooltip="labels.inactive"><i class="question circle icon"></i></span>
-                </td>
-                <td>
-                  <div class="ui toggle checkbox">
-                    <input
-                      @change="update('is_active')"
-                      v-model="object.is_active" type="checkbox">
-                    <label></label>
-                  </div>
-                </td>
-              </tr>
-              <tr>
-                <td>
-                  <translate>Permissions</translate>
-                </td>
-                <td>
-                  <select
-                    @change="update('permissions')"
-                    v-model="permissions"
-                    multiple
-                    class="ui search selection dropdown">
-                    <option v-for="p in allPermissions" :value="p.code">{{ p.label }}</option>
-                  </select>
-                </td>
-              </tr>
-              <tr>
-                <td>
-                  <translate>Upload quota</translate>
-                  <span :data-tooltip="labels.uploadQuota"><i class="question circle icon"></i></span>
-                </td>
-                <td>
-                  <div class="ui right labeled input">
-                  <input
-                    class="ui input"
-                    @change="update('upload_quota', true)"
-                    v-model.number="object.upload_quota"
-                    step="100"
-                    type="number" />
-                  <div class="ui basic label">
-                    <translate>MB</translate>
-                  </div>
-                </div>
-                </td>
-              </tr>
-            </tbody>
-          </table>
-        </div>
-        <div class="ui hidden divider"></div>
-        <button @click="fetchData" class="ui basic button"><translate>Refresh</translate></button>
-      </section>
-    </template>
-  </main>
-</template>
-
-<script>
-import $ from "jquery"
-import axios from "axios"
-import logger from "@/logging"
-
-export default {
-  props: ["id"],
-  data() {
-    return {
-      isLoading: true,
-      object: null,
-      permissions: []
-    }
-  },
-  created() {
-    this.fetchData()
-  },
-  methods: {
-    fetchData() {
-      var self = this
-      this.isLoading = true
-      let url = "manage/users/users/" + this.id + "/"
-      axios.get(url).then(response => {
-        self.object = response.data
-        self.permissions = []
-        self.allPermissions.forEach(p => {
-          if (self.object.permissions[p.code]) {
-            self.permissions.push(p.code)
-          }
-        })
-        self.isLoading = false
-      })
-    },
-    update(attr, toNull) {
-      let newValue = this.object[attr]
-      if (toNull && !newValue) {
-        newValue = null
-      }
-      let params = {}
-      if (attr === "permissions") {
-        params["permissions"] = {}
-        this.allPermissions.forEach(p => {
-          params["permissions"][p.code] = this.permissions.indexOf(p.code) > -1
-        })
-      } else {
-        params[attr] = newValue
-      }
-      axios.patch("manage/users/users/" + this.id + "/", params).then(
-        response => {
-          logger.default.info(
-            `${attr} was updated succcessfully to ${newValue}`
-          )
-        },
-        error => {
-          logger.default.error(
-            `Error while setting ${attr} to ${newValue}`,
-            error
-          )
-        }
-      )
-    }
-  },
-  computed: {
-    labels() {
-      return {
-        inactive: this.$gettext(
-          "Determine if the user account is active or not. Inactive users cannot login or use the service."
-        ),
-        uploadQuota: this.$gettext(
-          "Determine how much content the user can upload. Leave empty to use the default value of the instance."
-        )
-      }
-    },
-    allPermissions() {
-      return [
-        {
-          code: "upload",
-          label: this.$gettext("Upload")
-        },
-        {
-          code: "library",
-          label: this.$gettext("Library")
-        },
-        {
-          code: "federation",
-          label: this.$gettext("Federation")
-        },
-        {
-          code: "settings",
-          label: this.$gettext("Settings")
-        }
-      ]
-    }
-  },
-  watch: {
-    object() {
-      this.$nextTick(() => {
-        $("select.dropdown").dropdown()
-      })
-    }
-  }
-}
-</script>
-
-<!-- Add "scoped" attribute to limit CSS to this component only -->
-<style scoped>
-</style>