Merge branch 'master' of github.com:supabase/supabase

This commit is contained in:
Terry Sutton committed 2024-11-15 10:40:46 -03:30
commit ef1110bcc4
4 files changed
+63 -50

No files matched your search

+17 -11
View File
@@ -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:
<p>Follow this link to confirm your user:</p>
<p>
<a href="{{ .SiteURL }}/auth/confirm?token_hash={{ .TokenHash }}&type=email"
<a
href="{{ .SiteURL }}/auth/confirm?token_hash={{ .TokenHash }}&type=email&next={{ .RedirectTo }}"
>Confirm your email</a
>
</p>
@@ -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',
},
})
}
```
@@ -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 (
<Form_Shadcn_ {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="flex flex-col gap-8">
@@ -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
<Alert
withIcon
variant="warning"
title={`${projectsWithComputeDowngrade.length} of your projects will be restarted ${willPlanDowngradeHappenImmediately ? 'upon clicking confirm' : 'once the downgrade takes effect at the end of your current billing cycle'}`}
title={`${projectsWithComputeDowngrade.length} of your projects will be restarted upon clicking confirm,`}
>
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
</Modal.Content>
<div className="flex items-center justify-between border-t px-4 py-4">
{willPlanDowngradeHappenImmediately && (
<p className="text-xs text-foreground-lighter">
The unused amount for the remaining of your billing cycle will be refunded as credits
</p>
)}
<p className="text-xs text-foreground-lighter">
The unused amount for the remaining time of your billing cycle will be refunded as
credits
</p>
<div className="flex items-center space-x-2">
<Button type="default" onClick={() => onClose()}>
Cancel
@@ -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 (
<>
<SidePanel