From 8e1701e4698bf88531cc83836b751f58e3cbda4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Iv=C3=A1n=20Vieitez=20Parra?= <3857362+corrideat@users.noreply.github.com> Date: Thu, 12 Oct 2023 19:01:00 +0200 Subject: [PATCH] Listen for login event before calling postSubmit --- frontend/controller/actions/identity.js | 3 +- frontend/utils/events.js | 1 + .../views/containers/access/LoginForm.vue | 32 ++++++++++++++++--- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/frontend/controller/actions/identity.js b/frontend/controller/actions/identity.js index 1e4c506a4d..f340d46717 100644 --- a/frontend/controller/actions/identity.js +++ b/frontend/controller/actions/identity.js @@ -9,7 +9,7 @@ import { difference, omit, pickWhere, uniq } from '@model/contracts/shared/giLod import sbp from '@sbp/sbp' import { imageUpload } from '@utils/image.js' import { SETTING_CURRENT_USER } from '~/frontend/model/database.js' -import { LOGIN, LOGOUT } from '~/frontend/utils/events.js' +import { LOGIN, LOGIN_ERROR, LOGOUT } from '~/frontend/utils/events.js' import { GIMessage } from '~/shared/domains/chelonia/GIMessage.js' import { boxKeyPair, buildRegisterSaltRequest, computeCAndHc, decryptContractSalt, hash, hashPassword, randomNonce } from '~/shared/zkpp.js' import { findKeyIdByName } from '~/shared/domains/chelonia/utils.js' @@ -455,6 +455,7 @@ export default (sbp('sbp/selectors/register', { sbp('okTurtles.events/emit', LOGIN, { username, identityContractID }) }).catch((err) => { + sbp('okTurtles.events/emit', LOGIN_ERROR, { username, identityContractID, error: err }) const errMessage = err?.message || String(err) console.error('Error during login contract sync', errMessage) diff --git a/frontend/utils/events.js b/frontend/utils/events.js index 7ad06712d7..e2dba06d09 100644 --- a/frontend/utils/events.js +++ b/frontend/utils/events.js @@ -6,6 +6,7 @@ // This file is primarily for frontend UI related events. export const LOGIN = 'login' +export const LOGIN_ERROR = 'login-error' export const LOGOUT = 'logout' export const REPLACED_STATE = 'replaced-state' diff --git a/frontend/views/containers/access/LoginForm.vue b/frontend/views/containers/access/LoginForm.vue index 697c9a8065..f50465761d 100644 --- a/frontend/views/containers/access/LoginForm.vue +++ b/frontend/views/containers/access/LoginForm.vue @@ -32,6 +32,7 @@ import sbp from '@sbp/sbp' import { validationMixin } from 'vuelidate' import { required } from 'vuelidate/lib/validators' import { L } from '@common/common.js' +import { LOGIN, LOGIN_ERROR } from '~/frontend/utils/events.js' import BannerScoped from '@components/banners/BannerScoped.vue' import ButtonSubmit from '@components/ButtonSubmit.vue' import PasswordForm from '@containers/access/PasswordForm.vue' @@ -85,14 +86,35 @@ export default ({ try { this.$refs.formMsg.clean() + const username = this.form.username + + // 'gi.actions/identity/login' syncs the identity contract without + // awaiting on it, which can cause issues because this.postSubmit() + // can get called before the state for the identity contract is complete. + // To avoid these issues, we set up an event handler (on LOGIN) to call + // this.postSubmit() once the identity contract has finished syncing + // If an error occurred during login, we set up an event handler (on + // LOGIN_ERROR) to remove the login event handler. + const loginEventHandler = async ({ username: user }) => { + if (user !== username) return + sbp('okTurtles.events/off', LOGIN_ERROR, loginErrorEventHandler) + await this.postSubmit() + this.$emit('submit-succeeded') + + requestNotificationPermission() + } + const loginErrorEventHandler = ({ username: user, error }) => { + if (user !== username) return + sbp('okTurtles.events/off', LOGIN, loginEventHandler) + this.$refs.formMsg.danger(error.message) + } + sbp('okTurtles.events/once', LOGIN, loginEventHandler) + sbp('okTurtles.events/once', LOGIN_ERROR, loginErrorEventHandler) + await sbp('gi.actions/identity/login', { - username: this.form.username, + username, passwordFn: wrapValueInFunction(this.form.password) }) - await this.postSubmit() - this.$emit('submit-succeeded') - - requestNotificationPermission() } catch (e) { console.error('FormLogin.vue login() error:', e) this.$refs.formMsg.danger(e.message)