瀏覽代碼

feat: delete a user

NGPixel 5 年之前
父節點
當前提交
f09f1f4f1e

+ 2 - 1
client/components/admin/admin-users-create.vue

@@ -57,7 +57,8 @@
           prepend-icon='mdi-account-group'
           v-model='group'
           label='Assign to Group(s)...'
-          dense
+          hint='Note that you cannot assign users to the Administrators or Guests groups from this dialog.'
+          persistent-hint
           clearable
           multiple
           )

+ 72 - 15
client/components/admin/admin-users-edit.vue

@@ -23,23 +23,30 @@
           v-spacer
           i18next.caption.grey--text.animated.fadeInRight.wait-p5s(path='admin:users.id', tag='div')
             strong(place='id') {{user.id}}
-          v-divider.animated.fadeInRight.wait-p3s.ml-3(vertical)
-          v-btn.ml-3.animated.fadeInDown.wait-p2s(color='grey', large, outlined, to='/users')
+          v-divider.animated.fadeInRight.wait-p4s.ml-3(vertical)
+          v-btn.ml-3.animated.fadeInDown.wait-p3s(color='grey', large, outlined, to='/users')
             v-icon mdi-arrow-left
-          v-dialog(v-model='deleteUserDialog', max-width='500', v-if='user.id !== currentUserId && !user.isSystem')
+          v-menu(offset-y, origin='top right')
             template(v-slot:activator='{ on }')
-              v-btn.ml-3.animated.fadeInDown.wait-p1s(color='red', large, outlined, v-on='on', disabled)
-                v-icon(color='red') mdi-trash-can-outline
-            v-card
-              .dialog-header.is-red Delete User?
-              v-card-text Are you sure you want to delete user #[strong {{ user.name }}]?
-              v-card-actions
-                v-spacer
-                v-btn(text, @click='deleteUserDialog = false') Cancel
-                v-btn(color='red', dark, @click='deleteUser') Delete
+              v-btn.ml-3.animated.fadeInDown.wait-p2s(color='indigo', v-on='on', large, depressed, dark)
+                span Actions
+                v-icon(right) mdi-chevron-down
+            v-list(dense, nav)
+              v-list-item(v-if='!user.isActive', @click='activateUser')
+                v-list-item-icon
+                  v-icon(color='purple') mdi-steering
+                v-list-item-title Activate
+              v-list-item(v-else, @click='deactivateUser', :disabled='user.id == currentUserId || user.isSystem')
+                v-list-item-icon
+                  v-icon(color='purple') mdi-cancel
+                v-list-item-title Deactivate
+              v-list-item(@click='deleteUserDialog = true', :disabled='user.id == currentUserId || user.isSystem')
+                v-list-item-icon
+                  v-icon(color='red') mdi-trash-can-outline
+                v-list-item-title Delete
           v-btn.ml-3.animated.fadeInDown(color='primary', large, depressed, @click='updateUser')
             v-icon(left) mdi-check
-            span Update User
+            span {{$t('admin:users.updateUser')}}
       v-flex(xs6)
         v-card.animated.fadeInUp
           v-toolbar(color='primary', dense, dark, flat)
@@ -208,7 +215,6 @@
               item-disabled='isSystem'
               solo
               flat
-              dense
               hide-details
               @keydown.esc='editPop.assignGroup = false'
               style='max-width: 300px;'
@@ -216,6 +222,10 @@
             v-btn.ml-2.px-4(depressed, color='primary', height='48', @click='assignGroup', :disabled='newGroup === 0')
               v-icon(left) mdi-clipboard-account-outline
               span {{$t('admin:users.groupAssign')}}
+          v-system-bar(window, :color='$vuetify.theme.dark ? `grey darken-4-l3` : `grey lighten-3`')
+            v-spacer
+            .caption {{$t('admin:users.groupAssignNotice')}}
+
       v-flex(xs6)
         v-card.animated.fadeInUp.wait-p2s
           v-toolbar(color='primary', dense, dark, flat)
@@ -317,6 +327,18 @@
           v-card-text
             em.caption.grey--text Coming soon
 
+    v-dialog(v-model='deleteUserDialog', max-width='500')
+      v-card
+        .dialog-header.is-red {{$t('admin:users.deleteConfirmTitle')}}
+        v-card-text.pt-5
+          i18next(path='admin:users.deleteConfirmText', tag='span')
+            strong(place='username') {{ user.email }}
+          .caption.mt-3 {{$t('admin:users.deleteConfirmForeignNotice')}}
+        v-card-actions
+          v-spacer
+          v-btn(text, @click='deleteUserDialog = false') {{$t('common:actions.cancel')}}
+          v-btn(color='red', dark, @click='deleteUser') {{$t('common:actions.delete')}}
+
 </template>
 <script>
 import _ from 'lodash'
@@ -327,6 +349,7 @@ import { StatusIndicator } from 'vue-status-indicator'
 import userQuery from 'gql/admin/users/users-query-single.gql'
 import groupsQuery from 'gql/admin/users/users-query-groups.gql'
 import updateUserMutation from 'gql/admin/users/users-mutation-update.gql'
+import deleteUserMutation from 'gql/admin/users/users-mutation-delete.gql'
 
 export default {
   components: {
@@ -615,7 +638,41 @@ export default {
     currentUserId: get('user/id')
   },
   methods: {
-    deleteUser() {},
+    async activateUser () {
+
+    },
+    async deactivateUser () {
+      this.$store.commit('showNotification', {
+        style: 'indigo',
+        message: `Coming soon...`,
+        icon: 'directions_boat'
+      })
+    },
+    async deleteUser () {
+      this.$store.commit(`loadingStart`, 'admin-users-delete')
+      const resp = await this.$apollo.mutate({
+        mutation: deleteUserMutation,
+        variables: {
+          id: this.user.id
+        }
+      })
+      if (_.get(resp, 'data.users.delete.responseResult.succeeded', false)) {
+        this.$store.commit('showNotification', {
+          style: 'success',
+          message: this.$t('admin:users.userDeleteSuccess'),
+          icon: 'check'
+        })
+        this.$router.push('/users')
+      } else {
+        this.$store.commit('showNotification', {
+          style: 'red',
+          message: _.get(resp, 'data.users.delete.responseResult.message', 'An unexpected error occured.'),
+          icon: 'warning'
+        })
+      }
+      this.deleteUserDialog = false
+      this.$store.commit(`loadingStop`, 'admin-users-delete')
+    },
     async updateUser() {
       this.$store.commit(`loadingStart`, 'admin-users-update')
       const resp = await this.$apollo.mutate({

+ 12 - 0
client/graph/admin/users/users-mutation-delete.gql

@@ -0,0 +1,12 @@
+mutation ($id: Int!) {
+  users {
+    delete(id: $id) {
+      responseResult {
+        succeeded
+        errorCode
+        slug
+        message
+      }
+    }
+  }
+}

+ 19 - 5
server/graph/resolvers/user.js

@@ -29,7 +29,7 @@ module.exports = {
     }
   },
   UserMutation: {
-    async create(obj, args) {
+    async create (obj, args) {
       try {
         await WIKI.models.users.createNewUser(args)
 
@@ -40,10 +40,24 @@ module.exports = {
         return graphHelper.generateError(err)
       }
     },
-    delete(obj, args) {
-      return WIKI.models.users.query().deleteById(args.id)
+    async delete (obj, args) {
+      try {
+        if (args.id <= 2) {
+          throw new WIKI.Error.UserDeleteProtected()
+        }
+        await WIKI.models.users.query().deleteById(args.id)
+        return {
+          responseResult: graphHelper.generateSuccess('User deleted successfully')
+        }
+      } catch (err) {
+        if (err.message.indexOf('foreign') >= 0) {
+          return graphHelper.generateError(new WIKI.Error.UserDeleteForeignConstraint())
+        } else {
+          return graphHelper.generateError(err)
+        }
+      }
     },
-    async update(obj, args) {
+    async update (obj, args) {
       try {
         await WIKI.models.users.updateUser(args)
 
@@ -54,7 +68,7 @@ module.exports = {
         return graphHelper.generateError(err)
       }
     },
-    resetPassword(obj, args) {
+    resetPassword (obj, args) {
       return false
     }
   },

+ 8 - 0
server/helpers/error.js

@@ -169,6 +169,14 @@ module.exports = {
     message: 'An unexpected error occured during user creation.',
     code: 1009
   }),
+  UserDeleteForeignConstraint: CustomError('UserCreationFailed', {
+    message: 'Cannot delete user because of content relational constraints.',
+    code: 1017
+  }),
+  UserDeleteProtected: CustomError('UserDeleteProtected', {
+    message: 'Cannot delete a protected system account.',
+    code: 1018
+  }),
   UserNotFound: CustomError('UserNotFound', {
     message: 'This user does not exist.',
     code: 1016

+ 8 - 0
server/modules/rendering/openapi-core/definition.yml

@@ -0,0 +1,8 @@
+key: openapiCore
+title: Core
+description: Basic OpenAPI Parser
+author: requarks.io
+input: openapi
+output: html
+icon: mdi-api
+props: {}

+ 14 - 0
server/modules/rendering/openapi-core/renderer.js

@@ -0,0 +1,14 @@
+const _ = require('lodash')
+
+module.exports = {
+  async render() {
+    let output = this.input
+
+    for (let child of this.children) {
+      const renderer = require(`../${_.kebabCase(child.key)}/renderer.js`)
+      output = await renderer.init(output, child.config)
+    }
+
+    return output
+  }
+}