diff --git a/src/api.js b/src/api.js
index 202c9126d139d73df6b2883e331ba95edecdf342..27d7d0072323ed8a98c0858f03775a532548172a 100644
--- a/src/api.js
+++ b/src/api.js
@@ -1,5 +1,8 @@
-const serverurl = 'http://localhost:8181/'
+const serverurl = 'http://localhost:8181/api/'
+// const serverurl = '/api/'
+// const serverurl = 'https://mozen.gltronic.ovh/api/'
 export const api = {
+  // PUBLIC
   async search (name, tags, param, sort, size, page) {
     var url = serverurl + 'search'
     const params = new URLSearchParams()
@@ -31,30 +34,28 @@ export const api = {
       return null
     }
   },
-  async getUser () {
-    const token = await localStorage.getItem('token')
-    const url = serverurl + 'users'
+  async getModel (id) {
+    const url = serverurl + 'models' + '?id=' + id
+    const response = await fetch(url)
     try {
-      const response = await fetch(url, { headers: { Authorization: 'Bearer ' + token } })
       return await response.json()
     } catch (error) {
       return null
     }
   },
-  async addNewCategory (name) {
-    const url = serverurl + 'tags/category'
-    const token = await localStorage.getItem('token')
+  async login (username, password) {
+    const url = serverurl + 'users/login'
     try {
       const response = await fetch(
         url, {
           method: 'POST',
           headers: {
             Accept: 'application/json',
-            'Content-Type': 'application/json',
-            Authorization: 'Bearer ' + token
+            'Content-Type': 'application/json'
           },
           body: JSON.stringify({
-            name: name
+            username: username,
+            password: password
           })
         }
       )
@@ -63,21 +64,20 @@ export const api = {
       return null
     }
   },
-  async addNewTag (tag, categoryId) {
-    const url = serverurl + 'tags'
-    const token = await localStorage.getItem('token')
+  async register (username, email, password) {
+    const url = serverurl + 'users/signup'
     try {
       const response = await fetch(
         url, {
           method: 'POST',
           headers: {
             Accept: 'application/json',
-            'Content-Type': 'application/json',
-            Authorization: 'Bearer ' + token
+            'Content-Type': 'application/json'
           },
           body: JSON.stringify({
-            name: tag,
-            categoryId: categoryId
+            email: email,
+            username: username,
+            password: password
           })
         }
       )
@@ -86,9 +86,40 @@ export const api = {
       return null
     }
   },
-  async getUserList () {
+  async getModelComments (id) {
+    const url = serverurl + 'comments' + '?id=' + id
+    const response = await fetch(url)
+    try {
+      return await response.json()
+    } catch (error) {
+      return null
+    }
+  },
+  async download (id, type, name) {
+    // c'est un peu hacky
+    // on créé un 'a' invisble avec un attribut 'download'
+    // le problème, c'est de créé un attribut dynamique
+    console.log('Download ' + id + ' | ' + name + ' | ' + type)
+    const url = serverurl + type + '/download?id=' + id
+
+    fetch(url)
+      .then(response => response.blob())
+      .then(blob => {
+        const url = window.URL.createObjectURL(blob)
+        const a = document.createElement('a')
+        a.style.display = 'none'
+        a.href = url
+        a.download = name
+        document.body.appendChild(a)
+        a.click()
+        window.URL.revokeObjectURL(url)
+      })
+      .catch(() => this.$buefy.toast.open('Download error'))
+  },
+  // USER
+  async getUser () {
     const token = await localStorage.getItem('token')
-    const url = serverurl + 'users/list'
+    const url = serverurl + 'users'
     try {
       const response = await fetch(url, { headers: { Authorization: 'Bearer ' + token } })
       return await response.json()
@@ -96,13 +127,26 @@ export const api = {
       return null
     }
   },
-  async getModelList () {
+  async putUser (account) {
     const token = await localStorage.getItem('token')
-    const url = serverurl + 'models/list'
+    const url = serverurl + 'users'
     try {
-      const response = await fetch(url, { headers: { Authorization: 'Bearer ' + token } })
+      const response = await fetch(url, {
+        method: 'PUT',
+        headers: {
+          Authorization: 'Bearer ' + token,
+          'Content-Type': 'application/json'
+        },
+        body: JSON.stringify({
+          email: account.email,
+          username: account.username,
+          password: account.password,
+          id: account.id
+        })
+      })
       return await response.json()
     } catch (error) {
+      console.log(error)
       return null
     }
   },
@@ -126,78 +170,138 @@ export const api = {
       return null
     }
   },
-  async getModel (id) {
-    const url = serverurl + 'models' + '?id=' + id
-    const response = await fetch(url)
+  async addNewTag (tag, categoryId) {
+    const url = serverurl + 'tags'
+    const token = await localStorage.getItem('token')
     try {
+      const response = await fetch(
+        url, {
+          method: 'POST',
+          headers: {
+            Accept: 'application/json',
+            'Content-Type': 'application/json',
+            Authorization: 'Bearer ' + token
+          },
+          body: JSON.stringify({
+            name: tag,
+            categoryId: categoryId
+          })
+        }
+      )
       return await response.json()
     } catch (error) {
       return null
     }
   },
-  async removeModel (id) {
+  async postModel (model) {
+    const url = serverurl + 'models'
     const token = await localStorage.getItem('token')
-    const url = serverurl + 'models' + '?id=' + id
     try {
-      await fetch(url, {
-        method: 'DELETE',
+      const response = await fetch(url, {
+        method: 'POST',
         headers: {
+          Accept: 'application/json',
+          'Content-Type': 'application/json',
           Authorization: 'Bearer ' + token
-        }
+        },
+        body: JSON.stringify({
+          name: model.name,
+          shortDescription: model.shortDescription,
+          longDescription: model.longDescription,
+          performance: model.performance,
+          performanceUnit: model.performanceUnit,
+          parameterCount: model.parameterCount,
+          tags: model.tags,
+          performanceLowerIsBetter: model.performanceLowerIsBetter
+        })
       })
-      return true
+      return await response.json()
     } catch (error) {
-      return false
+      return null
     }
   },
-  async removeTag (id) {
+  async putModel (id, model) {
+    const url = serverurl + 'models' + '?id=' + id
     const token = await localStorage.getItem('token')
-    const url = serverurl + 'tags' + '?id=' + id
-    try {
-      await fetch(url, {
-        method: 'DELETE',
-        headers: {
-          Authorization: 'Bearer ' + token
-        }
+    const response = await fetch(url, {
+      method: 'PUT',
+      headers: {
+        Accept: 'application/json',
+        'Content-Type': 'application/json',
+        Authorization: 'Bearer ' + token
+      },
+      body: JSON.stringify({
+        name: model.name,
+        shortDescription: model.shortDescription,
+        longDescription: model.longDescription,
+        performance: model.performance,
+        performanceUnit: model.performanceUnit,
+        parameterCount: model.parameterCount,
+        tags: model.tags,
+        performanceLowerIsBetter: model.performanceLowerIsBetter
       })
-      return true
+    })
+    try {
+      return await response.json()
     } catch (error) {
-      return false
+      return null
     }
   },
-  async removeCategory (id) {
+  async uploadModelFile (id, file) {
+    const data = new FormData()
+    const url = serverurl + 'models/upload'
     const token = await localStorage.getItem('token')
-    const url = serverurl + 'tags/category' + '?id=' + id
+
+    data.append('file', file)
+    data.append('id', id)
+
     try {
-      await fetch(url, {
-        method: 'DELETE',
+      const response = await fetch(url, {
+        method: 'POST',
         headers: {
           Authorization: 'Bearer ' + token
-        }
+        },
+        body: data
       })
+      if (response.status !== 200) return false
       return true
     } catch (error) {
       return false
     }
   },
-  async removeComment (id) {
+  async uploadLayers (id, customLayers) {
     const token = await localStorage.getItem('token')
-    const url = serverurl + 'comments' + '?id=' + id
-    try {
-      await fetch(url, {
-        method: 'DELETE',
-        headers: {
-          Authorization: 'Bearer ' + token
-        }
-      })
-      return true
-    } catch (error) {
-      return false
+    for (var i = 0; i < customLayers.length; i++) {
+      const layer = customLayers[i]
+      const data = new FormData()
+      const url = serverurl + 'layers/upload'
+
+      console.log('Uploading layer ' + i + ' | ' + layer.file + ' to ' + id)
+      if (layer.file === undefined) continue
+      if (layer.name === undefined) continue
+
+      data.append('file', layer.file)
+      data.append('name', layer.name)
+      data.append('id', id)
+
+      try {
+        const response = await fetch(url, {
+          method: 'POST',
+          headers: {
+            Authorization: 'Bearer ' + token
+          },
+          body: data
+        })
+        if (response.status !== 200) return false
+      } catch (error) {
+        return false
+      }
     }
+    return true
   },
-  async removeUser (id) {
+  async removeModel (id) {
     const token = await localStorage.getItem('token')
-    const url = serverurl + 'users' + '?id=' + id
+    const url = serverurl + 'models' + '?id=' + id
     try {
       await fetch(url, {
         method: 'DELETE',
@@ -210,62 +314,40 @@ export const api = {
       return false
     }
   },
-  async login (username, password) {
-    const url = serverurl + 'login'
-    try {
-      const response = await fetch(
-        url, {
-          method: 'POST',
-          headers: {
-            Accept: 'application/json',
-            'Content-Type': 'application/json'
-          },
-          body: JSON.stringify({
-            username: username,
-            password: password
-          })
-        }
-      )
-      return await response.json()
-    } catch (error) {
-      return null
-    }
-  },
-  async register (username, email, password) {
-    const url = serverurl + 'users/signup'
+  async getVoteStatus (id) {
+    const url = serverurl + 'vote' + '?id=' + id
+    const token = await localStorage.getItem('token')
+    const response = await fetch(url, {
+      headers: {
+        Authorization: 'Bearer ' + token
+      }
+    })
     try {
-      const response = await fetch(
-        url, {
-          method: 'POST',
-          headers: {
-            Accept: 'application/json',
-            'Content-Type': 'application/json'
-          },
-          body: JSON.stringify({
-            email: email,
-            username: username,
-            password: password
-          })
-        }
-      )
       return await response.json()
     } catch (error) {
       return null
     }
   },
-  async getModelComments (id) {
-    const url = serverurl + 'comments' + '?id=' + id
-    const response = await fetch(url)
+  async addVote (id, isDown) {
+    const url = serverurl + 'vote' + '?id=' + id + '&isDown=' + isDown
+    const token = await localStorage.getItem('token')
+    const response = await fetch(url, {
+      method: 'PUT',
+      headers: {
+        Authorization: 'Bearer ' + token
+      }
+    })
     try {
       return await response.json()
     } catch (error) {
       return null
     }
   },
-  async getCommentList (id) {
+  async removeVote (id, isDown) {
+    const url = serverurl + 'vote' + '?id=' + id + '&isDown=' + isDown
     const token = await localStorage.getItem('token')
-    const url = serverurl + 'comments/list'
     const response = await fetch(url, {
+      method: 'DELETE',
       headers: {
         Authorization: 'Bearer ' + token
       }
@@ -299,113 +381,112 @@ export const api = {
       return null
     }
   },
-  async setVerified (id) {
-    const url = serverurl + 'models/setVerified' + '?id=' + id
+  async removeComment (id) {
     const token = await localStorage.getItem('token')
-    const response = await fetch(url, {
-      headers: {
-        Authorization: 'Bearer ' + token
-      }
-    })
+    const url = serverurl + 'comments' + '?id=' + id
     try {
+      await fetch(url, {
+        method: 'DELETE',
+        headers: {
+          Authorization: 'Bearer ' + token
+        }
+      })
+      return true
+    } catch (error) {
+      return false
+    }
+  },
+  // ADMIN
+  async addNewCategory (name) {
+    const url = serverurl + 'tags/category'
+    const token = await localStorage.getItem('token')
+    try {
+      const response = await fetch(
+        url, {
+          method: 'POST',
+          headers: {
+            Accept: 'application/json',
+            'Content-Type': 'application/json',
+            Authorization: 'Bearer ' + token
+          },
+          body: JSON.stringify({
+            name: name
+          })
+        }
+      )
       return await response.json()
     } catch (error) {
       return null
     }
   },
-  async postModel (model) {
-    const url = serverurl + 'models'
+  async getUserList () {
     const token = await localStorage.getItem('token')
+    const url = serverurl + 'users/list'
     try {
-      const response = await fetch(url, {
-        method: 'POST',
-        headers: {
-          Accept: 'application/json',
-          'Content-Type': 'application/json',
-          Authorization: 'Bearer ' + token
-        },
-        body: JSON.stringify({
-          name: model.name,
-          shortDescription: model.shortDescription,
-          longDescription: model.longDescription,
-          performance: model.performance,
-          performanceUnit: model.performanceUnit,
-          parameterCount: model.parameterCount,
-          tags: model.tags,
-          performanceLowerIsBetter: model.performanceLowerIsBetter
-        })
-      })
+      const response = await fetch(url, { headers: { Authorization: 'Bearer ' + token } })
       return await response.json()
     } catch (error) {
       return null
     }
   },
-  async putModel (id, model) {
-    const url = serverurl + 'models' + '?id=' + id
+  async getModelList () {
     const token = await localStorage.getItem('token')
-    const response = await fetch(url, {
-      method: 'PUT',
-      headers: {
-        Accept: 'application/json',
-        'Content-Type': 'application/json',
-        Authorization: 'Bearer ' + token
-      },
-      body: JSON.stringify({
-        name: model.name,
-        shortDescription: model.shortDescription,
-        longDescription: model.longDescription,
-        performance: model.performance,
-        performanceUnit: model.performanceUnit,
-        parameterCount: model.parameterCount,
-        tags: model.tags,
-        performanceLowerIsBetter: model.performanceLowerIsBetter
-      })
-    })
+    const url = serverurl + 'models/list'
     try {
+      const response = await fetch(url, { headers: { Authorization: 'Bearer ' + token } })
       return await response.json()
     } catch (error) {
       return null
     }
   },
-  async uploadModelFile (id, file) {
-    const data = new FormData()
-    const url = serverurl + 'models/upload'
+  async removeTag (id) {
     const token = await localStorage.getItem('token')
-
-    data.append('file', file)
-    data.append('id', id)
-
+    const url = serverurl + 'tags' + '?id=' + id
     try {
-      const response = await fetch(url, {
-        method: 'POST',
+      await fetch(url, {
+        method: 'DELETE',
         headers: {
           Authorization: 'Bearer ' + token
-        },
-        body: data
+        }
       })
-      if (response.status !== 200) return false
       return true
     } catch (error) {
       return false
     }
   },
-  async setAdmin (id) {
-    const url = serverurl + 'users/setAdmin' + '?id=' + id
+  async removeCategory (id) {
     const token = await localStorage.getItem('token')
-    const response = await fetch(url, {
-      headers: {
-        Authorization: 'Bearer ' + token
-      }
-    })
+    const url = serverurl + 'tags/category' + '?id=' + id
     try {
-      return await response.json()
+      await fetch(url, {
+        method: 'DELETE',
+        headers: {
+          Authorization: 'Bearer ' + token
+        }
+      })
+      return true
     } catch (error) {
-      return null
+      return false
     }
   },
-  async getVoteStatus (id) {
-    const url = serverurl + 'vote' + '?id=' + id
+  async removeUser (id) {
     const token = await localStorage.getItem('token')
+    const url = serverurl + 'users' + '?id=' + id
+    try {
+      await fetch(url, {
+        method: 'DELETE',
+        headers: {
+          Authorization: 'Bearer ' + token
+        }
+      })
+      return true
+    } catch (error) {
+      return false
+    }
+  },
+  async getCommentList (id) {
+    const token = await localStorage.getItem('token')
+    const url = serverurl + 'comments/list'
     const response = await fetch(url, {
       headers: {
         Authorization: 'Bearer ' + token
@@ -417,11 +498,10 @@ export const api = {
       return null
     }
   },
-  async addVote (id, isDown) {
-    const url = serverurl + 'vote' + '?id=' + id + '&isDown=' + isDown
+  async setVerified (id) {
+    const url = serverurl + 'models/setVerified' + '?id=' + id
     const token = await localStorage.getItem('token')
     const response = await fetch(url, {
-      method: 'PUT',
       headers: {
         Authorization: 'Bearer ' + token
       }
@@ -432,11 +512,10 @@ export const api = {
       return null
     }
   },
-  async removeVote (id, isDown) {
-    const url = serverurl + 'vote' + '?id=' + id + '&isDown=' + isDown
+  async setAdmin (id) {
+    const url = serverurl + 'users/setAdmin' + '?id=' + id
     const token = await localStorage.getItem('token')
     const response = await fetch(url, {
-      method: 'DELETE',
       headers: {
         Authorization: 'Bearer ' + token
       }
@@ -446,31 +525,5 @@ export const api = {
     } catch (error) {
       return null
     }
-  },
-  async download (id, type, name) {
-    // c'est un peu hacky
-    // on créé un 'a' invisble avec un attribut 'download'
-    // le problème, c'est de créé un attribut dynamique
-    console.log('Download ' + id + ' | ' + name + ' | ' + type)
-    const url = serverurl + type + '/download?id=' + id
-    const token = await localStorage.getItem('token')
-
-    fetch(url, {
-      headers: {
-        Authorization: 'Bearer ' + token
-      }
-    })
-      .then(response => response.blob())
-      .then(blob => {
-        const url = window.URL.createObjectURL(blob)
-        const a = document.createElement('a')
-        a.style.display = 'none'
-        a.href = url
-        a.download = name
-        document.body.appendChild(a)
-        a.click()
-        window.URL.revokeObjectURL(url)
-      })
-      .catch(() => this.$buefy.toast.open('Download error'))
   }
 }
diff --git a/src/components/Filters.vue b/src/components/Filters.vue
index dd404d4a9207ff8f4a0a7feec4fc3f5d5c6a0f9c..82ed1eecb425d3b521392f792f321625dbbd11e5 100644
--- a/src/components/Filters.vue
+++ b/src/components/Filters.vue
@@ -1,9 +1,11 @@
 <template>
   <b-menu>
     <div>
+      <!--
       <b-menu-list label="Verified">
         <b-checkbox v-model="verifiedOnly" @input="changeTag">Verified models only</b-checkbox>
       </b-menu-list>
+      -->
       <b-menu-list v-for="category in tags" v-bind:key="category.name" :label="category.name">
         <b-field v-for="tag in category.tags" v-bind:key="tag.name">
           <b-checkbox
diff --git a/src/components/LoginForm.vue b/src/components/LoginForm.vue
index 8cafe669c326b7c29ff0eb0b8ee65f21a2f72da1..ff3744e79caccd2aad994a139caabd41c1af83d1 100644
--- a/src/components/LoginForm.vue
+++ b/src/components/LoginForm.vue
@@ -15,7 +15,7 @@
           <b-input type="password" v-model="password" password-reveal placeholder="password" required/>
         </b-field>
 
-        <b-button class="is-text is-small">forgot password ?</b-button >
+        <b-button class="is-text is-small" disabled>forgot password ?</b-button >
 
       </section>
       <footer class="modal-card-foot">
@@ -41,14 +41,14 @@ export default {
     async onLogin () {
       var response = await api.login(this.username, this.password)
       console.log('LOGIN RESPONSE ' + response)
-      if (response !== null) {
+      if (response.error) {
+        this.errorMessage = 'Username or password incorect'
+      } else {
         console.log('LOGIN TOKEN OK')
         await localStorage.setItem('token', response.message)
         this.$parent.close()
         this.$router.push({ name: 'Account' })
         this.$router.go()
-      } else {
-        this.errorMessage = 'Username or password incorect'
       }
     }
   }
diff --git a/src/components/ModelUpdate.vue b/src/components/ModelUpdate.vue
index b860f3a8339eb51259403617196ceea0df73fdf3..3b3658bcc46765aca4f67daaf1404ee87d77ecbe 100644
--- a/src/components/ModelUpdate.vue
+++ b/src/components/ModelUpdate.vue
@@ -105,7 +105,7 @@ export default {
         console.log('Upload layers ' + this.model.customLayers)
         this.setProgress(2)
         this.subProgress = true
-        if (!await this.uploadLayers(this.model.id)) {
+        if (!await api.uploadLayers(this.model.id, this.model.customLayers)) {
           this.subProgress = false
           this.setError('Custom layer upload error')
           return
@@ -114,38 +114,6 @@ export default {
       }
 
       this.setProgress(3)
-    },
-    async uploadLayers (id) {
-      const token = await localStorage.getItem('token')
-      for (var i = 0; i < this.model.customLayers.length; i++) {
-        const layer = this.model.customLayers[i]
-        const data = new FormData()
-        const url = this.$serverurl + 'layers/upload'
-
-        this.subMessage = 'Uploading ' + layer.name
-
-        console.log('Uploading layer ' + i + ' | ' + layer.file + ' to ' + id)
-        if (layer.file === undefined) continue
-        if (layer.name === undefined) continue
-
-        data.append('file', layer.file)
-        data.append('name', layer.name)
-        data.append('id', id)
-
-        try {
-          const response = await fetch(url, {
-            method: 'POST',
-            headers: {
-              Authorization: 'Bearer ' + token
-            },
-            body: data
-          })
-          if (response.status !== 200) return false
-        } catch (error) {
-          return false
-        }
-      }
-      return true
     }
   }
 }
diff --git a/src/components/ModelUpload.vue b/src/components/ModelUpload.vue
index bf595b62b4b4d9b4e7ee64d55d6dadd90797fbdc..816722e13591a71cd4e763af9830106ad593d124 100644
--- a/src/components/ModelUpload.vue
+++ b/src/components/ModelUpload.vue
@@ -107,7 +107,7 @@ export default {
         console.log('Upload layers ' + this.model.customLayers)
         this.setProgress(2)
         this.subProgress = true
-        if (!await this.uploadLayers()) {
+        if (!await api.uploadLayers(this.model.id, this.model.customLayers)) {
           this.subProgress = false
           this.setError('Custom layer upload error')
           return
@@ -116,38 +116,6 @@ export default {
       }
 
       this.setProgress(3)
-    },
-    async uploadLayers () {
-      const token = await localStorage.getItem('token')
-      for (var i = 0; i < this.model.customLayers.length; i++) {
-        const layer = this.model.customLayers[i]
-        const data = new FormData()
-        const url = this.$serverurl + 'layers/upload'
-
-        this.subMessage = 'Uploading ' + layer.name
-
-        console.log('Uploading layer ' + i + ' | ' + layer.file + ' to ' + this.modelId)
-        if (layer.file === undefined) continue
-        if (layer.name === undefined) continue
-
-        data.append('file', layer.file)
-        data.append('name', layer.name)
-        data.append('id', this.modelId)
-
-        try {
-          const response = await fetch(url, {
-            method: 'POST',
-            headers: {
-              Authorization: 'Bearer ' + token
-            },
-            body: data
-          })
-          if (response.status !== 200) return false
-        } catch (error) {
-          return false
-        }
-      }
-      return true
     }
   }
 }
diff --git a/src/components/RegisterForm.vue b/src/components/RegisterForm.vue
index 69896193d4392e6158380fa0ced4641765276aa5..31d6da8fb4b5aa226f1c12f877239a45aeb62dca 100644
--- a/src/components/RegisterForm.vue
+++ b/src/components/RegisterForm.vue
@@ -52,7 +52,8 @@ export default {
       }
       const response = await api.register(this.username, this.email, this.password)
       if (response.error) {
-        this.errorMessage = response.message
+        this.errorMessage = 'Invalid email or username'
+        // this.errorMessage = response.message
       } else {
         await localStorage.setItem('token', response.message)
         this.$parent.close()
diff --git a/src/main.js b/src/main.js
index 33ad0b8f8fd649d8c90e9d0e1438fcb487d51707..3127687e5990b9e257aac3ef715cf1232572197a 100644
--- a/src/main.js
+++ b/src/main.js
@@ -8,9 +8,6 @@ import './assets/style.scss'
 Vue.use(Buefy)
 Vue.config.productionTip = false
 
-// Vue.prototype.$serverurl = process.env.VUE_APP_SERVER_URL
-Vue.prototype.$serverurl = 'http://localhost:8181/'
-
 new Vue({
   router,
   render: h => h(App)
diff --git a/src/router/index.js b/src/router/index.js
index 25e57a8fef78b0c158ab7043d2973d089be7c588..a3a87af398712c56cd030cc9f8a8e9c14f7acc3b 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -28,7 +28,11 @@ const routes = [
   {
     path: '/useredit',
     name: 'UserEdit',
-    component: () => import('../views/UserEdit.vue')
+    component: () => import('../views/UserEdit.vue'),
+    props: true,
+    meta: {
+      requiresAuth: true
+    }
   },
   {
     path: '/model',
diff --git a/src/views/Account.vue b/src/views/Account.vue
index a5e6e57b9b7db5dc54a3ed1dcc662b153782b234..a94264c94d91696b979945e2166b415ff2c96c3b 100644
--- a/src/views/Account.vue
+++ b/src/views/Account.vue
@@ -15,7 +15,7 @@
          icon-left="pencil"
          type="is-info"
          tag="router-link"
-         :to="{ name: 'UserEdit' }"
+         :to="{ name: 'UserEdit', params: {user: account} }"
         >
         Change account details
         </b-button>
diff --git a/src/views/Admin.vue b/src/views/Admin.vue
index 89a20eaf75313b4faa622bc708016b03cccfe9bd..d93ff73169e8b53aa9482e174089488e77f4fd7b 100644
--- a/src/views/Admin.vue
+++ b/src/views/Admin.vue
@@ -1,5 +1,5 @@
 <template>
-  <div class="adminDiv container">
+  <div class="admin container">
     <div class="box">
       <h1 class="title">Admin panel</h1>
       <b-tabs>
@@ -84,6 +84,7 @@
 
               <b-table-column label="" centered>
                 <b-button class="actionButton" icon-left="cctv" type="is-success" @click="setAdminPrompt(props.row.id, props.row.username)" outlined/>
+                <b-button class="actionButton" icon-left="pencil" type="is-warning" tag="router-link" :to="{ name: 'UserEdit', params: { user: props.row } }" outlined/>
                 <b-button class="actionButton" icon-left="delete" type="is-danger" @click="removePrompt(props.row.id, props.row.username, 'user')" outlined/>
               </b-table-column>
             </template>
@@ -220,6 +221,9 @@ export default {
 </script>
 
 <style scoped>
+.admin{
+  margin-top: 20px;
+}
 .actionButton {
   margin-left:8px;
 }
diff --git a/src/views/ModelAdd.vue b/src/views/ModelAdd.vue
index 922ee8a636df54bd90f91e6f3766497d765f2211..b00a09b47bd84b79023b9df39a02982ee99e5cc6 100644
--- a/src/views/ModelAdd.vue
+++ b/src/views/ModelAdd.vue
@@ -18,7 +18,7 @@
           <b-field>
             <b-input type="number" placeholder="98" max="10000000" step="0.01" v-model="model.performance"/>
             <b-autocomplete open-on-focus placeholder="accuracy" :data="performanceTypes" v-model="model.performanceUnit" maxlength="50"/>
-            <b-checkbox v-model="model.performanceLowerIsBetter">Lower is better</b-checkbox>
+            <b-checkbox-button v-model="model.performanceLowerIsBetter" type="is-success">Lower is better</b-checkbox-button>
           </b-field>
         </b-field>
 
diff --git a/src/views/ModelEdit.vue b/src/views/ModelEdit.vue
index 8ca5831aefbb5341ca2b548a66d6805ea561e847..7885e204207ddc966c8f44be5c445b46663d1522 100644
--- a/src/views/ModelEdit.vue
+++ b/src/views/ModelEdit.vue
@@ -20,7 +20,7 @@
             <b-field>
               <b-input type="number" placeholder="98" max="10000000" step="0.01" v-model="model.performance"/>
               <b-autocomplete open-on-focus placeholder="accuracy" :data="performanceTypes" v-model="model.performanceUnit" maxlength="50"/>
-              <b-checkbox v-model="model.performanceLowerIsBetter">Lower is better</b-checkbox>
+              <b-checkbox-button v-model="model.performanceLowerIsBetter" type="is-success">Lower is better</b-checkbox-button>
             </b-field>
           </b-field>
 
@@ -65,7 +65,7 @@
       </b-tabs>
     </div>
 
-    <div class="box buttons">
+    <div class="box buttons is-right">
       <b-button tag="router-link" :to="{ name: 'Account' }">Cancel</b-button>
       <b-button type="is-success" @click="openUpdateModal">Save</b-button>
     </div>
diff --git a/src/views/UserEdit.vue b/src/views/UserEdit.vue
index 65f1cf6197b7b759f3538c93a60bd33e53f291a8..44196693ca6a99470191b5da5fa0f4117f593576 100644
--- a/src/views/UserEdit.vue
+++ b/src/views/UserEdit.vue
@@ -1,22 +1,30 @@
 <template>
   <div class="userEdit container">
-    <h1 class="title">Account details</h1>
+    <div class="box">
+      <h1 class="title">Account details</h1>
 
-    <b-field label="Email">
-      <b-input v-model="user.email" type="email"  maxlength="50"/>
-    </b-field>
+      <b-field label="Email">
+        <b-input v-model="user.email" type="email"  maxlength="50"/>
+      </b-field>
 
-    <b-field label="Username">
-      <b-input v-model="user.username" maxlength="30"/>
-    </b-field>
+      <b-field label="Username">
+        <b-input v-model="user.username" maxlength="30" disabled/>
+      </b-field>
 
-    <b-field label="Password">
-      <b-input type="password" v-model="user.password" password-reveal maxlength="50"/>
-    </b-field>
+      <b-field label="Password">
+        <b-input type="password" v-model="user.password" password-reveal maxlength="50"/>
+      </b-field>
+    </div>
+    <div class="box buttons is-right">
+      <b-button tag="router-link" :to="{ name: 'Account' }">Cancel</b-button>
+      <b-button type="is-success" @click="saveUser">Save</b-button>
+    </div>
   </div>
 </template>
 
 <script>
+import { api } from '@/api.js'
+
 export default {
   name: 'UserEdit',
   props: {
@@ -28,13 +36,21 @@ export default {
     }
   },
   methods: {
-    saveUser () {
-
+    async saveUser () {
+      this.$buefy.toast.open('Updating user...')
+      const response = await api.putUser(this.user)
+      if (response.error) this.$buefy.toast.open('Update error ' + response.message)
+      else {
+        this.$buefy.toast.open('User successfully updated')
+        this.$router.push({ name: 'Account' })
+      }
     }
   }
 }
 </script>
 
-<style>
-
+<style scoped>
+.userEdit{
+  margin-top: 20px;
+}
 </style>