summaryrefslogtreecommitdiffstats
path: root/src/components/settings/Security.vue
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/settings/Security.vue')
-rw-r--r--src/components/settings/Security.vue228
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>