Bläddra i källkod

feat: admin auth - save config

NGPixel 7 år sedan
förälder
incheckning
2500d8b054

+ 27 - 5
client/app.js

@@ -49,11 +49,33 @@ moment.locale(siteConfig.lang)
 
 const graphQLEndpoint = window.location.protocol + '//' + window.location.host + '/graphql'
 
-const graphQLLink = createPersistedQueryLink().concat(createHttpLink({
-  includeExtensions: true,
-  uri: graphQLEndpoint,
-  credentials: 'include'
-}))
+const graphQLLink = createPersistedQueryLink().concat(
+  createHttpLink({
+    includeExtensions: true,
+    uri: graphQLEndpoint,
+    credentials: 'include',
+    fetch: (uri, options) => {
+      // Strip __typename fields from variables
+      let body = JSON.parse(options.body)
+      // body = body.map(bd => {
+      //   return ({
+      //     ...bd,
+      //     variables: JSON.parse(JSON.stringify(bd.variables), (key, value) => { return key === '__typename' ? undefined : value })
+      //   })
+      // })
+      body = {
+        ...body,
+        variables: JSON.parse(JSON.stringify(body.variables), (key, value) => { return key === '__typename' ? undefined : value })
+      }
+      options.body = JSON.stringify(body)
+
+      // Inject authentication token
+      options.headers.Authorization = `Bearer TODO`
+
+      return fetch(uri, options)
+    }
+  })
+)
 
 window.graphQL = new ApolloClient({
   link: graphQLLink,

+ 66 - 35
client/components/admin/admin-auth.vue

@@ -13,12 +13,11 @@
           .caption.grey--text.pb-2 Some strategies require additional configuration in their dedicated tab (when selected).
           v-form
             v-checkbox(
-              v-for='strategy in strategies',
-              v-model='selectedStrategies',
-              :key='strategy.key',
-              :label='strategy.title',
-              :value='strategy.key',
-              color='primary',
+              v-for='strategy in strategies'
+              v-model='strategy.isEnabled'
+              :key='strategy.key'
+              :label='strategy.title'
+              color='primary'
               :disabled='strategy.key === `local`'
               hide-details
             )
@@ -38,29 +37,43 @@
               )
             v-divider
             v-subheader.pl-0 Registration
-            v-switch.ml-3(
-              v-model='allowSelfRegistration',
-              label='Allow self-registration',
-              :value='true',
-              color='primary',
-              hint='Allow any user successfully authorized by the strategy to access the wiki.',
-              persistent-hint
-            )
-            v-text-field.ml-3(
-              label='Limit to specific email domains'
-              prepend-icon='mail_outline'
-              hint='Domain(s) seperated by comma. (e.g. domain1.com, domain2.com)'
-              persistent-hint
-              )
-            v-text-field.ml-3(
-              label='Assign to group'
-              prepend-icon='people'
-              hint='Automatically assign new users to these groups.'
-              persistent-hint
+            .pr-3
+              v-switch.ml-3(
+                v-model='strategy.selfRegistration'
+                label='Allow self-registration'
+                color='primary'
+                hint='Allow any user successfully authorized by the strategy to access the wiki.'
+                persistent-hint
               )
+              v-select.ml-3(
+                label='Limit to specific email domains'
+                v-model='strategy.domainWhitelist'
+                prepend-icon='mail_outline'
+                persistent-hint
+                deletable-chips
+                clearable
+                multiple
+                chips
+                tags
+                )
+              v-select.ml-3(
+                :items='groups'
+                item-text='name'
+                item-value='id'
+                label='Assign to group'
+                v-model='strategy.autoEnrollGroups'
+                prepend-icon='people'
+                hint='Automatically assign new users to these groups.'
+                persistent-hint
+                deletable-chips
+                autocomplete
+                clearable
+                multiple
+                chips
+                )
 
     v-card-chin
-      v-btn(color='primary')
+      v-btn(color='primary', @click='save')
         v-icon(left) chevron_right
         span Save
       v-spacer
@@ -72,22 +85,20 @@
 <script>
 import _ from 'lodash'
 
+import groupsQuery from 'gql/admin/auth/auth-query-groups.gql'
 import strategiesQuery from 'gql/admin/auth/auth-query-strategies.gql'
 import strategiesSaveMutation from 'gql/admin/auth/auth-mutation-save-strategies.gql'
 
 export default {
   data() {
     return {
-      strategies: [],
-      selectedStrategies: ['local'],
-      selfRegistration: false,
-      domainWhitelist: [],
-      autoEnrollGroups: []
+      groups: [],
+      strategies: []
     }
   },
   computed: {
     activeStrategies() {
-      return _.filter(this.strategies, prv => _.includes(this.selectedStrategies, prv.key))
+      return _.filter(this.strategies, 'isEnabled')
     }
   },
   methods: {
@@ -99,14 +110,26 @@ export default {
         icon: 'cached'
       })
     },
-    async saveProviders() {
+    async save() {
       this.$store.commit(`loadingStart`, 'admin-auth-savestrategies')
       await this.$apollo.mutate({
         mutation: strategiesSaveMutation,
         variables: {
-          strategies: this.auths
+          strategies: this.strategies.map(str => _.pick(str, [
+            'isEnabled',
+            'key',
+            'config',
+            'selfRegistration',
+            'domainWhitelist',
+            'autoEnrollGroups'
+          ]))
         }
       })
+      this.$store.commit('showNotification', {
+        message: 'Strategies saved successfully.',
+        style: 'success',
+        icon: 'check'
+      })
       this.$store.commit(`loadingStop`, 'admin-auth-savestrategies')
     }
   },
@@ -114,10 +137,18 @@ export default {
     strategies: {
       query: strategiesQuery,
       fetchPolicy: 'network-only',
-      update: (data) => data.authentication.strategies,
+      update: (data) => _.cloneDeep(data.authentication.strategies),
       watchLoading (isLoading) {
         this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-auth-refresh')
       }
+    },
+    groups: {
+      query: groupsQuery,
+      fetchPolicy: 'network-only',
+      update: (data) => data.groups.list,
+      watchLoading (isLoading) {
+        this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-auth-groups-refresh')
+      }
     }
   }
 }

+ 3 - 3
client/graph/admin/auth/auth-mutation-save-strategies.gql

@@ -1,6 +1,6 @@
-mutation($locale: String!, $autoUpdate: Boolean!, $namespacing: Boolean!, $namespaces: [String]!) {
-  localization {
-    updateLocale(locale: $locale, autoUpdate: $autoUpdate, namespacing: $namespacing, namespaces: $namespaces) {
+mutation($strategies: [AuthenticationStrategyInput]) {
+  authentication {
+    updateStrategies(strategies: $strategies) {
       responseResult {
         succeeded
         errorCode

+ 8 - 0
client/graph/admin/auth/auth-query-groups.gql

@@ -0,0 +1,8 @@
+query {
+  groups {
+    list {
+      id
+      name
+    }
+  }
+}

+ 21 - 0
server/graph/resolvers/authentication.js

@@ -50,6 +50,27 @@ module.exports = {
       } catch (err) {
         return graphHelper.generateError(err)
       }
+    },
+    async updateStrategies(obj, args, context) {
+      try {
+        for (let str of args.strategies) {
+          await WIKI.db.authentication.query().patch({
+            isEnabled: str.isEnabled,
+            config: _.reduce(str.config, (result, value, key) => {
+              _.set(result, value.key, value.value)
+              return result
+            }, {}),
+            selfRegistration: str.selfRegistration,
+            domainWhitelist: { v: str.domainWhitelist },
+            autoEnrollGroups: { v: str.autoEnrollGroups }
+          }).where('key', str.key)
+        }
+        return {
+          responseResult: graphHelper.generateSuccess('Strategies updated successfully')
+        }
+      } catch (err) {
+        return graphHelper.generateError(err)
+      }
     }
   },
   AuthenticationStrategy: {

+ 12 - 5
server/graph/schemas/authentication.graphql

@@ -37,10 +37,8 @@ type AuthenticationMutation {
     securityCode: String!
   ): DefaultResponse
 
-  updateStrategy(
-    strategy: String!
-    isEnabled: Boolean!
-    config: [KeyValuePairInput]
+  updateStrategies(
+    strategies: [AuthenticationStrategyInput]
   ): DefaultResponse
 }
 
@@ -58,7 +56,7 @@ type AuthenticationStrategy {
   config: [KeyValuePair]
   selfRegistration: Boolean!
   domainWhitelist: [String]!
-  autoEnrollGroups: [String]!
+  autoEnrollGroups: [Int]!
 }
 
 type AuthenticationLoginResponse {
@@ -66,3 +64,12 @@ type AuthenticationLoginResponse {
   tfaRequired: Boolean
   tfaLoginToken: String
 }
+
+input AuthenticationStrategyInput {
+  isEnabled: Boolean!
+  key: String!
+  config: [KeyValuePairInput]
+  selfRegistration: Boolean!
+  domainWhitelist: [String]!
+  autoEnrollGroups: [Int]!
+}