From d401f1183e292855925e720ae115848d355d9bc5 Mon Sep 17 00:00:00 2001 From: tdgao Date: Tue, 31 Mar 2026 00:15:32 -0600 Subject: [PATCH] feat: add shared UI package auth DI --- apps/app-frontend/src/App.vue | 18 +++++++++++++++- apps/frontend/src/providers/setup.ts | 2 ++ apps/frontend/src/providers/setup/auth.ts | 26 +++++++++++++++++++++++ packages/ui/src/providers/auth.ts | 11 ++++++++++ packages/ui/src/providers/index.ts | 1 + 5 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 apps/frontend/src/providers/setup/auth.ts create mode 100644 packages/ui/src/providers/auth.ts diff --git a/apps/app-frontend/src/App.vue b/apps/app-frontend/src/App.vue index 63fbe35edb..1e165fcec5 100644 --- a/apps/app-frontend/src/App.vue +++ b/apps/app-frontend/src/App.vue @@ -40,6 +40,7 @@ import { OverflowMenu, PopupNotificationPanel, ProgressSpinner, + provideAuth, provideModalBehavior, provideModrinthClient, provideNotificationManager, @@ -57,7 +58,7 @@ import { openUrl } from '@tauri-apps/plugin-opener' import { type } from '@tauri-apps/plugin-os' import { saveWindowState, StateFlags } from '@tauri-apps/plugin-window-state' import { $fetch } from 'ofetch' -import { computed, onMounted, onUnmounted, provide, ref, watch } from 'vue' +import { computed, onMounted, onUnmounted, provide, reactive, ref, watch, watchEffect } from 'vue' import { RouterView, useRoute, useRouter } from 'vue-router' import ModrinthAppLogo from '@/assets/modrinth_app.svg?component' @@ -454,6 +455,21 @@ const credentials = ref() const modrinthLoginFlowWaitModal = ref() +const authProvider = reactive({ + session_token: null, + user: null, + requestSignIn: async (_redirectPath) => { + await signIn() + }, +}) + +watchEffect(() => { + authProvider.session_token = credentials.value?.session ?? null + authProvider.user = credentials.value?.user ?? null +}) + +provideAuth(authProvider) + async function fetchCredentials() { const creds = await getCreds().catch(handleError) if (creds && creds.user_id) { diff --git a/apps/frontend/src/providers/setup.ts b/apps/frontend/src/providers/setup.ts index c558dc4c79..9b68c64e98 100644 --- a/apps/frontend/src/providers/setup.ts +++ b/apps/frontend/src/providers/setup.ts @@ -1,6 +1,7 @@ import { provideNotificationManager } from '@modrinth/ui' import { FrontendNotificationManager } from './frontend-notifications' +import { setupAuthProvider } from './setup/auth' import { setupFilePickerProvider } from './setup/file-picker' import { setupModrinthClientProvider } from './setup/modrinth-client' import { setupPageContextProvider } from './setup/page-context' @@ -9,6 +10,7 @@ import { setupTagsProvider } from './setup/tags' export function setupProviders(auth: Awaited>) { provideNotificationManager(new FrontendNotificationManager()) + setupAuthProvider(auth) setupModrinthClientProvider(auth) setupTagsProvider() setupFilePickerProvider() diff --git a/apps/frontend/src/providers/setup/auth.ts b/apps/frontend/src/providers/setup/auth.ts new file mode 100644 index 0000000000..3681f6e4f1 --- /dev/null +++ b/apps/frontend/src/providers/setup/auth.ts @@ -0,0 +1,26 @@ +import type { Labrinth } from '@modrinth/api-client' +import { type AuthProvider, provideAuth } from '@modrinth/ui' +import { reactive, watchEffect } from 'vue' + +export function setupAuthProvider(auth: Awaited>) { + const router = useRouter() + const authProvider = reactive({ + session_token: null, + user: null, + requestSignIn: async (redirectPath: string) => { + await router.push({ + path: '/auth/sign-in', + query: { + redirect: redirectPath, + }, + }) + }, + }) + + watchEffect(() => { + authProvider.session_token = auth.value.token || null + authProvider.user = (auth.value.user as Labrinth.Users.v2.User | null) ?? null + }) + + provideAuth(authProvider) +} diff --git a/packages/ui/src/providers/auth.ts b/packages/ui/src/providers/auth.ts new file mode 100644 index 0000000000..8e2708a8be --- /dev/null +++ b/packages/ui/src/providers/auth.ts @@ -0,0 +1,11 @@ +import type { Labrinth } from '@modrinth/api-client/src/modules/labrinth/types' + +import { createContext } from './create-context' + +export interface AuthProvider { + session_token: string | null + user: Labrinth.Users.v2.User | null + requestSignIn: (redirectPath: string) => void | Promise +} + +export const [injectAuth, provideAuth] = createContext('root', 'auth') diff --git a/packages/ui/src/providers/index.ts b/packages/ui/src/providers/index.ts index 3eac3d13f9..8765728c30 100644 --- a/packages/ui/src/providers/index.ts +++ b/packages/ui/src/providers/index.ts @@ -1,4 +1,5 @@ export * from './api-client' +export * from './auth' export * from './app-backup' export * from './content-manager' export { createContext } from './create-context'