mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	Reset password and users table on settings page
This commit is contained in:
		
							parent
							
								
									9331b5870f
								
							
						
					
					
						commit
						f4cb5d101e
					
				@ -62,3 +62,7 @@
 | 
				
			|||||||
  border-right: 6px solid transparent;
 | 
					  border-right: 6px solid transparent;
 | 
				
			||||||
  border-top: 6px solid white;
 | 
					  border-top: 6px solid white;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.icon-text {
 | 
				
			||||||
 | 
					  font-size: 1.1rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -26,10 +26,11 @@ export default {
 | 
				
			|||||||
  data() {
 | 
					  data() {
 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
      menuItems: [
 | 
					      menuItems: [
 | 
				
			||||||
        // {
 | 
					        {
 | 
				
			||||||
        //   value: 'settings',
 | 
					          value: 'account',
 | 
				
			||||||
        //   text: 'Settings'
 | 
					          text: 'Account',
 | 
				
			||||||
        // },
 | 
					          to: '/account'
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          value: 'logout',
 | 
					          value: 'logout',
 | 
				
			||||||
          text: 'Logout'
 | 
					          text: 'Logout'
 | 
				
			||||||
@ -72,8 +73,6 @@ export default {
 | 
				
			|||||||
    menuAction(action) {
 | 
					    menuAction(action) {
 | 
				
			||||||
      if (action === 'logout') {
 | 
					      if (action === 'logout') {
 | 
				
			||||||
        this.logout()
 | 
					        this.logout()
 | 
				
			||||||
      } else if (action === 'settings') {
 | 
					 | 
				
			||||||
        // Show settings modal
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
@ -83,7 +82,6 @@ export default {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<style>
 | 
					<style>
 | 
				
			||||||
#appbar {
 | 
					#appbar {
 | 
				
			||||||
  /* box-shadow: 0px 8px 8px #111111aa; */
 | 
					 | 
				
			||||||
  box-shadow: 0px 5px 5px #11111155;
 | 
					  box-shadow: 0px 5px 5px #11111155;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
@ -12,11 +12,18 @@
 | 
				
			|||||||
    <transition name="menu">
 | 
					    <transition name="menu">
 | 
				
			||||||
      <ul v-show="showMenu" class="absolute z-10 -mt-px w-full bg-primary border border-black-200 shadow-lg max-h-56 rounded-b-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm" tabindex="-1" role="listbox" aria-activedescendant="listbox-option-3">
 | 
					      <ul v-show="showMenu" class="absolute z-10 -mt-px w-full bg-primary border border-black-200 shadow-lg max-h-56 rounded-b-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm" tabindex="-1" role="listbox" aria-activedescendant="listbox-option-3">
 | 
				
			||||||
        <template v-for="item in items">
 | 
					        <template v-for="item in items">
 | 
				
			||||||
 | 
					          <nuxt-link :key="item.value" v-if="item.to" :to="item.to">
 | 
				
			||||||
            <li :key="item.value" class="text-gray-100 select-none relative py-2 cursor-pointer hover:bg-black-400" id="listbox-option-0" role="option" @click="clickedOption(item.value)">
 | 
					            <li :key="item.value" class="text-gray-100 select-none relative py-2 cursor-pointer hover:bg-black-400" id="listbox-option-0" role="option" @click="clickedOption(item.value)">
 | 
				
			||||||
              <div class="flex items-center">
 | 
					              <div class="flex items-center">
 | 
				
			||||||
                <span class="font-normal ml-3 block truncate font-sans">{{ item.text }}</span>
 | 
					                <span class="font-normal ml-3 block truncate font-sans">{{ item.text }}</span>
 | 
				
			||||||
              </div>
 | 
					              </div>
 | 
				
			||||||
            </li>
 | 
					            </li>
 | 
				
			||||||
 | 
					          </nuxt-link>
 | 
				
			||||||
 | 
					          <li v-else :key="item.value" class="text-gray-100 select-none relative py-2 cursor-pointer hover:bg-black-400" id="listbox-option-0" role="option" @click="clickedOption(item.value)">
 | 
				
			||||||
 | 
					            <div class="flex items-center">
 | 
				
			||||||
 | 
					              <span class="font-normal ml-3 block truncate font-sans">{{ item.text }}</span>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </li>
 | 
				
			||||||
        </template>
 | 
					        </template>
 | 
				
			||||||
      </ul>
 | 
					      </ul>
 | 
				
			||||||
    </transition>
 | 
					    </transition>
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										92
									
								
								client/pages/account.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								client/pages/account.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,92 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
					  <div class="w-full h-full p-8">
 | 
				
			||||||
 | 
					    <div class="w-full max-w-2xl mx-auto">
 | 
				
			||||||
 | 
					      <h1 class="text-2xl">Account</h1>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <div class="my-4">
 | 
				
			||||||
 | 
					        <div class="flex -mx-2">
 | 
				
			||||||
 | 
					          <div class="w-2/3 px-2">
 | 
				
			||||||
 | 
					            <ui-text-input-with-label disabled :value="username" label="Username" />
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					          <div class="w-1/3 px-2">
 | 
				
			||||||
 | 
					            <ui-text-input-with-label disabled :value="usertype" label="Account Type" />
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <div class="w-full h-px bg-primary my-4" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <p class="mb-4 text-lg">Change Password</p>
 | 
				
			||||||
 | 
					        <form @submit.prevent="submitChangePassword">
 | 
				
			||||||
 | 
					          <ui-text-input-with-label v-model="password" :disabled="changingPassword" type="password" label="Password" class="my-2" />
 | 
				
			||||||
 | 
					          <ui-text-input-with-label v-model="newPassword" :disabled="changingPassword" type="password" label="New Password" class="my-2" />
 | 
				
			||||||
 | 
					          <ui-text-input-with-label v-model="confirmPassword" :disabled="changingPassword" type="password" label="Confirm Password" class="my-2" />
 | 
				
			||||||
 | 
					          <div class="flex items-center py-2">
 | 
				
			||||||
 | 
					            <p v-if="isRoot" class="text-error py-2 text-xs">* Root user is the only user that can have an empty password</p>
 | 
				
			||||||
 | 
					            <div class="flex-grow" />
 | 
				
			||||||
 | 
					            <ui-btn type="submit" :loading="changingPassword" color="success">Submit</ui-btn>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </form>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script>
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					  data() {
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					      password: null,
 | 
				
			||||||
 | 
					      newPassword: null,
 | 
				
			||||||
 | 
					      confirmPassword: null,
 | 
				
			||||||
 | 
					      changingPassword: false
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  computed: {
 | 
				
			||||||
 | 
					    user() {
 | 
				
			||||||
 | 
					      return this.$store.state.user || null
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    username() {
 | 
				
			||||||
 | 
					      return this.user.username
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    usertype() {
 | 
				
			||||||
 | 
					      return this.user.type
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    isRoot() {
 | 
				
			||||||
 | 
					      return this.usertype === 'root'
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  methods: {
 | 
				
			||||||
 | 
					    resetForm() {
 | 
				
			||||||
 | 
					      this.password = null
 | 
				
			||||||
 | 
					      this.newPassword = null
 | 
				
			||||||
 | 
					      this.confirmPassword = null
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    submitChangePassword() {
 | 
				
			||||||
 | 
					      if (this.newPassword !== this.confirmPassword) {
 | 
				
			||||||
 | 
					        return this.$toast.error('New password and confirm password do not match')
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      this.changingPassword = true
 | 
				
			||||||
 | 
					      this.$axios
 | 
				
			||||||
 | 
					        .$patch('/api/user/password', {
 | 
				
			||||||
 | 
					          password: this.password,
 | 
				
			||||||
 | 
					          newPassword: this.newPassword
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .then((res) => {
 | 
				
			||||||
 | 
					          if (res.success) {
 | 
				
			||||||
 | 
					            this.$toast.success('Password Changed Successfully')
 | 
				
			||||||
 | 
					            this.resetForm()
 | 
				
			||||||
 | 
					          } else {
 | 
				
			||||||
 | 
					            this.$toast.error(res.error || 'Unknown Error')
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          this.changingPassword = false
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .catch((error) => {
 | 
				
			||||||
 | 
					          console.error(error)
 | 
				
			||||||
 | 
					          this.$toast.error('Api call failed')
 | 
				
			||||||
 | 
					          this.changingPassword = false
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  mounted() {}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
@ -1,10 +1,29 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <div class="page p-6" :class="streamAudiobook ? 'streaming' : ''">
 | 
					  <div class="page p-6" :class="streamAudiobook ? 'streaming' : ''">
 | 
				
			||||||
    <div class="w-full max-w-4xl mx-auto">
 | 
					    <div class="w-full max-w-4xl mx-auto">
 | 
				
			||||||
      <h1 class="text-2xl mb-2">Config</h1>
 | 
					      <div class="flex items-center mb-2">
 | 
				
			||||||
 | 
					        <h1 class="text-2xl">Users</h1>
 | 
				
			||||||
 | 
					        <div class="mx-2 w-7 h-7 flex items-center justify-center rounded-full cursor-pointer hover:bg-white hover:bg-opacity-10 text-center" @click="clickAddUser">
 | 
				
			||||||
 | 
					          <span class="material-icons" style="font-size: 1.4rem">add</span>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <!-- <ui-btn small :padding-x="4" class="h-8">Create User</ui-btn> -->
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
      <div class="h-0.5 bg-primary bg-opacity-50 w-full" />
 | 
					      <div class="h-0.5 bg-primary bg-opacity-50 w-full" />
 | 
				
			||||||
      <div class="p-4 text-center h-20">
 | 
					      <div class="p-4 text-center">
 | 
				
			||||||
        <p>Nothing much here yet...</p>
 | 
					        <table id="accounts" class="mb-8">
 | 
				
			||||||
 | 
					          <tr>
 | 
				
			||||||
 | 
					            <th>Username</th>
 | 
				
			||||||
 | 
					            <th>Account Type</th>
 | 
				
			||||||
 | 
					            <th style="width: 200px">Created At</th>
 | 
				
			||||||
 | 
					          </tr>
 | 
				
			||||||
 | 
					          <tr v-for="user in users" :key="user.id">
 | 
				
			||||||
 | 
					            <td>{{ user.username }}</td>
 | 
				
			||||||
 | 
					            <td>{{ user.type }}</td>
 | 
				
			||||||
 | 
					            <td class="text-sm font-mono">
 | 
				
			||||||
 | 
					              {{ new Date(user.createdAt).toISOString() }}
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					          </tr>
 | 
				
			||||||
 | 
					        </table>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      <div class="h-0.5 bg-primary bg-opacity-50 w-full" />
 | 
					      <div class="h-0.5 bg-primary bg-opacity-50 w-full" />
 | 
				
			||||||
      <div class="flex items-center py-4 mb-8">
 | 
					      <div class="flex items-center py-4 mb-8">
 | 
				
			||||||
@ -16,7 +35,7 @@
 | 
				
			|||||||
      <div class="h-0.5 bg-primary bg-opacity-50 w-full" />
 | 
					      <div class="h-0.5 bg-primary bg-opacity-50 w-full" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <div class="flex items-center py-4">
 | 
					      <div class="flex items-center py-4">
 | 
				
			||||||
        <ui-btn color="error" small :padding-x="4" :loading="isResettingAudiobooks" @click="resetAudiobooks">Reset All Audiobooks</ui-btn>
 | 
					        <ui-btn color="bg" small :padding-x="4" :loading="isResettingAudiobooks" @click="resetAudiobooks">Reset All Audiobooks</ui-btn>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <div class="h-0.5 bg-primary bg-opacity-50 w-full" />
 | 
					      <div class="h-0.5 bg-primary bg-opacity-50 w-full" />
 | 
				
			||||||
@ -41,7 +60,8 @@
 | 
				
			|||||||
export default {
 | 
					export default {
 | 
				
			||||||
  data() {
 | 
					  data() {
 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
      isResettingAudiobooks: false
 | 
					      isResettingAudiobooks: false,
 | 
				
			||||||
 | 
					      users: null
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  computed: {
 | 
					  computed: {
 | 
				
			||||||
@ -53,6 +73,19 @@ export default {
 | 
				
			|||||||
    scan() {
 | 
					    scan() {
 | 
				
			||||||
      this.$root.socket.emit('scan')
 | 
					      this.$root.socket.emit('scan')
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    clickAddUser() {
 | 
				
			||||||
 | 
					      this.$toast.info('Under Construction: User management coming soon.')
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    loadUsers() {
 | 
				
			||||||
 | 
					      this.$axios
 | 
				
			||||||
 | 
					        .$get('/api/users')
 | 
				
			||||||
 | 
					        .then((users) => {
 | 
				
			||||||
 | 
					          this.users = users
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .catch((error) => {
 | 
				
			||||||
 | 
					          console.error('Failed', error)
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    resetAudiobooks() {
 | 
					    resetAudiobooks() {
 | 
				
			||||||
      if (confirm('WARNING! This action will remove all audiobooks from the database including any updates or matches you have made. This does not do anything to your actual files. Shall we continue?')) {
 | 
					      if (confirm('WARNING! This action will remove all audiobooks from the database including any updates or matches you have made. This does not do anything to your actual files. Shall we continue?')) {
 | 
				
			||||||
        this.isResettingAudiobooks = true
 | 
					        this.isResettingAudiobooks = true
 | 
				
			||||||
@ -70,6 +103,39 @@ export default {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  mounted() {}
 | 
					  mounted() {
 | 
				
			||||||
 | 
					    this.loadUsers()
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style>
 | 
				
			||||||
 | 
					#accounts {
 | 
				
			||||||
 | 
					  table-layout: fixed;
 | 
				
			||||||
 | 
					  border-collapse: collapse;
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#accounts td,
 | 
				
			||||||
 | 
					#accounts th {
 | 
				
			||||||
 | 
					  border: 1px solid #2e2e2e;
 | 
				
			||||||
 | 
					  padding: 8px 8px;
 | 
				
			||||||
 | 
					  text-align: left;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#accounts tr:nth-child(even) {
 | 
				
			||||||
 | 
					  background-color: #3a3a3a;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#accounts tr:hover {
 | 
				
			||||||
 | 
					  background-color: #444;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#accounts th {
 | 
				
			||||||
 | 
					  font-size: 0.8rem;
 | 
				
			||||||
 | 
					  font-weight: 600;
 | 
				
			||||||
 | 
					  padding-top: 5px;
 | 
				
			||||||
 | 
					  padding-bottom: 5px;
 | 
				
			||||||
 | 
					  background-color: #333;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
@ -28,7 +28,9 @@ class ApiController {
 | 
				
			|||||||
    this.router.get('/metadata/:id/:trackIndex', this.getMetadata.bind(this))
 | 
					    this.router.get('/metadata/:id/:trackIndex', this.getMetadata.bind(this))
 | 
				
			||||||
    this.router.patch('/match/:id', this.match.bind(this))
 | 
					    this.router.patch('/match/:id', this.match.bind(this))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.router.get('/users', this.getUsers.bind(this))
 | 
				
			||||||
    this.router.delete('/user/audiobook/:id', this.resetUserAudiobookProgress.bind(this))
 | 
					    this.router.delete('/user/audiobook/:id', this.resetUserAudiobookProgress.bind(this))
 | 
				
			||||||
 | 
					    this.router.patch('/user/password', this.userChangePassword.bind(this))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.router.post('/authorize', this.authorize.bind(this))
 | 
					    this.router.post('/authorize', this.authorize.bind(this))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -156,6 +158,11 @@ class ApiController {
 | 
				
			|||||||
    res.sendStatus(200)
 | 
					    res.sendStatus(200)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  getUsers(req, res) {
 | 
				
			||||||
 | 
					    if (req.user.type !== 'root') return res.sendStatus(403)
 | 
				
			||||||
 | 
					    return res.json(this.db.users.map(u => u.toJSONForBrowser()))
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async resetUserAudiobookProgress(req, res) {
 | 
					  async resetUserAudiobookProgress(req, res) {
 | 
				
			||||||
    req.user.resetAudiobookProgress(req.params.id)
 | 
					    req.user.resetAudiobookProgress(req.params.id)
 | 
				
			||||||
    await this.db.updateEntity('user', req.user)
 | 
					    await this.db.updateEntity('user', req.user)
 | 
				
			||||||
@ -163,6 +170,10 @@ class ApiController {
 | 
				
			|||||||
    res.sendStatus(200)
 | 
					    res.sendStatus(200)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  userChangePassword(req, res) {
 | 
				
			||||||
 | 
					    this.auth.userChangePassword(req, res)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  getGenres(req, res) {
 | 
					  getGenres(req, res) {
 | 
				
			||||||
    res.json({
 | 
					    res.json({
 | 
				
			||||||
      genres: this.db.getGenres()
 | 
					      genres: this.db.getGenres()
 | 
				
			||||||
 | 
				
			|||||||
@ -114,65 +114,50 @@ class Auth {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async checkAuth(req, res) {
 | 
					  comparePassword(password, user) {
 | 
				
			||||||
    var username = req.body.username
 | 
					    if (user.type === 'root' && !password && !user.pash) return true
 | 
				
			||||||
    Logger.debug('Check Auth', username, !!req.body.password)
 | 
					    if (!password || !user.pash) return false
 | 
				
			||||||
 | 
					    return bcrypt.compare(password, user.pash)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var matchingUser = this.users.find(u => u.username === username)
 | 
					  async userChangePassword(req, res) {
 | 
				
			||||||
    if (!matchingUser) {
 | 
					    var { password, newPassword } = req.body
 | 
				
			||||||
 | 
					    newPassword = newPassword || ''
 | 
				
			||||||
 | 
					    var matchingUser = this.users.find(u => u.id === req.user.id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Only root can have an empty password
 | 
				
			||||||
 | 
					    if (matchingUser.type !== 'root' && !newPassword) {
 | 
				
			||||||
      return res.json({
 | 
					      return res.json({
 | 
				
			||||||
        error: 'User not found'
 | 
					        error: 'Invalid new password - Only root can have an empty password'
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var cleanedUser = { ...matchingUser }
 | 
					    var compare = await this.comparePassword(password, matchingUser)
 | 
				
			||||||
    delete cleanedUser.pash
 | 
					    if (!compare) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
    // check for empty password (default)
 | 
					 | 
				
			||||||
    if (!req.body.password) {
 | 
					 | 
				
			||||||
      if (!matchingUser.pash) {
 | 
					 | 
				
			||||||
        res.cookie('user', username, { signed: true })
 | 
					 | 
				
			||||||
      return res.json({
 | 
					      return res.json({
 | 
				
			||||||
          user: cleanedUser
 | 
					        error: 'Invalid password'
 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        return res.json({
 | 
					 | 
				
			||||||
          error: 'Invalid Password'
 | 
					 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Set root password first time
 | 
					    var pw = ''
 | 
				
			||||||
    if (matchingUser.type === 'root' && !matchingUser.pash && req.body.password && req.body.password.length > 1) {
 | 
					    if (newPassword) {
 | 
				
			||||||
      console.log('Set root pash')
 | 
					      pw = await this.hashPass(newPassword)
 | 
				
			||||||
      var pw = await this.hashPass(req.body.password)
 | 
					 | 
				
			||||||
      if (!pw) {
 | 
					      if (!pw) {
 | 
				
			||||||
        return res.json({
 | 
					        return res.json({
 | 
				
			||||||
          error: 'Hash failed'
 | 
					          error: 'Hash failed'
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      this.users = this.users.map(u => {
 | 
					 | 
				
			||||||
        if (u.username === matchingUser.username) {
 | 
					 | 
				
			||||||
          u.pash = pw
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return u
 | 
					 | 
				
			||||||
      })
 | 
					 | 
				
			||||||
      await this.saveAuthDb()
 | 
					 | 
				
			||||||
      return res.json({
 | 
					 | 
				
			||||||
        setroot: true,
 | 
					 | 
				
			||||||
        user: cleanedUser
 | 
					 | 
				
			||||||
      })
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var compare = await bcrypt.compare(req.body.password, matchingUser.pash)
 | 
					    matchingUser.pash = pw
 | 
				
			||||||
    if (compare) {
 | 
					    var success = await this.db.updateEntity('user', matchingUser)
 | 
				
			||||||
      res.cookie('user', username, { signed: true })
 | 
					    if (success) {
 | 
				
			||||||
      res.json({
 | 
					      res.json({
 | 
				
			||||||
        user: cleanedUser
 | 
					        success: true
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      res.json({
 | 
					      res.json({
 | 
				
			||||||
        error: 'Invalid Password'
 | 
					        error: 'Unknown error'
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
@ -143,8 +143,10 @@ class Db {
 | 
				
			|||||||
      this[arrayKey] = this[arrayKey].map(e => {
 | 
					      this[arrayKey] = this[arrayKey].map(e => {
 | 
				
			||||||
        return e.id === entity.id ? entity : e
 | 
					        return e.id === entity.id ? entity : e
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
 | 
					      return true
 | 
				
			||||||
    }).catch((error) => {
 | 
					    }).catch((error) => {
 | 
				
			||||||
      Logger.error(`[DB] Update entity ${entityName} Failed: ${error}`)
 | 
					      Logger.error(`[DB] Update entity ${entityName} Failed: ${error}`)
 | 
				
			||||||
 | 
					      return false
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,6 @@ const express = require('express')
 | 
				
			|||||||
const http = require('http')
 | 
					const http = require('http')
 | 
				
			||||||
const SocketIO = require('socket.io')
 | 
					const SocketIO = require('socket.io')
 | 
				
			||||||
const fs = require('fs-extra')
 | 
					const fs = require('fs-extra')
 | 
				
			||||||
const cookieparser = require('cookie-parser')
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const Auth = require('./Auth')
 | 
					const Auth = require('./Auth')
 | 
				
			||||||
const Watcher = require('./Watcher')
 | 
					const Watcher = require('./Watcher')
 | 
				
			||||||
@ -101,7 +100,6 @@ class Server {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    this.server = http.createServer(app)
 | 
					    this.server = http.createServer(app)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    app.use(cookieparser('secret_family_recipe'))
 | 
					 | 
				
			||||||
    app.use(this.auth.cors)
 | 
					    app.use(this.auth.cors)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Static path to generated nuxt
 | 
					    // Static path to generated nuxt
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user