All files / src/stores auth.ts

96.61% Statements 57/59
76.92% Branches 10/13
100% Functions 4/4
96.61% Lines 57/59

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108  2x 2x 2x                                                                           2x 2x 2x 4x 4x 4x 4x     4x     4x 1x 1x 1x 1x 1x 1x 1x 1x     1x 1x 1x 1x   4x 2x 1x 1x 1x 1x 2x 1x 1x 1x 1x 2x   4x 1x 1x   4x 2x 2x 2x 2x 2x   4x 4x 4x 4x 4x 4x   4x 4x 4x 4x 4x 2x    
// region Dependency Injection
import {defineStore} from 'pinia'
import {computed, ref} from 'vue'
import {getAuth, onIdTokenChanged, type User} from 'firebase/auth'
// endregion Dependency Injection
 
// region Component Injection
// endregion Component Injection
 
// region interface
type AppUser = {
  id?: string
  uid: string
  email?: string | null
  name?: string | null
  role?: string | null
}
// endregion interface
 
// region constants
// endregion constants
 
// region props
// endregion props
 
// region variable
// endregion variable
 
// region properties
// endregion properties
 
// region emits
// endregion emits
 
// region validator
// endregion validator
 
// region methods
// endregion methods
 
// region export
export const useAuthStore = defineStore(
  'auth',
  () => {
    const firebaseUser = ref<User | null>(null)
    const idToken = ref<string | null>(null)
    const idTokenRefreshedAt = ref(0)
    const appUser = ref<AppUser | null>(null)
 
    // getter
    const isAuthenticated = computed(() => !!firebaseUser.value && !!idToken.value)
 
    // actions
    const init = async () => {
      const auth = getAuth()
      return new Promise<void>((resolve) => {
        onIdTokenChanged(auth, async (user) => {
          firebaseUser.value = user
          if (user) {
            idToken.value = await user.getIdToken(false)
            idTokenRefreshedAt.value = Date.now()
          } else {
            clear()
          }
          resolve()
        })
      })
    }
 
    const refreshIdToken = async (force = false) => {
      if (!firebaseUser.value) {
        idToken.value = null
        return null
      }
      const stale = Date.now() - idTokenRefreshedAt.value > 5 * 60 * 1000
      if (force || stale || !idToken.value) {
        idToken.value = await firebaseUser.value.getIdToken(force)
        idTokenRefreshedAt.value = Date.now()
      }
      return idToken.value
    }
 
    const setAppUser = (u: AppUser | null) => {
      appUser.value = u
    }
 
    const clear = () => {
      firebaseUser.value = null
      idToken.value = null
      idTokenRefreshedAt.value = 0
      appUser.value = null
    }
 
    return {
      firebaseUser,
      idToken,
      idTokenRefreshedAt,
      appUser,
      isAuthenticated,
 
      init,
      refreshIdToken,
      setAppUser,
      clear,    }
  }
)
// endregion export