Skip to content

Commit 03b971e

Browse files
committed
feat: add logs
1 parent 6e627ca commit 03b971e

File tree

6 files changed

+96
-7
lines changed

6 files changed

+96
-7
lines changed

packages/nuxt/src/logging.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export type LogType = 'debug' | 'info' | 'warn' | 'error' | 'trace'
2+
3+
// TODO: allow disabling logs with some env variables
4+
5+
export function log(type: LogType, ...args: any[]): void
6+
export function log(...args: any[]): void
7+
export function log(typeOrLog?: unknown, ...args: any[]): void {
8+
const type = typeof typeOrLog === 'string' ? (typeOrLog as LogType) : 'log'
9+
console[type]('[VueFire]:', ...args)
10+
}

packages/nuxt/src/module.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import type {
1919
import { markRaw } from 'vue'
2020
import type { NuxtVueFireAppCheckOptions } from './runtime/app-check'
2121
import { addMissingAlias } from './firebaseAliases'
22+
import { log } from './logging'
2223

2324
export interface VueFireNuxtModuleOptions {
2425
/**
@@ -161,8 +162,9 @@ const VueFire: NuxtModule<VueFireNuxtModuleOptions> =
161162
// TODO: if options.admin
162163
if (options.admin || nuxt.options.ssr) {
163164
if (!nuxt.options.ssr) {
164-
console.warn(
165-
'[VueFire]: The "admin" option is only used during SSR. You should reenable ssr to use it.'
165+
log(
166+
'warn',
167+
'The "admin" option is only used during SSR. You should reenable ssr to use it.'
166168
)
167169
}
168170
// TODO: check env variables are present

packages/nuxt/src/runtime/admin/plugin-auth-user.server.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { getCookie } from 'h3'
55
// FirebaseError is an interface here but is a class in firebase/app
66
import type { FirebaseError } from 'firebase-admin'
77
import { AUTH_COOKIE_NAME } from '../auth/api.session'
8+
import { log } from '../../logging'
89
import { defineNuxtPlugin, useRequestEvent } from '#app'
910

1011
/**
@@ -15,6 +16,8 @@ export default defineNuxtPlugin(async (nuxtApp) => {
1516
const token = getCookie(event, AUTH_COOKIE_NAME)
1617
let user: UserRecord | undefined
1718

19+
log(`Getting user from "${AUTH_COOKIE_NAME}"`, token)
20+
1821
if (token) {
1922
const adminApp = nuxtApp.$firebaseAdminApp as AdminApp
2023
const adminAuth = getAdminAuth(adminApp)
@@ -29,10 +32,10 @@ export default defineNuxtPlugin(async (nuxtApp) => {
2932
if (isFirebaseError(err) && err.code === 'auth/id-token-expired') {
3033
// Other errors to be handled: auth/argument-error
3134
// the error is fine, the user is not logged in
32-
console.log('[VueFire]: Token expired -', err)
35+
log('Token expired -', err)
3336
} else {
3437
// ignore the error and consider the user as not logged in
35-
console.error('[VueFire]: Unknown Error -', err)
38+
log('error', 'Unknown Error -', err)
3639
}
3740
}
3841
}

packages/nuxt/src/runtime/admin/plugin.server.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
// renamed because there seems to be a global Credential type in vscode
88
Credential as FirebaseAdminCredential,
99
} from 'firebase-admin/app'
10+
import { log } from '../../logging'
1011
import { defineNuxtPlugin, useAppConfig } from '#app'
1112

1213
export default defineNuxtPlugin((nuxtApp) => {
@@ -28,13 +29,13 @@ export default defineNuxtPlugin((nuxtApp) => {
2829
} = process.env
2930

3031
if (FIREBASE_CONFIG || FUNCTION_NAME) {
31-
console.log('[VueFire]: using FIREBASE_CONFIG env variable')
32+
log('using FIREBASE_CONFIG env variable')
3233
initializeApp()
3334
} else {
3435
let credential: FirebaseAdminCredential
3536
// This version should work in Firebase Functions and other providers while applicationDefault() only works on
3637
if (FIREBASE_PRIVATE_KEY) {
37-
console.log('[VueFire]: using FIREBASE_PRIVATE_KEY env variable')
38+
log('using FIREBASE_PRIVATE_KEY env variable')
3839
credential = cert({
3940
projectId: FIREBASE_PROJECT_ID,
4041
clientEmail: FIREBASE_CLIENT_EMAIL,

packages/nuxt/src/runtime/app/plugin.server.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { deleteApp, FirebaseApp, initializeApp } from 'firebase/app'
22
import { User } from 'firebase/auth'
33
import LRU from 'lru-cache'
44
import { UserSymbol } from '../admin/plugin-auth-user.server'
5+
import { log } from '../../logging'
56
import { defineNuxtPlugin, useAppConfig } from '#app'
67

78
// TODO: allow customizing
@@ -31,18 +32,20 @@ export default defineNuxtPlugin((nuxtApp) => {
3132

3233
let firebaseApp: FirebaseApp
3334

35+
log('initializing app with', appConfig.firebaseConfig)
3436
if (uid) {
3537
if (!appCache.has(uid)) {
3638
const randomId = Math.random().toString(36).slice(2)
3739
const appName = `auth:${user.uid}:${randomId}`
3840

39-
console.log('✅ creating new app', appName)
41+
log('✅ creating new app', appName)
4042

4143
appCache.set(uid, initializeApp(appConfig.firebaseConfig, appName))
4244
}
4345
firebaseApp = appCache.get(uid)!
4446
} else {
4547
// anonymous session, just create a new app
48+
log('anonymous session')
4649
firebaseApp = initializeApp(appConfig.firebaseConfig)
4750
}
4851

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { getApp } from 'firebase-admin/app'
2+
import { getAuth as getAdminAuth } from 'firebase-admin/auth'
3+
import {
4+
readBody,
5+
setCookie,
6+
assertMethod,
7+
defineEventHandler,
8+
deleteCookie,
9+
sendRedirect,
10+
} from 'h3'
11+
import { log } from '../../logging'
12+
import { AUTH_COOKIE_MAX_AGE, AUTH_COOKIE_NAME } from './api.session'
13+
14+
// This version is used at https://github.com/FirebaseExtended/firebase-framework-tools/blob/e69f5bdd44695274ad88dbb4e21aac778ba60cc8/src/firebase-aware.ts#L39 but doesn't work locally. Should it maybe be used in production only? Seems unlikely.
15+
16+
/**
17+
* Setups an API endpoint to be used by the client to mint a cookie based auth session.
18+
*/
19+
export default defineEventHandler(async (event) => {
20+
assertMethod(event, 'POST')
21+
const { token } = await readBody(event)
22+
23+
log('minting a session cookie')
24+
const adminApp = getApp()
25+
const adminAuth = getAdminAuth(adminApp)
26+
27+
log('read idToken from Authorization header', token)
28+
const verifiedIdToken = token ? await adminAuth.verifyIdToken(token) : null
29+
30+
if (verifiedIdToken) {
31+
if (
32+
new Date().getTime() / 1_000 - verifiedIdToken.auth_time >
33+
ID_TOKEN_MAX_AGE
34+
) {
35+
event.node.res.statusCode = 301
36+
return ''
37+
} else {
38+
const cookie = await adminAuth
39+
.createSessionCookie(token!, { expiresIn: AUTH_COOKIE_MAX_AGE })
40+
.catch((e: any) => {
41+
log('error', 'Error minting the cookie -', e.message)
42+
})
43+
if (cookie) {
44+
log('minted a session cookie', cookie)
45+
setCookie(event, AUTH_COOKIE_NAME, cookie, {
46+
maxAge: AUTH_COOKIE_MAX_AGE,
47+
secure: true,
48+
httpOnly: true,
49+
path: '/',
50+
sameSite: 'lax',
51+
})
52+
event.node.res.statusCode = 201
53+
return ''
54+
} else {
55+
log('failed to mint a session cookie')
56+
event.node.res.statusCode = 401
57+
return ''
58+
}
59+
}
60+
} else {
61+
log('deleting the session cookie')
62+
deleteCookie(event, AUTH_COOKIE_NAME)
63+
event.node.res.statusCode = 204
64+
}
65+
66+
// empty response
67+
return ''
68+
})
69+
70+
export const ID_TOKEN_MAX_AGE = 5 * 60

0 commit comments

Comments
 (0)