From ec60894a3cb6736623c67318bc4783e81c46dce3 Mon Sep 17 00:00:00 2001 From: lewisblackburn Date: Sun, 27 Oct 2024 12:21:34 +0000 Subject: [PATCH] fix(merge): merge from remote --- ' | 225 + app/root.tsx | 91 +- .../_auth+/auth.$provider.callback.test.ts | 2 +- app/routes/_auth+/verify.server.ts | 6 +- .../settings+/profile.two-factor.index.tsx | 2 +- .../settings+/profile.two-factor.verify.tsx | 2 + app/routes/resources+/theme-switch.tsx | 17 +- app/utils/client-hints.tsx | 7 +- app/utils/providers/github.server.ts | 2 +- app/utils/request-info.ts | 12 +- eslint.config.js | 4 + package-lock.json | 50379 ++++++++-------- package.json | 376 +- tests/e2e/2fa.test.ts | 21 +- tests/mocks/index.ts | 1 - tests/setup/custom-matchers.ts | 5 +- vite.config.ts | 7 + 17 files changed, 25718 insertions(+), 25441 deletions(-) create mode 100644 ' diff --git a/' b/' new file mode 100644 index 0000000..c5aa962 --- /dev/null +++ b/' @@ -0,0 +1,225 @@ +import { + json, + type LoaderFunctionArgs, + type HeadersFunction, + type LinksFunction, + type MetaFunction, +} from '@remix-run/node' +import { + Links, + Meta, + Outlet, + Scripts, + ScrollRestoration, + useLoaderData, +} from '@remix-run/react' +import { withSentry } from '@sentry/remix' +import { HoneypotProvider } from 'remix-utils/honeypot/react' +// eslint-disable-next-line no-warning-comments +// FIXME: This and the file should be removed when sonnerStyles are fixed (https://github.com/epicweb-dev/epic-stack/issues/842) +import sonnerStyles from '#app/styles/sonner.css?url' +import appleTouchIconAssetUrl from './assets/favicons/apple-touch-icon.png' +import faviconAssetUrl from './assets/favicons/favicon.svg' +import Banner from './components/banner.tsx' +import { GeneralErrorBoundary } from './components/error-boundary.tsx' +import { EpicProgress } from './components/progress-bar.tsx' +import { useToast } from './components/toaster.tsx' +import { href as iconsHref } from './components/ui/icon.tsx' +import { EpicToaster } from './components/ui/sonner.tsx' +import { + ThemeSwitch, + useOptionalTheme, + useTheme, +} from './routes/resources+/theme-switch.tsx' +import tailwindStyleSheetUrl from './styles/tailwind.css?url' +import { getUserId, logout } from './utils/auth.server.ts' +import { ClientHintCheck, getHints } from './utils/client-hints.tsx' +import { prisma } from './utils/db.server.ts' +import { getEnv } from './utils/env.server.ts' +import { honeypot } from './utils/honeypot.server.ts' +import { combineHeaders, getDomainUrl } from './utils/misc.tsx' +import { useNonce } from './utils/nonce-provider.ts' +import { type Theme, getTheme } from './utils/theme.server.ts' +import { makeTimings, time } from './utils/timing.server.ts' +import { getToast } from './utils/toast.server.ts' + +export const links: LinksFunction = () => { + return [ + // Preload svg sprite as a resource to avoid render blocking + { rel: 'preload', href: iconsHref, as: 'image' }, + { + rel: 'icon', + href: '/favicon.ico', + sizes: '48x48', + }, + { rel: 'icon', type: 'image/svg+xml', href: faviconAssetUrl }, + { rel: 'apple-touch-icon', href: appleTouchIconAssetUrl }, + { + rel: 'manifest', + href: '/site.webmanifest', + crossOrigin: 'use-credentials', + } as const, // necessary to make typescript happy + { rel: 'stylesheet', href: tailwindStyleSheetUrl }, + { rel: 'stylesheet', href: sonnerStyles }, + ].filter(Boolean) +} + +export const meta: MetaFunction = ({ data }) => { + return [ + { title: data ? 'Metabase' : 'Error | Metabase' }, + { name: 'description', content: `Your own captain's log` }, + ] +} + +export async function loader({ request }: LoaderFunctionArgs) { + const timings = makeTimings('root loader') + const userId = await time(() => getUserId(request), { + timings, + type: 'getUserId', + desc: 'getUserId in root', + }) + + const user = userId + ? await time( + () => + prisma.user.findUniqueOrThrow({ + select: { + id: true, + name: true, + username: true, + image: { select: { id: true } }, + initials: true, + roles: { + select: { + name: true, + permissions: { + select: { entity: true, action: true, access: true }, + }, + }, + }, + }, + where: { id: userId }, + }), + { timings, type: 'find user', desc: 'find user in root' }, + ) + : null + if (userId && !user) { + console.info('something weird happened') + // something weird happened... The user is authenticated but we can't find + // them in the database. Maybe they were deleted? Let's log them out. + await logout({ request, redirectTo: '/' }) + } + const { toast, headers: toastHeaders } = await getToast(request) + const honeyProps = honeypot.getInputProps() + + return json( + { + user, + requestInfo: { + hints: getHints(request), + origin: getDomainUrl(request), + path: new URL(request.url).pathname, + userPrefs: { + theme: getTheme(request), + }, + }, + ENV: getEnv(), + toast, + honeyProps, + }, + { + headers: combineHeaders( + { 'Server-Timing': timings.toString() }, + toastHeaders, + ), + }, + ) +} + +export const headers: HeadersFunction = ({ loaderHeaders }) => { + const headers = { + 'Server-Timing': loaderHeaders.get('Server-Timing') ?? '', + } + return headers +} + +function Document({ + children, + nonce, + theme = 'light', + env = {}, +}: { + children: React.ReactNode + nonce: string + theme?: Theme + env?: Record +}) { + const allowIndexing = ENV.ALLOW_INDEXING !== 'false' + return ( + + + + + + + {allowIndexing ? null : ( + + )} + + + + {children} +