mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 09:55:06 +03:00
feat: improve fly sso flow (#18867)
* feat: improve fly sso flow * fix: typecheck
This commit is contained in:
5 files changed
+225
-283
No files matched your search
Vendored
+73
-256
@@ -133,9 +133,13 @@ export interface paths {
|
||||
'/platform/organizations': {
|
||||
/** Gets user's organizations */
|
||||
get: operations['OrganizationsController_getOrganizations']
|
||||
/** Creates an organization (v2) */
|
||||
/** Creates an organization */
|
||||
post: operations['OrganizationsController_createOrganizationWithTier']
|
||||
}
|
||||
'/platform/organizations/fly/{fly_organization_id}': {
|
||||
/** Gets organization linked to fly organization id */
|
||||
get: operations['OrganizationsController_getOrganizationByFlyOrganizationId']
|
||||
}
|
||||
'/platform/organizations/{slug}': {
|
||||
/** Deletes organization */
|
||||
delete: operations['OrganizationSlugController_deleteOrganization']
|
||||
@@ -443,6 +447,10 @@ export interface paths {
|
||||
/** Creates a project */
|
||||
post: operations['ProjectsController_createProject']
|
||||
}
|
||||
'/platform/projects/fly/{fly_extension_id}': {
|
||||
/** Gets project linked to fly extension id */
|
||||
get: operations['ProjectsController_getProjectByFlyExtensionId']
|
||||
}
|
||||
'/platform/projects/{ref}/content': {
|
||||
/** Gets project's content */
|
||||
get: operations['ContentController_getContent']
|
||||
@@ -529,10 +537,6 @@ export interface paths {
|
||||
*/
|
||||
post: operations['UpdateController_updateProject']
|
||||
}
|
||||
'/platform/projects/{ref}/usage': {
|
||||
/** Gets project's usage */
|
||||
get: operations['UsageController_getUsageStatusConfig']
|
||||
}
|
||||
'/platform/projects/{ref}/transfer/preview': {
|
||||
/** Previews transfering a project to a different organizations, shows eligibility and impact. */
|
||||
post: operations['ProjectTransferController_previewTransfer']
|
||||
@@ -595,20 +599,6 @@ export interface paths {
|
||||
/** Removes project addon */
|
||||
delete: operations['ProjectAddonController_removeAddon']
|
||||
}
|
||||
'/platform/projects/{ref}/billing/subscription': {
|
||||
/** Gets the current subscription */
|
||||
get: operations['SubscriptionController_getSubscription']
|
||||
/** Updates subscription */
|
||||
put: operations['SubscriptionController_updateSubscription']
|
||||
}
|
||||
'/platform/projects/{ref}/billing/plans': {
|
||||
/** Gets subscription plans */
|
||||
get: operations['ProjectPlansController_getAvailablePlans']
|
||||
}
|
||||
'/platform/projects/{ref}/billing/invoices/upcoming': {
|
||||
/** Gets the upcoming invoice */
|
||||
get: operations['ProjectInvoicesController_getUpcomingInvoice']
|
||||
}
|
||||
'/platform/props/project/{ref}/api': {
|
||||
/**
|
||||
* Gets project's api info
|
||||
@@ -876,10 +866,6 @@ export interface paths {
|
||||
/** Allows a project to obtain temporary credentials. */
|
||||
post: operations['AwsCredentialsController_getTemporaryCredentials']
|
||||
}
|
||||
'/system/projects/{ref}/billing/subscription': {
|
||||
/** Updates subscription */
|
||||
put: operations['SubscriptionController_updateSubscription']
|
||||
}
|
||||
'/system/projects/{ref}/billing/addons': {
|
||||
/** Updates project addon */
|
||||
post: operations['AddonsController_updateAddon']
|
||||
@@ -888,18 +874,6 @@ export interface paths {
|
||||
/** Removes project addon */
|
||||
delete: operations['AddonsController_removeAddon']
|
||||
}
|
||||
'/system/billing/migrate/org-level-billing': {
|
||||
/** Migrates org to org-level billing. */
|
||||
post: operations['BillingMigrationController_migrateToOrgLevelBilling']
|
||||
}
|
||||
'/system/billing/migrate/org-level-billing-preview': {
|
||||
/** Previews the migration of the organization to the new org level billing. */
|
||||
post: operations['BillingMigrationController_preview']
|
||||
}
|
||||
'/system/billing/migrate/org-level-billing-attach': {
|
||||
/** Attaches subscription id to org and projects. */
|
||||
put: operations['BillingMigrationController_attachSubscriptionId']
|
||||
}
|
||||
'/system/projects/{ref}/config/update-jwt/complete': {
|
||||
/** Handle update project jwt on completion */
|
||||
post: operations['ProjectUpdateJwtController_completeUpdateJwt']
|
||||
@@ -1013,9 +987,13 @@ export interface paths {
|
||||
'/v0/organizations': {
|
||||
/** Gets user's organizations */
|
||||
get: operations['OrganizationsController_getOrganizations']
|
||||
/** Creates an organization (v2) */
|
||||
/** Creates an organization */
|
||||
post: operations['OrganizationsController_createOrganizationWithTier']
|
||||
}
|
||||
'/v0/organizations/fly/{fly_organization_id}': {
|
||||
/** Gets organization linked to fly organization id */
|
||||
get: operations['OrganizationsController_getOrganizationByFlyOrganizationId']
|
||||
}
|
||||
'/v0/organizations/{slug}': {
|
||||
/** Deletes organization */
|
||||
delete: operations['OrganizationSlugController_deleteOrganization']
|
||||
@@ -1199,6 +1177,10 @@ export interface paths {
|
||||
/** Creates a project */
|
||||
post: operations['ProjectsController_createProject']
|
||||
}
|
||||
'/v0/projects/fly/{fly_extension_id}': {
|
||||
/** Gets project linked to fly extension id */
|
||||
get: operations['ProjectsController_getProjectByFlyExtensionId']
|
||||
}
|
||||
'/v0/projects/metrics': {
|
||||
/**
|
||||
* Get metrics
|
||||
@@ -1285,10 +1267,6 @@ export interface paths {
|
||||
/** Gets project's status */
|
||||
get: operations['StatusController_getStatus']
|
||||
}
|
||||
'/v0/projects/{ref}/usage': {
|
||||
/** Gets project's usage */
|
||||
get: operations['UsageController_getUsageStatusConfig']
|
||||
}
|
||||
'/v0/projects/{ref}/analytics/endpoints/functions.inv-stats': {
|
||||
/** Gets a project's function invocation statistics */
|
||||
get: operations['FunctionLogsController_getStatus']
|
||||
@@ -1343,20 +1321,6 @@ export interface paths {
|
||||
/** Removes project addon */
|
||||
delete: operations['ProjectAddonController_removeAddon']
|
||||
}
|
||||
'/v0/projects/{ref}/billing/subscription': {
|
||||
/** Gets the current subscription */
|
||||
get: operations['SubscriptionController_getSubscription']
|
||||
/** Updates subscription */
|
||||
put: operations['SubscriptionController_updateSubscription']
|
||||
}
|
||||
'/v0/projects/{ref}/billing/plans': {
|
||||
/** Gets subscription plans */
|
||||
get: operations['ProjectPlansController_getAvailablePlans']
|
||||
}
|
||||
'/v0/projects/{ref}/billing/invoices/upcoming': {
|
||||
/** Gets the upcoming invoice */
|
||||
get: operations['ProjectInvoicesController_getUpcomingInvoice']
|
||||
}
|
||||
'/v0/storage/{ref}/buckets/{id}': {
|
||||
/** Gets bucket */
|
||||
get: operations['StorageBucketIdController_getBucket']
|
||||
@@ -2273,17 +2237,12 @@ export interface components {
|
||||
id: string
|
||||
name: string
|
||||
}
|
||||
GetOrganizationByFlyOrganizationIdResponse: {
|
||||
slug: string
|
||||
}
|
||||
CreateOrganizationBody: {
|
||||
name: string
|
||||
}
|
||||
CreateOrganizationBodyV2: {
|
||||
name: string
|
||||
kind?: string
|
||||
size?: string
|
||||
/** @enum {string} */
|
||||
tier: 'tier_payg' | 'tier_pro' | 'tier_free' | 'tier_team' | 'tier_enterprise'
|
||||
payment_method?: string
|
||||
}
|
||||
UpdateOrganizationBody: {
|
||||
name: string
|
||||
billing_email: string
|
||||
@@ -3353,6 +3312,9 @@ export interface components {
|
||||
preview_branch_refs: string[]
|
||||
disk_volume_size_gb?: number
|
||||
}
|
||||
GetProjectByFlyExtensionIdResponse: {
|
||||
ref: string
|
||||
}
|
||||
AmiSearchOptions: {
|
||||
search_tags?: Record<string, never>
|
||||
}
|
||||
@@ -3367,7 +3329,8 @@ export interface components {
|
||||
/** @description Slug of your organization */
|
||||
organization_id: string
|
||||
/**
|
||||
* @description Subscription plan
|
||||
* @deprecated
|
||||
* @description Subscription plan is now set on organization level and is ignored in this request
|
||||
* @example free
|
||||
* @enum {string}
|
||||
*/
|
||||
@@ -3595,26 +3558,6 @@ export interface components {
|
||||
jwt_secret?: string
|
||||
service_api_keys?: components['schemas']['ProjectServiceApiKeyResponse'][]
|
||||
}
|
||||
UsageStatus: {
|
||||
usage: number
|
||||
limit: number
|
||||
cost: number
|
||||
available_in_plan: boolean
|
||||
}
|
||||
UsageStatusResponse: {
|
||||
db_size: components['schemas']['UsageStatus']
|
||||
storage_size: components['schemas']['UsageStatus']
|
||||
db_egress: components['schemas']['UsageStatus']
|
||||
storage_egress: components['schemas']['UsageStatus']
|
||||
storage_image_render_count: components['schemas']['UsageStatus']
|
||||
monthly_active_users: components['schemas']['UsageStatus']
|
||||
monthly_active_sso_users: components['schemas']['UsageStatus']
|
||||
func_invocations: components['schemas']['UsageStatus']
|
||||
func_count: components['schemas']['UsageStatus']
|
||||
realtime_message_count: components['schemas']['UsageStatus']
|
||||
realtime_peak_connection: components['schemas']['UsageStatus']
|
||||
disk_volume_size_gb: number
|
||||
}
|
||||
TransferProjectBody: {
|
||||
target_organization_slug: string
|
||||
}
|
||||
@@ -3777,11 +3720,6 @@ export interface components {
|
||||
/** @enum {string} */
|
||||
addon_type: 'custom_domain' | 'compute_instance' | 'pitr'
|
||||
}
|
||||
UpdateSubscriptionV2Body: {
|
||||
payment_method?: string
|
||||
/** @enum {string} */
|
||||
tier: 'tier_payg' | 'tier_pro' | 'tier_free' | 'tier_team' | 'tier_enterprise'
|
||||
}
|
||||
ServiceApiKey: {
|
||||
api_key_encrypted?: string
|
||||
tags: string
|
||||
@@ -4266,41 +4204,24 @@ export interface components {
|
||||
/** Format: date-time */
|
||||
expiry_time: string
|
||||
}
|
||||
UpdateSubscriptionV2AdminBody: {
|
||||
payment_method?: string
|
||||
/** @enum {string} */
|
||||
tier: 'tier_payg' | 'tier_pro' | 'tier_free' | 'tier_team' | 'tier_enterprise'
|
||||
price_id?: string
|
||||
}
|
||||
UpdateAddonAdminBody: {
|
||||
addon_variant: string
|
||||
/** @enum {string} */
|
||||
addon_type: 'custom_domain' | 'compute_instance' | 'pitr'
|
||||
price_id?: string
|
||||
}
|
||||
MigrateToOrgLevelBillingBody: {
|
||||
org_slug: string
|
||||
/** @enum {string} */
|
||||
tier: 'tier_payg' | 'tier_pro' | 'tier_free' | 'tier_team' | 'tier_enterprise'
|
||||
custom_usage_fees?: components['schemas']['BillingUsageBasedPrice'][]
|
||||
tier_price_id?: string
|
||||
compute_credits?: number
|
||||
payment_method_id?: string
|
||||
existing_org_subscription_id?: string
|
||||
dryRun?: boolean
|
||||
force?: boolean
|
||||
billing_cycle_anchor?: string
|
||||
}
|
||||
AttachSubscriptionIdBody: {
|
||||
org_slug: string
|
||||
subscription_id: string
|
||||
}
|
||||
DatabaseResponse: {
|
||||
/** @description Database host */
|
||||
host: string
|
||||
/** @description Database version */
|
||||
version: string
|
||||
}
|
||||
UpdateSubscriptionV2AdminBody: {
|
||||
payment_method?: string
|
||||
/** @enum {string} */
|
||||
tier: 'tier_payg' | 'tier_pro' | 'tier_free' | 'tier_team' | 'tier_enterprise'
|
||||
price_id?: string
|
||||
}
|
||||
GetMetricsBody: {
|
||||
/** @enum {string} */
|
||||
metric: 'user_queries'
|
||||
@@ -4342,6 +4263,7 @@ export interface components {
|
||||
UpdateBranchBody: {
|
||||
branch_name?: string
|
||||
git_branch?: string
|
||||
reset_on_push?: boolean
|
||||
}
|
||||
BranchResponse: {
|
||||
id: string
|
||||
@@ -4351,6 +4273,7 @@ export interface components {
|
||||
is_default: boolean
|
||||
git_branch?: string
|
||||
pr_number?: number
|
||||
reset_on_push: boolean
|
||||
created_at: string
|
||||
updated_at: string
|
||||
}
|
||||
@@ -5537,11 +5460,11 @@ export interface operations {
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Creates an organization (v2) */
|
||||
/** Creates an organization */
|
||||
OrganizationsController_createOrganizationWithTier: {
|
||||
requestBody: {
|
||||
content: {
|
||||
'application/json': components['schemas']['CreateOrganizationBodyV2']
|
||||
'application/json': components['schemas']['CreateOrganizationBody']
|
||||
}
|
||||
}
|
||||
responses: {
|
||||
@@ -5556,6 +5479,21 @@ export interface operations {
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Gets organization linked to fly organization id */
|
||||
OrganizationsController_getOrganizationByFlyOrganizationId: {
|
||||
parameters: {
|
||||
path: {
|
||||
fly_organization_id: string
|
||||
}
|
||||
}
|
||||
responses: {
|
||||
200: {
|
||||
content: {
|
||||
'application/json': components['schemas']['GetOrganizationByFlyOrganizationIdResponse']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Deletes organization */
|
||||
OrganizationSlugController_deleteOrganization: {
|
||||
parameters: {
|
||||
@@ -6192,8 +6130,8 @@ export interface operations {
|
||||
SubscriptionController_getSubscription: {
|
||||
parameters: {
|
||||
path: {
|
||||
/** @description Project ref */
|
||||
ref: string
|
||||
/** @description Organization slug */
|
||||
slug: string
|
||||
}
|
||||
}
|
||||
responses: {
|
||||
@@ -6215,13 +6153,13 @@ export interface operations {
|
||||
SubscriptionController_updateSubscription: {
|
||||
parameters: {
|
||||
path: {
|
||||
/** @description Project ref */
|
||||
ref: string
|
||||
/** @description Organization slug */
|
||||
slug: string
|
||||
}
|
||||
}
|
||||
requestBody: {
|
||||
content: {
|
||||
'application/json': components['schemas']['UpdateSubscriptionV2Body']
|
||||
'application/json': components['schemas']['UpdateSubscriptionBody']
|
||||
}
|
||||
}
|
||||
responses: {
|
||||
@@ -6231,7 +6169,7 @@ export interface operations {
|
||||
403: {
|
||||
content: never
|
||||
}
|
||||
/** @description Failed to update subscription */
|
||||
/** @description Failed to update subscription change */
|
||||
500: {
|
||||
content: never
|
||||
}
|
||||
@@ -8133,6 +8071,21 @@ export interface operations {
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Gets project linked to fly extension id */
|
||||
ProjectsController_getProjectByFlyExtensionId: {
|
||||
parameters: {
|
||||
path: {
|
||||
fly_extension_id: string
|
||||
}
|
||||
}
|
||||
responses: {
|
||||
200: {
|
||||
content: {
|
||||
'application/json': components['schemas']['GetProjectByFlyExtensionIdResponse']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Gets project's content */
|
||||
ContentController_getContent: {
|
||||
parameters: {
|
||||
@@ -8666,26 +8619,6 @@ export interface operations {
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Gets project's usage */
|
||||
UsageController_getUsageStatusConfig: {
|
||||
parameters: {
|
||||
path: {
|
||||
/** @description Project ref */
|
||||
ref: string
|
||||
}
|
||||
}
|
||||
responses: {
|
||||
200: {
|
||||
content: {
|
||||
'application/json': components['schemas']['UsageStatusResponse']
|
||||
}
|
||||
}
|
||||
/** @description Failed to retrieve project's usage */
|
||||
500: {
|
||||
content: never
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Previews transfering a project to a different organizations, shows eligibility and impact. */
|
||||
ProjectTransferController_previewTransfer: {
|
||||
parameters: {
|
||||
@@ -9127,52 +9060,6 @@ export interface operations {
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Gets subscription plans */
|
||||
ProjectPlansController_getAvailablePlans: {
|
||||
parameters: {
|
||||
path: {
|
||||
/** @description Project ref */
|
||||
ref: string
|
||||
}
|
||||
}
|
||||
responses: {
|
||||
200: {
|
||||
content: {
|
||||
'application/json': Record<string, never>
|
||||
}
|
||||
}
|
||||
403: {
|
||||
content: never
|
||||
}
|
||||
/** @description Failed to get subscription plans */
|
||||
500: {
|
||||
content: never
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Gets the upcoming invoice */
|
||||
ProjectInvoicesController_getUpcomingInvoice: {
|
||||
parameters: {
|
||||
path: {
|
||||
/** @description Project ref */
|
||||
ref: string
|
||||
}
|
||||
}
|
||||
responses: {
|
||||
200: {
|
||||
content: {
|
||||
'application/json': Record<string, never>
|
||||
}
|
||||
}
|
||||
403: {
|
||||
content: never
|
||||
}
|
||||
/** @description Failed to retrieve upcoming invoice */
|
||||
500: {
|
||||
content: never
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Gets project's api info
|
||||
* @deprecated
|
||||
@@ -10191,7 +10078,7 @@ export interface operations {
|
||||
GitHubPullRequestController_getPullRequestsByNumber: {
|
||||
parameters: {
|
||||
query: {
|
||||
pr_number: number
|
||||
pr_number: number[]
|
||||
}
|
||||
path: {
|
||||
organization_integration_id: string
|
||||
@@ -10237,25 +10124,6 @@ export interface operations {
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Create CLI login session */
|
||||
CliLoginController_createCliLoginSession: {
|
||||
requestBody: {
|
||||
content: {
|
||||
'application/json': components['schemas']['CreateCliLoginSessionBody']
|
||||
}
|
||||
}
|
||||
responses: {
|
||||
/** @description Failed to create CLI login session */
|
||||
500: never
|
||||
}
|
||||
}
|
||||
/** Retrieve CLI login session */
|
||||
CliLoginController_getCliLoginSession: {
|
||||
responses: {
|
||||
/** @description Failed to retrieve CLI login session */
|
||||
500: never
|
||||
}
|
||||
}
|
||||
/** Gets GoTrue template */
|
||||
AuthTemplateController_getTemplate: {
|
||||
parameters: {
|
||||
@@ -10654,57 +10522,6 @@ export interface operations {
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Migrates org to org-level billing. */
|
||||
BillingMigrationController_migrateToOrgLevelBilling: {
|
||||
requestBody: {
|
||||
content: {
|
||||
'application/json': components['schemas']['MigrateToOrgLevelBillingBody']
|
||||
}
|
||||
}
|
||||
responses: {
|
||||
201: {
|
||||
content: never
|
||||
}
|
||||
/** @description Failed to migrate org. */
|
||||
500: {
|
||||
content: never
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Previews the migration of the organization to the new org level billing. */
|
||||
BillingMigrationController_preview: {
|
||||
requestBody: {
|
||||
content: {
|
||||
'application/json': components['schemas']['MigrateToOrgLevelBillingBody']
|
||||
}
|
||||
}
|
||||
responses: {
|
||||
201: {
|
||||
content: never
|
||||
}
|
||||
/** @description Failed to preview org billing organization */
|
||||
500: {
|
||||
content: never
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Attaches subscription id to org and projects. */
|
||||
BillingMigrationController_attachSubscriptionId: {
|
||||
requestBody: {
|
||||
content: {
|
||||
'application/json': components['schemas']['AttachSubscriptionIdBody']
|
||||
}
|
||||
}
|
||||
responses: {
|
||||
200: {
|
||||
content: never
|
||||
}
|
||||
/** @description Failed to preview org billing organization */
|
||||
500: {
|
||||
content: never
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Handle update project jwt on completion */
|
||||
ProjectUpdateJwtController_completeUpdateJwt: {
|
||||
parameters: {
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import { useMutation, UseMutationOptions } from '@tanstack/react-query'
|
||||
|
||||
import { get } from 'data/fetchers'
|
||||
import toast from 'react-hot-toast'
|
||||
import { ResponseError } from 'types'
|
||||
|
||||
export type OrganizationByFlyOrgIdVariables = {
|
||||
flyOrganizationId: string
|
||||
}
|
||||
|
||||
export async function getOrganizationByFlyOrgId({
|
||||
flyOrganizationId,
|
||||
}: OrganizationByFlyOrgIdVariables) {
|
||||
const { data, error } = await get('/platform/organizations/fly/{fly_organization_id}', {
|
||||
params: { path: { fly_organization_id: flyOrganizationId } },
|
||||
})
|
||||
if (error) throw error
|
||||
return data as { slug: string }
|
||||
}
|
||||
|
||||
type OrganizationByFlyOrgIdData = Awaited<ReturnType<typeof getOrganizationByFlyOrgId>>
|
||||
|
||||
export const useOrganizationByFlyOrgIdMutation = ({
|
||||
onSuccess,
|
||||
onError,
|
||||
...options
|
||||
}: Omit<
|
||||
UseMutationOptions<OrganizationByFlyOrgIdData, ResponseError, OrganizationByFlyOrgIdVariables>,
|
||||
'mutationFn'
|
||||
> = {}) => {
|
||||
return useMutation<OrganizationByFlyOrgIdData, ResponseError, OrganizationByFlyOrgIdVariables>(
|
||||
(vars) => getOrganizationByFlyOrgId(vars),
|
||||
{
|
||||
async onSuccess(data, variables, context) {
|
||||
await onSuccess?.(data, variables, context)
|
||||
},
|
||||
async onError(data, variables, context) {
|
||||
if (onError === undefined) {
|
||||
toast.error(`Failed to get organization: ${data.message}`)
|
||||
} else {
|
||||
onError(data, variables, context)
|
||||
}
|
||||
},
|
||||
...options,
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -15,22 +15,11 @@ export type OrganizationCreateVariables = {
|
||||
V2?: boolean
|
||||
}
|
||||
|
||||
export async function createOrganization({
|
||||
name,
|
||||
kind,
|
||||
size,
|
||||
tier,
|
||||
payment_method,
|
||||
V2 = false,
|
||||
}: OrganizationCreateVariables) {
|
||||
export async function createOrganization({ name, V2 = false }: OrganizationCreateVariables) {
|
||||
const { data, error } = await post('/platform/organizations', {
|
||||
// @ts-ignore [Joshen] Generated API spec is wrong?
|
||||
body: {
|
||||
name,
|
||||
kind,
|
||||
...(kind == 'COMPANY' ? { size } : {}),
|
||||
...(tier !== undefined ? { tier } : {}),
|
||||
...(payment_method !== undefined ? { payment_method } : {}),
|
||||
},
|
||||
...(V2 ? { headers: { Version: '2' } } : {}),
|
||||
})
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import { useMutation, UseMutationOptions } from '@tanstack/react-query'
|
||||
|
||||
import { get } from 'data/fetchers'
|
||||
import toast from 'react-hot-toast'
|
||||
import { ResponseError } from 'types'
|
||||
|
||||
export type ProjectByFlyExtensionIdVariables = {
|
||||
flyExtensionId: string
|
||||
}
|
||||
|
||||
export async function getProjectByFlyExtensionId({
|
||||
flyExtensionId,
|
||||
}: ProjectByFlyExtensionIdVariables) {
|
||||
const { data, error } = await get('/platform/projects/fly/{fly_extension_id}', {
|
||||
params: { path: { fly_extension_id: flyExtensionId } },
|
||||
})
|
||||
if (error) throw error
|
||||
return data as { ref: string }
|
||||
}
|
||||
|
||||
type ProjectByFlyExtensionIdData = Awaited<ReturnType<typeof getProjectByFlyExtensionId>>
|
||||
|
||||
export const useProjectByFlyExtensionIdMutation = ({
|
||||
onSuccess,
|
||||
onError,
|
||||
...options
|
||||
}: Omit<
|
||||
UseMutationOptions<ProjectByFlyExtensionIdData, ResponseError, ProjectByFlyExtensionIdVariables>,
|
||||
'mutationFn'
|
||||
> = {}) => {
|
||||
return useMutation<ProjectByFlyExtensionIdData, ResponseError, ProjectByFlyExtensionIdVariables>(
|
||||
(vars) => getProjectByFlyExtensionId(vars),
|
||||
{
|
||||
async onSuccess(data, variables, context) {
|
||||
await onSuccess?.(data, variables, context)
|
||||
},
|
||||
async onError(data, variables, context) {
|
||||
if (onError === undefined) {
|
||||
toast.error(`Failed to get project: ${data.message}`)
|
||||
} else {
|
||||
onError(data, variables, context)
|
||||
}
|
||||
},
|
||||
...options,
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -1,22 +1,60 @@
|
||||
import { useRouter } from 'next/router'
|
||||
import Link from 'next/link'
|
||||
import Image from 'next/image'
|
||||
import { useRouter } from 'next/router'
|
||||
import { Button } from 'ui'
|
||||
import { useTheme } from 'next-themes'
|
||||
import { API_URL } from 'lib/constants'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useIsLoggedIn } from 'common'
|
||||
import { useProjectByFlyExtensionIdMutation } from 'data/projects/project-by-fly-extension-id-mutation'
|
||||
import { useOrganizationByFlyOrgIdMutation } from 'data/organizations/organization-by-fly-organization-id-mutation'
|
||||
|
||||
const SignInFlyTos = () => {
|
||||
const [loading, setLoading] = useState(true)
|
||||
const isLoggedIn = useIsLoggedIn()
|
||||
const router = useRouter()
|
||||
const {
|
||||
isReady,
|
||||
query: { extension_id, organization_id },
|
||||
query: { fly_extension_id, fly_organization_id },
|
||||
} = router
|
||||
const { resolvedTheme } = useTheme()
|
||||
const { mutateAsync: getProjectByFlyExtensionId } = useProjectByFlyExtensionIdMutation({
|
||||
onSuccess: (res) => {
|
||||
router.replace(`/project/${res.ref}`)
|
||||
},
|
||||
onError: (_) => {
|
||||
setLoading(false)
|
||||
},
|
||||
})
|
||||
const { mutateAsync: getOrgByFlyOrgId } = useOrganizationByFlyOrgIdMutation({
|
||||
onSuccess: (_) => {
|
||||
router.replace('/projects')
|
||||
},
|
||||
onError: (_) => {
|
||||
setLoading(false)
|
||||
},
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (!isReady) {
|
||||
return
|
||||
}
|
||||
if (!isLoggedIn) {
|
||||
setLoading(false)
|
||||
return
|
||||
}
|
||||
|
||||
fly_extension_id
|
||||
? getProjectByFlyExtensionId({ flyExtensionId: fly_extension_id as string })
|
||||
: fly_organization_id
|
||||
? getOrgByFlyOrgId({ flyOrganizationId: fly_organization_id as string })
|
||||
: setLoading(false)
|
||||
}, [isReady])
|
||||
|
||||
const onSignInWithFly = async () => {
|
||||
window.location.href = extension_id
|
||||
? `${API_URL}/tos/fly?extension_id=${extension_id}`
|
||||
: `${API_URL}/tos/fly?organization_id=${organization_id}`
|
||||
window.location.href = fly_extension_id
|
||||
? `${API_URL}/tos/fly?extension_id=${fly_extension_id}`
|
||||
: `${API_URL}/tos/fly?organization_id=${fly_organization_id}`
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -46,16 +84,20 @@ const SignInFlyTos = () => {
|
||||
<div className="flex w-[320px] flex-col items-center justify-center space-y-3">
|
||||
<h4 className="text-lg">Continue to Supabase Dashboard</h4>
|
||||
</div>
|
||||
<div className="flex flex-col items-center space-x-4 space-y-4">
|
||||
<Button onClick={onSignInWithFly} disabled={!extension_id && !organization_id}>
|
||||
Login with Fly.io
|
||||
</Button>
|
||||
{isReady && !extension_id && !organization_id && (
|
||||
<p className="text-red-900 text-sm">
|
||||
An extension ID or organization ID is required to login
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
{loading ? (
|
||||
<p className="text-sm">Checking your access rights...</p>
|
||||
) : (
|
||||
<div className="flex flex-col items-center space-x-4 space-y-4">
|
||||
<Button onClick={onSignInWithFly} disabled={!fly_extension_id && !fly_organization_id}>
|
||||
Login with Fly.io
|
||||
</Button>
|
||||
{isReady && !fly_extension_id && !fly_organization_id && (
|
||||
<p className="text-red-900 text-sm">
|
||||
A fly extension ID or organization ID is required to login
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div className="sm:text-center">
|
||||
<p className="text-xs text-foreground-lighter sm:mx-auto sm:max-w-sm">
|
||||
By continuing, you agree to Supabase's{' '}
|
||||
|
||||
Reference in new issue
Block a user