diff --git a/src/composables/auth/useCurrentUser.ts b/src/composables/auth/useCurrentUser.ts index 3999aa9c1..cf89c1069 100644 --- a/src/composables/auth/useCurrentUser.ts +++ b/src/composables/auth/useCurrentUser.ts @@ -1,3 +1,4 @@ +import { whenever } from '@vueuse/core' import { computed } from 'vue' import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions' @@ -6,6 +7,7 @@ import { useDialogService } from '@/services/dialogService' import { useApiKeyAuthStore } from '@/stores/apiKeyAuthStore' import { useCommandStore } from '@/stores/commandStore' import { useFirebaseAuthStore } from '@/stores/firebaseAuthStore' +import type { AuthUserInfo } from '@/types/authTypes' export const useCurrentUser = () => { const authStore = useFirebaseAuthStore() @@ -20,6 +22,27 @@ export const useCurrentUser = () => { () => !!isApiKeyLogin.value || firebaseUser.value !== null ) + const resolvedUserInfo = computed(() => { + if (isApiKeyLogin.value && apiKeyStore.currentUser) { + return { id: apiKeyStore.currentUser.id } + } + + if (firebaseUser.value) { + return { id: firebaseUser.value.uid } + } + + return null + }) + + const onUserResolved = (callback: (user: AuthUserInfo) => void) => { + if (resolvedUserInfo.value) { + callback(resolvedUserInfo.value) + } + + const stop = whenever(resolvedUserInfo, callback) + return () => stop() + } + const userDisplayName = computed(() => { if (isApiKeyLogin.value) { return apiKeyStore.currentUser?.name @@ -112,8 +135,10 @@ export const useCurrentUser = () => { userPhotoUrl, providerName, providerIcon, + resolvedUserInfo, handleSignOut, handleSignIn, - handleDeleteAccount + handleDeleteAccount, + onUserResolved } } diff --git a/src/services/extensionService.ts b/src/services/extensionService.ts index 457f566b9..26b67fba7 100644 --- a/src/services/extensionService.ts +++ b/src/services/extensionService.ts @@ -1,3 +1,4 @@ +import { useCurrentUser } from '@/composables/auth/useCurrentUser' import { useErrorHandling } from '@/composables/useErrorHandling' import { useSettingStore } from '@/platform/settings/settingStore' import { api } from '@/scripts/api' @@ -72,6 +73,13 @@ export const useExtensionService = () => { } })() } + + if (extension.onAuthUserResolved) { + const { onUserResolved } = useCurrentUser() + onUserResolved((user) => { + void extension.onAuthUserResolved?.(user, app) + }) + } } /** diff --git a/src/types/authTypes.ts b/src/types/authTypes.ts index 07bb43dd6..5f3891bd5 100644 --- a/src/types/authTypes.ts +++ b/src/types/authTypes.ts @@ -7,3 +7,7 @@ export type ApiKeyAuthHeader = { } export type AuthHeader = LoggedInAuthHeader | ApiKeyAuthHeader + +export interface AuthUserInfo { + id: string +} diff --git a/src/types/comfy.ts b/src/types/comfy.ts index 8cfb8fa61..53ce42ce8 100644 --- a/src/types/comfy.ts +++ b/src/types/comfy.ts @@ -7,6 +7,7 @@ import type { ComfyNodeDef } from '@/schemas/nodeDefSchema' import type { ComfyApp } from '@/scripts/app' import type { ComfyWidgetConstructor } from '@/scripts/widgets' import type { ComfyCommand } from '@/stores/commandStore' +import type { AuthUserInfo } from '@/types/authTypes' import type { BottomPanelExtension } from '@/types/extensionTypes' type Widgets = Record @@ -166,5 +167,12 @@ export interface ComfyExtension { missingNodeTypes: MissingNodeType[] ): Promise | void + /** + * Fired whenever authentication resolves, providing the anonymized user id.. + * Extensions can register at any time and will receive the latest value immediately. + * This is an experimental API and may be changed or removed in the future. + */ + onAuthUserResolved?(user: AuthUserInfo, app: ComfyApp): Promise | void + [key: string]: any }