UNPKG

apphouse

Version:

Component library for React that uses observable state management and theme-able components.

338 lines (300 loc) 8.53 kB
import { getAuth, createUserWithEmailAndPassword, signOut, onAuthStateChanged, signInWithEmailAndPassword, updateProfile, sendPasswordResetEmail } from 'firebase/auth'; import { getDatabase, ref, onValue } from 'firebase/database'; import { makeAutoObservable } from 'mobx'; import { currentLocale } from '../app/i18n/Locale'; import { UserProfile, GET_FIREBASE_STORAGE_IMAGE_PROFILE_PATH, GET_FIREBASE_STORAGE_RESIZED_IMAGE_PROFILE_PATH } from './UserProfile'; import { getStorage, ref as storageRef, getDownloadURL, deleteObject } from 'firebase/storage'; export interface UserType { displayName: string; language: string; email?: string; photoURL?: string; uid?: string; } export class User { authenticated: boolean; authorized: boolean; displayName: string; language: string; email?: string; errorCode?: string; errorMessage?: string; firebaseUser: any; photoURL?: string; uid?: string; firebase: any; allowDiscovery: boolean; analytics: any; connected: boolean; lastUpdated?: number; profile: UserProfile; profilePhotoToken?: string; onLogout: () => void; constructor(onLogout: () => void) { this.authenticated = false; // NOTE: You can be authenticated but not authorized this.authorized = false; this.language = currentLocale.locale; this.allowDiscovery = false; this.displayName = ''; this.connected = false; this.lastUpdated = undefined; this.email = undefined; this.profile = new UserProfile({}); this.onLogout = onLogout; this.profilePhotoToken = undefined; makeAutoObservable(this); } get hasAccess(): boolean { return this.authenticated && this.authorized; } get isPremiumMember(): boolean { return this.profile.membership === 'premium'; } initFirebase = () => { // Attach observer const auth = getAuth(); onAuthStateChanged(auth, async (user) => { if (user) { // User is signed in, see docs for a list of available properties // https://firebase.google.com/docs/reference/js/firebase.User const uid = auth.currentUser?.uid; this.setAuthorized(true); this.setFirebaseUser(user); this.setDisplayName(user?.displayName || undefined); this.setPhotoURL(user?.photoURL || undefined); this.setUid(uid); this.setEmail(user?.email || undefined); this.setAuthenticated(true); this.detectConnectionState(); } else { // User is signed out this.setAuthorized(false); this.setAuthenticated(true); } }); }; setFirebase = (firebase: any) => { this.firebase = firebase; }; setFirebaseUser = (user: any) => { this.firebaseUser = user; }; private setAuthorized = (value: boolean) => { this.authorized = value; }; setLanguage = (value: string) => { this.language = value; currentLocale.setStringsForLocale(value); }; setEmail = (value?: string) => { this.email = value; }; setDisplayName = (value?: string) => { this.displayName = value || ''; }; setUid = (value?: string) => { this.uid = value; }; setErrorCode = (value?: string) => { this.errorCode = value; }; setErrorMessage = (value?: string) => { this.errorMessage = value; }; private setAuthenticated = (value: boolean) => { this.authenticated = value; }; setPhotoURL = (value?: string) => { this.photoURL = value; }; static getProfileImageUrl = async (userId: string) => { const storage = getStorage(); const imageRefUrl = GET_FIREBASE_STORAGE_RESIZED_IMAGE_PROFILE_PATH(userId); const sRef = storageRef(storage, imageRefUrl); return await getDownloadURL(sRef); }; setAllowDiscovery = (value?: boolean) => { this.allowDiscovery = value || false; }; sendPasswordResetEmail = (email: string) => { const auth = getAuth(); return sendPasswordResetEmail(auth, email); }; signupWithEmailAndPassword = async (email: string, password: string) => { this.setAuthenticated(false); // using firebase v8 const auth = getAuth(); await createUserWithEmailAndPassword(auth, email.toLowerCase(), password) .then((userCredential) => { // Signed in const user = userCredential.user; this.setUid(user.uid); this.setEmail(user?.email || undefined); this.setAuthenticated(true); this.setAuthorized(true); // CREATE USER PROFILE WHEN SIGNING UP }) .catch((error) => { const errorCode = error.code; const errorMessage = error.message; this.setAuthenticated(true); this.setAuthorized(false); this.setErrorMessage(errorMessage); this.setErrorCode(errorCode); }); }; signIn = async (email: string, password: string): Promise<boolean> => { console.log('signIn', email, password); this.setAuthenticated(false); const { setUid, setEmail, setAuthenticated, setAuthorized, setErrorMessage, setErrorCode } = this; // using firebase v8 const auth = getAuth(); const signedIn = await signInWithEmailAndPassword( auth, email.toLocaleLowerCase(), password ) .then((userCredential) => { // Signed in const user = userCredential.user; setUid(user.uid); setEmail(user?.email || undefined); setAuthenticated(true); setAuthorized(true); setErrorMessage(undefined); setErrorCode(undefined); return true; }) .catch((error) => { console.log('error', error); const errorCode = error.code; const errorMessage = error.message; setAuthenticated(true); setAuthorized(false); setErrorMessage(errorMessage); setErrorCode(errorCode); return false; }); return signedIn; }; updateDisplayName = (displayName: string) => { if (this.firebaseUser) { // Updates the user attributes: updateProfile(this.firebaseUser, { displayName }).then( () => { // Profile updated successfully! const displayName = this.firebaseUser.displayName; this.setDisplayName(displayName); }, (error: any) => { // An error happened. console.log({ error }); } ); } }; updatePhotoUrl = (photoURL: string) => { if (this.firebaseUser) { // Updates the user attributes: this.firebaseUser .updateProfile({ photoURL }) .then( () => { // Profile updated successfully! const photoURL = this.firebaseUser.photoURL; this.setPhotoURL(photoURL); }, (error: any) => { // An error happened. console.log({ error }); } ); } }; logout = () => { this.onLogout(); const auth = getAuth(); signOut(auth) .then(() => { // Sign-out successful. this.setUid(undefined); this.setAuthorized(false); this.setAuthenticated(true); this.setEmail(undefined); this.setDisplayName(undefined); this.setPhotoURL(undefined); }) .catch((error) => { console.log({ error }); // An error happened. }); }; detectConnectionState() { const db = getDatabase(); const connectedRef = ref(db, '.info/connected'); onValue(connectedRef, (snap) => { if (snap.val() === true) { this.setConnected(true); } else { this.setConnected(false); } }); } setConnected = (value: boolean) => { this.connected = value; }; setLastUpdated = (value: number) => { this.lastUpdated = value; }; onDeleteImageProfile = async () => { const email = this.email; if (email) { const storage = getStorage(); // Create a reference to the file to delete const desertRef = storageRef( storage, GET_FIREBASE_STORAGE_IMAGE_PROFILE_PATH(email) ); // Delete the file await deleteObject(desertRef); } }; } // export const GET_FIREBASE_STORAGE_IMAGE_PROFILE_PATH_URI = ( // email: string, // token: string // ) => { // return `https://firebasestorage.googleapis.com/v0/b/${ // firebaseConfig.storageBucket // }/o/${encodeURIComponent( // GET_FIREBASE_STORAGE_IMAGE_PROFILE_PATH(email) // )}?alt=media&token=${token}`; // };