feat: vue-apollo + auth providers resolver (wip)
This commit is contained in:
@@ -10,10 +10,9 @@ import VueClipboards from 'vue-clipboards'
|
|||||||
import VueSimpleBreakpoints from 'vue-simple-breakpoints'
|
import VueSimpleBreakpoints from 'vue-simple-breakpoints'
|
||||||
import VeeValidate from 'vee-validate'
|
import VeeValidate from 'vee-validate'
|
||||||
import { ApolloClient } from 'apollo-client'
|
import { ApolloClient } from 'apollo-client'
|
||||||
import { ApolloLink } from 'apollo-link'
|
|
||||||
import { createApolloFetch } from 'apollo-fetch'
|
|
||||||
import { BatchHttpLink } from 'apollo-link-batch-http'
|
import { BatchHttpLink } from 'apollo-link-batch-http'
|
||||||
import { InMemoryCache } from 'apollo-cache-inmemory'
|
import { InMemoryCache } from 'apollo-cache-inmemory'
|
||||||
|
import VueApollo from 'vue-apollo'
|
||||||
import Vuetify from 'vuetify'
|
import Vuetify from 'vuetify'
|
||||||
import Velocity from 'velocity-animate'
|
import Velocity from 'velocity-animate'
|
||||||
import Hammer from 'hammerjs'
|
import Hammer from 'hammerjs'
|
||||||
@@ -36,7 +35,7 @@ import helpers from './helpers'
|
|||||||
// Initialize Global Vars
|
// Initialize Global Vars
|
||||||
// ====================================
|
// ====================================
|
||||||
|
|
||||||
window.wiki = null
|
window.WIKI = null
|
||||||
window.boot = boot
|
window.boot = boot
|
||||||
window.CONSTANTS = CONSTANTS
|
window.CONSTANTS = CONSTANTS
|
||||||
window.Hammer = Hammer
|
window.Hammer = Hammer
|
||||||
@@ -47,31 +46,11 @@ window.Hammer = Hammer
|
|||||||
|
|
||||||
const graphQLEndpoint = window.location.protocol + '//' + window.location.host + siteConfig.path + 'graphql'
|
const graphQLEndpoint = window.location.protocol + '//' + window.location.host + siteConfig.path + 'graphql'
|
||||||
|
|
||||||
const apolloFetch = createApolloFetch({
|
|
||||||
uri: graphQLEndpoint,
|
|
||||||
constructOptions: (requestOrRequests, options) => ({
|
|
||||||
...options,
|
|
||||||
method: 'POST',
|
|
||||||
body: JSON.stringify(requestOrRequests),
|
|
||||||
credentials: 'include'
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
window.graphQL = new ApolloClient({
|
window.graphQL = new ApolloClient({
|
||||||
link: ApolloLink.from([
|
link: new BatchHttpLink({
|
||||||
new ApolloLink((operation, forward) => {
|
uri: graphQLEndpoint,
|
||||||
operation.setContext({
|
credentials: 'include'
|
||||||
headers: {
|
}),
|
||||||
'Content-Type': 'application/json'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return forward(operation)
|
|
||||||
}),
|
|
||||||
new BatchHttpLink({
|
|
||||||
fetch: apolloFetch
|
|
||||||
})
|
|
||||||
]),
|
|
||||||
cache: new InMemoryCache(),
|
cache: new InMemoryCache(),
|
||||||
connectToDevTools: (process.env.node_env === 'development')
|
connectToDevTools: (process.env.node_env === 'development')
|
||||||
})
|
})
|
||||||
@@ -81,6 +60,7 @@ window.graphQL = new ApolloClient({
|
|||||||
// ====================================
|
// ====================================
|
||||||
|
|
||||||
Vue.use(VueRouter)
|
Vue.use(VueRouter)
|
||||||
|
Vue.use(VueApollo)
|
||||||
Vue.use(VueClipboards)
|
Vue.use(VueClipboards)
|
||||||
Vue.use(VueSimpleBreakpoints)
|
Vue.use(VueSimpleBreakpoints)
|
||||||
Vue.use(localization.VueI18Next)
|
Vue.use(localization.VueI18Next)
|
||||||
@@ -121,15 +101,20 @@ let bootstrap = () => {
|
|||||||
store.dispatch('startLoading')
|
store.dispatch('startLoading')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const apolloProvider = new VueApollo({
|
||||||
|
defaultClient: window.graphQL
|
||||||
|
})
|
||||||
|
|
||||||
// ====================================
|
// ====================================
|
||||||
// Bootstrap Vue
|
// Bootstrap Vue
|
||||||
// ====================================
|
// ====================================
|
||||||
|
|
||||||
const i18n = localization.init()
|
const i18n = localization.init()
|
||||||
window.wiki = new Vue({
|
window.WIKI = new Vue({
|
||||||
el: '#app',
|
el: '#app',
|
||||||
components: {},
|
components: {},
|
||||||
mixins: [helpers],
|
mixins: [helpers],
|
||||||
|
provide: apolloProvider.provide(),
|
||||||
store,
|
store,
|
||||||
i18n
|
i18n
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -5,6 +5,9 @@
|
|||||||
.subheading.grey--text Manage keys to access the API
|
.subheading.grey--text Manage keys to access the API
|
||||||
v-card
|
v-card
|
||||||
v-card-title
|
v-card-title
|
||||||
|
v-btn(color='green', dark)
|
||||||
|
v-icon(left) power_settings_new
|
||||||
|
| Enable API
|
||||||
v-btn(color='primary', dark)
|
v-btn(color='primary', dark)
|
||||||
v-icon(left) add
|
v-icon(left) add
|
||||||
| New API Key
|
| New API Key
|
||||||
|
|||||||
@@ -6,24 +6,12 @@
|
|||||||
.subheading.grey--text Configure the authentication settings of your wiki
|
.subheading.grey--text Configure the authentication settings of your wiki
|
||||||
v-tabs(color='grey lighten-4', grow, slider-color='primary', show-arrows)
|
v-tabs(color='grey lighten-4', grow, slider-color='primary', show-arrows)
|
||||||
v-tab(key='settings'): v-icon settings
|
v-tab(key='settings'): v-icon settings
|
||||||
v-tab(key='db') Local
|
v-tab(v-for='provider in providers', :key='provider.key') {{ provider.title }}
|
||||||
v-tab(key='algolia') Auth0
|
|
||||||
v-tab(key='elasticsearch') Azure AD
|
|
||||||
v-tab(key='solr') Discord
|
|
||||||
v-tab(key='solr') Dropbox
|
|
||||||
v-tab(key='solr') Facebook
|
|
||||||
v-tab(key='solr') GitHub
|
|
||||||
v-tab(key='solr') Google
|
|
||||||
v-tab(key='solr') LDAP
|
|
||||||
v-tab(key='solr') Microsoft
|
|
||||||
v-tab(key='solr') OAuth2 Generic
|
|
||||||
v-tab(key='solr') Slack
|
|
||||||
v-tab(key='solr') Twitch
|
|
||||||
|
|
||||||
v-tab-item(key='settings')
|
v-tab-item(key='settings')
|
||||||
v-card.pa-3
|
v-card.pa-3
|
||||||
v-form
|
v-form
|
||||||
v-checkbox(v-for='(engine, n) in engines', v-model='auths', :key='n', :label='engine.text', :value='engine.value', color='primary')
|
v-checkbox(v-for='(provider, n) in providers', v-model='auths', :key='provider.key', :label='provider.title', :value='provider.key', color='primary')
|
||||||
v-divider
|
v-divider
|
||||||
v-btn(color='primary')
|
v-btn(color='primary')
|
||||||
v-icon(left) chevron_right
|
v-icon(left) chevron_right
|
||||||
@@ -34,18 +22,20 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
/* global CONSTANTS */
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
engines: [
|
providers: [],
|
||||||
{ text: 'Local', value: 'local' },
|
|
||||||
{ text: 'Auth0', value: 'auth0' },
|
|
||||||
{ text: 'Algolia', value: 'algolia' },
|
|
||||||
{ text: 'Elasticsearch', value: 'elasticsearch' },
|
|
||||||
{ text: 'Solr', value: 'solr' }
|
|
||||||
],
|
|
||||||
auths: ['local']
|
auths: ['local']
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
apollo: {
|
||||||
|
providers: {
|
||||||
|
query: CONSTANTS.GRAPH.AUTHENTICATION.QUERY_PROVIDERS,
|
||||||
|
update: (data) => data.authentication.providers
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
v-toolbar-title
|
v-toolbar-title
|
||||||
span.subheading Wiki.js
|
span.subheading Wiki.js
|
||||||
v-spacer
|
v-spacer
|
||||||
v-progress-circular.mr-3(indeterminate, color='blue')
|
v-progress-circular.mr-3(indeterminate, color='blue', v-if='$apollo.loading')
|
||||||
v-btn(icon)
|
v-btn(icon)
|
||||||
v-icon(color='grey') search
|
v-icon(color='grey') search
|
||||||
v-btn(icon, @click.native='darkTheme = !darkTheme')
|
v-btn(icon, @click.native='darkTheme = !darkTheme')
|
||||||
|
|||||||
@@ -1,16 +1,26 @@
|
|||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
GQL_QUERY_AUTHENTICATION: gql`
|
AUTHENTICATION: {
|
||||||
query($mode: String!) {
|
QUERY_PROVIDERS: gql`
|
||||||
authentication(mode:$mode) {
|
query {
|
||||||
key
|
authentication {
|
||||||
useForm
|
providers {
|
||||||
title
|
isEnabled
|
||||||
icon
|
key
|
||||||
|
props
|
||||||
|
title
|
||||||
|
useForm
|
||||||
|
icon
|
||||||
|
config {
|
||||||
|
key
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
`
|
||||||
`,
|
},
|
||||||
GQL_QUERY_TRANSLATIONS: gql`
|
GQL_QUERY_TRANSLATIONS: gql`
|
||||||
query($locale: String!, $namespace: String!) {
|
query($locale: String!, $namespace: String!) {
|
||||||
translations(locale:$locale, namespace:$namespace) {
|
translations(locale:$locale, namespace:$namespace) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import GRAPHQL from './graphql'
|
import GRAPH from './graphql'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
GRAPHQL
|
GRAPH
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,7 +135,6 @@
|
|||||||
"yargs": "11.0.0"
|
"yargs": "11.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@glimpse/glimpse": "0.22.15",
|
|
||||||
"@panter/vue-i18next": "0.9.1",
|
"@panter/vue-i18next": "0.9.1",
|
||||||
"apollo-client-preset": "1.0.8",
|
"apollo-client-preset": "1.0.8",
|
||||||
"apollo-fetch": "0.7.0",
|
"apollo-fetch": "0.7.0",
|
||||||
@@ -198,6 +197,7 @@
|
|||||||
"vee-validate": "2.0.5",
|
"vee-validate": "2.0.5",
|
||||||
"velocity-animate": "1.5.1",
|
"velocity-animate": "1.5.1",
|
||||||
"vue": "2.5.13",
|
"vue": "2.5.13",
|
||||||
|
"vue-apollo": "3.0.0-beta.4",
|
||||||
"vue-clipboards": "1.2.2",
|
"vue-clipboards": "1.2.2",
|
||||||
"vue-codemirror": "4.0.3",
|
"vue-codemirror": "4.0.3",
|
||||||
"vue-hot-reload-api": "2.3.0",
|
"vue-hot-reload-api": "2.3.0",
|
||||||
@@ -211,7 +211,7 @@
|
|||||||
"vuex-persistedstate": "2.4.2",
|
"vuex-persistedstate": "2.4.2",
|
||||||
"webpack": "3.11.0",
|
"webpack": "3.11.0",
|
||||||
"webpack-bundle-analyzer": "2.11.1",
|
"webpack-bundle-analyzer": "2.11.1",
|
||||||
"webpack-dev-middleware": "3.0.0",
|
"webpack-dev-middleware": "2.0.3",
|
||||||
"webpack-hot-middleware": "2.21.2",
|
"webpack-hot-middleware": "2.21.2",
|
||||||
"webpack-merge": "4.1.2",
|
"webpack-merge": "4.1.2",
|
||||||
"whatwg-fetch": "2.0.3",
|
"whatwg-fetch": "2.0.3",
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ defaults:
|
|||||||
public: false
|
public: false
|
||||||
strategies:
|
strategies:
|
||||||
local:
|
local:
|
||||||
enabled: true
|
isEnabled: true
|
||||||
allowSelfRegister: false
|
allowSelfRegister: false
|
||||||
git:
|
git:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ const _ = require('lodash')
|
|||||||
const passport = require('passport')
|
const passport = require('passport')
|
||||||
const fs = require('fs-extra')
|
const fs = require('fs-extra')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
const autoload = require('auto-load')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
strategies: {},
|
strategies: {},
|
||||||
@@ -31,26 +32,29 @@ module.exports = {
|
|||||||
|
|
||||||
// Load authentication strategies
|
// Load authentication strategies
|
||||||
|
|
||||||
_.forOwn(_.omitBy(WIKI.config.auth.strategies, s => s.enabled === false), (strategyConfig, strategyKey) => {
|
const modules = _.values(autoload(path.join(WIKI.SERVERPATH, 'modules/authentication')))
|
||||||
strategyConfig.callbackURL = `${WIKI.config.site.host}${WIKI.config.site.path}login/${strategyKey}/callback`
|
_.forEach(modules, (strategy) => {
|
||||||
let strategy = require(`../modules/authentication/${strategyKey}`)
|
const strategyConfig = _.get(WIKI.config.auth.strategies, strategy.key, {})
|
||||||
try {
|
strategyConfig.callbackURL = `${WIKI.config.site.host}${WIKI.config.site.path}login/${strategy.key}/callback`
|
||||||
strategy.init(passport, strategyConfig)
|
if (strategyConfig.isEnabled) {
|
||||||
} catch (err) {
|
try {
|
||||||
WIKI.logger.error(`Authentication Provider ${strategyKey}: [ FAILED ]`)
|
strategy.init(passport, strategyConfig)
|
||||||
WIKI.logger.error(err)
|
} catch (err) {
|
||||||
|
WIKI.logger.error(`Authentication Provider ${strategy.title}: [ FAILED ]`)
|
||||||
|
WIKI.logger.error(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fs.readFile(path.join(WIKI.ROOTPATH, `assets/svg/auth-icon-${strategyKey}.svg`), 'utf8').then(iconData => {
|
fs.readFile(path.join(WIKI.ROOTPATH, `assets/svg/auth-icon-${strategy.key}.svg`), 'utf8').then(iconData => {
|
||||||
strategy.icon = iconData
|
strategy.icon = iconData
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
if (err.code === 'ENOENT') {
|
if (err.code === 'ENOENT') {
|
||||||
strategy.icon = '[missing icon]'
|
strategy.icon = '[missing icon]'
|
||||||
} else {
|
} else {
|
||||||
WIKI.logger.error(err)
|
WIKI.logger.warn(err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.strategies[strategy.key] = strategy
|
this.strategies[strategy.key] = strategy
|
||||||
WIKI.logger.info(`Authentication Provider ${strategyKey}: [ OK ]`)
|
WIKI.logger.info(`Authentication Provider ${strategy.title}: [ OK ]`)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Create Guest account for first-time
|
// Create Guest account for first-time
|
||||||
|
|||||||
@@ -13,28 +13,19 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
AuthenticationQuery: {
|
AuthenticationQuery: {
|
||||||
providers(obj, args, context, info) {
|
providers(obj, args, context, info) {
|
||||||
switch (args.mode) {
|
return _.chain(WIKI.auth.strategies).map(str => {
|
||||||
case 'active':
|
return {
|
||||||
let strategies = _.chain(WIKI.auth.strategies).map(str => {
|
isEnabled: true,
|
||||||
return {
|
key: str.key,
|
||||||
key: str.key,
|
title: str.title,
|
||||||
title: str.title,
|
useForm: str.useForm
|
||||||
useForm: str.useForm
|
}
|
||||||
}
|
}).sortBy(['title']).value()
|
||||||
}).sortBy(['title']).value()
|
|
||||||
let localStrategy = _.remove(strategies, str => str.key === 'local')
|
|
||||||
return _.concat(localStrategy, strategies)
|
|
||||||
case 'all':
|
|
||||||
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
AuthenticationProvider: {
|
AuthenticationProvider: {
|
||||||
icon (ap, args) {
|
icon (ap, args) {
|
||||||
return fs.readFileAsync(path.join(WIKI.ROOTPATH, `assets/svg/auth-icon-${ap.key}.svg`), 'utf8').catch(err => {
|
return fs.readFile(path.join(WIKI.ROOTPATH, `assets/svg/auth-icon-${ap.key}.svg`), 'utf8').catch(err => {
|
||||||
if (err.code === 'ENOENT') {
|
if (err.code === 'ENOENT') {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,13 @@ type AuthenticationQuery {
|
|||||||
providers: [AuthenticationProvider]
|
providers: [AuthenticationProvider]
|
||||||
}
|
}
|
||||||
|
|
||||||
type AuthenticationMutation
|
type AuthenticationMutation {
|
||||||
|
updateProvider(
|
||||||
|
provider: String!
|
||||||
|
isEnabled: Boolean!
|
||||||
|
config: [KeyValuePairInput]
|
||||||
|
): DefaultResponse
|
||||||
|
}
|
||||||
|
|
||||||
type AuthenticationProvider {
|
type AuthenticationProvider {
|
||||||
isEnabled: Boolean!
|
isEnabled: Boolean!
|
||||||
@@ -19,5 +25,5 @@ type AuthenticationProvider {
|
|||||||
title: String!
|
title: String!
|
||||||
useForm: Boolean!
|
useForm: Boolean!
|
||||||
icon: String
|
icon: String
|
||||||
config: String
|
config: [KeyValuePair]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,26 @@ interface Base {
|
|||||||
|
|
||||||
# TYPES
|
# TYPES
|
||||||
|
|
||||||
|
type KeyValuePair {
|
||||||
|
key: String!
|
||||||
|
value: String!
|
||||||
|
}
|
||||||
|
input KeyValuePairInput {
|
||||||
|
key: String!
|
||||||
|
value: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
type DefaultResponse {
|
||||||
|
operation: ResponseStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResponseStatus {
|
||||||
|
succeeded: Boolean!
|
||||||
|
code: Int!
|
||||||
|
slug: String!
|
||||||
|
message: String
|
||||||
|
}
|
||||||
|
|
||||||
type Comment implements Base {
|
type Comment implements Base {
|
||||||
id: Int!
|
id: Int!
|
||||||
createdAt: Date
|
createdAt: Date
|
||||||
|
|||||||
@@ -17,10 +17,6 @@ let WIKI = {
|
|||||||
}
|
}
|
||||||
global.WIKI = WIKI
|
global.WIKI = WIKI
|
||||||
|
|
||||||
// if (WIKI.IS_DEBUG) {
|
|
||||||
// require('@glimpse/glimpse').init()
|
|
||||||
// }
|
|
||||||
|
|
||||||
WIKI.configSvc.init()
|
WIKI.configSvc.init()
|
||||||
|
|
||||||
// ----------------------------------------
|
// ----------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user