浏览代码

feat: users create (wip)

Nick 6 年之前
父节点
当前提交
4f23984ac6

+ 5 - 1
client/components/admin.vue

@@ -1,6 +1,10 @@
 <template lang='pug'>
   v-app(:dark='darkMode').admin
-    nav-header
+    nav-header(hide-search)
+      template(slot='mid')
+        v-spacer
+        .subheading.grey--text Administration Area
+        v-spacer
     v-navigation-drawer.pb-0.admin-sidebar(v-model='adminDrawerShown', app, fixed, clipped, left, permanent)
       vue-scroll(:ops='scrollStyle')
         v-list(dense)

+ 1 - 1
client/components/admin/admin-auth.vue

@@ -130,7 +130,7 @@
                   persistent-hint
                 )
                 v-switch.ml-3(
-                  v-if='strategy.useForm'
+                  v-if='strategy.key === `local`'
                   :disabled='!strategy.selfRegistration || true'
                   v-model='strategy.recaptcha'
                   label='Use reCAPTCHA by Google'

+ 1 - 1
client/components/admin/admin-dashboard.vue

@@ -45,7 +45,7 @@
           :class='isLatestVersion ? "teal lighten-2" : "red lighten-2"'
           dark
           )
-          v-btn(fab, absolute, right, top, small, light, to='system', v-if='hasPermission(`manage:system`)')
+          v-btn.btn-animate-wrench(fab, absolute, right, top, small, light, to='system', v-if='hasPermission(`manage:system`)')
             v-icon(:color='isLatestVersion ? `teal` : `red darken-4`') build
           v-card-text
             v-icon.dashboard-icon blur_on

+ 1 - 1
client/components/admin/admin-system.vue

@@ -10,7 +10,7 @@
         v-layout.mt-3(row wrap)
           v-flex(lg6 xs12)
             v-card.animated.fadeInUp
-              v-btn.animated.fadeInLeft.wait-p2s(fab, absolute, right, top, small, light, @click='refresh'): v-icon refresh
+              v-btn.animated.fadeInLeft.wait-p2s.btn-animate-rotate(fab, absolute, right, top, small, light, @click='refresh'): v-icon refresh
               v-list(two-line, dense)
                 v-subheader Wiki.js
                 v-list-tile(avatar)

+ 46 - 8
client/components/admin/admin-users-create.vue

@@ -1,10 +1,10 @@
 <template lang="pug">
-  v-dialog(v-model='isShown', max-width='550')
+  v-dialog(v-model='isShown', max-width='650', persistent)
     v-card.wiki-form
       .dialog-header.is-short
         span New User
       v-card-text
-        v-select.md2(
+        v-select(
           :items='providers'
           item-text='title'
           item-value='key'
@@ -13,40 +13,66 @@
           v-model='provider'
           label='Provider'
           )
-        v-text-field.md2(
+        v-text-field(
           outline
           prepend-icon='email'
           v-model='email'
           label='Email Address'
           ref='emailInput'
           )
-        v-text-field.md2(
+        v-text-field(
           v-if='provider === `local`'
           outline
           prepend-icon='lock'
           append-icon='casino'
           v-model='password'
-          label='Password'
+          :label='mustChangePwd ? `Temporary Password` : `Password`'
           counter='255'
           @click:append='generatePwd'
           )
-        v-text-field.md2(
+        v-text-field(
           outline
           prepend-icon='person'
           v-model='name'
           label='Name'
           )
+        v-select(
+          :items='groups'
+          item-text='name'
+          item-value='key'
+          outline
+          prepend-icon='people'
+          v-model='group'
+          label='Assign to Group(s)...'
+          clearable
+          multiple
+          )
+        v-divider
+        v-checkbox(
+          color='primary'
+          label='Require password change on first login'
+          v-if='provider === `local`'
+          v-model='mustChangePwd'
+          hide-details
+        )
+        v-checkbox(
+          color='primary'
+          label='Send a welcome email'
+          hide-details
+          v-model='sendWelcomeEmail'
+        )
       v-card-chin
         v-spacer
         v-btn(flat, @click='isShown = false') Cancel
         v-btn(color='primary', @click='newUser') Create
+        v-btn(color='primary', @click='newUser') Create and Close
 </template>
 
 <script>
-import _ from 'lodash'
 import uuidv4 from 'uuid/v4'
 
 import providersQuery from 'gql/admin/users/users-query-strategies.gql'
+import groupsQuery from 'gql/admin/auth/auth-query-groups.gql'
 
 export default {
   props: {
@@ -61,7 +87,11 @@ export default {
       provider: 'local',
       email: '',
       password: '',
-      name: ''
+      name: '',
+      groups: [],
+      group: '',
+      mustChangePwd: false,
+      sendWelcomeEmail: false
     }
   },
   computed: {
@@ -95,6 +125,14 @@ export default {
       watchLoading (isLoading) {
         this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-users-strategies-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')
+      }
     }
   }
 }

+ 13 - 13
client/components/admin/admin-users-edit.vue

@@ -3,17 +3,17 @@
     v-layout(row, wrap)
       v-flex(xs12)
         .admin-header
-          img(src='/svg/icon-male-user.svg', alt='Edit User', style='width: 80px;')
+          img.animated.fadeInUp(src='/svg/icon-male-user.svg', alt='Edit User', style='width: 80px;')
           .admin-header-title
-            .headline.blue--text.text--darken-2 Edit User
-            .subheading.grey--text {{user.name}}
+            .headline.blue--text.text--darken-2.animated.fadeInLeft Edit User
+            .subheading.grey--text.animated.fadeInLeft.wait-p2s {{user.name}}
           v-spacer
-          .caption.grey--text ID #[strong {{user.id}}]
-          v-divider.mx-3(vertical)
-          v-btn(color='grey', large, outline, to='/users')
+          .caption.grey--text.animated.fadeInRight.wait-p5s ID #[strong {{user.id}}]
+          v-divider.animated.fadeInRight.wait-p3s.mx-3(vertical)
+          v-btn.animated.fadeInDown.wait-p2s(color='grey', large, outline, to='/users')
             v-icon arrow_back
           v-dialog(v-model='deleteUserDialog', max-width='500', v-if='user.id !== currentUserId && !user.isSystem')
-            v-btn(color='red', large, outline, slot='activator')
+            v-btn.animated.fadeInDown.wait-p1s(color='red', large, outline, slot='activator')
               v-icon(color='red') delete
             v-card
               .dialog-header.is-red Delete User?
@@ -22,11 +22,11 @@
                 v-spacer
                 v-btn(flat, @click='deleteUserDialog = false') Cancel
                 v-btn(color='red', dark, @click='deleteUser') Delete
-          v-btn(color='primary', large, depressed, @click='updateUser')
+          v-btn.animated.fadeInDown(color='primary', large, depressed, @click='updateUser')
             v-icon(left) check
             span Update User
       v-flex(xs5)
-        v-card
+        v-card.animated.fadeInUp
           v-toolbar(color='primary', dense, dark, flat)
             v-icon.mr-2 directions_run
             span Basic Info
@@ -50,7 +50,7 @@
               v-list-tile-action
                   v-btn(icon, color='grey', flat)
                     v-icon edit
-        v-card.mt-3(v-if='!user.isSystem')
+        v-card.mt-3.animated.fadeInUp.wait-p2s(v-if='!user.isSystem')
           v-toolbar(color='primary', dense, dark, flat)
             v-icon.mr-2 lock_outline
             span Authentication
@@ -95,7 +95,7 @@
                   v-list-tile-content
                     v-list-tile-title Provider Id
                     v-list-tile-sub-title {{ user.providerId }}
-        v-card.mt-3
+        v-card.mt-3.animated.fadeInUp.wait-p4s
           v-toolbar(color='primary', dense, dark, flat)
             v-icon.mr-2 people
             span User Groups
@@ -116,7 +116,7 @@
               v-icon(left) how_to_reg
               span Assign to group
       v-flex(xs7)
-        v-card
+        v-card.animated.fadeInUp.wait-p2s
           v-toolbar(color='primary', dense, dark, flat)
             v-icon.mr-2 directions_walk
             span Extended Metadata
@@ -150,7 +150,7 @@
               v-list-tile-action
                   v-btn(icon, color='grey', flat)
                     v-icon edit
-        v-card.mt-3
+        v-card.mt-3.animated.fadeInUp.wait-p4s
           v-toolbar(color='primary', dense, dark, flat)
             v-icon.mr-2 insert_drive_file
             span Content

+ 52 - 7
client/components/admin/admin-users.vue

@@ -6,21 +6,42 @@
           img.animated.fadeInUp(src='/svg/icon-customer.svg', alt='Users', style='width: 80px;')
           .admin-header-title
             .headline.blue--text.text--darken-2.animated.fadeInLeft Users
-            .subheading.grey--text.animated.fadeInLeft.wait-p4s Manage users
+            .subheading.grey--text.animated.fadeInLeft.wait-p2s Manage users
           v-spacer
           v-btn.animated.fadeInDown.wait-p2s(outline, color='grey', large, @click='refresh')
             v-icon refresh
-          v-btn.animated.fadeInDown(color='primary', large, depressed, @click='createUser')
+          v-btn.animated.fadeInDown(color='primary', large, depressed, @click='createUser', disabled)
             v-icon(left) add
             span New User
-        v-card.mt-3.animated.fadeInUp
+        v-card.wiki-form.mt-3.animated.fadeInUp
+          v-toolbar(flat, :color='$vuetify.dark ? `grey darken-3-d5` : `grey lighten-5`', height='80')
+            v-spacer
+            v-text-field(
+              outline
+              v-model='search'
+              prepend-inner-icon='search'
+              label='Search Users...'
+              hide-details
+              )
+            v-select.ml-2(
+              outline
+              hide-details
+              label='Identity Provider'
+              :items='strategies'
+              v-model='filterStrategy'
+              item-text='title'
+              item-value='key'
+            )
+            v-spacer
+          v-divider
           v-data-table(
             v-model='selected'
-            :items='users',
+            :items='usersFiltered',
             :headers='headers',
             :search='search',
             :pagination.sync='pagination',
             :rows-per-page-items='[15]'
+            :loading='loading'
             hide-actions,
             disable-initial-sort
           )
@@ -51,7 +72,7 @@
             template(slot='no-data')
               .pa-3
                 v-alert(icon='warning', :value='true', outline) No users to display!
-          v-card-chin(v-if='this.pages > 0')
+          v-card-chin(v-if='this.pages > 1')
             v-spacer
             v-pagination(v-model='pagination.page', :length='pages')
             v-spacer
@@ -60,7 +81,10 @@
 </template>
 
 <script>
+import _ from 'lodash'
+
 import usersQuery from 'gql/admin/users/users-query-list.gql'
+import providersQuery from 'gql/admin/users/users-query-strategies.gql'
 
 import UserCreate from './admin-users-create.vue'
 
@@ -81,17 +105,24 @@ export default {
         { text: 'Created', value: 'createdAt', sortable: true },
         { text: '', value: 'actions', sortable: false, width: 50 }
       ],
+      strategies: [],
+      filterStrategy: 'all',
       search: '',
+      loading: false,
       isCreateDialogShown: false
     }
   },
   computed: {
+    usersFiltered () {
+      const all = this.filterStrategy === 'all' || this.filterStrategy === ''
+      return _.filter(this.users, u => all || u.providerKey === this.filterStrategy)
+    },
     pages () {
-      if (this.pagination.rowsPerPage == null || this.pagination.totalItems == null) {
+      if (this.pagination.rowsPerPage == null || this.usersFiltered.length < 1) {
         return 0
       }
 
-      return Math.ceil(this.pagination.totalItems / this.pagination.rowsPerPage)
+      return Math.ceil(this.usersFiltered.length / this.pagination.rowsPerPage)
     }
   },
   methods: {
@@ -128,8 +159,22 @@ export default {
       fetchPolicy: 'network-only',
       update: (data) => data.users.list,
       watchLoading (isLoading) {
+        this.loading = isLoading
         this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-users-refresh')
       }
+    },
+    strategies: {
+      query: providersQuery,
+      fetchPolicy: 'network-only',
+      update: (data) => {
+        return _.concat({
+          key: 'all',
+          title: 'All'
+        }, data.authentication.strategies)
+      },
+      watchLoading (isLoading) {
+        this.$store.commit(`loading${isLoading ? 'Start' : 'Stop'}`, 'admin-users-strategies-refresh')
+      }
     }
   }
 }

+ 10 - 0
client/scss/components/v-btn.scss

@@ -32,6 +32,16 @@
   }
 }
 
+.btn-animate-wrench {
+  i {
+    transition: all .7s cubic-bezier(0.68, -0.55, 0.265, 1.55);
+    transform: rotate(0deg);
+  }
+  &:hover i {
+    transform: rotate(45deg);
+  }
+}
+
 .btn-animate-app {
   i {
     transition: all .6s ease;

+ 6 - 5
server/modules/authentication/azure/authentication.js

@@ -17,14 +17,15 @@ module.exports = {
         resource: conf.resource,
         tenant: conf.tenant
       }, (accessToken, refreshToken, params, profile, cb) => {
+        console.info(params, profile)
         let waadProfile = jwt.decode(params.id_token)
         waadProfile.id = waadProfile.oid
         waadProfile.provider = 'azure'
-        WIKI.models.users.processProfile(waadProfile).then((user) => {
-          return cb(null, user) || true
-        }).catch((err) => {
-          return cb(err, null) || true
-        })
+        // WIKI.models.users.processProfile(waadProfile).then((user) => {
+        //   return cb(null, user) || true
+        // }).catch((err) => {
+        //   return cb(err, null) || true
+        // })
       }
       ))
   }

+ 1 - 0
server/modules/authentication/azure/definition.yml

@@ -5,6 +5,7 @@ author: requarks.io
 logo: https://static.requarks.io/logo/azure.svg
 color: blue darken-3
 website: https://azure.microsoft.com/services/active-directory/
+isAvailable: false
 useForm: false
 props:
   clientId: String