"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "helpers/fb/auth.ts" between
hoppscotch-2.0.0.tar.gz and hoppscotch-2.1.0.tar.gz

About: Hoppscotch is a light-weight, web based API development suite.

auth.ts  (hoppscotch-2.0.0):auth.ts  (hoppscotch-2.1.0)
import firebase from "firebase/app" import {
import "firebase/firestore" User,
import "firebase/auth" getAuth,
onAuthStateChanged,
onIdTokenChanged,
signInWithPopup,
GoogleAuthProvider,
GithubAuthProvider,
signInWithEmailAndPassword as signInWithEmailAndPass,
isSignInWithEmailLink as isSignInWithEmailLinkFB,
fetchSignInMethodsForEmail,
sendSignInLinkToEmail,
signInWithEmailLink as signInWithEmailLinkFB,
ActionCodeSettings,
signOut,
linkWithCredential,
AuthCredential,
UserCredential,
updateProfile,
} from "firebase/auth"
import {
onSnapshot,
getFirestore,
setDoc,
doc,
updateDoc,
} from "firebase/firestore"
import { import {
BehaviorSubject, BehaviorSubject,
distinctUntilChanged, distinctUntilChanged,
filter, filter,
map, map,
Subject, Subject,
Subscription, Subscription,
} from "rxjs" } from "rxjs"
import { onBeforeUnmount, onMounted } from "@nuxtjs/composition-api" import { onBeforeUnmount, onMounted } from "@nuxtjs/composition-api"
import {
setLocalConfig,
getLocalConfig,
removeLocalConfig,
} from "~/newstore/localpersistence"
export type HoppUser = firebase.User & { export type HoppUser = User & {
provider?: string provider?: string
accessToken?: string accessToken?: string
} }
type AuthEvents = type AuthEvents =
| { event: "login"; user: HoppUser } | { event: "probable_login"; user: HoppUser } // We have previous login state,
| { event: "logout" } but the app is waiting for authentication
| { event: "authTokenUpdate"; user: HoppUser; newToken: string | null } | { event: "login"; user: HoppUser } // We are authenticated
| { event: "logout" } // No authentication and we have no previous state
| { event: "authTokenUpdate"; user: HoppUser; newToken: string | null } // Tok
en has been updated
/** /**
* A BehaviorSubject emitting the currently logged in user (or null if not logge d in) * A BehaviorSubject emitting the currently logged in user (or null if not logge d in)
*/ */
export const currentUser$ = new BehaviorSubject<HoppUser | null>(null) export const currentUser$ = new BehaviorSubject<HoppUser | null>(null)
/** /**
* A BehaviorSubject emitting the current idToken * A BehaviorSubject emitting the current idToken
*/ */
export const authIdToken$ = new BehaviorSubject<string | null>(null) export const authIdToken$ = new BehaviorSubject<string | null>(null)
/** /**
* A subject that emits events related to authentication flows * A subject that emits events related to authentication flows
*/ */
export const authEvents$ = new Subject<AuthEvents>() export const authEvents$ = new Subject<AuthEvents>()
/** /**
* Like currentUser$ but also gives probable user value
*/
export const probableUser$ = new BehaviorSubject<HoppUser | null>(null)
/**
* Resolves when the probable login resolves into proper login
*/
export const waitProbableLoginToConfirm = () =>
new Promise<void>((resolve, reject) => {
if (authIdToken$.value) resolve()
if (!probableUser$.value) reject(new Error("no_probable_user"))
const sub = authIdToken$.pipe(filter((token) => !!token)).subscribe(() => {
sub?.unsubscribe()
resolve()
})
})
/**
* Initializes the firebase authentication related subjects * Initializes the firebase authentication related subjects
*/ */
export function initAuth() { export function initAuth() {
const auth = getAuth()
const firestore = getFirestore()
let extraSnapshotStop: (() => void) | null = null let extraSnapshotStop: (() => void) | null = null
firebase.auth().onAuthStateChanged((user) => { probableUser$.next(JSON.parse(getLocalConfig("login_state") ?? "null"))
onAuthStateChanged(auth, (user) => {
/** Whether the user was logged in before */ /** Whether the user was logged in before */
const wasLoggedIn = currentUser$.value !== null const wasLoggedIn = currentUser$.value !== null
if (user) {
probableUser$.next(user)
} else {
probableUser$.next(null)
removeLocalConfig("login_state")
}
if (!user && extraSnapshotStop) { if (!user && extraSnapshotStop) {
extraSnapshotStop() extraSnapshotStop()
extraSnapshotStop = null extraSnapshotStop = null
} else if (user) { } else if (user) {
// Merge all the user info from all the authenticated providers // Merge all the user info from all the authenticated providers
user.providerData.forEach((profile) => { user.providerData.forEach((profile) => {
if (!profile) return if (!profile) return
const us = { const us = {
updatedOn: new Date(), updatedOn: new Date(),
provider: profile.providerId, provider: profile.providerId,
name: profile.displayName, name: profile.displayName,
email: profile.email, email: profile.email,
photoUrl: profile.photoURL, photoUrl: profile.photoURL,
uid: profile.uid, uid: profile.uid,
} }
firebase setDoc(doc(firestore, "users", user.uid), us, { merge: true }).catch(
.firestore() (e) => console.error("error updating", us, e)
.collection("users") )
.doc(user.uid)
.set(us, { merge: true })
.catch((e) => console.error("error updating", us, e))
}) })
extraSnapshotStop = firebase extraSnapshotStop = onSnapshot(
.firestore() doc(firestore, "users", user.uid),
.collection("users") (doc) => {
.doc(user.uid)
.onSnapshot((doc) => {
const data = doc.data() const data = doc.data()
const userUpdate: HoppUser = user const userUpdate: HoppUser = user
if (data) { if (data) {
// Write extra provider data // Write extra provider data
userUpdate.provider = data.provider userUpdate.provider = data.provider
userUpdate.accessToken = data.accessToken userUpdate.accessToken = data.accessToken
} }
currentUser$.next(userUpdate) currentUser$.next(userUpdate)
}) }
)
} }
currentUser$.next(user) currentUser$.next(user)
// User wasn't found before, but now is there (login happened) // User wasn't found before, but now is there (login happened)
if (!wasLoggedIn && user) { if (!wasLoggedIn && user) {
authEvents$.next({ authEvents$.next({
event: "login", event: "login",
user: currentUser$.value!!, user: currentUser$.value!!,
}) })
} else if (wasLoggedIn && !user) { } else if (wasLoggedIn && !user) {
// User was found before, but now is not there (logout happened) // User was found before, but now is not there (logout happened)
authEvents$.next({ authEvents$.next({
event: "logout", event: "logout",
}) })
} }
}) })
firebase.auth().onIdTokenChanged(async (user) => { onIdTokenChanged(auth, async (user) => {
if (user) { if (user) {
authIdToken$.next(await user.getIdToken()) authIdToken$.next(await user.getIdToken())
authEvents$.next({ authEvents$.next({
event: "authTokenUpdate", event: "authTokenUpdate",
newToken: authIdToken$.value, newToken: authIdToken$.value,
user: currentUser$.value!!, // Force not-null because user is defined user: currentUser$.value!!, // Force not-null because user is defined
}) })
setLocalConfig("login_state", JSON.stringify(user))
} else { } else {
authIdToken$.next(null) authIdToken$.next(null)
} }
}) })
} }
export function getAuthIDToken(): string | null {
return authIdToken$.getValue()
}
/** /**
* Sign user in with a popup using Google * Sign user in with a popup using Google
*/ */
export async function signInUserWithGoogle() { export async function signInUserWithGoogle() {
return await firebase return await signInWithPopup(getAuth(), new GoogleAuthProvider())
.auth()
.signInWithPopup(new firebase.auth.GoogleAuthProvider())
} }
/** /**
* Sign user in with a popup using Github * Sign user in with a popup using Github
*/ */
export async function signInUserWithGithub() { export async function signInUserWithGithub() {
return await firebase return await signInWithPopup(
.auth() getAuth(),
.signInWithPopup(new firebase.auth.GithubAuthProvider().addScope("gist")) new GithubAuthProvider().addScope("gist")
)
} }
/** /**
* Sign user in with email and password * Sign user in with email and password
*/ */
export async function signInWithEmailAndPassword( export async function signInWithEmailAndPassword(
email: string, email: string,
password: string password: string
) { ) {
return await firebase.auth().signInWithEmailAndPassword(email, password) return await signInWithEmailAndPass(getAuth(), email, password)
} }
/** /**
* Gets the sign in methods for a given email address * Gets the sign in methods for a given email address
* *
* @param email - Email to get the methods of * @param email - Email to get the methods of
* *
* @returns Promise for string array of the auth provider methods accessible * @returns Promise for string array of the auth provider methods accessible
*/ */
export async function getSignInMethodsForEmail(email: string) { export async function getSignInMethodsForEmail(email: string) {
return await firebase.auth().fetchSignInMethodsForEmail(email) return await fetchSignInMethodsForEmail(getAuth(), email)
}
export async function linkWithFBCredential(
user: User,
credential: AuthCredential
) {
return await linkWithCredential(user, credential)
} }
/** /**
* Sends an email with the signin link to the user * Sends an email with the signin link to the user
* *
* @param email - Email to send the email to * @param email - Email to send the email to
* @param actionCodeSettings - The settings to apply to the link * @param actionCodeSettings - The settings to apply to the link
*/ */
export async function signInWithEmail( export async function signInWithEmail(
email: string, email: string,
actionCodeSettings: firebase.auth.ActionCodeSettings actionCodeSettings: ActionCodeSettings
) { ) {
return await firebase.auth().sendSignInLinkToEmail(email, actionCodeSettings) return await sendSignInLinkToEmail(getAuth(), email, actionCodeSettings)
} }
/** /**
* Checks and returns whether the sign in link is an email link * Checks and returns whether the sign in link is an email link
* *
* @param url - The URL to look in * @param url - The URL to look in
*/ */
export function isSignInWithEmailLink(url: string) { export function isSignInWithEmailLink(url: string) {
return firebase.auth().isSignInWithEmailLink(url) return isSignInWithEmailLinkFB(getAuth(), url)
} }
/** /**
* Sends an email with sign in with email link * Sends an email with sign in with email link
* *
* @param email - Email to log in to * @param email - Email to log in to
* @param url - The action URL which is used to validate login * @param url - The action URL which is used to validate login
*/ */
export async function signInWithEmailLink(email: string, url: string) { export async function signInWithEmailLink(email: string, url: string) {
return await firebase.auth().signInWithEmailLink(email, url) return await signInWithEmailLinkFB(getAuth(), email, url)
} }
/** /**
* Signs out the user * Signs out the user
*/ */
export async function signOutUser() { export async function signOutUser() {
if (!currentUser$.value) throw new Error("No user has logged in") if (!currentUser$.value) throw new Error("No user has logged in")
await firebase.auth().signOut() await signOut(getAuth())
} }
/** /**
* Sets the provider id and relevant provider auth token * Sets the provider id and relevant provider auth token
* as user metadata * as user metadata
* *
* @param id - The provider ID * @param id - The provider ID
* @param token - The relevant auth token for the given provider * @param token - The relevant auth token for the given provider
*/ */
export async function setProviderInfo(id: string, token: string) { export async function setProviderInfo(id: string, token: string) {
if (!currentUser$.value) throw new Error("No user has logged in") if (!currentUser$.value) throw new Error("No user has logged in")
const us = { const us = {
updatedOn: new Date(), updatedOn: new Date(),
provider: id, provider: id,
accessToken: token, accessToken: token,
} }
try { try {
await firebase await updateDoc(
.firestore() doc(getFirestore(), "users", currentUser$.value.uid),
.collection("users") us
.doc(currentUser$.value.uid) ).catch((e) => console.error("error updating", us, e))
.update(us)
.catch((e) => console.error("error updating", us, e))
} catch (e) { } catch (e) {
console.error("error updating", e) console.error("error updating", e)
throw e throw e
} }
} }
/** /**
* Sets the user's display name
*
* @param name - The new display name
*/
export async function setDisplayName(name: string) {
if (!currentUser$.value) throw new Error("No user has logged in")
const us = {
displayName: name,
}
try {
await updateProfile(currentUser$.value, us).catch((e) =>
console.error("error updating", us, e)
)
} catch (e) {
console.error("error updating", e)
throw e
}
}
export function getGithubCredentialFromResult(result: UserCredential) {
return GithubAuthProvider.credentialFromResult(result)
}
/**
* A Vue composable function that is called when the auth status * A Vue composable function that is called when the auth status
* is being updated to being logged in (fired multiple times), * is being updated to being logged in (fired multiple times),
* this is also called on component mount if the login * this is also called on component mount if the login
* was already resolved before mount. * was already resolved before mount.
*/ */
export function onLoggedIn(exec: (user: HoppUser) => void) { export function onLoggedIn(exec: (user: HoppUser) => void) {
let sub: Subscription | null = null let sub: Subscription | null = null
onMounted(() => { onMounted(() => {
sub = currentUser$ sub = currentUser$
 End of changes. 25 change blocks. 
40 lines changed or deleted 136 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)