diff options
Diffstat (limited to 'src/components/settings/Security.vue')
-rw-r--r-- | src/components/settings/Security.vue | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/src/components/settings/Security.vue b/src/components/settings/Security.vue new file mode 100644 index 0000000..5d8aed8 --- /dev/null +++ b/src/components/settings/Security.vue @@ -0,0 +1,228 @@ +<template> + <div> + <div v-if="settingsLoaded" class="my-4"> + <!-- Change Password --> + <template v-if="!settings.disableAuth"> + <p> + {{ $t("Current User") }}: <strong>{{ $root.username }}</strong> + <button v-if="! settings.disableAuth" id="logout-btn" class="btn btn-danger ms-4 me-2 mb-2" @click="$root.logout">{{ $t("Logout") }}</button> + </p> + + <h5 class="my-4 settings-subheading">{{ $t("Change Password") }}</h5> + <form class="mb-3" @submit.prevent="savePassword"> + <div class="mb-3"> + <label for="current-password" class="form-label"> + {{ $t("Current Password") }} + </label> + <input + id="current-password" + v-model="password.currentPassword" + type="password" + class="form-control" + autocomplete="current-password" + required + /> + </div> + + <div class="mb-3"> + <label for="new-password" class="form-label"> + {{ $t("New Password") }} + </label> + <input + id="new-password" + v-model="password.newPassword" + type="password" + class="form-control" + autocomplete="new-password" + required + /> + </div> + + <div class="mb-3"> + <label for="repeat-new-password" class="form-label"> + {{ $t("Repeat New Password") }} + </label> + <input + id="repeat-new-password" + v-model="password.repeatNewPassword" + type="password" + class="form-control" + :class="{ 'is-invalid': invalidPassword }" + autocomplete="new-password" + required + /> + <div class="invalid-feedback"> + {{ $t("passwordNotMatchMsg") }} + </div> + </div> + + <div> + <button class="btn btn-primary" type="submit"> + {{ $t("Update Password") }} + </button> + </div> + </form> + </template> + + <div v-if="! settings.disableAuth" class="mt-5 mb-3"> + <h5 class="my-4 settings-subheading"> + {{ $t("Two Factor Authentication") }} + </h5> + <div class="mb-4"> + <button + class="btn btn-primary me-2" + type="button" + @click="$refs.TwoFADialog.show()" + > + {{ $t("2FA Settings") }} + </button> + </div> + </div> + + <div class="my-4"> + <!-- Advanced --> + <h5 class="my-4 settings-subheading">{{ $t("Advanced") }}</h5> + + <div class="mb-4"> + <button v-if="settings.disableAuth" id="enableAuth-btn" class="btn btn-outline-primary me-2 mb-2" @click="enableAuth">{{ $t("Enable Auth") }}</button> + <button v-if="! settings.disableAuth" id="disableAuth-btn" class="btn btn-primary me-2 mb-2" @click="confirmDisableAuth">{{ $t("Disable Auth") }}</button> + </div> + </div> + </div> + + <TwoFADialog ref="TwoFADialog" /> + + <Confirm ref="confirmDisableAuth" btn-style="btn-danger" :yes-text="$t('I understand, please disable')" :no-text="$t('Leave')" @yes="disableAuth"> + <i18n-t tag="p" keypath="disableauth.message1"> + <template #disableAuth> + <strong>{{ $t('disable authentication') }}</strong> + </template> + </i18n-t> + <i18n-t tag="p" keypath="disableauth.message2"> + <template #intendThirdPartyAuth> + <strong>{{ $t('intend to implement third-party authentication') }}</strong> + </template> + </i18n-t> + <p>{{ $t("Please use this option carefully!") }}</p> + + <div class="mb-3"> + <label for="current-password2" class="form-label"> + {{ $t("Current Password") }} + </label> + <input + id="current-password2" + v-model="password.currentPassword" + type="password" + class="form-control" + required + /> + </div> + </Confirm> + </div> +</template> + +<script> +import Confirm from "../../components/Confirm.vue"; +import TwoFADialog from "../../components/TwoFADialog.vue"; + +export default { + components: { + Confirm, + TwoFADialog + }, + + data() { + return { + invalidPassword: false, + password: { + currentPassword: "", + newPassword: "", + repeatNewPassword: "", + } + }; + }, + + computed: { + settings() { + return this.$parent.$parent.$parent.settings; + }, + saveSettings() { + return this.$parent.$parent.$parent.saveSettings; + }, + settingsLoaded() { + return this.$parent.$parent.$parent.settingsLoaded; + } + }, + + watch: { + "password.repeatNewPassword"() { + this.invalidPassword = false; + }, + }, + + methods: { + /** + * Check new passwords match before saving them + * @returns {void} + */ + savePassword() { + if (this.password.newPassword !== this.password.repeatNewPassword) { + this.invalidPassword = true; + } else { + this.$root + .getSocket() + .emit("changePassword", this.password, (res) => { + this.$root.toastRes(res); + if (res.ok) { + this.password.currentPassword = ""; + this.password.newPassword = ""; + this.password.repeatNewPassword = ""; + + // Update token of the current session + if (res.token) { + this.$root.storage().token = res.token; + this.$root.socket.token = res.token; + } + } + }); + } + }, + + /** + * Disable authentication for web app access + * @returns {void} + */ + disableAuth() { + this.settings.disableAuth = true; + + // Need current password to disable auth + // Set it to empty if done + this.saveSettings(() => { + this.password.currentPassword = ""; + this.$root.username = null; + this.$root.socket.token = "autoLogin"; + }, this.password.currentPassword); + }, + + /** + * Enable authentication for web app access + * @returns {void} + */ + enableAuth() { + this.settings.disableAuth = false; + this.saveSettings(); + this.$root.storage().removeItem("token"); + location.reload(); + }, + + /** + * Show confirmation dialog for disable auth + * @returns {void} + */ + confirmDisableAuth() { + this.$refs.confirmDisableAuth.show(); + }, + + }, +}; +</script> |