|
@@ -1,56 +1,94 @@
|
|
<template>
|
|
<template>
|
|
<div class="content security-tab">
|
|
<div class="content security-tab">
|
|
- <div v-if="!isPasswordLinked || (isPasswordLinked && isGithubLinked)">
|
|
|
|
- <h4 class="section-title" v-if="!isPasswordLinked">
|
|
|
|
- Set a password
|
|
|
|
- </h4>
|
|
|
|
- <h4 class="section-title" v-else>
|
|
|
|
- Remove password
|
|
|
|
|
|
+ <div v-if="isPasswordLinked">
|
|
|
|
+ <h4 class="section-title">
|
|
|
|
+ Change password
|
|
</h4>
|
|
</h4>
|
|
|
|
|
|
- <p class="section-description" v-if="!isPasswordLinked">
|
|
|
|
- Set a password, as an alternative to signing in with GitHub.
|
|
|
|
|
|
+ <p class="section-description">
|
|
|
|
+ To change your password, you will need to know your previous
|
|
|
|
+ password.
|
|
|
|
+ </p>
|
|
|
|
+
|
|
|
|
+ <br />
|
|
|
|
+
|
|
|
|
+ <p class="control is-expanded">
|
|
|
|
+ <label for="previous-password">Previous password</label>
|
|
|
|
+ <input
|
|
|
|
+ class="input"
|
|
|
|
+ id="previous-password"
|
|
|
|
+ type="password"
|
|
|
|
+ placeholder="Enter your old password here..."
|
|
|
|
+ v-model="previousPassword"
|
|
|
|
+ />
|
|
</p>
|
|
</p>
|
|
- <p class="section-description" v-else>
|
|
|
|
- Remove password from your Musare account.
|
|
|
|
|
|
+
|
|
|
|
+ <label for="new-password">New password</label>
|
|
|
|
+ <div class="control is-grouped input-with-button">
|
|
|
|
+ <p id="new-password-again-input" class="control is-expanded">
|
|
|
|
+ <input
|
|
|
|
+ class="input"
|
|
|
|
+ id="new-password"
|
|
|
|
+ type="password"
|
|
|
|
+ placeholder="Enter new password here..."
|
|
|
|
+ v-model="validation.newPassword.value"
|
|
|
|
+ @keyup.enter="changePassword()"
|
|
|
|
+ @blur="onInputBlur('newPassword')"
|
|
|
|
+ />
|
|
|
|
+ </p>
|
|
|
|
+ <p class="control">
|
|
|
|
+ <a
|
|
|
|
+ id="change-password-button"
|
|
|
|
+ class="button is-success"
|
|
|
|
+ href="#"
|
|
|
|
+ @click.prevent="changePassword()"
|
|
|
|
+ >
|
|
|
|
+ Change password</a
|
|
|
|
+ >
|
|
|
|
+ </p>
|
|
|
|
+ </div>
|
|
|
|
+ <p
|
|
|
|
+ class="help"
|
|
|
|
+ v-if="validation.newPassword.entered"
|
|
|
|
+ :class="
|
|
|
|
+ validation.newPassword.valid ? 'is-success' : 'is-danger'
|
|
|
|
+ "
|
|
|
|
+ >
|
|
|
|
+ {{ validation.newPassword.message }}
|
|
|
|
+ </p>
|
|
|
|
+
|
|
|
|
+ <hr style="margin: 30px 0;" />
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <div v-if="!isPasswordLinked">
|
|
|
|
+ <h4 class="section-title">
|
|
|
|
+ Add a password
|
|
|
|
+ </h4>
|
|
|
|
+ <p class="section-description">
|
|
|
|
+ Add a password, as an alternative to signing in with GitHub.
|
|
</p>
|
|
</p>
|
|
|
|
|
|
<br />
|
|
<br />
|
|
|
|
|
|
- <router-link
|
|
|
|
- v-if="!isPasswordLinked"
|
|
|
|
- to="/set_password"
|
|
|
|
- class="button is-default"
|
|
|
|
- href="#"
|
|
|
|
|
|
+ <router-link to="/set_password" class="button is-default" href="#"
|
|
><i class="material-icons icon-with-button">create</i>Set
|
|
><i class="material-icons icon-with-button">create</i>Set
|
|
Password
|
|
Password
|
|
</router-link>
|
|
</router-link>
|
|
|
|
|
|
- <a
|
|
|
|
- v-else
|
|
|
|
- class="button is-danger"
|
|
|
|
- href="#"
|
|
|
|
- @click.prevent="unlinkPassword()"
|
|
|
|
- ><i class="material-icons icon-with-button">link_off</i>Remove
|
|
|
|
- logging in with password
|
|
|
|
- </a>
|
|
|
|
-
|
|
|
|
<hr style="margin: 30px 0;" />
|
|
<hr style="margin: 30px 0;" />
|
|
</div>
|
|
</div>
|
|
|
|
|
|
- <div v-if="!isGithubLinked || (isPasswordLinked && isGithubLinked)">
|
|
|
|
|
|
+ <div v-if="!isGithubLinked">
|
|
<h4 class="section-title">
|
|
<h4 class="section-title">
|
|
- {{ isGithubLinked ? "Unlink" : "Link" }} GitHub
|
|
|
|
|
|
+ Link GitHub
|
|
</h4>
|
|
</h4>
|
|
<p class="section-description">
|
|
<p class="section-description">
|
|
- {{ isGithubLinked ? "Unlink" : "Link" }} your Musare account
|
|
|
|
- with GitHub.
|
|
|
|
|
|
+ Link your Musare account with GitHub.
|
|
</p>
|
|
</p>
|
|
|
|
|
|
<br />
|
|
<br />
|
|
|
|
|
|
<a
|
|
<a
|
|
- v-if="!isGithubLinked"
|
|
|
|
class="button is-github"
|
|
class="button is-github"
|
|
:href="`${serverDomain}/auth/github/link`"
|
|
:href="`${serverDomain}/auth/github/link`"
|
|
>
|
|
>
|
|
@@ -60,13 +98,31 @@
|
|
Link GitHub to account
|
|
Link GitHub to account
|
|
</a>
|
|
</a>
|
|
|
|
|
|
|
|
+ <hr style="margin: 30px 0;" />
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <div v-if="isPasswordLinked && isGithubLinked">
|
|
|
|
+ <h4 class="section-title">
|
|
|
|
+ Remove login methods
|
|
|
|
+ </h4>
|
|
|
|
+ <p class="section-description">
|
|
|
|
+ Remove your password as a login method or unlink GitHub.
|
|
|
|
+ </p>
|
|
|
|
+
|
|
|
|
+ <br />
|
|
|
|
+
|
|
<a
|
|
<a
|
|
- v-else
|
|
|
|
|
|
+ v-if="isPasswordLinked"
|
|
class="button is-danger"
|
|
class="button is-danger"
|
|
href="#"
|
|
href="#"
|
|
- @click.prevent="unlinkGitHub()"
|
|
|
|
|
|
+ @click.prevent="unlinkPassword()"
|
|
|
|
+ ><i class="material-icons icon-with-button">close</i>Remove
|
|
|
|
+ password
|
|
|
|
+ </a>
|
|
|
|
+
|
|
|
|
+ <a class="button is-danger" href="#" @click.prevent="unlinkGitHub()"
|
|
><i class="material-icons icon-with-button">link_off</i>Remove
|
|
><i class="material-icons icon-with-button">link_off</i>Remove
|
|
- logging in with GitHub
|
|
|
|
|
|
+ GitHub from account
|
|
</a>
|
|
</a>
|
|
|
|
|
|
<hr style="margin: 30px 0;" />
|
|
<hr style="margin: 30px 0;" />
|
|
@@ -75,7 +131,7 @@
|
|
<div>
|
|
<div>
|
|
<h4 class="section-title">Log out everywhere</h4>
|
|
<h4 class="section-title">Log out everywhere</h4>
|
|
<p class="section-description">
|
|
<p class="section-description">
|
|
- Remove all sessions for your account.
|
|
|
|
|
|
+ Remove all currently logged-in sessions for your account.
|
|
</p>
|
|
</p>
|
|
|
|
|
|
<br />
|
|
<br />
|
|
@@ -96,11 +152,21 @@ import Toast from "toasters";
|
|
import { mapGetters, mapState } from "vuex";
|
|
import { mapGetters, mapState } from "vuex";
|
|
|
|
|
|
import io from "../../../io";
|
|
import io from "../../../io";
|
|
|
|
+import validation from "../../../validation";
|
|
|
|
|
|
export default {
|
|
export default {
|
|
data() {
|
|
data() {
|
|
return {
|
|
return {
|
|
- serverDomain: ""
|
|
|
|
|
|
+ serverDomain: "",
|
|
|
|
+ previousPassword: "",
|
|
|
|
+ validation: {
|
|
|
|
+ newPassword: {
|
|
|
|
+ value: "",
|
|
|
|
+ valid: false,
|
|
|
|
+ entered: false,
|
|
|
|
+ message: "Please enter a valid password."
|
|
|
|
+ }
|
|
|
|
+ }
|
|
};
|
|
};
|
|
},
|
|
},
|
|
computed: {
|
|
computed: {
|
|
@@ -122,6 +188,43 @@ export default {
|
|
});
|
|
});
|
|
},
|
|
},
|
|
methods: {
|
|
methods: {
|
|
|
|
+ onInputBlur(inputName) {
|
|
|
|
+ this.validation[inputName].entered = true;
|
|
|
|
+ },
|
|
|
|
+ changePassword() {
|
|
|
|
+ const newPassword = this.validation.newPassword.value;
|
|
|
|
+
|
|
|
|
+ if (this.previousPassword === "")
|
|
|
|
+ return new Toast({
|
|
|
|
+ content: "Please enter a previous password.",
|
|
|
|
+ timeout: 8000
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ if (!this.validation.newPassword.valid)
|
|
|
|
+ return new Toast({
|
|
|
|
+ content: "Please enter a valid new password.",
|
|
|
|
+ timeout: 8000
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ return this.socket.emit(
|
|
|
|
+ "users.updatePassword",
|
|
|
|
+ this.previousPassword,
|
|
|
|
+ newPassword,
|
|
|
|
+ res => {
|
|
|
|
+ if (res.status !== "success")
|
|
|
|
+ new Toast({ content: res.message, timeout: 8000 });
|
|
|
|
+ else {
|
|
|
|
+ this.previousPassword = "";
|
|
|
|
+ this.validation.newPassword.value = "";
|
|
|
|
+
|
|
|
|
+ new Toast({
|
|
|
|
+ content: "Successfully changed password.",
|
|
|
|
+ timeout: 4000
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ );
|
|
|
|
+ },
|
|
unlinkPassword() {
|
|
unlinkPassword() {
|
|
this.socket.emit("users.unlinkPassword", res => {
|
|
this.socket.emit("users.unlinkPassword", res => {
|
|
new Toast({ content: res.message, timeout: 8000 });
|
|
new Toast({ content: res.message, timeout: 8000 });
|
|
@@ -130,7 +233,6 @@ export default {
|
|
unlinkGitHub() {
|
|
unlinkGitHub() {
|
|
this.socket.emit("users.unlinkGitHub", res => {
|
|
this.socket.emit("users.unlinkGitHub", res => {
|
|
new Toast({ content: res.message, timeout: 8000 });
|
|
new Toast({ content: res.message, timeout: 8000 });
|
|
- console.log("hi");
|
|
|
|
});
|
|
});
|
|
},
|
|
},
|
|
removeSessions() {
|
|
removeSessions() {
|
|
@@ -138,6 +240,23 @@ export default {
|
|
new Toast({ content: res.message, timeout: 4000 });
|
|
new Toast({ content: res.message, timeout: 4000 });
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
+ },
|
|
|
|
+ watch: {
|
|
|
|
+ // eslint-disable-next-line func-names
|
|
|
|
+ "validation.newPassword.value": function(value) {
|
|
|
|
+ if (!validation.isLength(value, 6, 200)) {
|
|
|
|
+ this.validation.newPassword.message =
|
|
|
|
+ "Password must have between 6 and 200 characters.";
|
|
|
|
+ this.validation.newPassword.valid = false;
|
|
|
|
+ } else if (!validation.regex.password.test(value)) {
|
|
|
|
+ this.validation.newPassword.message =
|
|
|
|
+ "Invalid password format. Must have one lowercase letter, one uppercase letter, one number and one special character.";
|
|
|
|
+ this.validation.newPassword.valid = false;
|
|
|
|
+ } else {
|
|
|
|
+ this.validation.newPassword.message = "Everything looks great!";
|
|
|
|
+ this.validation.newPassword.valid = true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
};
|
|
};
|
|
</script>
|
|
</script>
|