diff --git a/CHANGELOG.md b/CHANGELOG.md
index e368ae700f8af41efda9fef2837e4f19e403611e..770681f77ccd345b338ea9fa54c2e17e2c8f2cdd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -25,6 +25,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Ability to confirm users' emails and resend confirmation emails
 - Report notes
 - Ability to moderate users on the statuses page
+- Ability to moderate user on the user's page
 
 ### Fixed
 
diff --git a/src/api/users.js b/src/api/users.js
index f3398c68da578ca44a2f108cc7ede9b64a2d1536..8298eeca047c6b890bbe5f84061401adca901fca 100644
--- a/src/api/users.js
+++ b/src/api/users.js
@@ -89,7 +89,7 @@ export async function getPasswordResetToken(nickname, authHost, token) {
   })
 }
 
-export async function requirePasswordReset(nicknames, authHost, token) {
+export async function forcePasswordReset(nicknames, authHost, token) {
   return await request({
     baseURL: baseName(authHost),
     url: `/api/pleroma/admin/users/force_password_reset`,
diff --git a/src/lang/en.js b/src/lang/en.js
index 1a8a8c9007c725227d3c000078b1427012caaec1..fa4d3209f5d3377e0c5e56d6d466316fff1d8b8f 100644
--- a/src/lang/en.js
+++ b/src/lang/en.js
@@ -202,6 +202,7 @@ export default {
     disableAnySubscriptionForMultiple: 'Disallow following users at all',
     requirePasswordReset: 'Require password reset on next login',
     selectUsers: 'Select users to apply actions to multiple users',
+    moderateUser: 'Moderate user',
     moderateUsers: 'Moderate multiple users',
     createAccount: 'Create new account',
     apply: 'apply',
diff --git a/src/store/modules/users.js b/src/store/modules/users.js
index dccbb1ca7284620f51f1465cd6150d8a085bfbd9..75b07402807d20ae9260cf72f09d87fb5a3ca710 100644
--- a/src/store/modules/users.js
+++ b/src/store/modules/users.js
@@ -12,7 +12,7 @@ import {
   searchUsers,
   tagUser,
   untagUser,
-  requirePasswordReset,
+  forcePasswordReset,
   confirmUserEmail,
   resendConfirmationEmail
 } from '@/api/users'
@@ -79,53 +79,46 @@ const users = {
     }
   },
   actions: {
-    async ActivateUsers({ commit, dispatch, getters, state }, users) {
+    async ActivateUsers({ dispatch, getters }, users) {
       const updatedUsers = users.map(user => {
         return { ...user, deactivated: false }
       })
+      const nicknames = users.map(user => user.nickname)
+      const callApiFn = async() => await activateUsers(nicknames, getters.authHost, getters.token)
+
+      dispatch('ApplyChanges', { updatedUsers, callApiFn, userId: users[0].id })
+    },
+    async ApplyChanges({ commit, dispatch, state }, { updatedUsers, callApiFn, userId }) {
       commit('SWAP_USERS', updatedUsers)
 
-      const usersNicknames = users.map(user => user.nickname)
       try {
-        await activateUsers(usersNicknames, getters.authHost, getters.token)
+        await callApiFn()
       } catch (_e) {
         return
       } finally {
         dispatch('SearchUsers', { query: state.searchQuery, page: state.currentPage })
       }
+
+      dispatch('FetchUserProfile', { userId, godmode: false })
       dispatch('SuccessMessage')
     },
-    async AddRight({ commit, dispatch, getters, state }, { users, right }) {
+    async AddRight({ dispatch, getters }, { users, right }) {
       const updatedUsers = users.map(user => {
         return user.local ? { ...user, roles: { ...user.roles, [right]: true }} : user
       })
-      commit('SWAP_USERS', updatedUsers)
+      const nicknames = users.map(user => user.nickname)
+      const callApiFn = async() => await addRight(nicknames, right, getters.authHost, getters.token)
 
-      const usersNicknames = users.map(user => user.nickname)
-      try {
-        await addRight(usersNicknames, right, getters.authHost, getters.token)
-      } catch (_e) {
-        return
-      } finally {
-        dispatch('SearchUsers', { query: state.searchQuery, page: state.currentPage })
-      }
-      dispatch('SuccessMessage')
+      dispatch('ApplyChanges', { updatedUsers, callApiFn, userId: users[0].id })
     },
-    async AddTag({ commit, dispatch, getters, state }, { users, tag }) {
+    async AddTag({ dispatch, getters }, { users, tag }) {
       const updatedUsers = users.map(user => {
         return { ...user, tags: [...user.tags, tag] }
       })
-      commit('SWAP_USERS', updatedUsers)
-
       const nicknames = users.map(user => user.nickname)
-      try {
-        await tagUser(nicknames, [tag], getters.authHost, getters.token)
-      } catch (_e) {
-        return
-      } finally {
-        dispatch('SearchUsers', { query: state.searchQuery, page: state.currentPage })
-      }
-      dispatch('SuccessMessage')
+      const callApiFn = async() => await tagUser(nicknames, [tag], getters.authHost, getters.token)
+
+      dispatch('ApplyChanges', { updatedUsers, callApiFn, userId: users[0].id })
     },
     async ClearFilters({ commit, dispatch, state }) {
       commit('CLEAR_USERS_FILTERS')
@@ -141,37 +134,23 @@ const users = {
       }
       dispatch('SuccessMessage')
     },
-    async DeactivateUsers({ commit, dispatch, getters, state }, users) {
+    async DeactivateUsers({ dispatch, getters }, users) {
       const updatedUsers = users.map(user => {
         return { ...user, deactivated: true }
       })
-      commit('SWAP_USERS', updatedUsers)
+      const nicknames = users.map(user => user.nickname)
+      const callApiFn = async() => await deactivateUsers(nicknames, getters.authHost, getters.token)
 
-      const usersNicknames = users.map(user => user.nickname)
-      try {
-        await deactivateUsers(usersNicknames, getters.authHost, getters.token)
-      } catch (_e) {
-        return
-      } finally {
-        dispatch('SearchUsers', { query: state.searchQuery, page: state.currentPage })
-      }
-      dispatch('SuccessMessage')
+      dispatch('ApplyChanges', { updatedUsers, callApiFn, userId: users[0].id })
     },
-    async ConfirmUsersEmail({ commit, dispatch, getters, state }, users) {
+    async ConfirmUsersEmail({ dispatch, getters }, users) {
       const updatedUsers = users.map(user => {
         return { ...user, confirmation_pending: false }
       })
-      commit('SWAP_USERS', updatedUsers)
+      const nicknames = users.map(user => user.nickname)
+      const callApiFn = async() => await confirmUserEmail(nicknames, getters.authHost, getters.token)
 
-      const usersNicknames = users.map(user => user.nickname)
-      try {
-        await confirmUserEmail(usersNicknames, getters.authHost, getters.token)
-      } catch (_e) {
-        return
-      } finally {
-        dispatch('SearchUsers', { query: state.searchQuery, page: state.currentPage })
-      }
-      dispatch('SuccessMessage')
+      dispatch('ApplyChanges', { updatedUsers, callApiFn, userId: users[0].id })
     },
     async ResendConfirmationEmail({ dispatch, getters }, users) {
       const usersNicknames = users.map(user => user.nickname)
@@ -182,21 +161,14 @@ const users = {
       }
       dispatch('SuccessMessage')
     },
-    async DeleteRight({ commit, dispatch, getters, state }, { users, right }) {
+    async DeleteRight({ dispatch, getters }, { users, right }) {
       const updatedUsers = users.map(user => {
         return user.local ? { ...user, roles: { ...user.roles, [right]: false }} : user
       })
-      commit('SWAP_USERS', updatedUsers)
+      const nicknames = users.map(user => user.nickname)
+      const callApiFn = async() => await deleteRight(nicknames, right, getters.authHost, getters.token)
 
-      const usersNicknames = users.map(user => user.nickname)
-      try {
-        await deleteRight(usersNicknames, right, getters.authHost, getters.token)
-      } catch (_e) {
-        return
-      } finally {
-        dispatch('SearchUsers', { query: state.searchQuery, page: state.currentPage })
-      }
-      dispatch('SuccessMessage')
+      dispatch('ApplyChanges', { updatedUsers, callApiFn, userId: users[0].id })
     },
     async DeleteUsers({ commit, dispatch, getters, state }, users) {
       const usersNicknames = users.map(user => user.nickname)
@@ -208,6 +180,8 @@ const users = {
       const deletedUsersIds = users.map(deletedUser => deletedUser.id)
       const updatedUsers = state.fetchedUsers.filter(user => !deletedUsersIds.includes(user.id))
       commit('SET_USERS', updatedUsers)
+
+      dispatch('FetchUserProfile', { userId: users[0].id, godmode: false })
       dispatch('SuccessMessage')
     },
     async FetchUsers({ commit, dispatch, getters, state }, { page }) {
@@ -224,25 +198,19 @@ const users = {
     RemovePasswordToken({ commit }) {
       commit('SET_PASSWORD_RESET_TOKEN', { link: '', token: '' })
     },
-    async RemoveTag({ commit, dispatch, getters, state }, { users, tag }) {
+    async RemoveTag({ dispatch, getters }, { users, tag }) {
       const updatedUsers = users.map(user => {
         return { ...user, tags: user.tags.filter(userTag => userTag !== tag) }
       })
-      commit('SWAP_USERS', updatedUsers)
-
       const nicknames = users.map(user => user.nickname)
-      try {
-        await untagUser(nicknames, [tag], getters.authHost, getters.token)
-      } catch (_e) {
-        return
-      } finally {
-        dispatch('SearchUsers', { query: state.searchQuery, page: state.currentPage })
-      }
-      dispatch('SuccessMessage')
+      const callApiFn = async() => await untagUser(nicknames, [tag], getters.authHost, getters.token)
+
+      dispatch('ApplyChanges', { updatedUsers, callApiFn, userId: users[0].id })
     },
-    async RequirePasswordReset({ dispatch, getters }, { nicknames }) {
+    async RequirePasswordReset({ dispatch, getters }, users) {
+      const nicknames = users.map(user => user.nickname)
       try {
-        await requirePasswordReset(nicknames, getters.authHost, getters.token)
+        await forcePasswordReset(nicknames, getters.authHost, getters.token)
       } catch (_e) {
         return
       }
diff --git a/src/views/users/components/ModerationDropdown.vue b/src/views/users/components/ModerationDropdown.vue
new file mode 100644
index 0000000000000000000000000000000000000000..d6e361ad4b52202f6bf00e487959917a2e07693c
--- /dev/null
+++ b/src/views/users/components/ModerationDropdown.vue
@@ -0,0 +1,182 @@
+<template>
+  <el-dropdown :hide-on-click="false" size="small" trigger="click">
+    <div>
+      <span v-if="page === 'users'" class="el-dropdown-link">
+        {{ $t('users.moderation') }}
+        <i v-if="isDesktop" class="el-icon-arrow-down el-icon--right"/>
+      </span>
+      <el-button v-if="page === 'userPage'" class="moderate-user-button">
+        <span class="moderate-user-button-container">
+          <span>
+            <i class="el-icon-edit" />
+            {{ $t('users.moderateUser') }}
+          </span>
+          <i class="el-icon-arrow-down el-icon--right"/>
+        </span>
+      </el-button>
+    </div>
+    <el-dropdown-menu slot="dropdown">
+      <el-dropdown-item
+        v-if="showAdminAction(user)"
+        @click.native="toggleUserRight(user, 'admin')">
+        {{ user.roles.admin ? $t('users.revokeAdmin') : $t('users.grantAdmin') }}
+      </el-dropdown-item>
+      <el-dropdown-item
+        v-if="showAdminAction(user)"
+        @click.native="toggleUserRight(user, 'moderator')">
+        {{ user.roles.moderator ? $t('users.revokeModerator') : $t('users.grantModerator') }}
+      </el-dropdown-item>
+      <el-dropdown-item
+        v-if="showDeactivatedButton(user.id)"
+        :divided="showAdminAction(user)"
+        @click.native="toggleActivation(user)">
+        {{ user.deactivated ? $t('users.activateAccount') : $t('users.deactivateAccount') }}
+      </el-dropdown-item>
+      <el-dropdown-item
+        v-if="showDeactivatedButton(user.id)"
+        @click.native="handleDeletion(user)">
+        {{ $t('users.deleteAccount') }}
+      </el-dropdown-item>
+      <el-dropdown-item
+        v-if="user.local && user.confirmation_pending"
+        divided
+        @click.native="handleEmailConfirmation(user)">
+        {{ $t('users.confirmAccount') }}
+      </el-dropdown-item>
+      <el-dropdown-item
+        v-if="user.local && user.confirmation_pending"
+        @click.native="handleConfirmationResend(user)">
+        {{ $t('users.resendConfirmation') }}
+      </el-dropdown-item>
+      <el-dropdown-item
+        :divided="showAdminAction(user)"
+        :class="{ 'active-tag': user.tags.includes('force_nsfw') }"
+        @click.native="toggleTag(user, 'force_nsfw')">
+        {{ $t('users.forceNsfw') }}
+        <i v-if="user.tags.includes('force_nsfw')" class="el-icon-check"/>
+      </el-dropdown-item>
+      <el-dropdown-item
+        :class="{ 'active-tag': user.tags.includes('strip_media') }"
+        @click.native="toggleTag(user, 'strip_media')">
+        {{ $t('users.stripMedia') }}
+        <i v-if="user.tags.includes('strip_media')" class="el-icon-check"/>
+      </el-dropdown-item>
+      <el-dropdown-item
+        :class="{ 'active-tag': user.tags.includes('force_unlisted') }"
+        @click.native="toggleTag(user, 'force_unlisted')">
+        {{ $t('users.forceUnlisted') }}
+        <i v-if="user.tags.includes('force_unlisted')" class="el-icon-check"/>
+      </el-dropdown-item>
+      <el-dropdown-item
+        :class="{ 'active-tag': user.tags.includes('sandbox') }"
+        @click.native="toggleTag(user, 'sandbox')">
+        {{ $t('users.sandbox') }}
+        <i v-if="user.tags.includes('sandbox')" class="el-icon-check"/>
+      </el-dropdown-item>
+      <el-dropdown-item
+        v-if="user.local"
+        :class="{ 'active-tag': user.tags.includes('disable_remote_subscription') }"
+        @click.native="toggleTag(user, 'disable_remote_subscription')">
+        {{ $t('users.disableRemoteSubscription') }}
+        <i v-if="user.tags.includes('disable_remote_subscription')" class="el-icon-check"/>
+      </el-dropdown-item>
+      <el-dropdown-item
+        v-if="user.local"
+        :class="{ 'active-tag': user.tags.includes('disable_any_subscription') }"
+        @click.native="toggleTag(user, 'disable_any_subscription')">
+        {{ $t('users.disableAnySubscription') }}
+        <i v-if="user.tags.includes('disable_any_subscription')" class="el-icon-check"/>
+      </el-dropdown-item>
+      <el-dropdown-item
+        v-if="user.local"
+        divided
+        @click.native="getPasswordResetToken(user.nickname)">
+        {{ $t('users.getPasswordResetToken') }}
+      </el-dropdown-item>
+      <el-dropdown-item
+        v-if="user.local"
+        @click.native="requirePasswordReset(user)">
+        {{ $t('users.requirePasswordReset') }}
+      </el-dropdown-item>
+    </el-dropdown-menu>
+  </el-dropdown>
+</template>
+
+<script>
+export default {
+  name: 'ModerationDropdown',
+  props: {
+    user: {
+      type: Object,
+      default: function() {
+        return {}
+      }
+    },
+    page: {
+      type: String,
+      default: 'users'
+    }
+  },
+  computed: {
+    isDesktop() {
+      return this.$store.state.app.device === 'desktop'
+    }
+  },
+  methods: {
+    getPasswordResetToken(nickname) {
+      this.$emit('open-reset-token-dialog')
+      this.$store.dispatch('GetPasswordResetToken', nickname)
+    },
+    handleConfirmationResend(user) {
+      this.$store.dispatch('ResendConfirmationEmail', [user])
+    },
+    handleDeletion(user) {
+      this.$store.dispatch('DeleteUsers', [user])
+    },
+    handleEmailConfirmation(user) {
+      this.$store.dispatch('ConfirmUsersEmail', [user])
+    },
+    requirePasswordReset(user) {
+      const mailerEnabled = this.$store.state.user.nodeInfo.metadata.mailerEnabled
+      if (!mailerEnabled) {
+        this.$alert(this.$t('users.mailerMustBeEnabled'), 'Error', { type: 'error' })
+        return
+      }
+      this.$store.dispatch('RequirePasswordReset', [user])
+    },
+    showAdminAction({ local, id }) {
+      return local && this.showDeactivatedButton(id)
+    },
+    showDeactivatedButton(id) {
+      return this.$store.state.user.id !== id
+    },
+    toggleActivation(user) {
+      user.deactivated
+        ? this.$store.dispatch('ActivateUsers', [user])
+        : this.$store.dispatch('DeactivateUsers', [user])
+    },
+    toggleTag(user, tag) {
+      user.tags.includes(tag)
+        ? this.$store.dispatch('RemoveTag', { users: [user], tag })
+        : this.$store.dispatch('AddTag', { users: [user], tag })
+    },
+    toggleUserRight(user, right) {
+      user.roles[right]
+        ? this.$store.dispatch('DeleteRight', { users: [user], right })
+        : this.$store.dispatch('AddRight', { users: [user], right })
+    }
+  }
+}
+</script>
+
+<style rel='stylesheet/scss' lang='scss'>
+  .moderate-user-button {
+    text-align: left;
+    width: 200px;
+    padding: 10px;
+  }
+  .moderate-user-button-container {
+    display: flex;
+    justify-content: space-between;
+  }
+</style>
diff --git a/src/views/users/components/MultipleUsersMenu.vue b/src/views/users/components/MultipleUsersMenu.vue
index 6eb18c1c63b727dac27489ddd49857ec103e9bfc..de058ad8f58dd2c394ead0634f9bac6a8c3d127a 100644
--- a/src/views/users/components/MultipleUsersMenu.vue
+++ b/src/views/users/components/MultipleUsersMenu.vue
@@ -216,9 +216,9 @@ export default {
         },
         requirePasswordReset: () => {
           const filtered = this.selectedUsers.filter(user => user.local)
-          const nicknames = filtered.map(u => u.nickname)
-          this.$store.dispatch('RequirePasswordReset', { nicknames })
-          this.$emit('apply-action')
+          const requirePasswordResetFn = async(users) => await this.$store.dispatch('RequirePasswordReset', users)
+
+          applyAction(filtered, requirePasswordResetFn)
         },
         confirmAccounts: () => {
           const filtered = this.selectedUsers.filter(user => user.local && user.confirmation_pending)
diff --git a/src/views/users/index.vue b/src/views/users/index.vue
index fee152918e98c9f694818194976e2a84922eed82..2940f77634fadb6c142ed385351f847c751eb8e6 100644
--- a/src/views/users/index.vue
+++ b/src/views/users/index.vue
@@ -66,96 +66,10 @@
       </el-table-column>
       <el-table-column :label="$t('users.actions')" fixed="right">
         <template slot-scope="scope">
-          <el-dropdown :hide-on-click="false" size="small" trigger="click">
-            <span class="el-dropdown-link">
-              {{ $t('users.moderation') }}
-              <i v-if="isDesktop" class="el-icon-arrow-down el-icon--right"/>
-            </span>
-            <el-dropdown-menu slot="dropdown">
-              <el-dropdown-item
-                v-if="showAdminAction(scope.row)"
-                @click.native="toggleUserRight(scope.row, 'admin')">
-                {{ scope.row.roles.admin ? $t('users.revokeAdmin') : $t('users.grantAdmin') }}
-              </el-dropdown-item>
-              <el-dropdown-item
-                v-if="showAdminAction(scope.row)"
-                @click.native="toggleUserRight(scope.row, 'moderator')">
-                {{ scope.row.roles.moderator ? $t('users.revokeModerator') : $t('users.grantModerator') }}
-              </el-dropdown-item>
-              <el-dropdown-item
-                v-if="showDeactivatedButton(scope.row.id)"
-                :divided="showAdminAction(scope.row)"
-                @click.native="toggleActivation(scope.row)">
-                {{ scope.row.deactivated ? $t('users.activateAccount') : $t('users.deactivateAccount') }}
-              </el-dropdown-item>
-              <el-dropdown-item
-                v-if="showDeactivatedButton(scope.row.id)"
-                @click.native="handleDeletion(scope.row)">
-                {{ $t('users.deleteAccount') }}
-              </el-dropdown-item>
-              <el-dropdown-item
-                v-if="scope.row.local && scope.row.confirmation_pending"
-                divided
-                @click.native="handleEmailConfirmation(scope.row)">
-                {{ $t('users.confirmAccount') }}
-              </el-dropdown-item>
-              <el-dropdown-item
-                v-if="scope.row.local && scope.row.confirmation_pending"
-                @click.native="handleConfirmationResend(scope.row)">
-                {{ $t('users.resendConfirmation') }}
-              </el-dropdown-item>
-              <el-dropdown-item
-                :divided="showAdminAction(scope.row)"
-                :class="{ 'active-tag': scope.row.tags.includes('force_nsfw') }"
-                @click.native="toggleTag(scope.row, 'force_nsfw')">
-                {{ $t('users.forceNsfw') }}
-                <i v-if="scope.row.tags.includes('force_nsfw')" class="el-icon-check"/>
-              </el-dropdown-item>
-              <el-dropdown-item
-                :class="{ 'active-tag': scope.row.tags.includes('strip_media') }"
-                @click.native="toggleTag(scope.row, 'strip_media')">
-                {{ $t('users.stripMedia') }}
-                <i v-if="scope.row.tags.includes('strip_media')" class="el-icon-check"/>
-              </el-dropdown-item>
-              <el-dropdown-item
-                :class="{ 'active-tag': scope.row.tags.includes('force_unlisted') }"
-                @click.native="toggleTag(scope.row, 'force_unlisted')">
-                {{ $t('users.forceUnlisted') }}
-                <i v-if="scope.row.tags.includes('force_unlisted')" class="el-icon-check"/>
-              </el-dropdown-item>
-              <el-dropdown-item
-                :class="{ 'active-tag': scope.row.tags.includes('sandbox') }"
-                @click.native="toggleTag(scope.row, 'sandbox')">
-                {{ $t('users.sandbox') }}
-                <i v-if="scope.row.tags.includes('sandbox')" class="el-icon-check"/>
-              </el-dropdown-item>
-              <el-dropdown-item
-                v-if="scope.row.local"
-                :class="{ 'active-tag': scope.row.tags.includes('disable_remote_subscription') }"
-                @click.native="toggleTag(scope.row, 'disable_remote_subscription')">
-                {{ $t('users.disableRemoteSubscription') }}
-                <i v-if="scope.row.tags.includes('disable_remote_subscription')" class="el-icon-check"/>
-              </el-dropdown-item>
-              <el-dropdown-item
-                v-if="scope.row.local"
-                :class="{ 'active-tag': scope.row.tags.includes('disable_any_subscription') }"
-                @click.native="toggleTag(scope.row, 'disable_any_subscription')">
-                {{ $t('users.disableAnySubscription') }}
-                <i v-if="scope.row.tags.includes('disable_any_subscription')" class="el-icon-check"/>
-              </el-dropdown-item>
-              <el-dropdown-item
-                v-if="scope.row.local"
-                divided
-                @click.native="getPasswordResetToken(scope.row.nickname)">
-                {{ $t('users.getPasswordResetToken') }}
-              </el-dropdown-item>
-              <el-dropdown-item
-                v-if="scope.row.local"
-                @click.native="requirePasswordReset(scope.row.nickname)">
-                {{ $t('users.requirePasswordReset') }}
-              </el-dropdown-item>
-            </el-dropdown-menu>
-          </el-dropdown>
+          <moderation-dropdown
+            :user="scope.row"
+            :page="'users'"
+            @open-reset-token-dialog="openResetPasswordDialog"/>
         </template>
       </el-table-column>
     </el-table>
@@ -191,13 +105,15 @@ import numeral from 'numeral'
 import UsersFilter from './components/UsersFilter'
 import MultipleUsersMenu from './components/MultipleUsersMenu'
 import NewAccountDialog from './components/NewAccountDialog'
+import ModerationDropdown from './components/ModerationDropdown'
 
 export default {
   name: 'Users',
   components: {
-    UsersFilter,
+    NewAccountDialog,
+    ModerationDropdown,
     MultipleUsersMenu,
-    NewAccountDialog
+    UsersFilter
   },
   data() {
     return {
@@ -257,6 +173,10 @@ export default {
     clearSelection() {
       this.$refs.usersTable.clearSelection()
     },
+    closeResetPasswordDialog() {
+      this.resetPasswordDialogOpen = false
+      this.$store.dispatch('RemovePasswordToken')
+    },
     async createNewAccount(accountData) {
       await this.$store.dispatch('CreateNewAccount', accountData)
       this.createAccountDialogOpen = false
@@ -264,29 +184,6 @@ export default {
     getFirstLetter(str) {
       return str.charAt(0).toUpperCase()
     },
-    getPasswordResetToken(nickname) {
-      this.resetPasswordDialogOpen = true
-      this.$store.dispatch('GetPasswordResetToken', nickname)
-    },
-    requirePasswordReset(nickname) {
-      const mailerEnabled = this.$store.state.user.nodeInfo.metadata.mailerEnabled
-
-      if (!mailerEnabled) {
-        this.$alert(this.$t('users.mailerMustBeEnabled'), 'Error', { type: 'error' })
-
-        return
-      }
-
-      this.$store.dispatch('RequirePasswordReset', { nicknames: [nickname] })
-    },
-    toggleActivation(user) {
-      user.deactivated
-        ? this.$store.dispatch('ActivateUsers', [user])
-        : this.$store.dispatch('DeactivateUsers', [user])
-    },
-    handleDeletion(user) {
-      this.$store.dispatch('DeleteUsers', [user])
-    },
     handlePageChange(page) {
       const searchQuery = this.$store.state.users.searchQuery
       if (searchQuery === '') {
@@ -298,31 +195,11 @@ export default {
     handleSelectionChange(value) {
       this.$data.selectedUsers = value
     },
-    closeResetPasswordDialog() {
-      this.resetPasswordDialogOpen = false
-      this.$store.dispatch('RemovePasswordToken')
-    },
-    showAdminAction({ local, id }) {
-      return local && this.showDeactivatedButton(id)
+    openResetPasswordDialog() {
+      this.resetPasswordDialogOpen = true
     },
     showDeactivatedButton(id) {
       return this.$store.state.user.id !== id
-    },
-    toggleTag(user, tag) {
-      user.tags.includes(tag)
-        ? this.$store.dispatch('RemoveTag', { users: [user], tag })
-        : this.$store.dispatch('AddTag', { users: [user], tag })
-    },
-    toggleUserRight(user, right) {
-      user.roles[right]
-        ? this.$store.dispatch('DeleteRight', { users: [user], right })
-        : this.$store.dispatch('AddRight', { users: [user], right })
-    },
-    handleEmailConfirmation(user) {
-      this.$store.dispatch('ConfirmUsersEmail', [user])
-    },
-    handleConfirmationResend(user) {
-      this.$store.dispatch('ResendConfirmationEmail', [user])
     }
   }
 }
diff --git a/src/views/users/show.vue b/src/views/users/show.vue
index 2b1146de0e17a9db1e3aaf54f15f2b44953bdf47..aa826c07c715ed751aeafbb27c7397359e18e57c 100644
--- a/src/views/users/show.vue
+++ b/src/views/users/show.vue
@@ -1,9 +1,28 @@
 <template>
   <main v-if="!userProfileLoading">
-    <header>
-      <el-avatar :src="user.avatar" size="large" />
-      <h1>{{ user.display_name }}</h1>
+    <header class="user-page-header">
+      <div class="avatar-name-container">
+        <el-avatar :src="user.avatar" size="large" />
+        <h1>{{ user.display_name }}</h1>
+      </div>
+      <moderation-dropdown
+        :user="user"
+        :page="'userPage'"
+        @open-reset-token-dialog="openResetPasswordDialog"/>
     </header>
+    <el-dialog
+      v-loading="loading"
+      :visible.sync="resetPasswordDialogOpen"
+      :title="$t('users.passwordResetTokenCreated')"
+      custom-class="password-reset-token-dialog"
+      @close="closeResetPasswordDialog">
+      <div>
+        <p class="password-reset-token">Password reset token was generated: {{ passwordResetToken }}</p>
+        <p>You can also use this link to reset password:
+          <a :href="passwordResetLink" target="_blank" class="reset-password-link">{{ passwordResetLink }}</a>
+        </p>
+      </div>
+    </el-dialog>
     <el-row>
       <el-col :span="8">
         <el-card class="user-profile-card">
@@ -84,16 +103,27 @@
 
 <script>
 import Status from '@/components/Status'
+import ModerationDropdown from './components/ModerationDropdown'
 
 export default {
   name: 'UsersShow',
-  components: { Status },
+  components: { ModerationDropdown, Status },
   data() {
     return {
-      showPrivate: false
+      showPrivate: false,
+      resetPasswordDialogOpen: false
     }
   },
   computed: {
+    loading() {
+      return this.$store.state.users.loading
+    },
+    passwordResetLink() {
+      return this.$store.state.users.passwordResetToken.link
+    },
+    passwordResetToken() {
+      return this.$store.state.users.passwordResetToken.token
+    },
     statuses() {
       return this.$store.state.userProfile.statuses
     },
@@ -111,14 +141,25 @@ export default {
     this.$store.dispatch('FetchUserProfile', { userId: this.$route.params.id, godmode: false })
   },
   methods: {
+    closeResetPasswordDialog() {
+      this.resetPasswordDialogOpen = false
+      this.$store.dispatch('RemovePasswordToken')
+    },
     onTogglePrivate() {
       this.$store.dispatch('FetchUserProfile', { userId: this.$route.params.id, godmode: this.showPrivate })
+    },
+    openResetPasswordDialog() {
+      this.resetPasswordDialogOpen = true
     }
   }
 }
 </script>
 
 <style rel='stylesheet/scss' lang='scss' scoped>
+.avatar-name-container {
+  display: flex;
+  align-items: center;
+}
 header {
   align-items: center;
   display: flex;
@@ -151,7 +192,6 @@ table {
 .no-statuses {
   margin-left: 28px;
   color: #606266;
-
 }
 .recent-statuses-header {
   margin-top: 10px;
@@ -160,16 +200,24 @@ table {
   padding: 0 20px 0 0;
 }
 .show-private {
-  text-align: right;
+  width: 200px;
+  text-align: left;
   line-height: 67px;
-  padding-right: 20px;
+  margin-right: 20px;
 }
 .recent-statuses {
   margin-left: 28px;
 }
+.user-page-header {
+  display: flex;
+  justify-content: space-between;
+  padding: 0 20px;
+  h1 {
+    display: inline
+  }
+}
 .user-profile-card {
-  margin-left: 15px;
-  margin-right: 20px;
+  margin: 0 20px;
 }
 .user-profile-table {
   margin: 0;