fix: authed

This commit is contained in:
Aslam H
2024-10-08 13:55:36 +07:00
parent 1ed8d39207
commit 7c31f9b417
4 changed files with 120 additions and 111 deletions

View File

@@ -1,28 +1,5 @@
import { clerkClient, getAuth } from "@clerk/tanstack-start/server"
import { createServerFn } from "@tanstack/start"
import { create, get } from "ronin"
import * as cheerio from "cheerio"
import { ensureUrlProtocol } from "@/lib/utils"
import { urlSchema } from "@/lib/utils/schema"
interface Metadata {
title: string
description: string
icon: string | null
url: string
}
const DEFAULT_VALUES = {
TITLE: "",
DESCRIPTION: "",
FAVICON: null,
}
export const fetchClerkAuth = createServerFn("GET", async (_, ctx) => {
const auth = await getAuth(ctx.request)
return auth
})
import { get } from "ronin"
export const getFeatureFlag = createServerFn(
"GET",
@@ -34,84 +11,3 @@ export const getFeatureFlag = createServerFn(
return response
},
)
export const sendFeedbackFn = createServerFn(
"POST",
async (data: { content: string }, { request }) => {
const auth = await getAuth(request)
if (!auth.userId) {
throw new Error("Unauthorized")
}
const user = await clerkClient({
telemetry: { disabled: true },
}).users.getUser(auth.userId)
await create.feedback.with({
message: data.content,
emailFrom: user.emailAddresses[0].emailAddress,
})
},
)
export const getMetadata = createServerFn("GET", async (url: string) => {
if (!url) {
return new Response('Missing "url" query parameter', {
status: 400,
})
}
const result = urlSchema.safeParse(url)
if (!result.success) {
throw new Error(
result.error.issues.map((issue) => issue.message).join(", "),
)
}
url = ensureUrlProtocol(url)
try {
const response = await fetch(url, {
headers: {
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
},
})
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}
const data = await response.text()
const $ = cheerio.load(data)
const metadata: Metadata = {
title:
$("title").text() ||
$('meta[property="og:title"]').attr("content") ||
DEFAULT_VALUES.TITLE,
description:
$('meta[name="description"]').attr("content") ||
$('meta[property="og:description"]').attr("content") ||
DEFAULT_VALUES.DESCRIPTION,
icon:
$('link[rel="icon"]').attr("href") ||
$('link[rel="shortcut icon"]').attr("href") ||
DEFAULT_VALUES.FAVICON,
url: url,
}
if (metadata.icon && !metadata.icon.startsWith("http")) {
metadata.icon = new URL(metadata.icon, url).toString()
}
return metadata
} catch (error) {
console.error("Error fetching metadata:", error)
const defaultMetadata: Metadata = {
title: DEFAULT_VALUES.TITLE,
description: DEFAULT_VALUES.DESCRIPTION,
icon: DEFAULT_VALUES.FAVICON,
url: url,
}
return defaultMetadata
}
})

View File

@@ -29,7 +29,28 @@ import { zodResolver } from "@hookform/resolvers/zod"
import { toast } from "sonner"
import { Spinner } from "@/components/custom/spinner"
import { Editor } from "@tiptap/react"
import { sendFeedbackFn } from "~/actions"
import { createServerFn } from "@tanstack/start"
import { clerkClient, getAuth } from "@clerk/tanstack-start/server"
import { create } from "ronin"
export const sendFeedbackFn = createServerFn(
"POST",
async (data: { content: string }, { request }) => {
const auth = await getAuth(request)
if (!auth.userId) {
throw new Error("User not authenticated")
}
const user = await clerkClient({
telemetry: { disabled: true },
}).users.getUser(auth.userId)
await create.feedback.with({
message: data.content,
emailFrom: user.emailAddresses[0].emailAddress,
})
},
)
const formSchema = z.object({
content: z.string().min(1, {

View File

@@ -1,13 +1,20 @@
/// <reference types="vite/client" />
import { getAuth } from "@clerk/tanstack-start/server"
import type { QueryClient } from "@tanstack/react-query"
import {
Outlet,
ScrollRestoration,
createRootRouteWithContext,
} from "@tanstack/react-router"
import { Body, Head, Html, Meta, Scripts } from "@tanstack/start"
import {
Body,
createServerFn,
Head,
Html,
Meta,
Scripts,
} from "@tanstack/start"
import * as React from "react"
import { fetchClerkAuth } from "~/actions"
import { DefaultCatchBoundary } from "~/components/DefaultCatchBoundary.js"
import { NotFound } from "~/components/NotFound.js"
import appCss from "~/styles/app.css?url"
@@ -25,11 +32,17 @@ export const ReactQueryDevtools =
process.env.NODE_ENV === "production"
? () => null
: React.lazy(() =>
import("@tanstack/react-query-devtools/production").then((d) => ({
import("@tanstack/react-query-devtools").then((d) => ({
default: d.ReactQueryDevtools,
})),
)
export const fetchClerkAuth = createServerFn("GET", async (_, ctx) => {
const auth = await getAuth(ctx.request)
return auth
})
export const Route = createRootRouteWithContext<{
queryClient: QueryClient
}>()({

View File

@@ -5,7 +5,7 @@ import { useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import { toast } from "sonner"
import { createLinkSchema, LinkFormValues } from "./-schema"
import { cn, generateUniqueSlug } from "@/lib/utils"
import { cn, ensureUrlProtocol, generateUniqueSlug } from "@/lib/utils"
import { Form } from "@/components/ui/form"
import { Button } from "@/components/ui/button"
import { atom, useAtom } from "jotai"
@@ -22,12 +22,91 @@ import { useOnClickOutside } from "~/hooks/use-on-click-outside"
import TopicSelector, {
topicSelectorAtom,
} from "~/components/custom/topic-selector"
import { getMetadata } from "~/actions"
import { createServerFn } from "@tanstack/start"
import { urlSchema } from "~/lib/utils/schema"
import * as cheerio from "cheerio"
interface Metadata {
title: string
description: string
icon: string | null
url: string
}
const DEFAULT_VALUES = {
TITLE: "",
DESCRIPTION: "",
FAVICON: null,
}
export const globalLinkFormExceptionRefsAtom = atom<
React.RefObject<HTMLElement>[]
>([])
export const getMetadata = createServerFn("GET", async (url: string) => {
if (!url) {
return new Response('Missing "url" query parameter', {
status: 400,
})
}
const result = urlSchema.safeParse(url)
if (!result.success) {
throw new Error(
result.error.issues.map((issue) => issue.message).join(", "),
)
}
url = ensureUrlProtocol(url)
try {
const response = await fetch(url, {
headers: {
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
},
})
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}
const data = await response.text()
const $ = cheerio.load(data)
const metadata: Metadata = {
title:
$("title").text() ||
$('meta[property="og:title"]').attr("content") ||
DEFAULT_VALUES.TITLE,
description:
$('meta[name="description"]').attr("content") ||
$('meta[property="og:description"]').attr("content") ||
DEFAULT_VALUES.DESCRIPTION,
icon:
$('link[rel="icon"]').attr("href") ||
$('link[rel="shortcut icon"]').attr("href") ||
DEFAULT_VALUES.FAVICON,
url: url,
}
if (metadata.icon && !metadata.icon.startsWith("http")) {
metadata.icon = new URL(metadata.icon, url).toString()
}
return metadata
} catch (error) {
console.error("Error fetching metadata:", error)
const defaultMetadata: Metadata = {
title: DEFAULT_VALUES.TITLE,
description: DEFAULT_VALUES.DESCRIPTION,
icon: DEFAULT_VALUES.FAVICON,
url: url,
}
return defaultMetadata
}
})
interface LinkFormProps extends React.ComponentPropsWithoutRef<"form"> {
onClose?: () => void
onSuccess?: () => void