feat: delete user with replace target

This commit is contained in:
NGPixel 2020-05-30 16:34:09 -04:00
parent 006dae1221
commit 1f9e5b3fd0
15 changed files with 1703 additions and 749 deletions

View File

@ -1,5 +1,5 @@
<template lang="pug"> <template lang="pug">
v-card v-card(flat)
v-card-text(v-if='group.id === 1') v-card-text(v-if='group.id === 1')
v-alert.radius-7( v-alert.radius-7(
:class='$vuetify.theme.dark ? "grey darken-4" : "orange lighten-5"' :class='$vuetify.theme.dark ? "grey darken-4" : "orange lighten-5"'

View File

@ -1,5 +1,5 @@
<template lang="pug"> <template lang="pug">
v-card v-card(flat)
v-card-title.pb-4(:class='$vuetify.theme.dark ? `grey darken-3-d3` : `grey lighten-5`') v-card-title.pb-4(:class='$vuetify.theme.dark ? `grey darken-3-d3` : `grey lighten-5`')
v-text-field( v-text-field(
outlined outlined
@ -8,6 +8,8 @@
v-model='search' v-model='search'
label='Search Group Users...' label='Search Group Users...'
hide-details hide-details
dense
style='max-width: 450px;'
) )
v-spacer v-spacer
v-btn(color='primary', depressed, @click='searchUserDialog = true', :disabled='group.id === 2') v-btn(color='primary', depressed, @click='searchUserDialog = true', :disabled='group.id === 2')
@ -65,7 +67,7 @@ export default {
data() { data() {
return { return {
headers: [ headers: [
{ text: 'ID', value: 'id', width: 50 }, { text: 'ID', value: 'id', width: 70 },
{ text: 'Name', value: 'name' }, { text: 'Name', value: 'name' },
{ text: 'Email', value: 'email' }, { text: 'Email', value: 'email' },
{ text: 'Actions', value: 'actions', sortable: false, width: 50 } { text: 'Actions', value: 'actions', sortable: false, width: 50 }
@ -90,7 +92,7 @@ export default {
} }
}, },
methods: { methods: {
async assignUser(id) { async assignUser({ id, email, name }) {
try { try {
await this.$apollo.mutate({ await this.$apollo.mutate({
mutation: assignUserMutation, mutation: assignUserMutation,

View File

@ -43,7 +43,7 @@
v-list-item-icon v-list-item-icon
v-icon(color='blue') mdi-account-check v-icon(color='blue') mdi-account-check
v-list-item-title Set as Verified v-list-item-title Set as Verified
v-list-item(@click='deleteUserDialog = true', :disabled='user.id == currentUserId || user.isSystem') v-list-item(@click='deleteUserConfirm', :disabled='user.id == currentUserId || user.isSystem')
v-list-item-icon v-list-item-icon
v-icon(color='red') mdi-trash-can-outline v-icon(color='red') mdi-trash-can-outline
v-list-item-title Delete v-list-item-title Delete
@ -221,8 +221,9 @@
hide-details hide-details
@keydown.esc='editPop.assignGroup = false' @keydown.esc='editPop.assignGroup = false'
style='max-width: 300px;' style='max-width: 300px;'
dense
) )
v-btn.ml-2.px-4(depressed, color='primary', height='48', @click='assignGroup', :disabled='newGroup === 0') v-btn.ml-2.px-4(depressed, color='primary', @click='assignGroup', :disabled='newGroup === 0')
v-icon(left) mdi-clipboard-account-outline v-icon(left) mdi-clipboard-account-outline
span {{$t('admin:users.groupAssign')}} span {{$t('admin:users.groupAssign')}}
v-system-bar(window, :color='$vuetify.theme.dark ? `grey darken-4-l3` : `grey lighten-3`') v-system-bar(window, :color='$vuetify.theme.dark ? `grey darken-4-l3` : `grey lighten-3`')
@ -349,20 +350,32 @@
v-card-text.pt-5 v-card-text.pt-5
i18next(path='admin:users.deleteConfirmText', tag='span') i18next(path='admin:users.deleteConfirmText', tag='span')
strong(place='username') {{ user.email }} strong(place='username') {{ user.email }}
.caption.mt-3 {{$t('admin:users.deleteConfirmForeignNotice')}} .mt-3 {{$t('admin:users.deleteConfirmReplaceWarn')}}
v-card-actions v-divider.my-3
.d-flex.align-center.mt-3
v-btn.text-none(color='primary', depressed, @click='deleteSearchUserDialog = true')
v-icon(left) mdi-clipboard-account
| Select User...
.caption.pl-3
strong ID {{deleteReplaceUser.id}}
.caption {{deleteReplaceUser.name}}
em {{deleteReplaceUser.email}}
v-card-chin
v-spacer v-spacer
v-btn(text, @click='deleteUserDialog = false') {{$t('common:actions.cancel')}} v-btn(text, @click='deleteUserDialog = false') {{$t('common:actions.cancel')}}
v-btn(color='red', dark, @click='deleteUser') {{$t('common:actions.delete')}} v-btn(color='red', dark, @click='deleteUser') {{$t('common:actions.delete')}}
user-search(v-model='deleteSearchUserDialog', @select='assignDeleteUser')
</template> </template>
<script> <script>
import _ from 'lodash' import _ from 'lodash'
import { get } from 'vuex-pathify' import { get } from 'vuex-pathify'
import gql from 'graphql-tag' import gql from 'graphql-tag'
import { StatusIndicator } from 'vue-status-indicator' import { StatusIndicator } from 'vue-status-indicator'
import UserSearch from '../common/user-search.vue'
import groupsQuery from 'gql/admin/users/users-query-groups.gql' import groupsQuery from 'gql/admin/users/users-query-groups.gql'
export default { export default {
@ -370,11 +383,18 @@ export default {
namespaces: ['admin', 'profile'] namespaces: ['admin', 'profile']
}, },
components: { components: {
StatusIndicator StatusIndicator,
UserSearch
}, },
data() { data () {
return { return {
deleteUserDialog: false, deleteUserDialog: false,
deleteSearchUserDialog: false,
deleteReplaceUser: {
id: 1,
name: '',
email: ''
},
editPop: { editPop: {
email: false, email: false,
name: false, name: false,
@ -738,13 +758,21 @@ export default {
/** /**
* Delete a user * Delete a user
*/ */
deleteUserConfirm () {
this.deleteUserDialog = true
this.deleteReplaceUser = {
id: this.currentUserId,
name: this.$store.get('user/name'),
email: this.$store.get('user/email')
}
},
async deleteUser () { async deleteUser () {
this.$store.commit(`loadingStart`, 'admin-users-delete') this.$store.commit(`loadingStart`, 'admin-users-delete')
const resp = await this.$apollo.mutate({ const resp = await this.$apollo.mutate({
mutation: gql` mutation: gql`
mutation ($id: Int!) { mutation ($id: Int!, $replaceId: Int!) {
users { users {
delete(id: $id) { delete(id: $id, replaceId: $replaceId) {
responseResult { responseResult {
succeeded succeeded
errorCode errorCode
@ -756,7 +784,8 @@ export default {
} }
`, `,
variables: { variables: {
id: this.user.id id: this.user.id,
replaceId: this.deleteReplaceUser.id
} }
}) })
if (_.get(resp, 'data.users.delete.responseResult.succeeded', false)) { if (_.get(resp, 'data.users.delete.responseResult.succeeded', false)) {
@ -776,6 +805,23 @@ export default {
this.deleteUserDialog = false this.deleteUserDialog = false
this.$store.commit(`loadingStop`, 'admin-users-delete') this.$store.commit(`loadingStop`, 'admin-users-delete')
}, },
assignDeleteUser (selUsr) {
if (selUsr.id === this.user.id) {
this.$store.commit('showNotification', {
style: 'red',
message: 'You cannot select the account you\'re about to delete!',
icon: 'warning'
})
} else if (selUsr.id === 2) {
this.$store.commit('showNotification', {
style: 'red',
message: 'You cannot use the guest account for this operation.',
icon: 'warning'
})
} else {
this.deleteReplaceUser = selUsr
}
},
/** /**
* Update a user * Update a user
*/ */

View File

@ -30,7 +30,7 @@
dense dense
) )
template(v-for='(usr, idx) in items') template(v-for='(usr, idx) in items')
v-list-item(:key='usr.id', @click='setUser(usr.id)') v-list-item(:key='usr.id', @click='setUser(usr)')
v-list-item-avatar(size='40', color='primary') v-list-item-avatar(size='40', color='primary')
span.body-1.white--text {{usr.name | initials}} span.body-1.white--text {{usr.name | initials}}
v-list-item-content v-list-item-content
@ -50,8 +50,7 @@
<script> <script>
import _ from 'lodash' import _ from 'lodash'
import gql from 'graphql-tag'
import searchUsersQuery from 'gql/common/common-users-query-search.gql'
export default { export default {
filters: { filters: {
@ -96,8 +95,8 @@ export default {
close() { close() {
this.$emit('input', false) this.$emit('input', false)
}, },
setUser(id) { setUser(usr) {
this.$emit('select', id) this.$emit('select', usr)
this.close() this.close()
}, },
searchFilter(item, queryText, itemText) { searchFilter(item, queryText, itemText) {
@ -106,7 +105,18 @@ export default {
}, },
apollo: { apollo: {
items: { items: {
query: searchUsersQuery, query: gql`
query ($query: String!) {
users {
search(query:$query) {
id
name
email
providerKey
}
}
}
`,
variables() { variables() {
return { return {
query: this.search query: this.search

View File

@ -1,10 +0,0 @@
query ($query: String!) {
users {
search(query:$query) {
id
name
email
providerKey
}
}
}

View File

@ -183,10 +183,12 @@ module.exports = {
startYear: 2017, startYear: 2017,
endYear: (new Date().getFullYear()) + 5 endYear: (new Date().getFullYear()) + 5
}), }),
new CopyWebpackPlugin([ new CopyWebpackPlugin({
{ from: 'client/static' }, patterns: [
{ from: './node_modules/prismjs/components', to: 'js/prism' } { from: 'client/static' },
], {}), { from: './node_modules/prismjs/components', to: 'js/prism' }
]
}),
new HtmlWebpackPlugin({ new HtmlWebpackPlugin({
template: 'dev/templates/master.pug', template: 'dev/templates/master.pug',
filename: '../server/views/master.pug', filename: '../server/views/master.pug',

View File

@ -190,10 +190,12 @@ module.exports = {
startYear: 2017, startYear: 2017,
endYear: (new Date().getFullYear()) + 5 endYear: (new Date().getFullYear()) + 5
}), }),
new CopyWebpackPlugin([ new CopyWebpackPlugin({
{ from: 'client/static' }, patterns: [
{ from: './node_modules/prismjs/components', to: 'js/prism' } { from: 'client/static' },
], {}), { from: './node_modules/prismjs/components', to: 'js/prism' }
]
}),
new MiniCssExtractPlugin({ new MiniCssExtractPlugin({
filename: 'css/bundle.[hash].css', filename: 'css/bundle.[hash].css',
chunkFilename: 'css/[name].[chunkhash].css' chunkFilename: 'css/[name].[chunkhash].css'

View File

@ -36,8 +36,8 @@
}, },
"dependencies": { "dependencies": {
"@aoberoi/passport-slack": "1.0.5", "@aoberoi/passport-slack": "1.0.5",
"@azure/storage-blob": "12.1.1", "@azure/storage-blob": "12.1.2",
"@bugsnag/js": "7.0.2", "@bugsnag/js": "7.1.1",
"@exlinc/keycloak-passport": "1.0.2", "@exlinc/keycloak-passport": "1.0.2",
"@root/csr": "0.8.1", "@root/csr": "0.8.1",
"@root/keypairs": "0.9.0", "@root/keypairs": "0.9.0",
@ -49,7 +49,7 @@
"apollo-server": "2.13.1", "apollo-server": "2.13.1",
"apollo-server-express": "2.13.1", "apollo-server-express": "2.13.1",
"auto-load": "3.0.4", "auto-load": "3.0.4",
"aws-sdk": "2.678.0", "aws-sdk": "2.686.0",
"azure-search-client": "3.1.5", "azure-search-client": "3.1.5",
"bcryptjs-then": "1.0.1", "bcryptjs-then": "1.0.1",
"bluebird": "3.7.2", "bluebird": "3.7.2",
@ -74,14 +74,14 @@
"elasticsearch6": "npm:@elastic/elasticsearch@6", "elasticsearch6": "npm:@elastic/elasticsearch@6",
"elasticsearch7": "npm:@elastic/elasticsearch@7", "elasticsearch7": "npm:@elastic/elasticsearch@7",
"emoji-regex": "9.0.0", "emoji-regex": "9.0.0",
"eventemitter2": "6.4.0", "eventemitter2": "6.4.1",
"express": "4.17.1", "express": "4.17.1",
"express-brute": "1.0.1", "express-brute": "1.0.1",
"express-session": "1.17.1", "express-session": "1.17.1",
"file-type": "14.4.0", "file-type": "14.5.0",
"filesize": "6.1.0", "filesize": "6.1.0",
"fs-extra": "9.0.0", "fs-extra": "9.0.0",
"getos": "3.2.0", "getos": "3.2.1",
"graphql": "14.6.0", "graphql": "14.6.0",
"graphql-list-fields": "2.0.2", "graphql-list-fields": "2.0.2",
"graphql-rate-limit-directive": "1.2.1", "graphql-rate-limit-directive": "1.2.1",
@ -89,22 +89,22 @@
"graphql-tools": "4.0.7", "graphql-tools": "4.0.7",
"he": "1.2.0", "he": "1.2.0",
"highlight.js": "10.0.3", "highlight.js": "10.0.3",
"i18next": "19.4.4", "i18next": "19.4.5",
"i18next-express-middleware": "2.0.0", "i18next-express-middleware": "2.0.0",
"i18next-node-fs-backend": "2.1.3", "i18next-node-fs-backend": "2.1.3",
"image-size": "0.8.3", "image-size": "0.8.3",
"js-base64": "2.5.2", "js-base64": "2.5.2",
"js-binary": "1.2.0", "js-binary": "1.2.0",
"js-yaml": "3.13.1", "js-yaml": "3.14.0",
"jsdom": "16.2.2", "jsdom": "16.2.2",
"jsonwebtoken": "8.5.1", "jsonwebtoken": "8.5.1",
"katex": "0.11.1", "katex": "0.11.1",
"klaw": "3.0.0", "klaw": "3.0.0",
"knex": "0.21.1", "knex": "0.21.1",
"lodash": "4.17.15", "lodash": "4.17.15",
"markdown-it": "10.0.0", "markdown-it": "11.0.0",
"markdown-it-abbr": "1.0.4", "markdown-it-abbr": "1.0.4",
"markdown-it-attrs": "3.0.2", "markdown-it-attrs": "3.0.3",
"markdown-it-emoji": "1.4.0", "markdown-it-emoji": "1.4.0",
"markdown-it-expand-tabs": "1.0.13", "markdown-it-expand-tabs": "1.0.13",
"markdown-it-external-links": "0.0.6", "markdown-it-external-links": "0.0.6",
@ -117,18 +117,18 @@
"markdown-it-task-lists": "2.1.1", "markdown-it-task-lists": "2.1.1",
"mathjax": "3.0.5", "mathjax": "3.0.5",
"mime-types": "2.1.27", "mime-types": "2.1.27",
"moment": "2.25.3", "moment": "2.26.0",
"moment-timezone": "0.5.29", "moment-timezone": "0.5.31",
"mongodb": "3.5.7", "mongodb": "3.5.8",
"ms": "2.1.2", "ms": "2.1.2",
"mssql": "6.2.0", "mssql": "6.2.0",
"multer": "1.4.2", "multer": "1.4.2",
"mysql2": "2.1.0", "mysql2": "2.1.0",
"nanoid": "3.1.8", "nanoid": "3.1.9",
"node-2fa": "1.1.2", "node-2fa": "1.1.2",
"node-cache": "5.1.0", "node-cache": "5.1.0",
"nodemailer": "6.4.6", "nodemailer": "6.4.8",
"objection": "2.1.3", "objection": "2.1.5",
"passport": "0.4.1", "passport": "0.4.1",
"passport-auth0": "1.3.2", "passport-auth0": "1.3.2",
"passport-azure-ad": "4.2.1", "passport-azure-ad": "4.2.1",
@ -154,7 +154,7 @@
"pg-pubsub": "0.5.0", "pg-pubsub": "0.5.0",
"pg-query-stream": "3.1.1", "pg-query-stream": "3.1.1",
"pg-tsquery": "8.1.0", "pg-tsquery": "8.1.0",
"pug": "2.0.4", "pug": "3.0.0",
"punycode": "2.1.1", "punycode": "2.1.1",
"qr-image": "3.2.0", "qr-image": "3.2.0",
"raven": "2.6.4", "raven": "2.6.4",
@ -166,7 +166,7 @@
"scim-query-filter-parser": "2.0.4", "scim-query-filter-parser": "2.0.4",
"semver": "7.3.2", "semver": "7.3.2",
"serve-favicon": "2.5.0", "serve-favicon": "2.5.0",
"simple-git": "2.4.0", "simple-git": "2.5.0",
"solr-node": "1.2.1", "solr-node": "1.2.1",
"sqlite3": "4.2.0", "sqlite3": "4.2.0",
"ssh2": "0.8.9", "ssh2": "0.8.9",
@ -176,30 +176,30 @@
"tar-fs": "2.1.0", "tar-fs": "2.1.0",
"twemoji": "13.0.0", "twemoji": "13.0.0",
"uslug": "1.0.4", "uslug": "1.0.4",
"uuid": "8.0.0", "uuid": "8.1.0",
"validate.js": "0.13.1", "validate.js": "0.13.1",
"winston": "3.2.1", "winston": "3.2.1",
"xss": "1.0.6", "xss": "1.0.6",
"yargs": "15.3.1" "yargs": "15.3.1"
}, },
"devDependencies": { "devDependencies": {
"@babel/cli": "^7.8.4", "@babel/cli": "^7.10.1",
"@babel/core": "^7.9.6", "@babel/core": "^7.10.1",
"@babel/plugin-proposal-class-properties": "^7.8.3", "@babel/plugin-proposal-class-properties": "^7.10.1",
"@babel/plugin-proposal-decorators": "^7.8.3", "@babel/plugin-proposal-decorators": "^7.10.1",
"@babel/plugin-proposal-export-namespace-from": "^7.8.3", "@babel/plugin-proposal-export-namespace-from": "^7.10.1",
"@babel/plugin-proposal-function-sent": "^7.8.3", "@babel/plugin-proposal-function-sent": "^7.10.1",
"@babel/plugin-proposal-json-strings": "^7.8.3", "@babel/plugin-proposal-json-strings": "^7.10.1",
"@babel/plugin-proposal-numeric-separator": "^7.8.3", "@babel/plugin-proposal-numeric-separator": "^7.10.1",
"@babel/plugin-proposal-throw-expressions": "^7.8.3", "@babel/plugin-proposal-throw-expressions": "^7.10.1",
"@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-syntax-import-meta": "^7.8.3", "@babel/plugin-syntax-import-meta": "^7.10.1",
"@babel/polyfill": "^7.8.7", "@babel/polyfill": "^7.10.1",
"@babel/preset-env": "^7.9.6", "@babel/preset-env": "^7.10.1",
"@mdi/font": "5.2.45", "@mdi/font": "5.3.45",
"@panter/vue-i18next": "0.15.2", "@panter/vue-i18next": "0.15.2",
"@requarks/ckeditor5": "12.4.0-wiki.16", "@requarks/ckeditor5": "12.4.0-wiki.16",
"@vue/babel-preset-app": "4.3.1", "@vue/babel-preset-app": "4.4.1",
"animate-sass": "0.8.2", "animate-sass": "0.8.2",
"animated-number-vue": "1.0.0", "animated-number-vue": "1.0.0",
"apollo-cache-inmemory": "1.6.6", "apollo-cache-inmemory": "1.6.6",
@ -211,7 +211,7 @@
"apollo-link-persisted-queries": "0.2.2", "apollo-link-persisted-queries": "0.2.2",
"apollo-link-ws": "1.0.20", "apollo-link-ws": "1.0.20",
"apollo-utilities": "1.3.4", "apollo-utilities": "1.3.4",
"autoprefixer": "9.7.6", "autoprefixer": "9.8.0",
"babel-eslint": "10.1.0", "babel-eslint": "10.1.0",
"babel-jest": "26.0.1", "babel-jest": "26.0.1",
"babel-loader": "^8.1.0", "babel-loader": "^8.1.0",
@ -224,15 +224,15 @@
"chart.js": "2.9.3", "chart.js": "2.9.3",
"clean-webpack-plugin": "3.0.0", "clean-webpack-plugin": "3.0.0",
"clipboard": "2.0.6", "clipboard": "2.0.6",
"codemirror": "5.53.2", "codemirror": "5.54.0",
"copy-webpack-plugin": "5.1.1", "copy-webpack-plugin": "6.0.1",
"core-js": "3.6.5", "core-js": "3.6.5",
"css-loader": "3.5.3", "css-loader": "3.5.3",
"cssnano": "4.1.10", "cssnano": "4.1.10",
"d3": "5.16.0", "d3": "5.16.0",
"duplicate-package-checker-webpack-plugin": "3.0.0", "duplicate-package-checker-webpack-plugin": "3.0.0",
"epic-spinners": "1.1.0", "epic-spinners": "1.1.0",
"eslint": "7.0.0", "eslint": "7.1.0",
"eslint-config-requarks": "1.0.7", "eslint-config-requarks": "1.0.7",
"eslint-config-standard": "14.1.1", "eslint-config-standard": "14.1.1",
"eslint-plugin-import": "2.20.2", "eslint-plugin-import": "2.20.2",
@ -242,7 +242,7 @@
"eslint-plugin-vue": "6.2.2", "eslint-plugin-vue": "6.2.2",
"fibers": "5.0.0", "fibers": "5.0.0",
"file-loader": "6.0.0", "file-loader": "6.0.0",
"filepond": "4.13.6", "filepond": "4.14.0",
"filepond-plugin-file-validate-type": "1.2.5", "filepond-plugin-file-validate-type": "1.2.5",
"filesize.js": "2.0.0", "filesize.js": "2.0.0",
"graphql-persisted-document-loader": "2.0.0", "graphql-persisted-document-loader": "2.0.0",
@ -257,7 +257,7 @@
"jest": "26.0.1", "jest": "26.0.1",
"js-beautify": "1.11.0", "js-beautify": "1.11.0",
"js-cookie": "2.2.1", "js-cookie": "2.2.1",
"mermaid": "8.5.0", "mermaid": "8.5.1",
"mini-css-extract-plugin": "0.9.0", "mini-css-extract-plugin": "0.9.0",
"moment-duration-format": "2.3.2", "moment-duration-format": "2.3.2",
"moment-timezone-data-webpack-plugin": "1.3.0", "moment-timezone-data-webpack-plugin": "1.3.0",
@ -277,13 +277,13 @@
"pug-plain-loader": "1.0.0", "pug-plain-loader": "1.0.0",
"raw-loader": "4.0.1", "raw-loader": "4.0.1",
"resolve-url-loader": "3.1.1", "resolve-url-loader": "3.1.1",
"sass": "1.26.5", "sass": "1.26.7",
"sass-loader": "8.0.2", "sass-loader": "8.0.2",
"sass-resources-loader": "2.0.3", "sass-resources-loader": "2.0.3",
"script-ext-html-webpack-plugin": "2.1.4", "script-ext-html-webpack-plugin": "2.1.4",
"simple-progress-webpack-plugin": "1.1.2", "simple-progress-webpack-plugin": "1.1.2",
"style-loader": "1.2.1", "style-loader": "1.2.1",
"terser": "4.6.13", "terser": "4.7.0",
"twemoji-awesome": "1.0.6", "twemoji-awesome": "1.0.6",
"url-loader": "4.1.0", "url-loader": "4.1.0",
"velocity-animate": "1.5.2", "velocity-animate": "1.5.2",
@ -296,19 +296,19 @@
"vue-hot-reload-api": "2.3.4", "vue-hot-reload-api": "2.3.4",
"vue-loader": "15.9.2", "vue-loader": "15.9.2",
"vue-moment": "4.1.0", "vue-moment": "4.1.0",
"vue-router": "3.1.6", "vue-router": "3.3.2",
"vue-status-indicator": "1.2.1", "vue-status-indicator": "1.2.1",
"vue-template-compiler": "2.6.11", "vue-template-compiler": "2.6.11",
"vue2-animate": "2.1.3", "vue2-animate": "2.1.3",
"vuedraggable": "2.23.2", "vuedraggable": "2.23.2",
"vuescroll": "4.15.0", "vuescroll": "4.15.1",
"vuetify": "2.2.28", "vuetify": "2.2.30",
"vuetify-loader": "1.4.3", "vuetify-loader": "1.4.4",
"vuex": "3.4.0", "vuex": "3.4.0",
"vuex-pathify": "1.4.1", "vuex-pathify": "1.4.1",
"vuex-persistedstate": "3.0.1", "vuex-persistedstate": "3.0.1",
"webpack": "4.43.0", "webpack": "4.43.0",
"webpack-bundle-analyzer": "3.7.0", "webpack-bundle-analyzer": "3.8.0",
"webpack-cli": "3.3.11", "webpack-cli": "3.3.11",
"webpack-dev-middleware": "3.7.2", "webpack-dev-middleware": "3.7.2",
"webpack-hot-middleware": "2.25.0", "webpack-hot-middleware": "2.25.0",

View File

@ -72,7 +72,7 @@ module.exports = {
if (args.id <= 2) { if (args.id <= 2) {
throw new WIKI.Error.UserDeleteProtected() throw new WIKI.Error.UserDeleteProtected()
} }
await WIKI.models.users.deleteUser(args.id) await WIKI.models.users.deleteUser(args.id, args.replaceId)
return { return {
responseResult: graphHelper.generateSuccess('User deleted successfully') responseResult: graphHelper.generateSuccess('User deleted successfully')
} }

View File

@ -63,6 +63,7 @@ type UserMutation {
delete( delete(
id: Int! id: Int!
replaceId: Int!
): DefaultResponse @auth(requires: ["manage:users", "manage:system"]) ): DefaultResponse @auth(requires: ["manage:users", "manage:system"])
verify( verify(

View File

@ -71,13 +71,19 @@ module.exports = {
['description', page.description], ['description', page.description],
['published', page.isPublished.toString()], ['published', page.isPublished.toString()],
['date', page.updatedAt], ['date', page.updatedAt],
['tags', page.tags ? page.tags.map(t => t.tag).join(', ') : ''] ['tags', page.tags ? page.tags.map(t => t.tag).join(', ') : ''],
['editor', page.editorKey]
] ]
switch (page.contentType) { switch (page.contentType) {
case 'markdown': case 'markdown':
return '---\n' + meta.map(mt => `${mt[0]}: ${mt[1]}`).join('\n') + '\n---\n\n' + page.content return '---\n' + meta.map(mt => `${mt[0]}: ${mt[1]}`).join('\n') + '\n---\n\n' + page.content
case 'html': case 'html':
return '<!--\n' + meta.map(mt => `${mt[0]}: ${mt[1]}`).join('\n') + '\n-->\n\n' + page.content return '<!--\n' + meta.map(mt => `${mt[0]}: ${mt[1]}`).join('\n') + '\n-->\n\n' + page.content
case 'json':
return {
...page.content,
_meta: _.fromPairs(meta)
}
default: default:
return page.content return page.content
} }

View File

@ -128,8 +128,10 @@ module.exports = class CommentProvider extends Model {
} else { } else {
WIKI.data.commentProvider = { WIKI.data.commentProvider = {
...WIKI.data.commentProvider, ...WIKI.data.commentProvider,
...require(`../modules/comments/${commentProvider.key}/comment`) ...require(`../modules/comments/${commentProvider.key}/comment`),
config: commentProvider.config
} }
await WIKI.data.commentProvider.init()
} }
WIKI.data.commentProvider.config = commentProvider.config WIKI.data.commentProvider.config = commentProvider.config
} }

View File

@ -613,9 +613,15 @@ module.exports = class User extends Model {
* *
* @param {*} id User ID * @param {*} id User ID
*/ */
static async deleteUser (id) { static async deleteUser (id, replaceId) {
const usr = await WIKI.models.users.query().findById(id) const usr = await WIKI.models.users.query().findById(id)
if (usr) { if (usr) {
await WIKI.models.assets.query().patch({ authorId: replaceId }).where('authorId', id)
await WIKI.models.comments.query().patch({ authorId: replaceId }).where('authorId', id)
await WIKI.models.pageHistory.query().patch({ authorId: replaceId }).where('authorId', id)
await WIKI.models.pages.query().patch({ authorId: replaceId }).where('authorId', id)
await WIKI.models.pages.query().patch({ creatorId: replaceId }).where('creatorId', id)
await WIKI.models.userKeys.query().delete().where('userId', id) await WIKI.models.userKeys.query().delete().where('userId', id)
await WIKI.models.users.query().deleteById(id) await WIKI.models.users.query().deleteById(id)
} else { } else {

View File

@ -10,8 +10,6 @@ const { AkismetClient } = require('akismet-api')
const window = new JSDOM('').window const window = new JSDOM('').window
const DOMPurify = createDOMPurify(window) const DOMPurify = createDOMPurify(window)
md.use(mdEmoji)
let akismetClient = null let akismetClient = null
// ------------------------------------ // ------------------------------------
@ -23,6 +21,7 @@ module.exports = {
* Init * Init
*/ */
async init (config) { async init (config) {
WIKI.logger.info('(COMMENTS/DEFAULT) Initializing...')
if (WIKI.data.commentProvider.config.akismet && WIKI.data.commentProvider.config.akismet.length > 2) { if (WIKI.data.commentProvider.config.akismet && WIKI.data.commentProvider.config.akismet.length > 2) {
akismetClient = new AkismetClient({ akismetClient = new AkismetClient({
key: WIKI.data.commentProvider.config.akismet, key: WIKI.data.commentProvider.config.akismet,
@ -33,14 +32,19 @@ module.exports = {
try { try {
const isValid = await akismetClient.verifyKey() const isValid = await akismetClient.verifyKey()
if (!isValid) { if (!isValid) {
WIKI.logger.warn('Akismet Key is invalid!') akismetClient = null
WIKI.logger.warn('(COMMENTS/DEFAULT) Akismet Key is invalid! [ DISABLED ]')
} else {
WIKI.logger.info('(COMMENTS/DEFAULT) Akismet key is valid. [ OK ]')
} }
} catch (err) { } catch (err) {
WIKI.logger.warn('Unable to verify Akismet Key: ' + err.message) akismetClient = null
WIKI.logger.warn('(COMMENTS/DEFAULT) Unable to verify Akismet Key: ' + err.message)
} }
} else { } else {
akismetClient = null akismetClient = null
} }
WIKI.logger.info('(COMMENTS/DEFAULT) Initialization completed.')
}, },
/** /**
* Create New Comment * Create New Comment
@ -56,6 +60,8 @@ module.exports = {
} }
}) })
mkdown.use(mdEmoji)
// -> Build New Comment // -> Build New Comment
const newComment = { const newComment = {
content, content,

2195
yarn.lock

File diff suppressed because it is too large Load Diff