Parcourir la source

refactor: webpack fixes, missing auth icons, auth resolvers

NGPixel il y a 7 ans
Parent
commit
16d3336cd0

+ 14 - 10
client/components/login.vue

@@ -106,16 +106,16 @@ export default {
       } else {
       } else {
         this.isLoading = true
         this.isLoading = true
         graphQL.mutate({
         graphQL.mutate({
-          mutation: CONSTANTS.GRAPHQL.GQL_MUTATION_LOGIN,
+          mutation: CONSTANTS.GRAPH.AUTHENTICATION.MUTATION_LOGIN,
           variables: {
           variables: {
             username: this.username,
             username: this.username,
             password: this.password,
             password: this.password,
             provider: this.selectedStrategy
             provider: this.selectedStrategy
           }
           }
         }).then(resp => {
         }).then(resp => {
-          if (resp.data.login) {
-            let respObj = resp.data.login
-            if (respObj.succeeded === true) {
+          if (_.has(resp, 'data.authentication.login')) {
+            let respObj = _.get(resp, 'data.authentication.login', {})
+            if (respObj.operation.succeeded === true) {
               if (respObj.tfaRequired === true) {
               if (respObj.tfaRequired === true) {
                 this.screen = 'tfa'
                 this.screen = 'tfa'
                 this.securityCode = ''
                 this.securityCode = ''
@@ -132,7 +132,7 @@ export default {
               }
               }
               this.isLoading = false
               this.isLoading = false
             } else {
             } else {
-              throw new Error(respObj.message)
+              throw new Error(respObj.operation.message)
             }
             }
           } else {
           } else {
             throw new Error('Authentication is unavailable.')
             throw new Error('Authentication is unavailable.')
@@ -159,15 +159,15 @@ export default {
       } else {
       } else {
         this.isLoading = true
         this.isLoading = true
         graphQL.mutate({
         graphQL.mutate({
-          mutation: CONSTANTS.GRAPHQL.GQL_MUTATION_LOGINTFA,
+          mutation: CONSTANTS.GRAPH.AUTHENTICATION.MUTATION_LOGINTFA,
           variables: {
           variables: {
             loginToken: this.loginToken,
             loginToken: this.loginToken,
             securityCode: this.securityCode
             securityCode: this.securityCode
           }
           }
         }).then(resp => {
         }).then(resp => {
-          if (resp.data.loginTFA) {
-            let respObj = resp.data.loginTFA
-            if (respObj.succeeded === true) {
+          if (_.has(resp, 'data.authentication.loginTFA')) {
+            let respObj = _.get(resp, 'data.authentication.loginTFA', {})
+            if (respObj.operation.succeeded === true) {
               this.$store.dispatch('alert', {
               this.$store.dispatch('alert', {
                 style: 'success',
                 style: 'success',
                 icon: 'gg-check',
                 icon: 'gg-check',
@@ -175,7 +175,7 @@ export default {
               })
               })
               this.isLoading = false
               this.isLoading = false
             } else {
             } else {
-              throw new Error(respObj.message)
+              throw new Error(respObj.operation.message)
             }
             }
           } else {
           } else {
             throw new Error('Authentication is unavailable.')
             throw new Error('Authentication is unavailable.')
@@ -382,6 +382,10 @@ export default {
           }
           }
         }
         }
 
 
+        em {
+          height: 20px;
+        }
+
         span {
         span {
           font-weight: 600;
           font-weight: 600;
 
 

+ 39 - 25
client/constants/graphql.js

@@ -33,32 +33,46 @@ export default {
           }
           }
         }
         }
       }
       }
-    `
-  },
-  GQL_QUERY_TRANSLATIONS: gql`
-    query($locale: String!, $namespace: String!) {
-      translations(locale:$locale, namespace:$namespace) {
-        key
-        value
+    `,
+    MUTATION_LOGIN: gql`
+      mutation($username: String!, $password: String!, $provider: String!) {
+        authentication {
+          login(username: $username, password: $password, provider: $provider) {
+            operation {
+              succeeded
+              code
+              slug
+              message
+            }
+            tfaRequired
+            tfaLoginToken
+          }
+        }
       }
       }
-    }
-  `,
-  GQL_MUTATION_LOGIN: gql`
-    mutation($username: String!, $password: String!, $provider: String!) {
-      login(username: $username, password: $password, provider: $provider) {
-        succeeded
-        message
-        tfaRequired
-        tfaLoginToken
+    `,
+    MUTATION_LOGINTFA: gql`
+      mutation($loginToken: String!, $securityCode: String!) {
+        authentication {
+          loginTFA(loginToken: $loginToken, securityCode: $securityCode) {
+            operation {
+              succeeded
+              code
+              slug
+              message
+            }
+          }
+        }
       }
       }
-    }
-  `,
-  GQL_MUTATION_LOGINTFA: gql`
-    mutation($loginToken: String!, $securityCode: String!) {
-      loginTFA(loginToken: $loginToken, securityCode: $securityCode) {
-        succeeded
-        message
+    `
+  },
+  TRANSLATIONS: {
+    QUERY_NAMESPACE: gql`
+      query($locale: String!, $namespace: String!) {
+        translations(locale:$locale, namespace:$namespace) {
+          key
+          value
+        }
       }
       }
-    }
-  `
+    `
+  }
 }
 }

+ 1 - 1
client/modules/localization.js

@@ -19,7 +19,7 @@ module.exports = {
           ajax: (url, opts, cb, data) => {
           ajax: (url, opts, cb, data) => {
             let langParams = url.split('/')
             let langParams = url.split('/')
             graphQL.query({
             graphQL.query({
-              query: CONSTANTS.GRAPHQL.GQL_QUERY_TRANSLATIONS,
+              query: CONSTANTS.GRAPH.TRANSLATIONS.QUERY_NAMESPACE,
               variables: {
               variables: {
                 locale: langParams[0],
                 locale: langParams[0],
                 namespace: langParams[1]
                 namespace: langParams[1]

+ 2 - 0
client/scss/app.scss

@@ -1,5 +1,7 @@
 @import "global";
 @import "global";
 
 
+@import "base/reset";
+@import "base/base";
 @import 'base/icons';
 @import 'base/icons';
 
 
 @import "../libs/animate/animate";
 @import "../libs/animate/animate";

+ 1 - 1
client/scss/components/setup.scss

@@ -2,7 +2,7 @@
   background-color: #1565c0;
   background-color: #1565c0;
   background-image: url('../static/svg/config-bg.svg');
   background-image: url('../static/svg/config-bg.svg');
   width: 100%;
   width: 100%;
-  min-height: 100%;
+  min-height: 100vh;
   padding-top: 1rem;
   padding-top: 1rem;
 
 
   .welcome {
   .welcome {

+ 0 - 2
client/scss/global.scss

@@ -4,6 +4,4 @@ $primary: 'indigo';
 
 
 @import "base/variables";
 @import "base/variables";
 @import "base/material";
 @import "base/material";
-@import "base/reset";
 @import "base/mixins";
 @import "base/mixins";
-@import "base/base";

+ 1 - 0
client/static/svg/auth-icon-auth0.svg

@@ -0,0 +1 @@
+<svg width="2230" height="2500" viewBox="0 0 256 287" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet"><path d="M203.24 231.531l-28.73-88.434 75.208-54.64h-92.966L128.019.025l-.009-.024h92.98l28.74 88.446.002-.002.024-.013c16.69 51.31-.5 109.67-46.516 143.098zm-150.45 0l-.023.017 75.228 54.655 75.245-54.67-75.221-54.656-75.228 54.654zM6.295 88.434c-17.57 54.088 2.825 111.4 46.481 143.108l.007-.028 28.735-88.429-75.192-54.63h92.944L128.004.024 128.01 0H35.025L6.294 88.434z" fill="#EB5424"/></svg>

+ 1 - 0
client/static/svg/auth-icon-discord.svg

@@ -0,0 +1 @@
+<svg width="2184" height="2500" viewBox="0 0 256 293" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid"><path d="M226.011 0H29.99C13.459 0 0 13.458 0 30.135v197.778c0 16.677 13.458 30.135 29.989 30.135h165.888l-7.754-27.063 18.725 17.408 17.7 16.384L256 292.571V30.135C256 13.458 242.542 0 226.011 0zm-56.466 191.05s-5.266-6.291-9.655-11.85c19.164-5.413 26.478-17.408 26.478-17.408-5.998 3.95-11.703 6.73-16.823 8.63-7.314 3.073-14.336 5.12-21.211 6.291-14.044 2.633-26.917 1.902-37.888-.146-8.339-1.61-15.507-3.95-21.504-6.29-3.365-1.317-7.022-2.926-10.68-4.974-.438-.293-.877-.439-1.316-.732-.292-.146-.439-.292-.585-.438-2.633-1.463-4.096-2.487-4.096-2.487s7.022 11.703 25.6 17.261c-4.388 5.56-9.801 12.142-9.801 12.142-32.33-1.024-44.617-22.235-44.617-22.235 0-47.104 21.065-85.285 21.065-85.285 21.065-15.799 41.106-15.36 41.106-15.36l1.463 1.756C80.75 77.53 68.608 89.088 68.608 89.088s3.218-1.755 8.63-4.242c15.653-6.876 28.088-8.777 33.208-9.216.877-.147 1.609-.293 2.487-.293a123.776 123.776 0 0 1 29.55-.292c13.896 1.609 28.818 5.705 44.031 14.043 0 0-11.556-10.971-36.425-18.578l2.048-2.34s20.041-.44 41.106 15.36c0 0 21.066 38.18 21.066 85.284 0 0-12.435 21.211-44.764 22.235zm-68.023-68.316c-8.338 0-14.92 7.314-14.92 16.237 0 8.924 6.728 16.238 14.92 16.238 8.339 0 14.921-7.314 14.921-16.238.147-8.923-6.582-16.237-14.92-16.237m53.394 0c-8.339 0-14.922 7.314-14.922 16.237 0 8.924 6.73 16.238 14.922 16.238 8.338 0 14.92-7.314 14.92-16.238 0-8.923-6.582-16.237-14.92-16.237" fill="#7289DA"/></svg>

+ 1 - 0
client/static/svg/auth-icon-dropbox.svg

@@ -0,0 +1 @@
+<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 42.4 39.5" width="2500" height="2329"><style>.st0{fill:#0062ff}</style><path class="st0" d="M10.6 1.7L0 8.5l10.6 6.7 10.6-6.7zm21.2 0L21.2 8.5l10.6 6.7 10.6-6.7zM0 22l10.6 6.8L21.2 22l-10.6-6.8zm31.8-6.8L21.2 22l10.6 6.8L42.4 22zM10.6 31l10.6 6.8L31.8 31l-10.6-6.7z"/></svg>

+ 1 - 4
client/static/svg/auth-icon-ldap.svg

@@ -1,7 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
 	 width="48px" height="48px" viewBox="0 0 48 48" enable-background="new 0 0 48 48" xml:space="preserve">
 	 width="48px" height="48px" viewBox="0 0 48 48" enable-background="new 0 0 48 48" xml:space="preserve">
 <path fill="#458BC4" d="M44.804,30.404l-20-27C24.615,3.15,24.308,3.023,24,3.023V46c0.2,0,0.401-0.061,0.573-0.181l20-14
 <path fill="#458BC4" d="M44.804,30.404l-20-27C24.615,3.15,24.308,3.023,24,3.023V46c0.2,0,0.401-0.061,0.573-0.181l20-14
 	c0.222-0.155,0.37-0.393,0.414-0.659C45.03,30.895,44.964,30.622,44.804,30.404z"/>
 	c0.222-0.155,0.37-0.393,0.414-0.659C45.03,30.895,44.964,30.622,44.804,30.404z"/>

+ 1 - 0
client/static/svg/auth-icon-oauth2.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M21 21v3h-18v-3h18zm-13-15c0-2.206 1.795-4 4-4s4 1.794 4 4v3h2v-3c0-3.313-2.687-6-6-6s-6 2.687-6 6v3h2v-3zm13 8v-3h-18v3h18zm0 5v-3h-18v3h18z"/></svg>

+ 1 - 0
client/static/svg/auth-icon-twitch.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="2500" height="2500" viewBox="0 0 300 300"><path fill-rule="evenodd" clip-rule="evenodd" fill="#65459B" d="M215.2 260.8h-58.7L117.4 300H78.3v-39.2H6.6V52.2L26.1 0h267.3v182.6l-78.2 78.2zm52.2-91.2V26.1H52.2v189.1h58.7v39.1l39.1-39.1h71.7l45.7-45.6z"/><path fill="#65459B" d="M195.6 78.3v78.3h26.1V78.3h-26.1zm-71.7 78.2H150V78.3h-26.1v78.2z"/></svg>

+ 41 - 31
dev/webpack/webpack.common.js

@@ -5,7 +5,6 @@ const webpack = require('webpack')
 const CopyWebpackPlugin = require('copy-webpack-plugin')
 const CopyWebpackPlugin = require('copy-webpack-plugin')
 const ExtractTextPlugin = require('extract-text-webpack-plugin')
 const ExtractTextPlugin = require('extract-text-webpack-plugin')
 const NameAllModulesPlugin = require('name-all-modules-plugin')
 const NameAllModulesPlugin = require('name-all-modules-plugin')
-const LodashModuleReplacementPlugin = require('lodash-webpack-plugin')
 
 
 const babelConfig = fs.readJsonSync(path.join(process.cwd(), '.babelrc'))
 const babelConfig = fs.readJsonSync(path.join(process.cwd(), '.babelrc'))
 const postCSSConfig = {
 const postCSSConfig = {
@@ -24,6 +23,7 @@ module.exports = {
   },
   },
   output: {
   output: {
     path: path.join(process.cwd(), 'assets'),
     path: path.join(process.cwd(), 'assets'),
+    publicPath: '/',
     filename: 'js/[name].js',
     filename: 'js/[name].js',
     chunkFilename: 'js/[name].chunk.js'
     chunkFilename: 'js/[name].chunk.js'
   },
   },
@@ -104,6 +104,10 @@ module.exports = {
             {
             {
               loader: 'css-loader'
               loader: 'css-loader'
             },
             },
+            {
+              loader: 'postcss-loader',
+              options: postCSSConfig
+            },
             {
             {
               loader: 'stylus-loader'
               loader: 'stylus-loader'
             }
             }
@@ -114,37 +118,43 @@ module.exports = {
         test: /\.vue$/,
         test: /\.vue$/,
         loader: 'vue-loader',
         loader: 'vue-loader',
         options: {
         options: {
-          extractCSS: ExtractTextPlugin,
-          postcss: postCSSConfig,
           loaders: {
           loaders: {
-            css: [
-              {
-                loader: 'vue-style-loader'
-              },
-              {
-                loader: 'css-loader'
-              }
-            ],
-            scss: [
-              {
-                loader: 'vue-style-loader'
-              },
-              {
-                loader: 'css-loader'
-              },
-              {
-                loader: 'sass-loader',
-                options: {
-                  sourceMap: false
+            css: ExtractTextPlugin.extract({
+              fallback: 'vue-style-loader',
+              use: [
+                {
+                  loader: 'css-loader'
+                },
+                {
+                  loader: 'postcss-loader',
+                  options: postCSSConfig
                 }
                 }
-              },
-              {
-                loader: 'sass-resources-loader',
-                options: {
-                  resources: path.join(process.cwd(), '/client/scss/global.scss')
+              ]
+            }),
+            scss: ExtractTextPlugin.extract({
+              fallback: 'vue-style-loader',
+              use: [
+                {
+                  loader: 'css-loader'
+                },
+                {
+                  loader: 'postcss-loader',
+                  options: postCSSConfig
+                },
+                {
+                  loader: 'sass-loader',
+                  options: {
+                    sourceMap: false
+                  }
+                },
+                {
+                  loader: 'sass-resources-loader',
+                  options: {
+                    resources: path.join(process.cwd(), '/client/scss/global.scss')
+                  }
                 }
                 }
-              }
-            ],
+              ]
+            }),
             js: [
             js: [
               {
               {
                 loader: 'cache-loader',
                 loader: 'cache-loader',
@@ -209,7 +219,6 @@ module.exports = {
     ], {
     ], {
 
 
     }),
     }),
-    new LodashModuleReplacementPlugin(),
     new webpack.NamedModulesPlugin(),
     new webpack.NamedModulesPlugin(),
     new webpack.NamedChunksPlugin((chunk) => {
     new webpack.NamedChunksPlugin((chunk) => {
       if (chunk.name) {
       if (chunk.name) {
@@ -237,7 +246,8 @@ module.exports = {
       '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'),
-      'apollo-utilities': path.join(process.cwd(), 'node_modules/apollo-utilities')
+      'apollo-utilities': path.join(process.cwd(), 'node_modules/apollo-utilities'),
+      'uc.micro': path.join(process.cwd(), 'node_modules/uc.micro')
     },
     },
     extensions: [
     extensions: [
       '.js',
       '.js',

+ 1 - 2
dev/webpack/webpack.dev.js

@@ -12,8 +12,7 @@ module.exports = merge(common, {
     client: ['./client/index.js', 'webpack-hot-middleware/client']
     client: ['./client/index.js', 'webpack-hot-middleware/client']
   },
   },
   output: {
   output: {
-    pathinfo: true,
-    publicPath: '/'
+    pathinfo: true
   },
   },
   plugins: [
   plugins: [
     new SimpleProgressWebpackPlugin({
     new SimpleProgressWebpackPlugin({

+ 9 - 1
dev/webpack/webpack.prod.js

@@ -8,6 +8,7 @@ const ExtractTextPlugin = require('extract-text-webpack-plugin')
 const OfflinePlugin = require('offline-plugin')
 const OfflinePlugin = require('offline-plugin')
 const DuplicatePackageCheckerPlugin = require('duplicate-package-checker-webpack-plugin')
 const DuplicatePackageCheckerPlugin = require('duplicate-package-checker-webpack-plugin')
 const SimpleProgressWebpackPlugin = require('simple-progress-webpack-plugin')
 const SimpleProgressWebpackPlugin = require('simple-progress-webpack-plugin')
+const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
 
 
 const common = require('./webpack.common.js')
 const common = require('./webpack.common.js')
 
 
@@ -35,7 +36,14 @@ module.exports = merge(common, {
     new webpack.DefinePlugin({
     new webpack.DefinePlugin({
       'process.env.NODE_ENV': JSON.stringify('production')
       'process.env.NODE_ENV': JSON.stringify('production')
     }),
     }),
-    new ExtractTextPlugin('css/bundle.css'),
+    new ExtractTextPlugin({
+      filename: 'css/bundle.css',
+      allChunks: true
+    }),
+    new OptimizeCssAssetsPlugin({
+      cssProcessorOptions: { discardComments: { removeAll: true } },
+      canPrint: true
+    }),
     new OfflinePlugin({
     new OfflinePlugin({
       publicPath: '/',
       publicPath: '/',
       externals: ['/'],
       externals: ['/'],

+ 1 - 0
package.json

@@ -182,6 +182,7 @@
     "name-all-modules-plugin": "1.0.1",
     "name-all-modules-plugin": "1.0.1",
     "node-sass": "4.7.2",
     "node-sass": "4.7.2",
     "offline-plugin": "4.9.0",
     "offline-plugin": "4.9.0",
+    "optimize-css-assets-webpack-plugin": "3.2.0",
     "postcss-flexbugs-fixes": "3.3.0",
     "postcss-flexbugs-fixes": "3.3.0",
     "postcss-flexibility": "2.0.0",
     "postcss-flexibility": "2.0.0",
     "postcss-loader": "2.1.1",
     "postcss-loader": "2.1.1",

+ 2 - 0
server/core/auth.js

@@ -33,10 +33,12 @@ module.exports = {
     // Load authentication strategies
     // Load authentication strategies
 
 
     const modules = _.values(autoload(path.join(WIKI.SERVERPATH, 'modules/authentication')))
     const modules = _.values(autoload(path.join(WIKI.SERVERPATH, 'modules/authentication')))
+    console.info(WIKI.config.auth)
     _.forEach(modules, (strategy) => {
     _.forEach(modules, (strategy) => {
       const strategyConfig = _.get(WIKI.config.auth.strategies, strategy.key, {})
       const strategyConfig = _.get(WIKI.config.auth.strategies, strategy.key, {})
       strategyConfig.callbackURL = `${WIKI.config.site.host}${WIKI.config.site.path}login/${strategy.key}/callback`
       strategyConfig.callbackURL = `${WIKI.config.site.host}${WIKI.config.site.path}login/${strategy.key}/callback`
       if (strategyConfig.isEnabled) {
       if (strategyConfig.isEnabled) {
+        console.info(strategy.title)
         try {
         try {
           strategy.init(passport, strategyConfig)
           strategy.init(passport, strategyConfig)
         } catch (err) {
         } catch (err) {

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

@@ -29,6 +29,30 @@ module.exports = {
       return prv
       return prv
     }
     }
   },
   },
+  AuthenticationMutation: {
+    async login(obj, args, context) {
+      try {
+        let authResult = await WIKI.db.User.login(args, context)
+        return {
+          ...authResult,
+          operation: graphHelper.generateSuccess('Login success')
+        }
+      } catch (err) {
+        return graphHelper.generateError(err)
+      }
+    },
+    async loginTFA(obj, args, context) {
+      try {
+        let authResult = await WIKI.db.User.loginTFA(args, context)
+        return {
+          ...authResult,
+          operation: graphHelper.generateSuccess('TFA success')
+        }
+      } catch (err) {
+        return graphHelper.generateError(err)
+      }
+    }
+  },
   AuthenticationProvider: {
   AuthenticationProvider: {
     icon (ap, args) {
     icon (ap, args) {
       return fs.readFile(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 => {

+ 0 - 16
server/graph/resolvers/user.js

@@ -19,22 +19,6 @@ module.exports = {
         limit: 1
         limit: 1
       })
       })
     },
     },
-    login(obj, args, context) {
-      return WIKI.db.User.login(args, context).catch(err => {
-        return {
-          succeeded: false,
-          message: err.message
-        }
-      })
-    },
-    loginTFA(obj, args, context) {
-      return WIKI.db.User.loginTFA(args, context).catch(err => {
-        return {
-          succeeded: false,
-          message: err.message
-        }
-      })
-    },
     modifyUser(obj, args) {
     modifyUser(obj, args) {
       return WIKI.db.User.update({
       return WIKI.db.User.update({
         email: args.email,
         email: args.email,

+ 33 - 0
server/graph/schemas/authentication.graphql

@@ -1,3 +1,7 @@
+# ===============================================
+# AUTHENTICATION
+# ===============================================
+
 extend type Query {
 extend type Query {
   authentication: AuthenticationQuery
   authentication: AuthenticationQuery
 }
 }
@@ -6,6 +10,10 @@ extend type Mutation {
   authentication: AuthenticationMutation
   authentication: AuthenticationMutation
 }
 }
 
 
+# -----------------------------------------------
+# QUERIES
+# -----------------------------------------------
+
 type AuthenticationQuery {
 type AuthenticationQuery {
   providers(
   providers(
     filter: String
     filter: String
@@ -13,7 +21,22 @@ type AuthenticationQuery {
   ): [AuthenticationProvider]
   ): [AuthenticationProvider]
 }
 }
 
 
+# -----------------------------------------------
+# MUTATIONS
+# -----------------------------------------------
+
 type AuthenticationMutation {
 type AuthenticationMutation {
+  login(
+    username: String!
+    password: String!
+    provider: String!
+  ): AuthenticationLoginResponse
+
+  loginTFA(
+    loginToken: String!
+    securityCode: String!
+  ): DefaultResponse
+
   updateProvider(
   updateProvider(
     provider: String!
     provider: String!
     isEnabled: Boolean!
     isEnabled: Boolean!
@@ -21,6 +44,10 @@ type AuthenticationMutation {
   ): DefaultResponse
   ): DefaultResponse
 }
 }
 
 
+# -----------------------------------------------
+# TYPES
+# -----------------------------------------------
+
 type AuthenticationProvider {
 type AuthenticationProvider {
   isEnabled: Boolean!
   isEnabled: Boolean!
   key: String!
   key: String!
@@ -30,3 +57,9 @@ type AuthenticationProvider {
   icon: String
   icon: String
   config: [KeyValuePair]
   config: [KeyValuePair]
 }
 }
+
+type AuthenticationLoginResponse {
+  operation: ResponseStatus
+  tfaRequired: Boolean
+  tfaLoginToken: String
+}

+ 0 - 18
server/graph/schemas/common.graphql

@@ -162,13 +162,6 @@ type OperationResult {
   data: String
   data: String
 }
 }
 
 
-type LoginResult {
-  succeeded: Boolean!
-  message: String
-  tfaRequired: Boolean
-  tfaLoginToken: String
-}
-
 # Query (Read)
 # Query (Read)
 type Query {
 type Query {
   comments(id: Int): [Comment]
   comments(id: Int): [Comment]
@@ -265,17 +258,6 @@ type Mutation {
     id: Int!
     id: Int!
   ): OperationResult
   ): OperationResult
 
 
-  login(
-    username: String!
-    password: String!
-    provider: String!
-  ): LoginResult
-
-  loginTFA(
-    loginToken: String!
-    securityCode: String!
-  ): OperationResult
-
   modifyComment(
   modifyComment(
     id: Int!
     id: Int!
     content: String!
     content: String!

+ 17 - 0
server/helpers/graph.js

@@ -2,6 +2,23 @@ const _ = require('lodash')
 const Filter = require('scim-query-filter-parser')
 const Filter = require('scim-query-filter-parser')
 
 
 module.exports = {
 module.exports = {
+  generateSuccess (msg) {
+    return {
+      succeeded: true,
+      code: 0,
+      slug: 'ok',
+      message: _.defaultTo(msg, 'Operation succeeded.')
+    }
+  },
+  generateError (err, complete = true) {
+    const error = {
+      succeeded: false,
+      code: err.code || 1,
+      slug: err.name,
+      message: err.message || 'An unexpected error occured.'
+    }
+    return (complete) ? { operation: error } : error
+  },
   filter (arr, filterString) {
   filter (arr, filterString) {
     const prvFilter = new Filter(_.toString(filterString).replace(/'/g, `"`))
     const prvFilter = new Filter(_.toString(filterString).replace(/'/g, `"`))
     return arr.filter(prvFilter.test)
     return arr.filter(prvFilter.test)

+ 0 - 4
server/models/user.js

@@ -103,8 +103,6 @@ module.exports = (sequelize, DataTypes) => {
               let loginToken = await securityHelper.generateToken(32)
               let loginToken = await securityHelper.generateToken(32)
               await WIKI.redis.set(`tfa:${loginToken}`, user.id, 'EX', 600)
               await WIKI.redis.set(`tfa:${loginToken}`, user.id, 'EX', 600)
               return resolve({
               return resolve({
-                succeeded: true,
-                message: 'Login Successful. Awaiting 2FA security code.',
                 tfaRequired: true,
                 tfaRequired: true,
                 tfaLoginToken: loginToken
                 tfaLoginToken: loginToken
               })
               })
@@ -117,8 +115,6 @@ module.exports = (sequelize, DataTypes) => {
             return context.req.logIn(user, err => {
             return context.req.logIn(user, err => {
               if (err) { return reject(err) }
               if (err) { return reject(err) }
               resolve({
               resolve({
-                succeeded: true,
-                message: 'Login Successful',
                 tfaRequired: false
                 tfaRequired: false
               })
               })
             })
             })

+ 6 - 0
server/views/main/setup.pug

@@ -0,0 +1,6 @@
+extends ../master.pug
+
+block body
+  body
+    #app.setup.is-fullscreen
+      setup(telemetry-id=telemetryClientID, wiki-version=packageObj.version, :langs!=JSON.stringify(data.langs).replace(/"/g, "'"))

+ 15 - 1
yarn.lock

@@ -2796,7 +2796,7 @@ cssnano@4.0.0-rc.2:
     is-resolvable "^1.0.0"
     is-resolvable "^1.0.0"
     postcss "^6.0.0"
     postcss "^6.0.0"
 
 
-cssnano@^3.10.0:
+cssnano@^3.10.0, cssnano@^3.4.0:
   version "3.10.0"
   version "3.10.0"
   resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-3.10.0.tgz#4f38f6cea2b9b17fa01490f23f1dc68ea65c1c38"
   resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-3.10.0.tgz#4f38f6cea2b9b17fa01490f23f1dc68ea65c1c38"
   dependencies:
   dependencies:
@@ -5749,6 +5749,13 @@ klaw@2.1.1:
   dependencies:
   dependencies:
     graceful-fs "^4.1.9"
     graceful-fs "^4.1.9"
 
 
+last-call-webpack-plugin@^2.1.2:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/last-call-webpack-plugin/-/last-call-webpack-plugin-2.1.2.tgz#ad80c6e310998294d2ed2180a68e9589e4768c44"
+  dependencies:
+    lodash "^4.17.4"
+    webpack-sources "^1.0.1"
+
 lazy-cache@^1.0.3:
 lazy-cache@^1.0.3:
   version "1.0.4"
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e"
   resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e"
@@ -6905,6 +6912,13 @@ optimist@^0.6.1:
     minimist "~0.0.1"
     minimist "~0.0.1"
     wordwrap "~0.0.2"
     wordwrap "~0.0.2"
 
 
+optimize-css-assets-webpack-plugin@3.2.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-3.2.0.tgz#09a40c4cefde1dd0142444a873c56aa29eb18e6f"
+  dependencies:
+    cssnano "^3.4.0"
+    last-call-webpack-plugin "^2.1.2"
+
 optionator@^0.8.1, optionator@^0.8.2:
 optionator@^0.8.1, optionator@^0.8.2:
   version "0.8.2"
   version "0.8.2"
   resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64"
   resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64"