Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 41 additions & 3 deletions src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import {
createWebHistory
} from 'vue-router'

import { useDialogService } from '@/services/dialogService'
import { useFirebaseAuthStore } from '@/stores/firebaseAuthStore'
import { useUserStore } from '@/stores/userStore'
import { isElectron } from '@/utils/envUtil'
import LayoutDefault from '@/views/layouts/LayoutDefault.vue'

import { useUserStore } from './stores/userStore'
import { isElectron } from './utils/envUtil'

const isFileProtocol = window.location.protocol === 'file:'
const basePath = isElectron() ? '/' : window.location.pathname

Expand Down Expand Up @@ -56,4 +57,41 @@ const router = createRouter({
}
})

// Global authentication guard
router.beforeEach(async (_to, _from, next) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

short term: isCloud
long term: extension for router hooks

const authStore = useFirebaseAuthStore()

// Wait for Firebase auth to initialize
if (!authStore.isInitialized) {
await new Promise<void>((resolve) => {
const unwatch = authStore.$subscribe((_, state) => {
if (state.isInitialized) {
unwatch()
resolve()
}
})
})
}

// Check if user is authenticated (Firebase or API key)
const authHeader = await authStore.getAuthHeader()

if (!authHeader) {
Copy link
Contributor Author

@arjansingh arjansingh Oct 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (authHeader) { 
  next()
  return
}

// User is not authenticated, show sign-in dialog
const dialogService = useDialogService()
const loginSuccess = await dialogService.showSignInDialog()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

double check to see if this is part of the app already.


if (loginSuccess) {
// After successful login, proceed to the intended route
next()
} else {
// User cancelled login, stay on current page or redirect to home
next(false)
}
} else {
// User is authenticated, proceed
next()
}
})

export default router
51 changes: 50 additions & 1 deletion src/scripts/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ import type {
} from '@/schemas/apiSchema'
import type { ComfyNodeDef } from '@/schemas/nodeDefSchema'
import type { NodeExecutionId } from '@/types/nodeIdentification'
<<<<<<< HEAD
=======
import { useFirebaseAuthStore } from '@/stores/firebaseAuthStore'
import { WorkflowTemplates } from '@/types/workflowTemplateTypes'
>>>>>>> 23e881e22 (Prevent access without login.)

interface QueuePromptRequestBody {
client_id: string
Expand Down Expand Up @@ -317,7 +322,27 @@ export class ComfyApi extends EventTarget {
return this.api_base + route
}

fetchApi(route: string, options?: RequestInit) {
/**
* Waits for Firebase auth to be initialized before proceeding
*/
async #waitForAuthInitialization(): Promise<void> {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private typescript

const authStore = useFirebaseAuthStore()

if (authStore.isInitialized) {
return
}

return new Promise<void>((resolve) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

await

const unwatch = authStore.$subscribe((_, state) => {
if (state.isInitialized) {
unwatch()
resolve()
}
})
})
}

async fetchApi(route: string, options?: RequestInit) {
if (!options) {
options = {}
}
Expand All @@ -328,6 +353,30 @@ export class ComfyApi extends EventTarget {
options.cache = 'no-cache'
}

// Wait for Firebase auth to be initialized before making any API request
await this.#waitForAuthInitialization()

// Add Firebase JWT token if user is logged in
try {
const authHeader = await useFirebaseAuthStore().getAuthHeader()
if (authHeader) {
if (Array.isArray(options.headers)) {
for (const [key, value] of Object.entries(authHeader)) {
options.headers.push([key, value])
}
} else if (options.headers instanceof Headers) {
for (const [key, value] of Object.entries(authHeader)) {
options.headers.set(key, value)
}
} else {
Object.assign(options.headers, authHeader)
}
}
} catch (error) {
// Silently ignore auth errors to avoid breaking API calls
console.warn('Failed to get auth header:', error)
}

if (Array.isArray(options.headers)) {
options.headers.push(['Comfy-User', this.user])
} else if (options.headers instanceof Headers) {
Expand Down