From 882c2b1c5177518153abd73953ff381f6fce44a5 Mon Sep 17 00:00:00 2001
From: Mark <mark@openappstack.net>
Date: Tue, 22 Oct 2019 15:59:38 +0200
Subject: [PATCH] Add applications to user management

---
 frontend/components/edit-user.vue  | 54 ++++++++++++++++++++++++++----
 frontend/components/edit-users.vue | 12 ++++---
 frontend/pages/users.vue           | 40 +++++++++++++++++++---
 3 files changed, 91 insertions(+), 15 deletions(-)

diff --git a/frontend/components/edit-user.vue b/frontend/components/edit-user.vue
index 9aa962c..75cb0f3 100644
--- a/frontend/components/edit-user.vue
+++ b/frontend/components/edit-user.vue
@@ -1,12 +1,12 @@
 <template>
   <b-row class="mb-2">
-    <b-col cols="3">
+    <b-col cols="2">
       {{ user.username }}
     </b-col>
     <b-col cols="2">
       <b-form-input type="password" v-model="user.password" placeholder="password"></b-form-input>
     </b-col>
-    <b-col cols="3">
+    <b-col cols="2">
       <b-form-input type="email" v-model="user.email"></b-form-input>
     </b-col>
     <b-col cols="1">
@@ -14,9 +14,15 @@
             {{role}} &times;
             </b-badge>
     </b-col>
-    <b-col cols="3">
-      <b-button-group v-show="!showAddRole">
+    <b-col cols="1">
+        <b-badge class="mr-1" href="#" variant="secondary" v-for="(application, index) in user.applications" v-bind:key="application" @click="user.applications.splice(index, 1)">
+            {{application}} &times;
+            </b-badge>
+    </b-col>
+    <b-col cols="4">
+      <b-button-group v-show="!showAddRole && !showAddApplication">
           <b-button variant="outline-primary" v-on:click="addRole">Add role</b-button>
+          <b-button variant="outline-secondary" v-on:click="addApplication">Add app</b-button>
           <b-button v-show="isModified" variant="outline-primary" v-on:click="savePressed()">Save</b-button>
           <b-button variant="outline-danger" v-on:click="$emit('delete')">Delete</b-button>
       </b-button-group>
@@ -29,14 +35,35 @@
           class="mr-1"
           trim>
         </b-form-input>
-        <b-button type="submit" variant="success">Add</b-button>
+        <b-button-group>
+          <b-button type="submit" variant="success">Add</b-button>
+          <b-button variant="outline-danger" aria-label="Close" @click="showAddRole=false">
+            <span aria-hidden="true">&times;</span>
+          </b-button>
+        </b-button-group>
+    </b-form>
+    <b-form inline @submit="addApplication" v-show="showAddApplication">
+        <b-form-input
+          style="width: 60%"
+          v-model="newApplication"
+          :state="addApplicationState"
+          placeholder="Enter App name"
+          class="mr-1"
+          trim>
+        </b-form-input>
+        <b-button-group>
+          <b-button type="submit" variant="success">Add</b-button>
+          <b-button variant="outline-danger" aria-label="Close" @click="showAddApplication=false">
+            <span aria-hidden="true">&times;</span>
+          </b-button>
+        </b-button-group>
     </b-form>
     </b-col>
   </b-row>
 </template>
 <script>
 export default {
-  props: ['user', 'roles'],
+  props: ['user', 'roles', 'applications'],
   methods: {
     savePressed: function(){
       this.$emit('save');
@@ -50,12 +77,25 @@ export default {
         this.newRole = "";
         this.showAddRole = false;
       }
+    },
+    addApplication: function(evt){
+      evt.preventDefault();
+      if(!this.showAddApplication){this.showAddApplication = true;}
+      else{
+        if(this.addApplicationState){this.user.applications.push(this.newApplication)}
+        this.newApplication = "";
+        this.showAddApplication = false;
+      }
     }
   },
   computed: {
     addRoleState(){
       if (!this.roles.includes(this.newRole)){return false}
       return true;
+    },
+    addApplicationState(){
+      if (!this.applications.includes(this.newApplication)){return false}
+      return true;
     }
   },
   watch: {
@@ -69,6 +109,8 @@ export default {
       isModified: false,
       showAddRole: false,
       newRole: "",
+      showAddApplication: false,
+      newApplication: "",
     }
   }
 }
diff --git a/frontend/components/edit-users.vue b/frontend/components/edit-users.vue
index be623a0..ca110b6 100644
--- a/frontend/components/edit-users.vue
+++ b/frontend/components/edit-users.vue
@@ -1,25 +1,29 @@
 <template>
   <div>
     <b-row class="mb-3 mt-3">
-      <b-col cols="3">
+      <b-col cols="2">
         <label>Username</label>
       </b-col>
       <b-col cols="2">
         <label>Password</label>
       </b-col>
-      <b-col cols="3">
+      <b-col cols="2">
         <label>Email</label>
       </b-col>
       <b-col cols="1">
         <label>Roles</label>
       </b-col>
-      <b-col cols="3">
+      <b-col cols="1">
+        <label>Applications</label>
+      </b-col>
+      <b-col cols="4">
       </b-col>
     </b-row>
     <edit-user v-for="(user, index) in users"
                v-model="users[index]"
                v-bind:user="user"
                v-bind:roles="roles"
+               v-bind:applications="applications"
                v-bind:key="user.username"
                v-on:delete="$emit('delete', user.username, index)"
                v-on:save="$emit('save', user.username, index)">
@@ -30,6 +34,6 @@
 import editUser from '~/components/edit-user'
 export default {
   components: { editUser },
-  props: ['users', 'roles']
+  props: ['users', 'roles', 'applications']
 }
 </script>
diff --git a/frontend/pages/users.vue b/frontend/pages/users.vue
index 4245732..8948f45 100644
--- a/frontend/pages/users.vue
+++ b/frontend/pages/users.vue
@@ -12,9 +12,10 @@
         </b-list-group-item>
     </b-list-group>
     </div>
-    <div class="container">
+    <b-container fluid class="pl-4 pr-4">
     <edit-users v-bind:users="selectedUsers"
                 v-bind:roles="roleList"
+                v-bind:applications="applicationList"
                 v-model="selectedUsers"
                 v-on:save="saveUser"
                 v-on:delete="deleteUser">
@@ -46,12 +47,13 @@
     </b-form>
     <edit-user v-bind:user="newUser"
                :roles="roleList"
+               :applications="applicationList"
                v-model="newUser"
                v-on:save="addUser"
                v-show="userFormVisibility"
                v-on:delete="cancelAddUser">
     </edit-user>
-    </div>
+    </b-container>
   </div>
 </template>
 <script>
@@ -86,6 +88,18 @@ export default {
             });
           }
         });
+      user.applications.forEach( app => {
+        var appObj = this.applications.find(element => {return element.name == app});
+        if (!appObj.users.includes(username)){
+          var addAppMutation = 'mutation{addApplicationToUser( application: "' + app + '", username: "' + username +'"){user{username}, application{name}}}'
+          axios.post(
+            '/api/admin/graphql', {
+                query: addAppMutation
+                }).then((res) => {
+                    appObj.users.push(username);
+            });
+          }
+        });
       this.roles.forEach( role => {
         if(role.users.includes(username) && !user.roles.includes(role.name)){
           var rmRoleMutation = 'mutation{removeRoleFromUser( role: "' + role.name + '", username: "' + username +'"){ok}}'
@@ -108,6 +122,7 @@ export default {
           query: 'mutation{deleteUser(username: "' + username + '"){ok}}'
         }).then((res) => {
             this.users.splice(index, 1);
+            this.roles.forEach( role => { role.users.splice(roles.users.findIndex( user => { return user == username }),1) });
           });
     },
     toggleAddUser: function(evt){
@@ -141,7 +156,8 @@ export default {
               username: newUser.username,
               email: newUser.email,
               password: "",
-              roles: []
+              roles: [],
+              applications: [],
             })
             index--;
             this.newUser.username = "";
@@ -157,7 +173,8 @@ export default {
       this.newUser.username = "";
       this.newUser.password = "";
       this.newUser.email = "";
-      this.newUser.roles = []
+      this.newUser.roles = [];
+      this.newUser.applications = [];
       this.toggleAddUser();
     }
   },
@@ -170,7 +187,7 @@ export default {
     }
     return axios.post(
       url, {
-        query: "query{allUsers{edges{node{username, email, roles{edges{node{name}}}}}},allRoles{edges{node{name, description, users{edges{node{username}}}}}}}"
+        query: "query{allUsers{edges{node{username, email, roles{edges{node{name}}}, applications{edges{node{name}}}}}},allRoles{edges{node{name, description, users{edges{node{username}}}}}},allApplications{edges{node{name, users{edges{node{username}}}}}}}"
       }).then((res) => {
         return {users: res.data.data.allUsers.edges.map(user => {
           var rUser = {};
@@ -179,6 +196,9 @@ export default {
           rUser["roles"] = user.node.roles.edges.map(role => {
             return role.node.name;
           });
+          rUser["applications"] = user.node.applications.edges.map(app => {
+            return app.node.name;
+          });
           rUser["password"] = "";
           return rUser;
         }), roles: res.data.data.allRoles.edges.map(role => {
@@ -189,6 +209,13 @@ export default {
             return user.node.username;
           });
           return rRole;
+        }), applications: res.data.data.allApplications.edges.map(app => {
+          var rApp = {};
+          rApp["name"] = app.node.name;
+          rApp["users"] = app.node.users.edges.map(user => {
+            return user.node.username;
+          });
+          return rApp;
         })}
       }).catch((e) => {
         console.log(e);
@@ -212,6 +239,9 @@ export default {
     roleList(){
       return this.roles.map( role => {return role.name})
     },
+    applicationList(){
+      return this.applications.map( app => {return app.name})
+    },
     newUsernameState(){
       if (this.newUser.username.length < 2){return false}
       return !this.users.find(function(user){
-- 
GitLab