Commit 904e2a6e authored by Nicolas Giard's avatar Nicolas Giard

fix: modules non-string config + live trail logging

parent 32a537ec
...@@ -8,8 +8,11 @@ import VeeValidate from 'vee-validate' ...@@ -8,8 +8,11 @@ import VeeValidate from 'vee-validate'
import { ApolloClient } from 'apollo-client' import { ApolloClient } from 'apollo-client'
import { createPersistedQueryLink } from 'apollo-link-persisted-queries' import { createPersistedQueryLink } from 'apollo-link-persisted-queries'
// import { BatchHttpLink } from 'apollo-link-batch-http' // import { BatchHttpLink } from 'apollo-link-batch-http'
import { split } from 'apollo-link'
import { createHttpLink } from 'apollo-link-http' import { createHttpLink } from 'apollo-link-http'
import { WebSocketLink } from 'apollo-link-ws'
import { InMemoryCache } from 'apollo-cache-inmemory' import { InMemoryCache } from 'apollo-cache-inmemory'
import { getMainDefinition } from 'apollo-utilities'
import VueApollo from 'vue-apollo' import VueApollo from 'vue-apollo'
import Vuetify from 'vuetify' import Vuetify from 'vuetify'
import Velocity from 'velocity-animate' import Velocity from 'velocity-animate'
...@@ -48,6 +51,7 @@ moment.locale(siteConfig.lang) ...@@ -48,6 +51,7 @@ moment.locale(siteConfig.lang)
// ==================================== // ====================================
const graphQLEndpoint = window.location.protocol + '//' + window.location.host + '/graphql' const graphQLEndpoint = window.location.protocol + '//' + window.location.host + '/graphql'
const graphQLWSEndpoint = ((window.location.protocol === 'https:') ? 'wss:' : 'ws:') + '//' + window.location.host + '/graphql-subscriptions'
const graphQLLink = createPersistedQueryLink().concat( const graphQLLink = createPersistedQueryLink().concat(
createHttpLink({ createHttpLink({
...@@ -77,8 +81,19 @@ const graphQLLink = createPersistedQueryLink().concat( ...@@ -77,8 +81,19 @@ const graphQLLink = createPersistedQueryLink().concat(
}) })
) )
const graphQLWSLink = new WebSocketLink({
uri: graphQLWSEndpoint,
options: {
reconnect: true,
lazy: true
}
})
window.graphQL = new ApolloClient({ window.graphQL = new ApolloClient({
link: graphQLLink, link: split(({ query }) => {
const { kind, operation } = getMainDefinition(query)
return kind === 'OperationDefinition' && operation === 'subscription'
}, graphQLWSLink, graphQLLink),
cache: new InMemoryCache(), cache: new InMemoryCache(),
connectToDevTools: (process.env.node_env === 'development') connectToDevTools: (process.env.node_env === 'development')
}) })
......
...@@ -164,7 +164,7 @@ export default { ...@@ -164,7 +164,7 @@ export default {
'selfRegistration', 'selfRegistration',
'domainWhitelist', 'domainWhitelist',
'autoEnrollGroups' 'autoEnrollGroups'
])).map(str => ({...str, config: str.config.map(cfg => ({...cfg, value: cfg.value.value}))})) ])).map(str => ({...str, config: str.config.map(cfg => ({...cfg, value: JSON.stringify({ v: cfg.value.value })}))}))
} }
}) })
this.$store.commit('showNotification', { this.$store.commit('showNotification', {
......
<template lang='pug'> <template lang='pug'>
v-card v-container(fluid, grid-list-lg)
v-card(flat, :color='$vuetify.dark ? "grey darken-4" : "grey lighten-5"').pa-3.pt-4 v-layout(row wrap)
.admin-header-icon: v-icon(size='80', color='grey lighten-2') people v-flex(xs12)
.headline.blue--text.text--darken-2 Edit Group .admin-header
.subheading.grey--text {{name}} v-icon(size='80', color='grey lighten-2') people
.admin-header-title
.headline.blue--text.text--darken-2 Edit Group
.subheading.grey--text {{name}}
v-btn(color='primary', fab, absolute, bottom, right, small, to='/groups'): v-icon arrow_upward v-btn(color='primary', fab, absolute, bottom, right, small, to='/groups'): v-icon arrow_upward
v-tabs(v-model='tab', :color='$vuetify.dark ? "primary" : "grey lighten-4"', fixed-tabs, :slider-color='$vuetify.dark ? "white" : "primary"', show-arrows) v-tabs(v-model='tab', :color='$vuetify.dark ? "primary" : "grey lighten-4"', fixed-tabs, :slider-color='$vuetify.dark ? "white" : "primary"', show-arrows)
v-tab(key='properties') Properties v-tab(key='properties') Properties
......
...@@ -26,6 +26,8 @@ import _ from 'lodash' ...@@ -26,6 +26,8 @@ import _ from 'lodash'
import { Terminal } from 'xterm' import { Terminal } from 'xterm'
import * as fit from 'xterm/lib/addons/fit/fit' import * as fit from 'xterm/lib/addons/fit/fit'
import livetrailSubscription from 'gql/admin/logging/logging-subscription-livetrail.gql'
Terminal.applyAddon(fit) Terminal.applyAddon(fit)
export default { export default {
...@@ -49,6 +51,8 @@ export default { ...@@ -49,6 +51,8 @@ export default {
this.term = new Terminal() this.term = new Terminal()
this.term.open(this.$refs.consoleContainer) this.term.open(this.$refs.consoleContainer)
this.term.writeln('Connecting to \x1B[1;3;31mconsole output\x1B[0m...') this.term.writeln('Connecting to \x1B[1;3;31mconsole output\x1B[0m...')
this.attach()
}, 100) }, 100)
} else { } else {
this.term.dispose() this.term.dispose()
...@@ -57,8 +61,7 @@ export default { ...@@ -57,8 +61,7 @@ export default {
} }
}, },
mounted() { mounted() {
this.term = new Terminal()
this.term.open(this.$refs.consoleContainer)
}, },
methods: { methods: {
clear() { clear() {
...@@ -66,6 +69,26 @@ export default { ...@@ -66,6 +69,26 @@ export default {
}, },
close() { close() {
this.isShown = false this.isShown = false
},
attach() {
const self = this
const observer = this.$apollo.subscribe({
query: livetrailSubscription
})
observer.subscribe({
next(data) {
const item = _.get(data, `data.loggingLiveTrail`, {})
console.info(item)
self.term.writeln(`${item.level}: ${item.output}`)
},
error(error) {
self.$store.commit('showNotification', {
style: 'red',
message: error.message,
icon: 'warning'
})
}
})
} }
} }
} }
......
...@@ -11,9 +11,9 @@ ...@@ -11,9 +11,9 @@
v-btn(outline, color='grey', @click='refresh', large) v-btn(outline, color='grey', @click='refresh', large)
v-icon refresh v-icon refresh
v-btn(color='black', dark, depressed, @click='toggleConsole', large) v-btn(color='black', dark, depressed, @click='toggleConsole', large)
v-icon(left) keyboard ConsoleLineIcon.mr-3
span View Console span Live Trail
v-btn(color='primary', @click='save', depressed, large) v-btn.mr-0(color='primary', @click='save', depressed, large)
v-icon(left) chevron_right v-icon(left) chevron_right
span Apply Configuration span Apply Configuration
...@@ -112,9 +112,12 @@ import LoggingConsole from './admin-logging-console.vue' ...@@ -112,9 +112,12 @@ import LoggingConsole from './admin-logging-console.vue'
import loggersQuery from 'gql/admin/logging/logging-query-loggers.gql' import loggersQuery from 'gql/admin/logging/logging-query-loggers.gql'
import loggersSaveMutation from 'gql/admin/logging/logging-mutation-save-loggers.gql' import loggersSaveMutation from 'gql/admin/logging/logging-mutation-save-loggers.gql'
import ConsoleLineIcon from 'mdi/ConsoleLine'
export default { export default {
components: { components: {
LoggingConsole LoggingConsole,
ConsoleLineIcon
}, },
data() { data() {
return { return {
...@@ -147,7 +150,7 @@ export default { ...@@ -147,7 +150,7 @@ export default {
'key', 'key',
'config', 'config',
'level' 'level'
])).map(str => ({...str, config: str.config.map(cfg => ({...cfg, value: cfg.value.value}))})) ])).map(str => ({...str, config: str.config.map(cfg => ({...cfg, value: JSON.stringify({ v: cfg.value.value })}))}))
} }
}) })
this.$store.commit('showNotification', { this.$store.commit('showNotification', {
...@@ -156,6 +159,9 @@ export default { ...@@ -156,6 +159,9 @@ export default {
icon: 'check' icon: 'check'
}) })
this.$store.commit(`loadingStop`, 'admin-logging-saveloggers') this.$store.commit(`loadingStop`, 'admin-logging-saveloggers')
},
toggleConsole() {
this.showConsole = !this.showConsole
} }
}, },
apollo: { apollo: {
......
...@@ -133,7 +133,7 @@ export default { ...@@ -133,7 +133,7 @@ export default {
'isEnabled', 'isEnabled',
'key', 'key',
'config' 'config'
])).map(str => ({...str, config: str.config.map(cfg => ({...cfg, value: cfg.value.value}))})) ])).map(str => ({...str, config: str.config.map(cfg => ({...cfg, value: JSON.stringify({ v: cfg.value.value })}))}))
} }
}) })
this.$store.commit('showNotification', { this.$store.commit('showNotification', {
......
...@@ -148,7 +148,7 @@ export default { ...@@ -148,7 +148,7 @@ export default {
'key', 'key',
'config', 'config',
'mode' 'mode'
])).map(str => ({...str, config: str.config.map(cfg => ({...cfg, value: cfg.value.value}))})) ])).map(str => ({...str, config: str.config.map(cfg => ({...cfg, value: JSON.stringify({ v: cfg.value.value })}))}))
} }
}) })
this.$store.commit('showNotification', { this.$store.commit('showNotification', {
......
subscription {
loggingLiveTrail {
level
output
timestamp
}
}
...@@ -74,6 +74,7 @@ ...@@ -74,6 +74,7 @@
"getos": "3.1.0", "getos": "3.1.0",
"graphql": "14.0.2", "graphql": "14.0.2",
"graphql-list-fields": "2.0.2", "graphql-list-fields": "2.0.2",
"graphql-subscriptions": "1.0.0",
"graphql-tools": "4.0.0", "graphql-tools": "4.0.0",
"highlight.js": "9.12.0", "highlight.js": "9.12.0",
"i18next": "11.9.0", "i18next": "11.9.0",
...@@ -147,6 +148,7 @@ ...@@ -147,6 +148,7 @@
"semver": "5.5.1", "semver": "5.5.1",
"serve-favicon": "2.5.0", "serve-favicon": "2.5.0",
"sqlite3": "4.0.2", "sqlite3": "4.0.2",
"subscriptions-transport-ws": "0.9.15",
"uslug": "1.0.4", "uslug": "1.0.4",
"uuid": "3.3.2", "uuid": "3.3.2",
"validator": "10.8.0", "validator": "10.8.0",
...@@ -179,6 +181,8 @@ ...@@ -179,6 +181,8 @@
"apollo-link-error": "1.1.1", "apollo-link-error": "1.1.1",
"apollo-link-http": "1.5.5", "apollo-link-http": "1.5.5",
"apollo-link-persisted-queries": "0.2.1", "apollo-link-persisted-queries": "0.2.1",
"apollo-link-ws": "1.0.9",
"apollo-utilities": "1.0.21",
"autoprefixer": "9.1.5", "autoprefixer": "9.1.5",
"babel-eslint": "10.0.1", "babel-eslint": "10.0.1",
"babel-jest": "23.6.0", "babel-jest": "23.6.0",
......
...@@ -3,11 +3,18 @@ const fs = require('fs') ...@@ -3,11 +3,18 @@ const fs = require('fs')
// const gqlTools = require('graphql-tools') // const gqlTools = require('graphql-tools')
const path = require('path') const path = require('path')
const autoload = require('auto-load') const autoload = require('auto-load')
const PubSub = require('graphql-subscriptions').PubSub
const util = require('util')
const winston = require('winston')
/* global WIKI */ /* global WIKI */
WIKI.logger.info(`Loading GraphQL Schema...`) WIKI.logger.info(`Loading GraphQL Schema...`)
// Init Subscription PubSub
WIKI.GQLEmitter = new PubSub()
// Schemas // Schemas
let typeDefs = [] let typeDefs = []
...@@ -24,10 +31,25 @@ resolversObj.forEach(resolver => { ...@@ -24,10 +31,25 @@ resolversObj.forEach(resolver => {
_.merge(resolvers, resolver) _.merge(resolvers, resolver)
}) })
// const Schema = gqlTools.makeExecutableSchema({ // Live Trail Logger (admin)
// typeDefs,
// resolvers let LiveTrailLogger = winston.transports.LiveTrailLogger = function (options) {
// }) this.name = 'livetrailLogger'
this.level = 'debug'
}
util.inherits(LiveTrailLogger, winston.Transport)
LiveTrailLogger.prototype.log = function (level, msg, meta, callback) {
WIKI.GQLEmitter.publish('livetrail', {
loggingLiveTrail: {
timestamp: new Date(),
level,
output: msg
}
})
callback(null, true)
}
WIKI.logger.add(new LiveTrailLogger({}))
WIKI.logger.info(`GraphQL Schema: [ OK ]`) WIKI.logger.info(`GraphQL Schema: [ OK ]`)
......
...@@ -68,7 +68,7 @@ module.exports = { ...@@ -68,7 +68,7 @@ module.exports = {
await WIKI.models.authentication.query().patch({ await WIKI.models.authentication.query().patch({
isEnabled: str.isEnabled, isEnabled: str.isEnabled,
config: _.reduce(str.config, (result, value, key) => { config: _.reduce(str.config, (result, value, key) => {
_.set(result, `${value.key}.value`, value.value) _.set(result, `${value.key}`, _.get(JSON.parse(value.value), 'v', null))
return result return result
}, {}), }, {}),
selfRegistration: str.selfRegistration, selfRegistration: str.selfRegistration,
......
...@@ -10,6 +10,11 @@ module.exports = { ...@@ -10,6 +10,11 @@ module.exports = {
Mutation: { Mutation: {
async logging() { return {} } async logging() { return {} }
}, },
Subscription: {
loggingLiveTrail: {
subscribe: () => WIKI.GQLEmitter.asyncIterator('livetrail')
}
},
LoggingQuery: { LoggingQuery: {
async loggers(obj, args, context, info) { async loggers(obj, args, context, info) {
let loggers = await WIKI.models.loggers.getLoggers() let loggers = await WIKI.models.loggers.getLoggers()
......
...@@ -42,7 +42,7 @@ module.exports = { ...@@ -42,7 +42,7 @@ module.exports = {
await WIKI.models.searchEngines.query().patch({ await WIKI.models.searchEngines.query().patch({
isEnabled: searchEngine.isEnabled, isEnabled: searchEngine.isEnabled,
config: _.reduce(searchEngine.config, (result, value, key) => { config: _.reduce(searchEngine.config, (result, value, key) => {
_.set(result, `${value.key}`, value.value) _.set(result, `${value.key}`, _.get(JSON.parse(value.value), 'v', null))
return result return result
}, {}) }, {})
}).where('key', searchEngine.key) }).where('key', searchEngine.key)
......
...@@ -43,7 +43,7 @@ module.exports = { ...@@ -43,7 +43,7 @@ module.exports = {
isEnabled: tgt.isEnabled, isEnabled: tgt.isEnabled,
mode: tgt.mode, mode: tgt.mode,
config: _.reduce(tgt.config, (result, value, key) => { config: _.reduce(tgt.config, (result, value, key) => {
_.set(result, `${value.key}`, value.value) _.set(result, `${value.key}`, _.get(JSON.parse(value.value), 'v', null))
return result return result
}, {}) }, {})
}).where('key', tgt.key) }).where('key', tgt.key)
......
...@@ -250,3 +250,5 @@ type Mutation { ...@@ -250,3 +250,5 @@ type Mutation {
filename: String! filename: String!
): File ): File
} }
type Subscription
...@@ -10,6 +10,10 @@ extend type Mutation { ...@@ -10,6 +10,10 @@ extend type Mutation {
logging: LoggingMutation logging: LoggingMutation
} }
extend type Subscription {
loggingLiveTrail: LoggerTrailLine
}
# ----------------------------------------------- # -----------------------------------------------
# QUERIES # QUERIES
# ----------------------------------------------- # -----------------------------------------------
...@@ -52,3 +56,9 @@ input LoggerInput { ...@@ -52,3 +56,9 @@ input LoggerInput {
level: String! level: String!
config: [KeyValuePairInput] config: [KeyValuePairInput]
} }
type LoggerTrailLine {
level: String!
output: String!
timestamp: Date!
}
...@@ -129,7 +129,13 @@ module.exports = async () => { ...@@ -129,7 +129,13 @@ module.exports = async () => {
const graphqlSchema = require('./graph') const graphqlSchema = require('./graph')
const apolloServer = new ApolloServer({ const apolloServer = new ApolloServer({
...graphqlSchema, ...graphqlSchema,
context: ({ req, res }) => ({ req, res }) context: ({ req, res }) => ({ req, res }),
subscriptions: {
onConnect: (connectionParams, webSocket) => {
},
path: '/graphql-subscriptions'
}
}) })
apolloServer.applyMiddleware({ app }) apolloServer.applyMiddleware({ app })
...@@ -169,6 +175,7 @@ module.exports = async () => { ...@@ -169,6 +175,7 @@ module.exports = async () => {
app.set('port', WIKI.config.port) app.set('port', WIKI.config.port)
WIKI.server = http.createServer(app) WIKI.server = http.createServer(app)
apolloServer.installSubscriptionHandlers(WIKI.server)
WIKI.server.listen(WIKI.config.port, WIKI.config.bindIP) WIKI.server.listen(WIKI.config.port, WIKI.config.bindIP)
WIKI.server.on('error', (error) => { WIKI.server.on('error', (error) => {
......
This diff was suppressed by a .gitattributes entry.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment