feat: admin groups - list + create, gql refactoring
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
v-card(flat)
|
v-card(flat)
|
||||||
v-card(flat, color='grey lighten-5').pa-3.pt-4
|
v-card(flat, color='grey lighten-5').pa-3.pt-4
|
||||||
.headline.blue--text.text--darken-2 Groups
|
.headline.blue--text.text--darken-2 Groups
|
||||||
.subheading.grey--text Manage groups
|
.subheading.grey--text Manage groups and their permissions
|
||||||
v-card
|
v-card
|
||||||
v-card-title
|
v-card-title
|
||||||
v-dialog(v-model='newGroupDialog', max-width='500')
|
v-dialog(v-model='newGroupDialog', max-width='500')
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
v-spacer
|
v-spacer
|
||||||
v-btn(flat, @click='newGroupDialog = false') Cancel
|
v-btn(flat, @click='newGroupDialog = false') Cancel
|
||||||
v-btn(color='primary', @click='createGroup') Create
|
v-btn(color='primary', @click='createGroup') Create
|
||||||
v-btn(icon)
|
v-btn(icon, @click='refresh')
|
||||||
v-icon.grey--text refresh
|
v-icon.grey--text refresh
|
||||||
v-spacer
|
v-spacer
|
||||||
v-text-field(append-icon='search', label='Search', single-line, hide-details, v-model='search')
|
v-text-field(append-icon='search', label='Search', single-line, hide-details, v-model='search')
|
||||||
@@ -44,6 +44,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import _ from 'lodash'
|
||||||
|
|
||||||
|
import groupsQuery from 'gql/admin-groups-query-list.gql'
|
||||||
|
import createGroupMutation from 'gql/admin-groups-mutation-create.gql'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -71,18 +76,53 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
async refresh() {
|
||||||
|
await this.$apollo.queries.groups.refetch()
|
||||||
|
this.$store.commit('showNotification', {
|
||||||
|
message: 'Groups have been refreshed.',
|
||||||
|
style: 'success',
|
||||||
|
icon: 'cached'
|
||||||
|
})
|
||||||
|
},
|
||||||
async createGroup() {
|
async createGroup() {
|
||||||
// try {
|
this.newGroupDialog = false
|
||||||
// const resp = await this.$apollo.mutate({
|
try {
|
||||||
// mutation: CONSTANTS.GRAPH.GROUPS.CREATE,
|
await this.$apollo.mutate({
|
||||||
// variables: {
|
mutation: createGroupMutation,
|
||||||
// name: this.newGroupName
|
variables: {
|
||||||
// }
|
name: this.newGroupName
|
||||||
// })
|
},
|
||||||
|
update (store, resp) {
|
||||||
|
const data = _.get(resp, 'data.groups.create', { responseResult: {} })
|
||||||
|
if (data.responseResult.succeeded === true) {
|
||||||
|
const apolloData = store.readQuery({ query: groupsQuery })
|
||||||
|
apolloData.groups.list.push(data.group)
|
||||||
|
store.writeQuery({ query: groupsQuery, data: apolloData })
|
||||||
|
} else {
|
||||||
|
throw new Error(data.responseResult.message)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watchLoading (isLoading) {
|
||||||
|
this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-groups-create')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.$store.commit('showNotification', {
|
||||||
|
style: 'success',
|
||||||
|
message: `Group has been created successfully.`,
|
||||||
|
icon: 'check'
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
|
||||||
// } catch (err) {
|
}
|
||||||
|
}
|
||||||
// }
|
},
|
||||||
|
apollo: {
|
||||||
|
groups: {
|
||||||
|
query: groupsQuery,
|
||||||
|
update: (data) => data.groups.list,
|
||||||
|
watchLoading (isLoading) {
|
||||||
|
this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-groups-refresh')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,24 +93,15 @@
|
|||||||
v-list-tile-content
|
v-list-tile-content
|
||||||
v-list-tile-title {{ info.postgreVersion }}
|
v-list-tile-title {{ info.postgreVersion }}
|
||||||
v-list-tile-sub-title {{ info.postgreHost }}
|
v-list-tile-sub-title {{ info.postgreHost }}
|
||||||
|
|
||||||
v-snackbar(
|
|
||||||
color='success'
|
|
||||||
top
|
|
||||||
v-model='refreshCompleted'
|
|
||||||
)
|
|
||||||
v-icon.mr-3(dark) cached
|
|
||||||
| System Info has been refreshed.
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import gql from 'graphql-tag'
|
|
||||||
|
|
||||||
import IconCube from 'mdi/cube'
|
import IconCube from 'mdi/cube'
|
||||||
import IconDatabase from 'mdi/database'
|
import IconDatabase from 'mdi/database'
|
||||||
import IconNodeJs from 'mdi/nodejs'
|
import IconNodeJs from 'mdi/nodejs'
|
||||||
|
|
||||||
|
import systemInfoQuery from 'gql/admin-system-query-info.gql'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
IconCube,
|
IconCube,
|
||||||
@@ -119,42 +110,26 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
info: {},
|
info: {}
|
||||||
refreshCompleted: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
apollo: {
|
|
||||||
info: {
|
|
||||||
query: gql`
|
|
||||||
query {
|
|
||||||
system {
|
|
||||||
info {
|
|
||||||
currentVersion
|
|
||||||
latestVersion
|
|
||||||
latestVersionReleaseDate
|
|
||||||
operatingSystem
|
|
||||||
hostname
|
|
||||||
cpuCores
|
|
||||||
ramTotal
|
|
||||||
workingDirectory
|
|
||||||
nodeVersion
|
|
||||||
redisVersion
|
|
||||||
redisUsedRAM
|
|
||||||
redisTotalRAM
|
|
||||||
redisHost
|
|
||||||
postgreVersion
|
|
||||||
postgreHost
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
update: (data) => data.system.info
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async refresh() {
|
async refresh() {
|
||||||
await this.$apollo.queries.info.refetch()
|
await this.$apollo.queries.info.refetch()
|
||||||
this.refreshCompleted = true
|
this.$store.commit('showNotification', {
|
||||||
|
message: 'System Info has been refreshed.',
|
||||||
|
style: 'success',
|
||||||
|
icon: 'cached'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
apollo: {
|
||||||
|
info: {
|
||||||
|
query: systemInfoQuery,
|
||||||
|
update: (data) => data.system.info,
|
||||||
|
watchLoading (isLoading) {
|
||||||
|
this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-system-refresh')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,10 +69,22 @@
|
|||||||
|
|
||||||
v-footer.py-2.justify-center(app, absolute, color='grey lighten-3', inset, height='auto')
|
v-footer.py-2.justify-center(app, absolute, color='grey lighten-3', inset, height='auto')
|
||||||
.caption.grey--text.text--darken-1 Powered by Wiki.js
|
.caption.grey--text.text--darken-1 Powered by Wiki.js
|
||||||
|
|
||||||
|
v-snackbar(
|
||||||
|
:color='notification.style'
|
||||||
|
bottom,
|
||||||
|
right,
|
||||||
|
multi-line,
|
||||||
|
v-model='notificationState'
|
||||||
|
)
|
||||||
|
.text-xs-left
|
||||||
|
v-icon.mr-3(dark) {{ notification.icon }}
|
||||||
|
span {{ notification.message }}
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import VueRouter from 'vue-router'
|
import VueRouter from 'vue-router'
|
||||||
|
import { mapState } from 'vuex'
|
||||||
|
|
||||||
const router = new VueRouter({
|
const router = new VueRouter({
|
||||||
mode: 'history',
|
mode: 'history',
|
||||||
@@ -105,6 +117,13 @@ export default {
|
|||||||
adminDrawerShown: true
|
adminDrawerShown: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState(['notification']),
|
||||||
|
notificationState: {
|
||||||
|
get() { return this.notification.isActive },
|
||||||
|
set(newState) { this.$store.commit('updateNotificationState', newState) }
|
||||||
|
}
|
||||||
|
},
|
||||||
router
|
router
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -38,10 +38,13 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
/* global graphQL, siteConfig */
|
/* global siteConfig */
|
||||||
|
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import gql from 'graphql-tag'
|
|
||||||
|
import strategiesQuery from 'gql/login-query-strategies.gql'
|
||||||
|
import loginMutation from 'gql/login-mutation-login.gql'
|
||||||
|
import tfaMutation from 'gql/login-mutation-tfa.gql'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data () {
|
data () {
|
||||||
@@ -81,22 +84,8 @@ export default {
|
|||||||
},
|
},
|
||||||
refreshStrategies () {
|
refreshStrategies () {
|
||||||
this.isLoading = true
|
this.isLoading = true
|
||||||
graphQL.query({
|
this.$apollo.query({
|
||||||
query: gql`
|
query: strategiesQuery
|
||||||
query {
|
|
||||||
authentication {
|
|
||||||
providers(
|
|
||||||
filter: "isEnabled eq true",
|
|
||||||
orderBy: "title ASC"
|
|
||||||
) {
|
|
||||||
key
|
|
||||||
title
|
|
||||||
useForm
|
|
||||||
icon
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
}).then(resp => {
|
}).then(resp => {
|
||||||
if (_.has(resp, 'data.authentication.providers')) {
|
if (_.has(resp, 'data.authentication.providers')) {
|
||||||
this.strategies = _.get(resp, 'data.authentication.providers', [])
|
this.strategies = _.get(resp, 'data.authentication.providers', [])
|
||||||
@@ -131,23 +120,8 @@ export default {
|
|||||||
this.$refs.iptPassword.focus()
|
this.$refs.iptPassword.focus()
|
||||||
} else {
|
} else {
|
||||||
this.isLoading = true
|
this.isLoading = true
|
||||||
graphQL.mutate({
|
this.$apollo.mutate({
|
||||||
mutation: gql`
|
mutation: loginMutation,
|
||||||
mutation($username: String!, $password: String!, $provider: String!) {
|
|
||||||
authentication {
|
|
||||||
login(username: $username, password: $password, provider: $provider) {
|
|
||||||
operation {
|
|
||||||
succeeded
|
|
||||||
code
|
|
||||||
slug
|
|
||||||
message
|
|
||||||
}
|
|
||||||
tfaRequired
|
|
||||||
tfaLoginToken
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
variables: {
|
variables: {
|
||||||
username: this.username,
|
username: this.username,
|
||||||
password: this.password,
|
password: this.password,
|
||||||
@@ -199,21 +173,8 @@ export default {
|
|||||||
this.$refs.iptTFA.focus()
|
this.$refs.iptTFA.focus()
|
||||||
} else {
|
} else {
|
||||||
this.isLoading = true
|
this.isLoading = true
|
||||||
graphQL.mutate({
|
this.$apollo.mutate({
|
||||||
mutation: gql`
|
mutation: tfaMutation,
|
||||||
mutation($loginToken: String!, $securityCode: String!) {
|
|
||||||
authentication {
|
|
||||||
loginTFA(loginToken: $loginToken, securityCode: $securityCode) {
|
|
||||||
operation {
|
|
||||||
succeeded
|
|
||||||
code
|
|
||||||
slug
|
|
||||||
message
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
variables: {
|
variables: {
|
||||||
loginToken: this.loginToken,
|
loginToken: this.loginToken,
|
||||||
securityCode: this.securityCode
|
securityCode: this.securityCode
|
||||||
|
|||||||
@@ -61,7 +61,7 @@
|
|||||||
color='blue'
|
color='blue'
|
||||||
)
|
)
|
||||||
v-spacer
|
v-spacer
|
||||||
v-progress-circular.mr-3(indeterminate, color='blue', v-show='$apollo.loading')
|
v-progress-circular.mr-3(indeterminate, color='blue', v-show='isLoading')
|
||||||
slot(name='actions')
|
slot(name='actions')
|
||||||
transition(name='navHeaderSearch')
|
transition(name='navHeaderSearch')
|
||||||
v-btn(icon, @click='searchToggle', v-if='!searchIsShown')
|
v-btn(icon, @click='searchToggle', v-if='!searchIsShown')
|
||||||
@@ -88,6 +88,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -97,6 +99,9 @@ export default {
|
|||||||
search: ''
|
search: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters(['isLoading'])
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
searchToggle() {
|
searchToggle() {
|
||||||
this.searchIsLoading = false
|
this.searchIsLoading = false
|
||||||
|
|||||||
18
client/graph/admin-groups-mutation-create.gql
Normal file
18
client/graph/admin-groups-mutation-create.gql
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
mutation ($name: String!) {
|
||||||
|
groups {
|
||||||
|
create(name: $name) {
|
||||||
|
responseResult {
|
||||||
|
succeeded
|
||||||
|
errorCode
|
||||||
|
slug
|
||||||
|
message
|
||||||
|
}
|
||||||
|
group {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
createdAt
|
||||||
|
updatedAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
client/graph/admin-groups-query-list.gql
Normal file
11
client/graph/admin-groups-query-list.gql
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
query {
|
||||||
|
groups {
|
||||||
|
list {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
userCount
|
||||||
|
createdAt
|
||||||
|
updatedAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
21
client/graph/admin-system-query-info.gql
Normal file
21
client/graph/admin-system-query-info.gql
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
query {
|
||||||
|
system {
|
||||||
|
info {
|
||||||
|
currentVersion
|
||||||
|
latestVersion
|
||||||
|
latestVersionReleaseDate
|
||||||
|
operatingSystem
|
||||||
|
hostname
|
||||||
|
cpuCores
|
||||||
|
ramTotal
|
||||||
|
workingDirectory
|
||||||
|
nodeVersion
|
||||||
|
redisVersion
|
||||||
|
redisUsedRAM
|
||||||
|
redisTotalRAM
|
||||||
|
redisHost
|
||||||
|
postgreVersion
|
||||||
|
postgreHost
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14
client/graph/login-mutation-login.gql
Normal file
14
client/graph/login-mutation-login.gql
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
mutation($username: String!, $password: String!, $provider: String!) {
|
||||||
|
authentication {
|
||||||
|
login(username: $username, password: $password, provider: $provider) {
|
||||||
|
responseResult {
|
||||||
|
succeeded
|
||||||
|
errorCode
|
||||||
|
slug
|
||||||
|
message
|
||||||
|
}
|
||||||
|
tfaRequired
|
||||||
|
tfaLoginToken
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
client/graph/login-mutation-tfa.gql
Normal file
12
client/graph/login-mutation-tfa.gql
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
mutation($loginToken: String!, $securityCode: String!) {
|
||||||
|
authentication {
|
||||||
|
loginTFA(loginToken: $loginToken, securityCode: $securityCode) {
|
||||||
|
responseResult {
|
||||||
|
succeeded
|
||||||
|
errorCode
|
||||||
|
slug
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
client/graph/login-query-strategies.gql
Normal file
13
client/graph/login-query-strategies.gql
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
query {
|
||||||
|
authentication {
|
||||||
|
providers(
|
||||||
|
filter: "isEnabled eq true",
|
||||||
|
orderBy: "title ASC"
|
||||||
|
) {
|
||||||
|
key
|
||||||
|
title
|
||||||
|
useForm
|
||||||
|
icon
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,24 +1,41 @@
|
|||||||
|
import _ from 'lodash'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import Vuex from 'vuex'
|
import Vuex from 'vuex'
|
||||||
|
|
||||||
import navigator from './modules/navigator'
|
|
||||||
|
|
||||||
Vue.use(Vuex)
|
Vue.use(Vuex)
|
||||||
|
|
||||||
export default new Vuex.Store({
|
export default new Vuex.Store({
|
||||||
state: {
|
state: {
|
||||||
loading: false
|
loadingStack: [],
|
||||||
|
notification: {
|
||||||
|
message: '',
|
||||||
|
style: 'primary',
|
||||||
|
icon: 'cached',
|
||||||
|
isActive: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getters: {
|
||||||
|
isLoading: state => { return state.loadingStack.length > 0 }
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
loadingChange: (state, loadingState) => { state.loading = loadingState }
|
loadingStart (state, stackName) {
|
||||||
|
state.loadingStack = _.union(state.loadingStack, [stackName])
|
||||||
|
},
|
||||||
|
loadingStop (state, stackName) {
|
||||||
|
state.loadingStack = _.without(state.loadingStack, stackName)
|
||||||
|
},
|
||||||
|
showNotification (state, opts) {
|
||||||
|
state.notification = _.defaults(opts, {
|
||||||
|
message: '',
|
||||||
|
style: 'primary',
|
||||||
|
icon: 'cached',
|
||||||
|
isActive: true
|
||||||
|
})
|
||||||
|
},
|
||||||
|
updateNotificationState (state, newState) {
|
||||||
|
state.notification.isActive = newState
|
||||||
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: { },
|
||||||
alert({ dispatch }, opts) { dispatch('navigator/alert', opts) },
|
modules: { }
|
||||||
startLoading({ commit }) { commit('loadingChange', true) },
|
|
||||||
stopLoading({ commit }) { commit('loadingChange', false) }
|
|
||||||
},
|
|
||||||
getters: {},
|
|
||||||
modules: {
|
|
||||||
navigator
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
import debounce from 'lodash/debounce'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
namespaced: true,
|
|
||||||
state: {
|
|
||||||
subtitleShown: false,
|
|
||||||
subtitleStyle: '',
|
|
||||||
subtitleIcon: false,
|
|
||||||
subtitleText: '',
|
|
||||||
subtitleStatic: 'Welcome'
|
|
||||||
},
|
|
||||||
getters: {},
|
|
||||||
mutations: {
|
|
||||||
subtitleChange (state, opts) {
|
|
||||||
state.subtitleShown = (opts.shown === true)
|
|
||||||
state.subtitleStyle = opts.style || ''
|
|
||||||
state.subtitleIcon = opts.icon || false
|
|
||||||
state.subtitleText = opts.msg || ''
|
|
||||||
},
|
|
||||||
subtitleStatic (state, text) {
|
|
||||||
state.subtitleText = text
|
|
||||||
state.subtitleStatic = text
|
|
||||||
}
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
alert ({ commit, dispatch }, opts) {
|
|
||||||
opts.shown = true
|
|
||||||
commit('subtitleChange', opts)
|
|
||||||
dispatch('alertDismiss')
|
|
||||||
},
|
|
||||||
alertDismiss: debounce(({ commit, state }) => {
|
|
||||||
let opts = {
|
|
||||||
shown: false,
|
|
||||||
style: state.subtitleStyle,
|
|
||||||
msg: state.subtitleStatic
|
|
||||||
}
|
|
||||||
commit('subtitleChange', opts)
|
|
||||||
}, 5000)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -21,14 +21,21 @@ paths:
|
|||||||
# ---------------------------------------------------------------------
|
# ---------------------------------------------------------------------
|
||||||
# Database
|
# Database
|
||||||
# ---------------------------------------------------------------------
|
# ---------------------------------------------------------------------
|
||||||
# PostgreSQL 9.5 or later required
|
# Supported Database Engines:
|
||||||
|
# - postgres = PostgreSQL 9.5 or later
|
||||||
|
# - mysql = MySQL 5.7.8 or later
|
||||||
|
# - sqlite = SQLite 3.9 or later
|
||||||
|
|
||||||
db:
|
db:
|
||||||
|
type: postgres
|
||||||
|
# PostgreSQL and MySQL only:
|
||||||
host: localhost
|
host: localhost
|
||||||
port: 5432
|
port: 5432
|
||||||
user: wikijs
|
user: wikijs
|
||||||
pass: wikijsrocks
|
pass: wikijsrocks
|
||||||
db: wiki
|
db: wiki
|
||||||
|
# SQLite only:
|
||||||
|
storage: path/to/database.sqlite
|
||||||
|
|
||||||
# ---------------------------------------------------------------------
|
# ---------------------------------------------------------------------
|
||||||
# Redis
|
# Redis
|
||||||
|
|||||||
@@ -162,6 +162,11 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
test: /\.(graphql|gql)$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
loader: 'graphql-tag/loader'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
test: /.jsx$/,
|
test: /.jsx$/,
|
||||||
loader: 'babel-loader',
|
loader: 'babel-loader',
|
||||||
@@ -226,7 +231,8 @@ module.exports = {
|
|||||||
alias: {
|
alias: {
|
||||||
'@': path.join(process.cwd(), 'client'),
|
'@': path.join(process.cwd(), 'client'),
|
||||||
'vue$': 'vue/dist/vue.esm.js',
|
'vue$': 'vue/dist/vue.esm.js',
|
||||||
'mdi': path.resolve(process.cwd(), 'node_modules/vue-material-design-icons'),
|
'gql': path.join(process.cwd(), 'client/graph'),
|
||||||
|
'mdi': path.join(process.cwd(), 'node_modules/vue-material-design-icons'),
|
||||||
// Duplicates fixes:
|
// Duplicates fixes:
|
||||||
'apollo-link': path.join(process.cwd(), 'node_modules/apollo-link'),
|
'apollo-link': path.join(process.cwd(), 'node_modules/apollo-link'),
|
||||||
'apollo-utilities': path.join(process.cwd(), 'node_modules/apollo-utilities'),
|
'apollo-utilities': path.join(process.cwd(), 'node_modules/apollo-utilities'),
|
||||||
|
|||||||
@@ -169,6 +169,11 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
test: /\.(graphql|gql)$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
loader: 'graphql-tag/loader'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
test: /.jsx$/,
|
test: /.jsx$/,
|
||||||
loader: 'babel-loader',
|
loader: 'babel-loader',
|
||||||
@@ -255,6 +260,7 @@ module.exports = {
|
|||||||
alias: {
|
alias: {
|
||||||
'@': path.join(process.cwd(), 'client'),
|
'@': path.join(process.cwd(), 'client'),
|
||||||
'vue$': 'vue/dist/vue.esm.js',
|
'vue$': 'vue/dist/vue.esm.js',
|
||||||
|
'gql': path.join(process.cwd(), 'client/graph'),
|
||||||
'mdi': path.resolve(process.cwd(), 'node_modules/vue-material-design-icons'),
|
'mdi': path.resolve(process.cwd(), 'node_modules/vue-material-design-icons'),
|
||||||
// Duplicates fixes:
|
// Duplicates fixes:
|
||||||
'apollo-link': path.join(process.cwd(), 'node_modules/apollo-link'),
|
'apollo-link': path.join(process.cwd(), 'node_modules/apollo-link'),
|
||||||
|
|||||||
@@ -98,6 +98,7 @@
|
|||||||
"moment-timezone": "0.5.14",
|
"moment-timezone": "0.5.14",
|
||||||
"mongodb": "3.0.4",
|
"mongodb": "3.0.4",
|
||||||
"multer": "1.3.0",
|
"multer": "1.3.0",
|
||||||
|
"mysql2": "1.5.3",
|
||||||
"node-2fa": "1.1.2",
|
"node-2fa": "1.1.2",
|
||||||
"oauth2orize": "1.11.0",
|
"oauth2orize": "1.11.0",
|
||||||
"ora": "2.0.0",
|
"ora": "2.0.0",
|
||||||
@@ -130,6 +131,7 @@
|
|||||||
"semver": "5.5.0",
|
"semver": "5.5.0",
|
||||||
"sequelize": "4.37.1",
|
"sequelize": "4.37.1",
|
||||||
"serve-favicon": "2.4.5",
|
"serve-favicon": "2.4.5",
|
||||||
|
"sqlite3": "4.0.0",
|
||||||
"uuid": "3.2.1",
|
"uuid": "3.2.1",
|
||||||
"validator": "9.4.1",
|
"validator": "9.4.1",
|
||||||
"validator-as-promised": "1.0.2",
|
"validator-as-promised": "1.0.2",
|
||||||
|
|||||||
@@ -11,11 +11,13 @@ defaults:
|
|||||||
repo: ./repo
|
repo: ./repo
|
||||||
data: ./data
|
data: ./data
|
||||||
db:
|
db:
|
||||||
|
type: postgres
|
||||||
host: localhost
|
host: localhost
|
||||||
port: 5432
|
port: 5432
|
||||||
user: wikijs
|
user: wikijs
|
||||||
pass: wikijsrocks
|
pass: wikijsrocks
|
||||||
db: wiki
|
db: wiki
|
||||||
|
storage: ./db.sqlite
|
||||||
redis:
|
redis:
|
||||||
host: localhost
|
host: localhost
|
||||||
port: 6379
|
port: 6379
|
||||||
|
|||||||
@@ -64,7 +64,8 @@ module.exports = {
|
|||||||
this.inst = new this.Sequelize(WIKI.config.db.db, WIKI.config.db.user, WIKI.config.db.pass, {
|
this.inst = new this.Sequelize(WIKI.config.db.db, WIKI.config.db.user, WIKI.config.db.pass, {
|
||||||
host: WIKI.config.db.host,
|
host: WIKI.config.db.host,
|
||||||
port: WIKI.config.db.port,
|
port: WIKI.config.db.port,
|
||||||
dialect: 'postgres',
|
dialect: WIKI.config.db.type,
|
||||||
|
storage: WIKI.config.db.storage,
|
||||||
pool: {
|
pool: {
|
||||||
max: 10,
|
max: 10,
|
||||||
min: 0,
|
min: 0,
|
||||||
@@ -77,9 +78,9 @@ module.exports = {
|
|||||||
// Attempt to connect and authenticate to DB
|
// Attempt to connect and authenticate to DB
|
||||||
|
|
||||||
this.inst.authenticate().then(() => {
|
this.inst.authenticate().then(() => {
|
||||||
WIKI.logger.info('Database (PostgreSQL) connection: [ OK ]')
|
WIKI.logger.info(`Database (${WIKI.config.db.type}) connection: [ OK ]`)
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
WIKI.logger.error('Failed to connect to PostgreSQL instance.')
|
WIKI.logger.error(`Failed to connect to ${WIKI.config.db.type} instance.`)
|
||||||
WIKI.logger.error(err)
|
WIKI.logger.error(err)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
})
|
})
|
||||||
@@ -112,7 +113,10 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
// -> Set Connection App Name
|
// -> Set Connection App Name
|
||||||
setAppName() {
|
setAppName() {
|
||||||
return self.inst.query(`set application_name = 'WIKI.js'`, { raw: true })
|
switch (WIKI.config.db.type) {
|
||||||
|
case 'postgres':
|
||||||
|
return self.inst.query(`set application_name = 'WIKI.js'`, { raw: true })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ module.exports = {
|
|||||||
let authResult = await WIKI.db.User.login(args, context)
|
let authResult = await WIKI.db.User.login(args, context)
|
||||||
return {
|
return {
|
||||||
...authResult,
|
...authResult,
|
||||||
operation: graphHelper.generateSuccess('Login success')
|
responseResult: graphHelper.generateSuccess('Login success')
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return graphHelper.generateError(err)
|
return graphHelper.generateError(err)
|
||||||
@@ -46,7 +46,7 @@ module.exports = {
|
|||||||
let authResult = await WIKI.db.User.loginTFA(args, context)
|
let authResult = await WIKI.db.User.loginTFA(args, context)
|
||||||
return {
|
return {
|
||||||
...authResult,
|
...authResult,
|
||||||
operation: graphHelper.generateSuccess('TFA success')
|
responseResult: graphHelper.generateSuccess('TFA success')
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return graphHelper.generateError(err)
|
return graphHelper.generateError(err)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
const graphHelper = require('../../helpers/graph')
|
||||||
|
|
||||||
/* global WIKI */
|
/* global WIKI */
|
||||||
|
|
||||||
@@ -11,8 +12,22 @@ module.exports = {
|
|||||||
async groups() { return {} }
|
async groups() { return {} }
|
||||||
},
|
},
|
||||||
GroupQuery: {
|
GroupQuery: {
|
||||||
list(obj, args, context, info) {
|
async list(obj, args, context, info) {
|
||||||
return WIKI.db.Group.findAll({ where: args })
|
return WIKI.db.Group.findAll({
|
||||||
|
attributes: {
|
||||||
|
include: [[WIKI.db.inst.fn('COUNT', WIKI.db.inst.col('users.id')), 'userCount']]
|
||||||
|
},
|
||||||
|
include: [{
|
||||||
|
model: WIKI.db.User,
|
||||||
|
attributes: [],
|
||||||
|
through: {
|
||||||
|
attributes: []
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
raw: true,
|
||||||
|
// TODO: Figure out how to exclude these extra fields...
|
||||||
|
group: ['group.id', 'users->userGroups.createdAt', 'users->userGroups.updatedAt', 'users->userGroups.version', 'users->userGroups.userId', 'users->userGroups.groupId']
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
GroupMutation: {
|
GroupMutation: {
|
||||||
@@ -29,8 +44,15 @@ module.exports = {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
create(obj, args) {
|
async create(obj, args) {
|
||||||
return WIKI.db.Group.create(args)
|
const group = await WIKI.db.Group.create({
|
||||||
|
name: args.name
|
||||||
|
})
|
||||||
|
console.info(group)
|
||||||
|
return {
|
||||||
|
responseResult: graphHelper.generateSuccess('Group created successfully.'),
|
||||||
|
group
|
||||||
|
}
|
||||||
},
|
},
|
||||||
delete(obj, args) {
|
delete(obj, args) {
|
||||||
return WIKI.db.Group.destroy({
|
return WIKI.db.Group.destroy({
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ type AuthenticationProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AuthenticationLoginResponse {
|
type AuthenticationLoginResponse {
|
||||||
operation: ResponseStatus
|
responseResult: ResponseStatus
|
||||||
tfaRequired: Boolean
|
tfaRequired: Boolean
|
||||||
tfaLoginToken: String
|
tfaLoginToken: String
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,12 +39,12 @@ input KeyValuePairInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type DefaultResponse {
|
type DefaultResponse {
|
||||||
operation: ResponseStatus
|
responseResult: ResponseStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResponseStatus {
|
type ResponseStatus {
|
||||||
succeeded: Boolean!
|
succeeded: Boolean!
|
||||||
code: Int!
|
errorCode: Int!
|
||||||
slug: String!
|
slug: String!
|
||||||
message: String
|
message: String
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ type GroupMutation {
|
|||||||
# -----------------------------------------------
|
# -----------------------------------------------
|
||||||
|
|
||||||
type GroupResponse {
|
type GroupResponse {
|
||||||
operation: ResponseStatus!
|
responseResult: ResponseStatus!
|
||||||
group: Group
|
group: Group
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,6 +64,7 @@ type Group {
|
|||||||
name: String!
|
name: String!
|
||||||
rights: [String]
|
rights: [String]
|
||||||
users: [User]
|
users: [User]
|
||||||
|
userCount: Int
|
||||||
createdAt: Date!
|
createdAt: Date!
|
||||||
updatedAt: Date!
|
updatedAt: Date!
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ module.exports = {
|
|||||||
generateSuccess (msg) {
|
generateSuccess (msg) {
|
||||||
return {
|
return {
|
||||||
succeeded: true,
|
succeeded: true,
|
||||||
code: 0,
|
errorCode: 0,
|
||||||
slug: 'ok',
|
slug: 'ok',
|
||||||
message: _.defaultTo(msg, 'Operation succeeded.')
|
message: _.defaultTo(msg, 'Operation succeeded.')
|
||||||
}
|
}
|
||||||
@@ -13,11 +13,11 @@ module.exports = {
|
|||||||
generateError (err, complete = true) {
|
generateError (err, complete = true) {
|
||||||
const error = {
|
const error = {
|
||||||
succeeded: false,
|
succeeded: false,
|
||||||
code: err.code || 1,
|
errorCode: err.code || 1,
|
||||||
slug: err.name,
|
slug: err.name,
|
||||||
message: err.message || 'An unexpected error occured.'
|
message: err.message || 'An unexpected error occured.'
|
||||||
}
|
}
|
||||||
return (complete) ? { operation: error } : error
|
return (complete) ? { responseResult: error } : error
|
||||||
},
|
},
|
||||||
filter (arr, filterString) {
|
filter (arr, filterString) {
|
||||||
const prvFilter = new Filter(_.toString(filterString).replace(/'/g, `"`))
|
const prvFilter = new Filter(_.toString(filterString).replace(/'/g, `"`))
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ module.exports = (sequelize, DataTypes) => {
|
|||||||
defaultValue: 'application/octet-stream'
|
defaultValue: 'application/octet-stream'
|
||||||
},
|
},
|
||||||
extra: {
|
extra: {
|
||||||
type: DataTypes.JSONB,
|
type: DataTypes.JSON,
|
||||||
allowNull: true
|
allowNull: true
|
||||||
},
|
},
|
||||||
filename: {
|
filename: {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ module.exports = (sequelize, DataTypes) => {
|
|||||||
allowNull: false
|
allowNull: false
|
||||||
},
|
},
|
||||||
config: {
|
config: {
|
||||||
type: DataTypes.JSONB,
|
type: DataTypes.JSON,
|
||||||
allowNull: false
|
allowNull: false
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
|
|||||||
Reference in New Issue
Block a user