feat: change and verify user's email address

This commit is contained in:
liyasthomas
2021-12-07 06:52:43 +05:30
parent 02be413eff
commit b0f02fee57
3 changed files with 148 additions and 6 deletions

View File

@@ -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)
}

View File

@@ -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": {

View File

@@ -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`,
})