From ef656ff753dbd50c31eb6958861700adb87b75e9 Mon Sep 17 00:00:00 2001 From: "T.K" <96774606+tk20211228@users.noreply.github.com> Date: Fri, 15 Nov 2024 05:58:23 +0900 Subject: [PATCH 1/3] docs(auth): update PKCE flow and Next.js example for password-based auth (#29971) * docs(auth): update PKCE flow and Next.js example for password-based auth Update the password-based authentication documentation to improve consistency and clarity: - Add email redirect information to PKCE flow, mirroring the Implicit flow section - Align the Next.js example in app/auth/confirm/route.ts with the official Supabase documentation for server-side auth in Next.js - Update email template to include 'next' parameter for better redirect handling - Improve error handling and redirect logic in the Next.js example These changes aim to provide a more comprehensive and consistent guide for implementing password-based authentication, especially for Next.js applications using the PKCE flow. Ref: https://supabase.com/docs/guides/auth/server-side/nextjs * fix(docs): format email confirmation link and update sign-up function example --- apps/docs/content/guides/auth/passwords.mdx | 28 +++++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/apps/docs/content/guides/auth/passwords.mdx b/apps/docs/content/guides/auth/passwords.mdx index 892c127e233..25ffbaea936 100644 --- a/apps/docs/content/guides/auth/passwords.mdx +++ b/apps/docs/content/guides/auth/passwords.mdx @@ -142,7 +142,7 @@ The PKCE flow allows for server-side authentication. Unlike the implicit flow, w ##### Step 1: Update signup confirmation email -Update your signup email template to send the token hash. See [Email Templates](/docs/guides/auth/auth-email-templates) for how to configure your email templates. +Update your signup email template to send the token hash. For detailed instructions on how to configure your email templates, including the use of variables like `{{ .SiteURL }}`, `{{ .TokenHash }}`, and `{{ .RedirectTo }}`, please refer to our [Email Templates](/docs/guides/auth/auth-email-templates) guide. Your signup email template should contain the following HTML: @@ -151,7 +151,8 @@ Your signup email template should contain the following HTML:

Follow this link to confirm your user:

- Confirm your email

@@ -170,18 +171,16 @@ Create a new file at `app/auth/confirm/route.ts` and populate with the following ```ts app/auth/confirm/route.ts import { type EmailOtpType } from '@supabase/supabase-js' -import { cookies } from 'next/headers' -import { NextRequest, NextResponse } from 'next/server' -// The client you created from the Server-Side Auth instructions +import { type NextRequest } from 'next/server' + import { createClient } from '@/utils/supabase/server' +import { redirect } from 'next/navigation' export async function GET(request: NextRequest) { const { searchParams } = new URL(request.url) const token_hash = searchParams.get('token_hash') const type = searchParams.get('type') as EmailOtpType | null const next = searchParams.get('next') ?? '/' - const redirectTo = request.nextUrl.clone() - redirectTo.pathname = next if (token_hash && type) { const supabase = await createClient() @@ -191,13 +190,13 @@ export async function GET(request: NextRequest) { token_hash, }) if (!error) { - return NextResponse.redirect(redirectTo) + // redirect user to specified redirect URL or root of app + redirect(next) } } - // return the user to an error page with some instructions - redirectTo.pathname = '/auth/auth-code-error' - return NextResponse.redirect(redirectTo) + // redirect the user to an error page with some instructions + redirect('/auth/auth-code-error') } ``` @@ -381,11 +380,18 @@ app.get("/auth/confirm", async function (req, res) { To sign up the user, call [signUp()](/docs/reference/javascript/auth-signup) with their email address and password: +You can optionally specify a URL to redirect to after the user clicks the confirmation link. This URL must be configured as a [Redirect URL](/docs/guides/auth/redirect-urls), which you can do in the [dashboard](/dashboard/project/_/auth/url-configuration) for hosted projects, or in the [configuration file](/docs/guides/cli/config#auth.additional_redirect_urls) for self-hosted projects. + +If you don't specify a redirect URL, the user is automatically redirected to your site URL. This defaults to `localhost:3000`, but you can also configure this. + ```js async function signUpNewUser() { const { data, error } = await supabase.auth.signUp({ email: 'example@email.com', password: 'example-password', + options: { + emailRedirectTo: 'https://example.com/welcome', + }, }) } ``` From 59ecdeb1b9999c66261969a0967b09ff479422a3 Mon Sep 17 00:00:00 2001 From: Jonathan Summers-Muir Date: Fri, 15 Nov 2024 15:48:11 +0800 Subject: [PATCH 2/3] chore: update compute redirect with flag (#30408) * Update ComputeInstanceSidePanel.tsx * add redirect on new page * Update ComputeInstanceSidePanel.tsx * Fix order * Small refactor --------- Co-authored-by: Joshen Lim --- .../DiskManagement/DiskManagementForm.tsx | 28 ++++++++++----- .../Addons/ComputeInstanceSidePanel.tsx | 34 ++++++++++--------- 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/apps/studio/components/interfaces/DiskManagement/DiskManagementForm.tsx b/apps/studio/components/interfaces/DiskManagement/DiskManagementForm.tsx index b9f2d95490f..ab1c663830f 100644 --- a/apps/studio/components/interfaces/DiskManagement/DiskManagementForm.tsx +++ b/apps/studio/components/interfaces/DiskManagement/DiskManagementForm.tsx @@ -4,6 +4,7 @@ import { useQueryClient } from '@tanstack/react-query' import { AnimatePresence, motion } from 'framer-motion' import { ChevronRight } from 'lucide-react' import Link from 'next/link' +import { useRouter } from 'next/router' import { useEffect, useState } from 'react' import { useForm } from 'react-hook-form' import { toast } from 'sonner' @@ -24,8 +25,10 @@ import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-que import { useProjectAddonUpdateMutation } from 'data/subscriptions/project-addon-update-mutation' import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query' import { AddonVariantId } from 'data/subscriptions/types' +import { useResourceWarningsQuery } from 'data/usage/resource-warnings-query' import { useCheckPermissions, usePermissionsLoaded } from 'hooks/misc/useCheckPermissions' import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization' +import { useFlag } from 'hooks/ui/useFlag' import { GB, PROJECT_STATUS } from 'lib/constants' import { Button, @@ -56,7 +59,6 @@ import { } from './ui/DiskManagement.constants' import { NoticeBar } from './ui/NoticeBar' import { SpendCapDisabledSection } from './ui/SpendCapDisabledSection' -import { useResourceWarningsQuery } from 'data/usage/resource-warnings-query' export function DiskManagementForm() { const { @@ -67,6 +69,8 @@ export function DiskManagementForm() { const org = useSelectedOrganization() const { ref: projectRef } = useParams() const queryClient = useQueryClient() + const router = useRouter() + const diskAndComputeForm = useFlag('diskAndComputeForm') const { data: resourceWarnings } = useResourceWarningsQuery() const projectResourceWarnings = (resourceWarnings ?? [])?.find( @@ -186,14 +190,6 @@ export function DiskManagementForm() { isFlyArchitecture const disableComputeInputs = isPlanUpgradeRequired - - useEffect(() => { - // Initialize field values properly when data has been loaded, preserving any user changes - if (isSuccess) { - form.reset(defaultValues, {}) - } - }, [isSuccess]) - const isDirty = !!Object.keys(form.formState.dirtyFields).length const isProjectResizing = project?.status === PROJECT_STATUS.RESIZING const isProjectRequestingDiskChanges = isRequestingChanges && !isProjectResizing @@ -262,6 +258,20 @@ export function DiskManagementForm() { } } + useEffect(() => { + // Initialize field values properly when data has been loaded, preserving any user changes + if (isSuccess) { + form.reset(defaultValues, {}) + } + }, [isSuccess]) + + // Redirect logic incase disk and compute feature is not live yet + useEffect(() => { + if (diskAndComputeForm !== undefined && !diskAndComputeForm && projectRef) { + router.push(`/project/${projectRef}/settings/addons?panel=computeInstance`) + } + }, [diskAndComputeForm, projectRef, router]) + return (
diff --git a/apps/studio/components/interfaces/Settings/Addons/ComputeInstanceSidePanel.tsx b/apps/studio/components/interfaces/Settings/Addons/ComputeInstanceSidePanel.tsx index f3c8beb61d3..789ee83d5b9 100644 --- a/apps/studio/components/interfaces/Settings/Addons/ComputeInstanceSidePanel.tsx +++ b/apps/studio/components/interfaces/Settings/Addons/ComputeInstanceSidePanel.tsx @@ -1,11 +1,11 @@ import * as Tooltip from '@radix-ui/react-tooltip' import { PermissionAction } from '@supabase/shared-types/out/constants' import { useQueryClient } from '@tanstack/react-query' +import { ExternalLink, Info } from 'lucide-react' import Link from 'next/link' import { useRouter } from 'next/router' import { useEffect, useMemo, useState } from 'react' import { toast } from 'sonner' -import { ExternalLink, Info } from 'lucide-react' import { useParams } from 'common' import { @@ -32,7 +32,6 @@ import { AlertTitle_Shadcn_, Badge, Button, - CriticalIcon, Modal, Radio, SidePanel, @@ -45,17 +44,14 @@ const ComputeInstanceSidePanel = () => { const { ref: projectRef } = useParams() const { project: selectedProject } = useProjectContext() const organization = useSelectedOrganization() - const computeSizeChangesDisabled = useFlag('disableComputeSizeChanges') + const diskAndComputeForm = useFlag('diskAndComputeForm') const [showConfirmationModal, setShowConfirmationModal] = useState(false) - const canUpdateCompute = useCheckPermissions( PermissionAction.BILLING_WRITE, 'stripe.subscriptions' ) - const isProjectActive = useIsProjectActive() - const { panel, setPanel, closePanel } = useAddonsPagePanel() const visible = panel === 'computeInstance' @@ -176,16 +172,6 @@ const ComputeInstanceSidePanel = () => { hasReadReplicas && (isDowngradingToBelowSmall || hasMoreThanTwoReplicasForXLAndAbove) - useEffect(() => { - if (visible) { - if (subscriptionCompute !== undefined) { - setSelectedOption(subscriptionCompute.variant.identifier) - } else { - setSelectedOption(defaultInstanceSize) - } - } - }, [visible, isLoading]) - const onConfirmUpdateComputeInstance = async () => { if (!projectRef) return console.error('Project ref is required') if (!projectId) return console.error('Project ID is required') @@ -210,6 +196,22 @@ const ComputeInstanceSidePanel = () => { } } + useEffect(() => { + if (visible) { + if (subscriptionCompute !== undefined) { + setSelectedOption(subscriptionCompute.variant.identifier) + } else { + setSelectedOption(defaultInstanceSize) + } + } + }, [visible, isLoading]) + + useEffect(() => { + if (visible && diskAndComputeForm) { + router.push(`/project/${projectRef}/settings/compute-and-disk`) + } + }, [visible, diskAndComputeForm, router, projectRef]) + return ( <> Date: Fri, 15 Nov 2024 17:01:20 +0800 Subject: [PATCH 3/3] fix: copy for downgrading Fly partner org (#30464) --- .../Subscription/ExitSurveyModal.tsx | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/ExitSurveyModal.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/ExitSurveyModal.tsx index 080ad8e8767..f62c0a34626 100644 --- a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/ExitSurveyModal.tsx +++ b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/ExitSurveyModal.tsx @@ -54,9 +54,6 @@ const ExitSurveyModal = ({ visible, subscription, projects, onClose }: ExitSurve const hasProjectsWithComputeDowngrade = projectsWithComputeDowngrade.length > 0 - const willPlanDowngradeHappenImmediately = - subscription?.billing_via_partner === false || subscription?.billing_partner !== 'fly' - function reducer(state: any, action: any) { if (includes(state, action.target.value)) { return without(state, action.target.value) @@ -105,11 +102,9 @@ const ExitSurveyModal = ({ visible, subscription, projects, onClose }: ExitSurve // [Joshen] In this case we don't raise any errors if the exit survey fails to send since it shouldn't block the user } finally { toast.success( - willPlanDowngradeHappenImmediately - ? hasProjectsWithComputeDowngrade - ? 'Successfully downgraded organization to the Free Plan. Your projects are currently restarting to update their compute instances.' - : 'Successfully downgraded organization to the Free Plan' - : 'Your organization is scheduled for the downgrade at the end of your current billing cycle', + hasProjectsWithComputeDowngrade + ? 'Successfully downgraded organization to the Free Plan. Your projects are currently restarting to update their compute instances.' + : 'Successfully downgraded organization to the Free Plan', { duration: hasProjectsWithComputeDowngrade ? 8000 : 4000 } ) onClose(true) @@ -199,7 +194,7 @@ const ExitSurveyModal = ({ visible, subscription, projects, onClose }: ExitSurve This is due to changes in compute instances from the downgrade. Affected projects include {projectsWithComputeDowngrade.map((project) => project.name).join(', ')}. @@ -209,11 +204,11 @@ const ExitSurveyModal = ({ visible, subscription, projects, onClose }: ExitSurve
- {willPlanDowngradeHappenImmediately && ( -

- The unused amount for the remaining of your billing cycle will be refunded as credits -

- )} +

+ The unused amount for the remaining time of your billing cycle will be refunded as + credits +

+