feat: change and verify user's email address
This commit is contained in:
@@ -17,6 +17,9 @@ import {
|
||||
AuthCredential,
|
||||
UserCredential,
|
||||
updateProfile,
|
||||
updateEmail,
|
||||
sendEmailVerification,
|
||||
reauthenticateWithCredential,
|
||||
} from "firebase/auth"
|
||||
import {
|
||||
onSnapshot,
|
||||
@@ -318,6 +321,78 @@ export async function setDisplayName(name: string) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send user's email address verification mail
|
||||
*/
|
||||
export async function verifyEmailAddress() {
|
||||
if (!currentUser$.value) throw new Error("No user has logged in")
|
||||
|
||||
try {
|
||||
await sendEmailVerification(currentUser$.value).catch((e) =>
|
||||
console.error("error updating", e)
|
||||
)
|
||||
} catch (e) {
|
||||
console.error("error updating", e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the user's email address
|
||||
*
|
||||
* @param email - The new email address
|
||||
*/
|
||||
export async function setEmailAddress(email: string) {
|
||||
if (!currentUser$.value) throw new Error("No user has logged in")
|
||||
|
||||
try {
|
||||
await updateEmail(currentUser$.value, email).catch(async (e) => {
|
||||
await reauthenticateUser()
|
||||
console.error("error updating", email, e)
|
||||
})
|
||||
} catch (e) {
|
||||
console.error("error updating", e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reauthenticate the user with the given credential
|
||||
*/
|
||||
async function reauthenticateUser() {
|
||||
if (!currentUser$.value) throw new Error("No user has logged in")
|
||||
const currentAuthMethod = await fetchSignInMethodsForEmail(
|
||||
getAuth(),
|
||||
currentUser$.value.email as string
|
||||
)
|
||||
console.log(currentAuthMethod)
|
||||
|
||||
let credential
|
||||
if (currentAuthMethod.includes("github.com")) {
|
||||
const result = await signInUserWithGithub()
|
||||
credential = GithubAuthProvider.credentialFromResult(result)
|
||||
} else if (currentAuthMethod.includes("google.com")) {
|
||||
const result = await signInUserWithGoogle()
|
||||
credential = GoogleAuthProvider.credentialFromResult(result)
|
||||
} else if (currentAuthMethod.includes("emailLink")) {
|
||||
const email = prompt("Email:")
|
||||
const actionCodeSettings = {
|
||||
url: `${process.env.BASE_URL}/enter`,
|
||||
handleCodeInApp: true,
|
||||
}
|
||||
await signInWithEmail(email as string, actionCodeSettings)
|
||||
}
|
||||
try {
|
||||
await reauthenticateWithCredential(
|
||||
currentUser$.value,
|
||||
credential as AuthCredential
|
||||
).catch((e) => console.error("error updating", e))
|
||||
} catch (e) {
|
||||
console.error("error updating", e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
export function getGithubCredentialFromResult(result: UserCredential) {
|
||||
return GithubAuthProvider.credentialFromResult(result)
|
||||
}
|
||||
|
||||
@@ -178,8 +178,8 @@
|
||||
"json_prettify_invalid_body": "Couldn't prettify an invalid body, solve json syntax errors and try again",
|
||||
"network_error": "There seems to be a network error. Please try again.",
|
||||
"network_fail": "Could not send request",
|
||||
"script_fail": "Could not execute pre-request script",
|
||||
"no_duration": "No duration",
|
||||
"script_fail": "Could not execute pre-request script",
|
||||
"something_went_wrong": "Something went wrong"
|
||||
},
|
||||
"export": {
|
||||
@@ -210,11 +210,11 @@
|
||||
"authorization": "The authorization header will be automatically generated when you send the request.",
|
||||
"generate_documentation_first": "Generate documentation first",
|
||||
"network_fail": "Unable to reach the API endpoint. Check your network connection or turn on Proxy Interceptor and try again.",
|
||||
"script_fail": "It seems there is a glitch in the pre-request script. Check the error below and fix the script accordingly.",
|
||||
"offline": "You seem to be offline. Data in this workspace might not be up to date.",
|
||||
"offline_short": "You seem to be offline.",
|
||||
"post_request_tests": "Test scripts are written in JavaScript, and are run after the response is received.",
|
||||
"pre_request_script": "Pre-request scripts are written in JavaScript, and are run before the request is sent.",
|
||||
"script_fail": "It seems there is a glitch in the pre-request script. Check the error below and fix the script accordingly.",
|
||||
"tests": "Write a test script to automate debugging."
|
||||
},
|
||||
"hide": {
|
||||
@@ -273,6 +273,7 @@
|
||||
"app_settings": "App Settings",
|
||||
"editor": "Editor",
|
||||
"editor_description": "Editors can add, edit, and delete requests.",
|
||||
"email_verification_mail": "A verification email has been sent to your email address. Please click on the link to verify your email address.",
|
||||
"no_permission": "You do not have permission to perform this action.",
|
||||
"owner": "Owner",
|
||||
"owner_description": "Owners can add, edit, and delete requests, collections and team members.",
|
||||
@@ -359,6 +360,7 @@
|
||||
"official_proxy_hosting": "Official Proxy is hosted by Hoppscotch.",
|
||||
"profile": "Profile",
|
||||
"profile_description": "Update your profile details",
|
||||
"profile_email": "Email address",
|
||||
"profile_name": "Profile name",
|
||||
"proxy": "Proxy",
|
||||
"proxy_url": "Proxy URL",
|
||||
@@ -377,7 +379,8 @@
|
||||
"theme": "Theme",
|
||||
"theme_description": "Customize your application theme.",
|
||||
"use_experimental_url_bar": "Use experimental URL bar with environment highlighting",
|
||||
"user": "User"
|
||||
"user": "User",
|
||||
"verify_email": "Verify email"
|
||||
},
|
||||
"shortcut": {
|
||||
"general": {
|
||||
|
||||
@@ -46,6 +46,15 @@
|
||||
name="verified"
|
||||
class="ml-2 text-green-500 svg-icons"
|
||||
/>
|
||||
<ButtonSecondary
|
||||
v-else
|
||||
:label="t('settings.verify_email')"
|
||||
svg="verified"
|
||||
class="ml-2"
|
||||
filled
|
||||
:loading="verifyingEmailAddress"
|
||||
@click.native="sendEmailVerification"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -99,6 +108,31 @@
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
<div class="py-4">
|
||||
<label for="emailAddress">
|
||||
{{ t("settings.profile_email") }}
|
||||
</label>
|
||||
<form
|
||||
class="flex mt-2 md:max-w-sm"
|
||||
@submit.prevent="updateEmailAddress"
|
||||
>
|
||||
<input
|
||||
id="emailAddress"
|
||||
v-model="emailAddress"
|
||||
class="input"
|
||||
:placeholder="`${t('settings.profile_name')}`"
|
||||
type="email"
|
||||
autocomplete="off"
|
||||
required
|
||||
/>
|
||||
<ButtonPrimary
|
||||
:label="t('action.save')"
|
||||
class="ml-2 min-w-16"
|
||||
type="submit"
|
||||
:loading="updatingEmailAddress"
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
<section class="p-4">
|
||||
<h4 class="font-semibold text-secondaryDark">
|
||||
@@ -150,11 +184,21 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, useMeta, defineComponent } from "@nuxtjs/composition-api"
|
||||
import { currentUser$, setDisplayName } from "~/helpers/fb/auth"
|
||||
import { useReadonlyStream, useI18n } from "~/helpers/utils/composables"
|
||||
import {
|
||||
currentUser$,
|
||||
setDisplayName,
|
||||
setEmailAddress,
|
||||
verifyEmailAddress,
|
||||
} from "~/helpers/fb/auth"
|
||||
import {
|
||||
useReadonlyStream,
|
||||
useI18n,
|
||||
useToast,
|
||||
} from "~/helpers/utils/composables"
|
||||
import { toggleSetting, useSetting } from "~/newstore/settings"
|
||||
|
||||
const t = useI18n()
|
||||
const toast = useToast()
|
||||
|
||||
const showLogin = ref(false)
|
||||
|
||||
@@ -168,11 +212,31 @@ const updatingDisplayName = ref(false)
|
||||
|
||||
const updateDisplayName = () => {
|
||||
updatingDisplayName.value = true
|
||||
setDisplayName(displayName.value).finally(() => {
|
||||
setDisplayName(displayName.value as string).finally(() => {
|
||||
updatingDisplayName.value = false
|
||||
})
|
||||
}
|
||||
|
||||
const emailAddress = ref(currentUser$.value?.email)
|
||||
const updatingEmailAddress = ref(false)
|
||||
|
||||
const updateEmailAddress = () => {
|
||||
updatingEmailAddress.value = true
|
||||
setEmailAddress(emailAddress.value as string).finally(() => {
|
||||
updatingEmailAddress.value = false
|
||||
})
|
||||
}
|
||||
|
||||
const verifyingEmailAddress = ref(false)
|
||||
|
||||
const sendEmailVerification = () => {
|
||||
verifyingEmailAddress.value = true
|
||||
verifyEmailAddress().finally(() => {
|
||||
verifyingEmailAddress.value = false
|
||||
toast.success(`${t("profile.email_verification_mail")}`)
|
||||
})
|
||||
}
|
||||
|
||||
useMeta({
|
||||
title: `${t("navigation.profile")} • Hoppscotch`,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user