| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363 | <template>	<div>		<main-header />		<div class="container">			<!--Implement Validation-->			<label class="label">Username</label>			<div class="control is-grouped">				<p class="control is-expanded has-icon has-icon-right">					<input						v-model="user.username"						class="input"						type="text"						placeholder="Change username"					/>					<!--Remove validation if it's their own without changing-->				</p>				<p class="control">					<button class="button is-success" @click="changeUsername()">						Save changes					</button>				</p>			</div>			<label class="label">Email</label>			<div v-if="user.email" class="control is-grouped">				<p class="control is-expanded has-icon has-icon-right">					<input						v-model="user.email.address"						class="input"						type="text"						placeholder="Change email address"					/>					<!--Remove validation if it's their own without changing-->				</p>				<p class="control is-expanded">					<button class="button is-success" @click="changeEmail()">						Save changes					</button>				</p>			</div>			<label v-if="password" class="label">Change Password</label>			<div v-if="password" class="control is-grouped">				<p class="control is-expanded has-icon has-icon-right">					<input						v-model="newPassword"						class="input"						type="password"						placeholder="Change password"					/>				</p>				<p class="control is-expanded">					<button class="button is-success" @click="changePassword()">						Change password					</button>				</p>			</div>			<label v-if="!password" class="label">Add password</label>			<div v-if="!password" class="control is-grouped">				<button					v-if="passwordStep === 1"					class="button is-success"					@click="requestPassword()"				>					Request password email				</button>				<br />				<p					v-if="passwordStep === 2"					class="control is-expanded has-icon has-icon-right"				>					<input						v-model="passwordCode"						class="input"						type="text"						placeholder="Code"					/>				</p>				<p v-if="passwordStep === 2" class="control is-expanded">					<button class="button is-success" v-on:click="verifyCode()">						Verify code					</button>				</p>				<p					v-if="passwordStep === 3"					class="control is-expanded has-icon has-icon-right"				>					<input						v-model="setNewPassword"						class="input"						type="password"						placeholder="New password"					/>				</p>				<p v-if="passwordStep === 3" class="control is-expanded">					<button class="button is-success" @click="setPassword()">						Set password					</button>				</p>			</div>			<a				v-if="passwordStep === 1 && !password"				href="#"				@click="passwordStep = 2"				>Skip this step</a			>			<a				v-if="!github"				class="button is-github"				:href="`${$parent.serverDomain}/auth/github/link`"			>				<div class="icon">					<img class="invert" src="/assets/social/github.svg" />				</div>				  Link GitHub to account			</a>			<button				v-if="password && github"				class="button is-danger"				@click="unlinkPassword()"			>				Remove logging in with password			</button>			<button				v-if="password && github"				class="button is-danger"				@click="unlinkGitHub()"			>				Remove logging in with GitHub			</button>			<br />			<button				class="button is-warning"				style="margin-top: 30px;"				@click="removeSessions()"			>				Log out everywhere			</button>		</div>		<main-footer />	</div></template><script>import { Toast } from "vue-roaster";import MainHeader from "../MainHeader.vue";import MainFooter from "../MainFooter.vue";import io from "../../io";import validation from "../../validation";export default {	components: { MainHeader, MainFooter },	data() {		return {			user: {},			newPassword: "",			password: false,			github: false,			setNewPassword: "",			passwordStep: 1,			passwordCode: ""		};	},	mounted() {		const _this = this;		io.getSocket(socket => {			_this.socket = socket;			_this.socket.emit("users.findBySession", res => {				if (res.status === "success") {					_this.user = res.data;					_this.password = _this.user.password;					_this.github = _this.user.github;				} else {					_this.$parent.isLoginActive = true;					Toast.methods.addToast(						"Your are currently not signed in",						3000					);				}			});			_this.socket.on("event:user.username.changed", username => {				_this.$parent.username = username;			});			_this.socket.on("event:user.linkPassword", () => {				_this.password = true;			});			_this.socket.on("event:user.linkGitHub", () => {				_this.github = true;			});			_this.socket.on("event:user.unlinkPassword", () => {				_this.password = false;			});			_this.socket.on("event:user.unlinkGitHub", () => {				_this.github = false;			});		});	},	methods: {		changeEmail() {			const email = this.user.email.address;			if (!validation.isLength(email, 3, 254))				return Toast.methods.addToast(					"Email must have between 3 and 254 characters.",					8000				);			if (				email.indexOf("@") !== email.lastIndexOf("@") ||				!validation.regex.emailSimple.test(email)			)				return Toast.methods.addToast("Invalid email format.", 8000);			return this.socket.emit(				"users.updateEmail",				this.$parent.userId,				email,				res => {					if (res.status !== "success")						Toast.methods.addToast(res.message, 8000);					else						Toast.methods.addToast(							"Successfully changed email address",							4000						);				}			);		},		changeUsername() {			const { username } = this.user;			if (!validation.isLength(username, 2, 32))				return Toast.methods.addToast(					"Username must have between 2 and 32 characters.",					8000				);			if (!validation.regex.azAZ09_.test(username))				return Toast.methods.addToast(					"Invalid username format. Allowed characters: a-z, A-Z, 0-9 and _.",					8000				);			return this.socket.emit(				"users.updateUsername",				this.$parent.userId,				username,				res => {					if (res.status !== "success")						Toast.methods.addToast(res.message, 8000);					else						Toast.methods.addToast(							"Successfully changed username",							4000						);				}			);		},		changePassword() {			const { newPassword } = this;			if (!validation.isLength(newPassword, 6, 200))				return Toast.methods.addToast(					"Password must have between 6 and 200 characters.",					8000				);			if (!validation.regex.password.test(newPassword))				return Toast.methods.addToast(					"Invalid password format. Must have one lowercase letter, one uppercase letter, one number and one special character.",					8000				);			return this.socket.emit(				"users.updatePassword",				newPassword,				res => {					if (res.status !== "success")						Toast.methods.addToast(res.message, 8000);					else						Toast.methods.addToast(							"Successfully changed password",							4000						);				}			);		},		requestPassword() {			return this.socket.emit("users.requestPassword", res => {				Toast.methods.addToast(res.message, 8000);				if (res.status === "success") {					this.passwordStep = 2;				}			});		},		verifyCode() {			if (!this.passwordCode)				return Toast.methods.addToast("Code cannot be empty", 8000);			return this.socket.emit(				"users.verifyPasswordCode",				this.passwordCode,				res => {					Toast.methods.addToast(res.message, 8000);					if (res.status === "success") {						this.passwordStep = 3;					}				}			);		},		setPassword() {			const newPassword = this.setNewPassword;			if (!validation.isLength(newPassword, 6, 200))				return Toast.methods.addToast(					"Password must have between 6 and 200 characters.",					8000				);			if (!validation.regex.password.test(newPassword))				return Toast.methods.addToast(					"Invalid password format. Must have one lowercase letter, one uppercase letter, one number and one special character.",					8000				);			return this.socket.emit(				"users.changePasswordWithCode",				this.passwordCode,				newPassword,				res => {					Toast.methods.addToast(res.message, 8000);				}			);		},		unlinkPassword() {			this.socket.emit("users.unlinkPassword", res => {				Toast.methods.addToast(res.message, 8000);			});		},		unlinkGitHub() {			this.socket.emit("users.unlinkGitHub", res => {				Toast.methods.addToast(res.message, 8000);			});		},		removeSessions() {			this.socket.emit(				`users.removeSessions`,				this.$parent.userId,				res => {					Toast.methods.addToast(res.message, 4000);				}			);		}	}};</script><style lang="scss" scoped>.container {	padding: 25px;}a {	color: #029ce3 !important;}</style>
 |