[API Node] Allow authentification via Comfy API key (#3815)

Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
Christian Byrne
2025-05-09 10:42:03 -07:00
committed by GitHub
parent aa46524829
commit 34b1fd5a72
17 changed files with 692 additions and 108 deletions

View File

@@ -20,6 +20,8 @@ import { useFirebaseAuth } from 'vuefire'
import { COMFY_API_BASE_URL } from '@/config/comfyApi'
import { t } from '@/i18n'
import { useApiKeyAuthStore } from '@/stores/apiKeyAuthStore'
import { type AuthHeader } from '@/types/authTypes'
import { operations } from '@/types/comfyRegistryTypes'
type CreditPurchaseResponse =
@@ -93,12 +95,34 @@ export const useFirebaseAuthStore = defineStore('firebaseAuth', () => {
return null
}
/**
* Retrieves the appropriate authentication header for API requests.
* Checks for authentication in the following order:
* 1. Firebase authentication token (if user is logged in)
* 2. API key (if stored in the browser's credential manager)
*
* @returns {Promise<AuthHeader | null>}
* - A LoggedInAuthHeader with Bearer token if Firebase authenticated
* - An ApiKeyAuthHeader with X-API-KEY if API key exists
* - null if neither authentication method is available
*/
const getAuthHeader = async (): Promise<AuthHeader | null> => {
const token = await getIdToken()
if (token) {
return {
Authorization: `Bearer ${token}`
}
}
const apiKeyStore = useApiKeyAuthStore()
return apiKeyStore.getAuthHeader()
}
const fetchBalance = async (): Promise<GetCustomerBalanceResponse | null> => {
isFetchingBalance.value = true
try {
const token = await getIdToken()
if (!token) {
isFetchingBalance.value = false
const authHeader = await getAuthHeader()
if (!authHeader) {
throw new FirebaseAuthStoreError(
t('toastMessages.userNotAuthenticated')
)
@@ -106,7 +130,8 @@ export const useFirebaseAuthStore = defineStore('firebaseAuth', () => {
const response = await fetch(`${COMFY_API_BASE_URL}/customers/balance`, {
headers: {
Authorization: `Bearer ${token}`
...authHeader,
'Content-Type': 'application/json'
}
})
@@ -133,14 +158,17 @@ export const useFirebaseAuthStore = defineStore('firebaseAuth', () => {
}
}
const createCustomer = async (
token: string
): Promise<CreateCustomerResponse> => {
const createCustomer = async (): Promise<CreateCustomerResponse> => {
const authHeader = await getAuthHeader()
if (!authHeader) {
throw new FirebaseAuthStoreError(t('toastMessages.userNotAuthenticated'))
}
const createCustomerRes = await fetch(`${COMFY_API_BASE_URL}/customers`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`
...authHeader,
'Content-Type': 'application/json'
}
})
if (!createCustomerRes.ok) {
@@ -181,7 +209,7 @@ export const useFirebaseAuthStore = defineStore('firebaseAuth', () => {
if (!token) {
throw new Error('Cannot create customer: User not authenticated')
}
await createCustomer(token)
await createCustomer()
}
return result
@@ -242,22 +270,22 @@ export const useFirebaseAuthStore = defineStore('firebaseAuth', () => {
const addCredits = async (
requestBodyContent: CreditPurchasePayload
): Promise<CreditPurchaseResponse> => {
const token = await getIdToken()
if (!token) {
const authHeader = await getAuthHeader()
if (!authHeader) {
throw new FirebaseAuthStoreError(t('toastMessages.userNotAuthenticated'))
}
// Ensure customer was created during login/registration
if (!customerCreated.value) {
await createCustomer(token)
await createCustomer()
customerCreated.value = true
}
const response = await fetch(`${COMFY_API_BASE_URL}/customers/credit`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`
...authHeader,
'Content-Type': 'application/json'
},
body: JSON.stringify(requestBodyContent)
})
@@ -282,16 +310,16 @@ export const useFirebaseAuthStore = defineStore('firebaseAuth', () => {
const accessBillingPortal = async (
requestBody?: AccessBillingPortalReqBody
): Promise<AccessBillingPortalResponse> => {
const token = await getIdToken()
if (!token) {
const authHeader = await getAuthHeader()
if (!authHeader) {
throw new FirebaseAuthStoreError(t('toastMessages.userNotAuthenticated'))
}
const response = await fetch(`${COMFY_API_BASE_URL}/customers/billing`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`
...authHeader,
'Content-Type': 'application/json'
},
...(requestBody && {
body: JSON.stringify(requestBody)
@@ -335,6 +363,7 @@ export const useFirebaseAuthStore = defineStore('firebaseAuth', () => {
fetchBalance,
accessBillingPortal,
sendPasswordReset,
updatePassword: _updatePassword
updatePassword: _updatePassword,
getAuthHeader
}
})