Skip to content

Commit

Permalink
Removing separate /connect/init endpoint by using client side setCook…
Browse files Browse the repository at this point in the history
…ie and redirect
  • Loading branch information
tonyxiao committed Oct 27, 2023
1 parent cff15c0 commit 8d84c8d
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 86 deletions.
26 changes: 26 additions & 0 deletions apps/web/app/connect/SetCookieAndRedirect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use client'

import {setCookie} from 'cookies-next'
import type {OptionsType} from 'cookies-next/lib/types'
import React from 'react'

/**
* Workaround for inability to set cookie in server components
* @see https://github.com/vercel/next.js/discussions/49843
*/
export function SetCookieAndRedirect(props: {
cookies: Array<{key: string; value: string; options: OptionsType}>
redirectUrl: string
}) {
React.useEffect(() => {
for (const {key, value, options} of props.cookies) {
setCookie(key, value, options)
}

// no need for NextRouter since we are doing a full page redirect
window.location.href = props.redirectUrl

// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
return null
}
3 changes: 2 additions & 1 deletion apps/web/app/connect/callback/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {FullScreenCenter} from '@/components/FullScreenCenter'
import {serverSideHelpersFromViewer} from '@/lib-server'
import {serverComponentGetViewer} from '@/lib-server/server-component-helpers'

import {kConnectSession, zConnectSession} from '../init/route'
import {kConnectSession, zConnectSession} from '../page'
import {CallbackEffect} from './CallbackEffect'

export const metadata = {
Expand All @@ -35,6 +35,7 @@ export default async function ConnectCallback({
}) {
const msg = await (async (): Promise<FrameMessage> => {
try {
// TODO: Can we use cookies-next to read cookie in this environment?
const cookie = cookies().get(kConnectSession)
if (!cookie) {
return {
Expand Down
80 changes: 0 additions & 80 deletions apps/web/app/connect/init/route.ts

This file was deleted.

34 changes: 30 additions & 4 deletions apps/web/app/connect/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {clerkClient} from '@clerk/nextjs'
import Image from 'next/image'
import {redirect} from 'next/navigation'

import {kAccessToken} from '@usevenice/app-config/constants'
import {env} from '@usevenice/app-config/env'
Expand All @@ -11,15 +10,25 @@ import {
getViewerId,
makeId,
makeNangoClient,
zId,
} from '@usevenice/cdk-core'
import {zConnectPageParams} from '@usevenice/engine-backend/router/endUserRouter'
import {makeUlid} from '@usevenice/util'
import {makeUlid, z} from '@usevenice/util'

import {ClientRoot} from '@/components/ClientRoot'
import {SuperHydrate} from '@/components/SuperHydrate'
import {createServerComponentHelpers} from '@/lib-server/server-component-helpers'

import ConnectPage from './ConnectPage'
import {SetCookieAndRedirect} from './SetCookieAndRedirect'

export const kConnectSession = 'connect-session'

type ConnectSession = z.infer<typeof zConnectSession>
export const zConnectSession = z.object({
token: z.string(),
resourceId: zId('reso'),
})

export const metadata = {
title: 'Venice Connect',
Expand Down Expand Up @@ -62,14 +71,31 @@ export default async function ConnectPageContainer({

if (intDef.metadata?.nangoProvider) {
const nango = makeNangoClient({secretKey: env.NANGO_SECRET_KEY})
const resourceId = makeId('reso', providerName, makeUlid())
const url = await nango.getOauthConnectUrl({
public_key: env.NEXT_PUBLIC_NANGO_PUBLIC_KEY,
connection_id: makeId('reso', providerName, makeUlid()),
connection_id: resourceId,
provider_config_key: params.integrationId,
// Consider using hookdeck so we can work with any number of urls
// redirect_uri: joinPath(getServerUrl(null), '/connect/callback'),
})
return redirect(url)
return (
<SetCookieAndRedirect
cookies={[
{
key: kConnectSession,
value: JSON.stringify({
resourceId,
token,
} satisfies ConnectSession),
// https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-03#section-4.1.2.7%7Cthe
// Need sameSite to be lax in order for this to work
options: {maxAge: 3600, sameSite: 'lax'},
},
]}
redirectUrl={url}
/>
)
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/engine-backend/router/endUserRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export const endUserRouter = trpc.router({
const token = ctx.jwt.signViewer(asEndUser(ctx.viewer, {endUserId}), {
validityInSeconds,
})
const url = new URL('/connect/init', ctx.apiUrl) // `/` will start from the root hostname itself
const url = new URL('/connect', ctx.apiUrl) // `/` will start from the root hostname itself
for (const [key, value] of Object.entries({...params, token})) {
url.searchParams.set(key, `${value ?? ''}`)
}
Expand Down

0 comments on commit 8d84c8d

Please sign in to comment.