diff --git a/vospace-ui-frontend/src/App.vue b/vospace-ui-frontend/src/App.vue
index 566eb288a621bd7838658eed94a85ea37ddc0b6f..cc2e8ecfe566c4f3871d28a8eea9ed4c9d7f98ca 100644
--- a/vospace-ui-frontend/src/App.vue
+++ b/vospace-ui-frontend/src/App.vue
@@ -70,7 +70,7 @@ export default {
   right: 0;
   left: 0;
   background-color: rgba(255, 255, 255, 0.7);
-  z-index: 1000;
+  z-index: 100000;
 }
 
 .spinner-wrapper {
diff --git a/vospace-ui-frontend/src/api/mock/data/sharing.json b/vospace-ui-frontend/src/api/mock/data/sharing.json
new file mode 100644
index 0000000000000000000000000000000000000000..7a000cd100e3a32f8245053570a252adee981a0d
--- /dev/null
+++ b/vospace-ui-frontend/src/api/mock/data/sharing.json
@@ -0,0 +1,4 @@
+{
+  "people": ["mario.rossi", "bianca.verdi"],
+  "groups": ["group1", "group2", "group3"]
+}
diff --git a/vospace-ui-frontend/src/api/mock/index.js b/vospace-ui-frontend/src/api/mock/index.js
index da818a1244c370383e099314882f89336d91deca..dbbddd775e3e1d81b398e8ff0774bf2fbaf1d608 100644
--- a/vospace-ui-frontend/src/api/mock/index.js
+++ b/vospace-ui-frontend/src/api/mock/index.js
@@ -4,6 +4,7 @@ import folder2 from './data/nodes/folder2';
 import job from './data/job';
 import jobs from './data/jobs';
 import user from './data/user';
+import sharing from './data/sharing';
 
 import store from '../../store';
 
@@ -59,6 +60,12 @@ export default {
     return fetch({});
   },
   keepalive() {
+    return fetch({}, false);
+  },
+  getSharingInfo() {
+    return fetch(sharing);
+  },
+  setNodeGroups() {
     return fetch({});
   }
 }
diff --git a/vospace-ui-frontend/src/api/server/index.js b/vospace-ui-frontend/src/api/server/index.js
index 23878170ddaacd4370fc4d8efa7899a2addbeee7..48974f142350ec9cfd3ff11697b0f27b7f072981 100644
--- a/vospace-ui-frontend/src/api/server/index.js
+++ b/vospace-ui-frontend/src/api/server/index.js
@@ -152,5 +152,28 @@ export default {
         'Cache-Control': 'no-cache'
       }
     }, false, false);
+  },
+  getSharingInfo() {
+    let url = BASE_API_URL + 'sharing';
+    return apiRequest({
+      method: 'GET',
+      url: url,
+      withCredentials: true,
+      headers: {
+        'Cache-Control': 'no-cache'
+      }
+    }, true, true);
+  },
+  setNodeGroups(data) {
+    let url = BASE_API_URL + 'sharing';
+    return apiRequest({
+      method: 'POST',
+      url: url,
+      withCredentials: true,
+      headers: {
+        'Cache-Control': 'no-cache'
+      },
+      data
+    }, true, true);
   }
 }
diff --git a/vospace-ui-frontend/src/components/modal/ConfirmDeleteModal.vue b/vospace-ui-frontend/src/components/modal/ConfirmDeleteModal.vue
index 69c448edca0e003b87bdcdcb4ab0e2dfb02a756e..720ff679070abb017f32f7bf9fbcdce870641b1e 100644
--- a/vospace-ui-frontend/src/components/modal/ConfirmDeleteModal.vue
+++ b/vospace-ui-frontend/src/components/modal/ConfirmDeleteModal.vue
@@ -1,5 +1,5 @@
 <template>
-<b-modal id="confirm-delete-modal" title="Confirm delete" okTitle="Yes, delete" @ok="deleteNodes" @hidden="reset" ok-variant="danger">
+<b-modal id="confirm-delete-modal" title="Confirm delete" okTitle="Yes, delete" @ok.prevent="deleteNodes" @hidden="reset" ok-variant="danger">
   <p>Do you really want to delete the following nodes?</p>
   <p>
   <ul>
@@ -19,10 +19,7 @@ export default {
     reset() {
       this.$store.commit('setNodesToDelete', []);
     },
-    deleteNodes(event) {
-      // Prevent modal from closing
-      event.preventDefault();
-
+    deleteNodes() {
       this.$store.dispatch('deleteNodes')
         .then(() => {
           this.$bvModal.hide('confirm-delete-modal');
diff --git a/vospace-ui-frontend/src/components/modal/CreateFolderModal.vue b/vospace-ui-frontend/src/components/modal/CreateFolderModal.vue
index d671009b8210fe5ee68e78aa6e3ea967a3e08cc7..c68e8b5f63fe41c7a2c01eb3684e3e99cc9bec93 100644
--- a/vospace-ui-frontend/src/components/modal/CreateFolderModal.vue
+++ b/vospace-ui-frontend/src/components/modal/CreateFolderModal.vue
@@ -1,5 +1,5 @@
 <template>
-<b-modal id="create-folder-modal" title="Create folder" okTitle="Create" @show="reset" @shown="afterShow" @ok="createFolder">
+<b-modal id="create-folder-modal" title="Create folder" okTitle="Create" @show="reset" @shown="afterShow" @ok.prevent="createFolder">
   <b-form inline>
     <label class="w-25" for="new-folder-name-input">Folder name</label>
     <b-form-input v-model.trim="newFolderName" id="new-folder-name-input" ref="newFolderNameInput" class="w-75" aria-describedby="new-folder-name-input-feedback" :state="newFolderNameState" v-on:input="resetError"
@@ -37,10 +37,7 @@ export default {
     resetError() {
       this.newFolderNameError = null;
     },
-    createFolder(event) {
-      // Prevent modal from closing
-      event.preventDefault();
-
+    createFolder() {
       if (!this.newFolderName) {
         this.newFolderNameError = "Folder name is required";
       } else if (/[<>?":\\/`|'*]/.test(this.newFolderName)) {
diff --git a/vospace-ui-frontend/src/components/modal/ShareInputGroup.vue b/vospace-ui-frontend/src/components/modal/ShareInputGroup.vue
new file mode 100644
index 0000000000000000000000000000000000000000..b721bdbe04c2687ad1cf83db53d88ea271a95208
--- /dev/null
+++ b/vospace-ui-frontend/src/components/modal/ShareInputGroup.vue
@@ -0,0 +1,71 @@
+<template>
+<div>
+  <div class="row">
+    <div class="col-2">
+      <label :for="id + '-input'" class="mt-2 float-right"><strong>{{label}}</strong></label>
+    </div>
+    <div class="col">
+      <b-input-group>
+        <b-form-input :list="id + '-list'" :id="id + '-input'" :placeholder="placeholder" v-model="inputValue" @input="resetError()" @keydown.native.enter="addItem()"></b-form-input>
+        <datalist :id="id + '-list'">
+          <option v-for="option in options" v-bind:key="option">{{option}}</option>
+        </datalist>
+        <b-input-group-append>
+          <b-button variant="success" @click="addItem()">{{buttonText}}</b-button>
+        </b-input-group-append>
+      </b-input-group>
+      <span class="text-danger" v-if="inputError">{{inputError}}</span>
+    </div>
+  </div>
+  <div class="row mb-3 mt-1">
+    <div class="col offset-2">
+      <b-badge variant="primary" v-for="value in values" size="lg" v-bind:key="value" class="mr-1">
+        {{value}}
+        <span class="pointer" @click="removeItem(value)">&times;</span>
+      </b-badge>
+    </div>
+  </div>
+</div>
+</template>
+
+<script>
+export default {
+  props: {
+    id: String,
+    values: Array,
+    options: Array,
+    label: String,
+    placeholder: String,
+    buttonText: String,
+  },
+  data() {
+    return {
+      inputValue: null,
+      inputError: null,
+    }
+  },
+  methods: {
+    addItem() {
+      if (this.options.indexOf(this.inputValue) === -1) {
+        this.inputError = "Please select one of the available values from the list";
+        return;
+      }
+      const index = this.values.indexOf(this.inputValue);
+      if (index === -1) {
+        this.values.push(this.inputValue);
+      }
+      this.inputError = null;
+      this.inputValue = null;
+    },
+    resetError() {
+      this.inputError = null;
+    },
+    removeItem(value) {
+      const index = this.values.indexOf(value);
+      if (index > -1) {
+        this.values.splice(index, 1);
+      }
+    }
+  }
+}
+</script>
diff --git a/vospace-ui-frontend/src/components/modal/ShareModal.vue b/vospace-ui-frontend/src/components/modal/ShareModal.vue
index ae9c9dff8f9cae057c27ad6f51d3b213ca7a3849..c07803d8c47865f7f112f9c77bdd5dab94cb11ea 100644
--- a/vospace-ui-frontend/src/components/modal/ShareModal.vue
+++ b/vospace-ui-frontend/src/components/modal/ShareModal.vue
@@ -1,82 +1,51 @@
 <template>
-<b-modal id="share-modal" :title="'Share ' + node.path" okTitle="Share" @show="reset" @ok="share" size="lg">
+<b-modal id="share-modal" :title="'Share ' + node.path" okTitle="Save" @show="onShow" @ok.prevent="share" size="lg">
   <h5>Read permissions</h5>
-  <div class="row">
-    <div class="col-2">
-      <label for="user-read-input" class="mt-2 float-right"><strong>Users</strong></label>
-    </div>
-    <div class="col">
-      <b-input-group>
-        <b-form-input list="user-read-list" id="user-read-input" placeholder="Search user..."></b-form-input>
-        <datalist id="user-read-list">
-          <option v-for="user in selectableUserRead" v-bind:key="user.id">{{user.label}}</option>
-        </datalist>
-        <b-input-group-append>
-          <b-button variant="success">Add user</b-button>
-        </b-input-group-append>
-      </b-input-group>
-    </div>
-  </div>
-  <div class="row">
-    <div class="col offset-2">
-      <b-badge variant="light" v-for="user in userRead" v-bind:key="user">{{user}}</b-badge>
-    </div>
-  </div>
-  <div class="row">
-    <div class="col-2">
-      <label for="group-read-input" class="mt-2 float-right"><strong>Groups</strong></label>
-    </div>
-    <div class="col">
-      <b-input-group>
-        <b-form-input list="group-read-list" id="group-read-input" placeholder="Search group..."></b-form-input>
-        <datalist id="group-read-list">
-          <option v-for="group in selectableGroupRead" v-bind:key="group">{{group}}</option>
-        </datalist>
-        <b-input-group-append>
-          <b-button variant="success">Add group</b-button>
-        </b-input-group-append>
-      </b-input-group>
-    </div>
-  </div>
-  <div class="row">
-    <div class="col offset-2">
-      <b-badge variant="primary" v-for="group in groupRead" size="lg" v-bind:key="group">
-        {{group}}
-        <span class="pointer" @click="removeItem(groupRead, group)">&times;</span>
-      </b-badge>
-    </div>
-  </div>
+  <ShareInputGroup id="user-read" :values="userRead" :options="people" label="Users" placeholder="Search user..." buttonText="Add user" />
+  <ShareInputGroup id="group-read" :values="groupRead" :options="groups" label="Groups" placeholder="Search group..." buttonText="Add group" />
   <h5 class="mt-3">Write permissions</h5>
-  <b-form inline>
-  </b-form>
+  <ShareInputGroup id="user-write" :values="userWrite" :options="people" label="Users" placeholder="Search user..." buttonText="Add user" />
+  <ShareInputGroup id="group-write" :values="groupWrite" :options="groups" label="Groups" placeholder="Search group..." buttonText="Add group" />
 </b-modal>
 </template>
 
 <script>
+import ShareInputGroup from './ShareInputGroup';
+import client from 'api-client';
+
+function setArray(array, newValues) {
+  array.splice(0, array.length);
+  for (let value of newValues) {
+    array.push(value);
+  }
+}
+
 export default {
+  components: {
+    ShareInputGroup
+  },
   computed: {
     node() { return this.$store.state.nodeToShare; }
   },
   data() {
     return {
-      userReadInput: null,
-      groupReadInput: null,
-      selectableUserRead: [],
-      selectableGroupRead: [],
       groupRead: [],
       userRead: [],
-      userWriteInput: null,
-      groupWriteInput: null,
-      selectableUserWrite: [],
-      selectableGroupWrite: [],
       groupWrite: [],
-      userWrite: []
+      userWrite: [],
+      people: [],
+      groups: []
     }
   },
   methods: {
-    reset() {
+    onShow() {
       this.setGroups(this.userRead, this.groupRead, this.node.groupRead);
       this.setGroups(this.userWrite, this.groupWrite, this.node.groupWrite);
+      client.getSharingInfo()
+        .then(res => {
+          setArray(this.people, res.people);
+          setArray(this.groups, res.groups);
+        });
     },
     setGroups(userArr, groupArr, nodeArr) {
       userArr.splice(0, userArr.length);
@@ -84,25 +53,23 @@ export default {
       for (let group of nodeArr.split(' ')) {
         if (group.startsWith('people.')) {
           userArr.push(group.substring('people.'.length).replaceAll('\\\\', '\\'));
-        } else {
+        } else if (group.trim() !== '') {
           groupArr.push(group.replaceAll('\\\\', '\\'));
         }
       }
     },
-    addItem(arr, value) {
-      const index = arr.indexOf(value);
-      if (index === -1) {
-        arr.push(value);
-      }
-    },
-    removeItem(arr, value) {
-      const index = arr.indexOf(value);
-      if (index > -1) {
-        arr.splice(index, 1);
-      }
-    },
     share() {
-      // TODO
+      client.setNodeGroups({
+        path: this.$store.state.nodeToShare.path,
+        groupRead: this.groupRead,
+        groupWrite: this.groupWrite,
+        userRead: this.userRead,
+        userWrite: this.userWrite
+      }).then(() => {
+        // Reload current path
+        this.$bvModal.hide('share-modal');
+        this.$store.dispatch('setPath', this.$store.state.path);
+      });
     }
   }
 }
diff --git a/vospace-ui-frontend/src/components/modal/UploadFilesModal.vue b/vospace-ui-frontend/src/components/modal/UploadFilesModal.vue
index 849c38b33367e93c68eb73080fd1fb7e41ea696e..4f3e39efde5a5c0bb93abcf53cd9130d3afc745f 100644
--- a/vospace-ui-frontend/src/components/modal/UploadFilesModal.vue
+++ b/vospace-ui-frontend/src/components/modal/UploadFilesModal.vue
@@ -1,5 +1,5 @@
 <template>
-<b-modal id="upload-files-modal" title="Upload file" okTitle="Upload" @show="reset" @ok="uploadFiles">
+<b-modal id="upload-files-modal" title="Upload file" okTitle="Upload" @show="reset" @ok.prevent="uploadFiles">
   <b-form-file v-model="files" :multiple="true" :state="fileState" placeholder="Choose your files or drop them here..." drop-placeholder="Drop files here..." @change="resetError"></b-form-file>
   <b-form-invalid-feedback id="upload-file-input-feedback" class="text-right">{{uploadFileError}}</b-form-invalid-feedback>
   <div class="mt-3">Selected files: {{ selectedFiles }}</div>
@@ -39,10 +39,7 @@ export default {
     resetError() {
       this.uploadFileError = null;
     },
-    uploadFiles(event) {
-      // Prevent modal from closing
-      event.preventDefault();
-
+    uploadFiles() {
       if (this.files.length === 0) {
         this.uploadFileError = "Select at least one file";
       } else {