From 1f4970368a146f17f3beba98869b0ac51cf38b17 Mon Sep 17 00:00:00 2001 From: N-Pex Date: Mon, 29 Mar 2021 21:55:43 +0200 Subject: [PATCH] Improved logout/login and change password support --- src/App.vue | 46 ++++++++------------- src/assets/css/chat.scss | 2 + src/components/Home.vue | 2 +- src/components/Join.vue | 7 +++- src/components/Profile.vue | 60 ++++++++++++++++++--------- src/components/RoomInfo.vue | 16 -------- src/services/matrix.service.js | 75 ++++++++++++++++++++-------------- 7 files changed, 109 insertions(+), 99 deletions(-) diff --git a/src/App.vue b/src/App.vue index bceb3d3..6c69705 100644 --- a/src/App.vue +++ b/src/App.vue @@ -9,17 +9,17 @@ diff --git a/src/assets/css/chat.scss b/src/assets/css/chat.scss index 02e2237..7563a2b 100644 --- a/src/assets/css/chat.scss +++ b/src/assets/css/chat.scss @@ -608,7 +608,9 @@ $admin-fg: white; .action { padding: 4px 20px; + cursor: pointer; &::after { + /* divider */ content: ' '; display: block; margin: 10px 0px; diff --git a/src/components/Home.vue b/src/components/Home.vue index 7bd9b39..f4bfde1 100644 --- a/src/components/Home.vue +++ b/src/components/Home.vue @@ -1,7 +1,7 @@ diff --git a/src/components/Join.vue b/src/components/Join.vue index 91f3926..11d1035 100644 --- a/src/components/Join.vue +++ b/src/components/Join.vue @@ -283,7 +283,10 @@ export default { * a random account. */ getLoginPromise() { - return this.$store.dispatch("auth/login", this.currentUser || this.guestUser); + if (this.$matrix.ready) { + return Promise.resolve(this.$matrix.currentUser); + } + return this.$store.dispatch("auth/login", this.currentUser || this.guestUser); }, getRoomInfo() { @@ -326,7 +329,7 @@ export default { }, handleLogin() { - this.$navigation.push({ name: "Login" }, 1); + this.$navigation.push({path: "/login"}, 1); }, handleOpenApp() { diff --git a/src/components/Profile.vue b/src/components/Profile.vue index f8528c1..e0b9063 100644 --- a/src/components/Profile.vue +++ b/src/components/Profile.vue @@ -31,7 +31,7 @@
This identity is temporary. Set a password to use it again.
- Logout + Logout @@ -41,21 +41,24 @@ - + Change password - Not yet implemented. - + + + +
{{ passwordErrorMessage }}
- Cancel + Cancel Ok @@ -97,6 +100,11 @@ export default { showEditPasswordDialog: false, showEditDisplaynameDialog: false, editValue: null, + password: null, + newPassword1: null, + newPassword2: null, + settingPassword: false, + passwordErrorMessage: null }; }, @@ -127,6 +135,10 @@ export default { return null; } return (this.user.displayName || this.user.userId.substring(1)).substring(0, 1).toUpperCase(); + }, + + passwordsMatch() { + return this.newPassword1 && this.newPassword2 && this.newPassword1 == this.newPassword2; } }, @@ -143,21 +155,29 @@ export default { this.$matrix.matrixClient.setDisplayName(name); }, - upgradeAccount() { - this.$matrix - .upgradeGuestAccount() - .then(user => { - // Done, login with the "new" account to get a real token instead of our guest token. - this.user = user; - return this.$store.dispatch("auth/login", this.user); - }) - .then(() => { - console.log("Upgrade done!"); - }) - .catch((err) => { - console.log("ERROR", err); - }); + setPassword(oldPassword, newPassword) { + this.settingPassword = true; + this.passwordErrorMessage = null; + this.$matrix.setPassword(oldPassword, newPassword) + .then(success => { + console.log(success ? "Password changed" : "Failed to change password"); + this.closeEditPasswordDialog(); + }) + .catch(error => { + this.passwordErrorMessage = error.message; + }) + .finally(() => { + this.settingPassword = false; + }); }, + + closeEditPasswordDialog() { + this.passwordErrorMessage = null; + this.password = null; + this.newPassword1 = null; + this.newPassword2 = null; + this.showEditPasswordDialog = false; + } }, }; diff --git a/src/components/RoomInfo.vue b/src/components/RoomInfo.vue index 25014d9..863170d 100644 --- a/src/components/RoomInfo.vue +++ b/src/components/RoomInfo.vue @@ -306,22 +306,6 @@ export default { this.$navigation.push({ name: "Profile" }, 1); }, - upgradeAccount() { - this.$matrix - .upgradeGuestAccount() - .then((user) => { - // Done, login with the "new" account to get a real token instead of our guest token. - this.user = user; - return this.$store.dispatch("auth/login", this.user); - }) - .then(() => { - console.log("Upgrade done!"); - }) - .catch((err) => { - console.log("ERROR", err); - }); - }, - copyRoomLink() { this.$copyText(this.roomLink).then( function (e) { diff --git a/src/services/matrix.service.js b/src/services/matrix.service.js index 26c6cc9..0ed2aff 100644 --- a/src/services/matrix.service.js +++ b/src/services/matrix.service.js @@ -77,7 +77,10 @@ export default { const tempMatrixClient = sdk.createClient(User.homeServerUrl(user.home_server)); var promiseLogin; - if (user.is_guest && !user.access_token) { + if (user.access_token) { + // Logged in on "real" account + promiseLogin = Promise.resolve(user); + } else if (user.is_guest && !user.user_id) { // Generate random username and password. We don't user REAL matrix // guest accounts because 1. They are not allowed to post media, 2. They // can not use avatars and 3. They can not seamlessly be upgraded to real accounts. @@ -96,9 +99,6 @@ export default { localStorage.setItem('user', JSON.stringify(response)); return response; }) - } else if (!user.is_guest && user.access_token) { - // Logged in on "real" account - promiseLogin = Promise.resolve(user); } else { var data = { user: User.localPart(user.user_id), password: user.password, type: "m.login.password" }; if (user.device_id) { @@ -155,29 +155,6 @@ export default { this.$store.commit("setCurrentRoomId", null); }, - /** - * Upgrade a guest account into a "normal" account. For now, use random user and pass... - */ - upgradeGuestAccount() { - if (!this.matrixClient || !this.currentUser || !this.currentUser.is_guest) { - return Promise.reject("Invalid params"); - } - const randomPassword = util.randomPass(); - const self = this; - return this.matrixClient.register(this.matrixClient.getUserIdLocalpart(), randomPassword, null, { - type: "m.login.dummy", - }, undefined, this.currentUser.access_token) - .then((response) => { - console.log("Response", response); - response.is_guest = false; - response.password = randomPassword; - self.currentUser = response; - localStorage.setItem('user', JSON.stringify(response)); // Update local storage as well. - self.logout(); - return self.currentUser; - }); - }, - initClient() { this.reloadRooms(); this.matrixClientReady = true; @@ -322,15 +299,23 @@ export default { this.matrixClient = null; this.matrixClientReady = false; } - this.$store.commit("setCurrentRoomId", null); + // For "real" accounts we totally wipe the user object, but for "guest" + // accounts (i.e. created from random data and with password never changed) + // we need to hang on to the generated password and use that to login to a new + // session, so only wipe the token in s that case. // Clear the access token var user = JSON.parse(localStorage.getItem('user')); - if (user) { + if (user.is_guest) { delete user.access_token; + localStorage.setItem('user', JSON.stringify(user)); + // Login again + this.login(user); + } else { + localStorage.removeItem('user'); + this.$store.commit("setCurrentRoomId", null); + this.$navigation.push({path: "/login"}, -1); } - localStorage.setItem('user', JSON.stringify(user)); - this.$navigation.push({ name: "Login" }, -1); }, reloadRooms() { @@ -398,6 +383,34 @@ export default { } }, + setPassword(oldPassword, newPassword) { + if (this.matrixClient && this.currentUser) { + const authDict = { + type: 'm.login.password', + identifier: { + type: 'm.id.user', + user: this.currentUser.user_id, + }, + // TODO: Remove `user` once servers support proper UIA + // See https://github.com/matrix-org/synapse/issues/5665 + user: this.currentUser.user_id, + password: oldPassword, + }; + const self = this; + return this.matrixClient.setPassword(authDict, newPassword) + .then(() => { + // Forget password and remove the 'is_guest' flag, we are now a "real" user! + self.currentUser.password = undefined; + self.currentUser.is_guest = false; + localStorage.setItem('user', JSON.stringify(self.currentUser)); + }) + .then(() => { + return true; + }) + } + return Promise.resolve(false); + }, + uploadFile(file, opts) { return this.matrixClient.uploadContent(file, opts); },