Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
29 changes: 29 additions & 0 deletions apps/docs/content/guides/auth/password-security.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,35 @@ Leaked password protection is available on the Pro Plan and above.

</Admonition>

## Require reauthentication when changing password

Users will need to be recently logged in to change their password without requiring reauthentication. (A user is considered recently logged in if the session was created within the last 24 hours.) If disabled, a user can change their password at any time.

When enabled, a `nonce` will be sent to the user and this nonce must be validated before the a password change can occur. This can be triggered with the [reauthenticate()](/docs/reference/javascript/auth-reauthentication) API call.

```
const { error } = await supabase.auth.reauthenticate()
...
// send the nonce provided by the user with the password change
const { data, error } = await supabase.auth.updateUser({
email: 'user@email.com',
nonce: `${nonce}`,
password: "new_super_strong_password"
})
```

## Require current password when changing password

Enforce that users supply their current password when trying to change the password. When enabled, the password change request will validate that the current password is correct before updating the user's password.

```
const { data, error } = await supabase.auth.updateUser({
email: 'user@email.com',
current_password: "correct_current_password",
password: "new_super_strong_password"
})
```

## Additional recommendations

In addition to choosing suitable password strength settings and preventing the use of leaked passwords, consider asking your users to:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ const PROVIDER_EMAIL = {
If disabled, a user can change their password at any time.`,
type: 'boolean',
},
SECURITY_UPDATE_PASSWORD_REQUIRE_CURRENT_PASSWORD: {
title: 'Require current password when updating',
description: `Requires that the user supplies their current password when changing their password. [Learn more](${DOCS_URL}/guides/auth/password-security#require-current-password-when-changing).`,
type: 'boolean',
isPaid: false,
},
PASSWORD_HIBP_ENABLED: {
title: 'Prevent use of leaked passwords',
description: `Rejects the use of known or easy to guess passwords on sign up or password change. Powered by the HaveIBeenPwned.org Pwned Passwords API. [Learn more](${DOCS_URL}/guides/auth/password-security#password-strength-and-leaked-password-protection)`,
Expand Down Expand Up @@ -70,7 +76,6 @@ const PROVIDER_EMAIL = {
},
],
},

MAILER_OTP_EXP: {
title: 'Email OTP expiration',
type: 'number',
Expand Down
24 changes: 14 additions & 10 deletions apps/studio/components/interfaces/Organization/OrganizationCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Fragment } from 'react'
import { cn, Tooltip, TooltipContent, TooltipTrigger } from 'ui'

import { ActionCard } from '@/components/ui/ActionCard'
import PartnerIcon from '@/components/ui/PartnerIcon'
import { useOrgProjectsInfiniteQuery } from '@/data/projects/org-projects-infinite-query'
import type { Organization } from '@/types'

Expand Down Expand Up @@ -49,16 +50,19 @@ export const OrganizationCard = ({
</>
)}
</div>
{isMfaRequired && (
<Tooltip>
<TooltipTrigger className="cursor-default">
<Lock size={12} />
</TooltipTrigger>
<TooltipContent side="bottom" className={!isUserMFAEnabled ? 'w-80' : ''}>
MFA enforced
</TooltipContent>
</Tooltip>
)}
<div className="flex items-center gap-x-2">
<PartnerIcon organization={organization} />
{isMfaRequired && (
<Tooltip>
<TooltipTrigger className="cursor-default">
<Lock size={12} />
</TooltipTrigger>
<TooltipContent side="bottom" className={!isUserMFAEnabled ? 'w-80' : ''}>
MFA enforced
</TooltipContent>
</Tooltip>
)}
</div>
</div>
}
/>
Expand Down
4 changes: 2 additions & 2 deletions apps/studio/data/__templates/resource-query.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useQuery, useQueryClient } from '@tanstack/react-query'
import { useCallback } from 'react'

import { get, handleError } from 'data/fetchers'
import type { ResponseError, UseCustomQueryOptions } from 'types'
import { resourceKeys } from './keys'
import { get, handleError } from '@/data/fetchers'
import type { ResponseError, UseCustomQueryOptions } from '@/types'

export type ResourceVariables = {
projectRef?: string
Expand Down
4 changes: 2 additions & 2 deletions apps/studio/data/__templates/resource-update-mutation.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { toast } from 'sonner'

import { handleError, patch } from 'data/fetchers'
import type { ResponseError, UseCustomMutationOptions } from 'types'
import { resourceKeys } from './keys'
import { handleError, patch } from '@/data/fetchers'
import type { ResponseError, UseCustomMutationOptions } from '@/types'

export type ResourceUpdateVariables = {
projectRef: string
Expand Down
4 changes: 2 additions & 2 deletions apps/studio/data/__templates/resources-query.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useQuery, useQueryClient } from '@tanstack/react-query'
import { useCallback } from 'react'

import { get, handleError } from 'data/fetchers'
import type { ResponseError, UseCustomQueryOptions } from 'types'
import { resourceKeys } from './keys'
import { get, handleError } from '@/data/fetchers'
import type { ResponseError, UseCustomQueryOptions } from '@/types'

export type ResourcesVariables = {
projectRef?: string
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { components } from 'api-types'
import { toast } from 'sonner'

import { components } from 'api-types'
import { handleError, post } from 'data/fetchers'
import type { ResponseError, UseCustomMutationOptions } from 'types'
import { accessTokenKeys } from './keys'
import { handleError, post } from '@/data/fetchers'
import type { ResponseError, UseCustomMutationOptions } from '@/types'

export type AccessTokenCreateVariables = components['schemas']['CreateAccessTokenBody']

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { toast } from 'sonner'

import { del, handleError } from 'data/fetchers'
import type { ResponseError, UseCustomMutationOptions } from 'types'
import { accessTokenKeys } from './keys'
import { del, handleError } from '@/data/fetchers'
import type { ResponseError, UseCustomMutationOptions } from '@/types'

export type AccessTokenDeleteVariables = {
id: number
Expand Down
4 changes: 2 additions & 2 deletions apps/studio/data/access-tokens/access-tokens-query.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useQuery } from '@tanstack/react-query'

import { get, handleError } from 'data/fetchers'
import type { ResponseError, UseCustomQueryOptions } from 'types'
import { accessTokenKeys } from './keys'
import { get, handleError } from '@/data/fetchers'
import type { ResponseError, UseCustomQueryOptions } from '@/types'

export async function getAccessTokens(signal?: AbortSignal) {
const { data, error } = await get('/platform/profile/access-tokens', { signal })
Expand Down
6 changes: 3 additions & 3 deletions apps/studio/data/actions/action-detail-query.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useQuery } from '@tanstack/react-query'

import { components } from 'api-types'
import { get, handleError } from 'data/fetchers'
import type { ResponseError, UseCustomQueryOptions } from 'types'

import { actionKeys } from './keys'
import { get, handleError } from '@/data/fetchers'
import type { ResponseError, UseCustomQueryOptions } from '@/types'

type ActionRunVariables = {
projectRef?: string
Expand Down
4 changes: 2 additions & 2 deletions apps/studio/data/actions/action-logs-query.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useQuery } from '@tanstack/react-query'

import { get, handleError } from 'data/fetchers'
import type { ResponseError, UseCustomQueryOptions } from 'types'
import { actionKeys } from './keys'
import { get, handleError } from '@/data/fetchers'
import type { ResponseError, UseCustomQueryOptions } from '@/types'

type ActionLogsVariables = {
projectRef?: string
Expand Down
6 changes: 3 additions & 3 deletions apps/studio/data/actions/action-runs-query.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useQuery } from '@tanstack/react-query'

import type { operations } from 'data/api'
import { get, handleError } from 'data/fetchers'
import type { ResponseError, UseCustomQueryOptions } from 'types'
import { actionKeys } from './keys'
import type { operations } from '@/data/api'
import { get, handleError } from '@/data/fetchers'
import type { ResponseError, UseCustomQueryOptions } from '@/types'

export type ActionsVariables = operations['v1-list-action-runs']['parameters']['path']

Expand Down
6 changes: 3 additions & 3 deletions apps/studio/data/ai/check-api-key-query.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useQuery } from '@tanstack/react-query'

import { constructHeaders, fetchHandler } from 'data/fetchers'
import { BASE_PATH, IS_PLATFORM } from 'lib/constants'
import { ResponseError, UseCustomQueryOptions } from 'types'
import { aiKeys } from './keys'
import { constructHeaders, fetchHandler } from '@/data/fetchers'
import { BASE_PATH, IS_PLATFORM } from '@/lib/constants'
import { ResponseError, UseCustomQueryOptions } from '@/types'

// check to see if the OPENAI_API_KEY env var is set in self-hosted
// so we can disable the chat editor and add a warning about manually adding the key
Expand Down
8 changes: 4 additions & 4 deletions apps/studio/data/ai/rate-message-mutation.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { UIMessage } from '@ai-sdk/react'
import { useMutation } from '@tanstack/react-query'

import type { RateMessageResponse } from 'components/ui/AIAssistantPanel/Message.utils'
import { constructHeaders, fetchHandler } from 'data/fetchers'
import { BASE_PATH } from 'lib/constants'
import { ResponseError, UseCustomMutationOptions } from 'types'
import type { RateMessageResponse } from '@/components/ui/AIAssistantPanel/Message.utils'
import { constructHeaders, fetchHandler } from '@/data/fetchers'
import { BASE_PATH } from '@/lib/constants'
import { ResponseError, UseCustomMutationOptions } from '@/types'

export type RateMessageVariables = {
rating: 'positive' | 'negative'
Expand Down
6 changes: 3 additions & 3 deletions apps/studio/data/ai/sql-cron-mutation.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useMutation } from '@tanstack/react-query'
import { toast } from 'sonner'

import { constructHeaders, fetchHandler } from 'data/fetchers'
import { BASE_PATH } from 'lib/constants'
import { ResponseError, UseCustomMutationOptions } from 'types'
import { constructHeaders, fetchHandler } from '@/data/fetchers'
import { BASE_PATH } from '@/lib/constants'
import { ResponseError, UseCustomMutationOptions } from '@/types'

export type SqlCronGenerateResponse = string

Expand Down
8 changes: 4 additions & 4 deletions apps/studio/data/ai/sql-filter-mutation.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { useMutation } from '@tanstack/react-query'
import { toast } from 'sonner'

import { constructHeaders, fetchHandler } from 'data/fetchers'
import { BASE_PATH } from 'lib/constants'
import { ResponseError, UseCustomMutationOptions } from 'types'
import { AIFilterRequestPayload, FilterGroup } from 'ui-patterns/FilterBar'

import { constructHeaders, fetchHandler } from '@/data/fetchers'
import { BASE_PATH } from '@/lib/constants'
import { ResponseError, UseCustomMutationOptions } from '@/types'

export type SqlFilterGenerateResponse = FilterGroup

export async function generateSqlFilters({
Expand Down
8 changes: 4 additions & 4 deletions apps/studio/data/ai/sql-policy-mutation.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { useMutation } from '@tanstack/react-query'
import { toast } from 'sonner'

import type { CreatePolicyBody } from 'data/database-policies/database-policy-create-mutation'
import { fetchPost } from 'data/fetchers'
import { BASE_PATH } from 'lib/constants'
import { ResponseError, UseCustomMutationOptions } from 'types'
import type { CreatePolicyBody } from '@/data/database-policies/database-policy-create-mutation'
import { fetchPost } from '@/data/fetchers'
import { BASE_PATH } from '@/lib/constants'
import { ResponseError, UseCustomMutationOptions } from '@/types'

export type SqlPolicyGenerateVariables = {
tableName: string
Expand Down
6 changes: 3 additions & 3 deletions apps/studio/data/ai/sql-title-mutation.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useMutation } from '@tanstack/react-query'
import { toast } from 'sonner'

import { constructHeaders, fetchHandler } from 'data/fetchers'
import { BASE_PATH } from 'lib/constants'
import { ResponseError, UseCustomMutationOptions } from 'types'
import { constructHeaders, fetchHandler } from '@/data/fetchers'
import { BASE_PATH } from '@/lib/constants'
import { ResponseError, UseCustomMutationOptions } from '@/types'

export type SqlTitleGenerateResponse = {
title: string
Expand Down
5 changes: 3 additions & 2 deletions apps/studio/data/analytics/functions-combined-stats-query.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { useQuery } from '@tanstack/react-query'
import { operations } from 'api-types'
import { get, handleError } from 'data/fetchers'

import { analyticsKeys } from './keys'
import { UseCustomQueryOptions } from 'types'
import { get, handleError } from '@/data/fetchers'
import { UseCustomQueryOptions } from '@/types'

export type FunctionsCombinedStatsVariables = {
projectRef?: string
Expand Down
5 changes: 3 additions & 2 deletions apps/studio/data/analytics/functions-req-stats-query.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { useQuery } from '@tanstack/react-query'
import { operations } from 'api-types'
import { get, handleError } from 'data/fetchers'

import { analyticsKeys } from './keys'
import { UseCustomQueryOptions } from 'types'
import { get, handleError } from '@/data/fetchers'
import { UseCustomQueryOptions } from '@/types'

export type FunctionsReqStatsVariables = {
projectRef?: string
Expand Down
5 changes: 3 additions & 2 deletions apps/studio/data/analytics/functions-resource-usage-query.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { useQuery } from '@tanstack/react-query'
import { operations } from 'api-types'
import { get, handleError } from 'data/fetchers'

import { analyticsKeys } from './keys'
import { UseCustomQueryOptions } from 'types'
import { get, handleError } from '@/data/fetchers'
import { UseCustomQueryOptions } from '@/types'

export type FunctionsResourceUsageVariables = {
projectRef?: string
Expand Down
10 changes: 5 additions & 5 deletions apps/studio/data/analytics/infra-monitoring-queries.test.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import dayjs from 'dayjs'
import { describe, expect, it } from 'vitest'

import {
aggregate1MinTo2Min,
mapMultiResponseToAnalyticsData,
mapResponseToAnalyticsData,
} from './infra-monitoring-queries'
import type {
InfraMonitoringMultiData,
InfraMonitoringMultiResponse,
InfraMonitoringSingleResponse,
} from './infra-monitoring-query'
import {
aggregate1MinTo2Min,
mapResponseToAnalyticsData,
mapMultiResponseToAnalyticsData,
} from './infra-monitoring-queries'

const mockMultiResponse: InfraMonitoringMultiResponse = {
data: [
Expand Down
5 changes: 2 additions & 3 deletions apps/studio/data/analytics/infra-monitoring-queries.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { useMemo } from 'react'
import type { UseQueryResult } from '@tanstack/react-query'

import dayjs from 'dayjs'
import { useMemo } from 'react'

import type { AnalyticsData, AnalyticsInterval, DataPoint } from './constants'
import type {
Expand All @@ -10,8 +9,8 @@ import type {
InfraMonitoringSingleResponse,
} from './infra-monitoring-query'
import {
InfraMonitoringMultiData,
InfraMonitoringError,
InfraMonitoringMultiData,
useInfraMonitoringAttributesQuery,
} from './infra-monitoring-query'

Expand Down
4 changes: 2 additions & 2 deletions apps/studio/data/analytics/infra-monitoring-query.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { useQuery } from '@tanstack/react-query'
import { paths } from 'api-types'
import { get, handleError } from 'data/fetchers'
import { UseCustomQueryOptions } from 'types'

import type { AnalyticsInterval } from './constants'
import { analyticsKeys } from './keys'
import { get, handleError } from '@/data/fetchers'
import { UseCustomQueryOptions } from '@/types'

export type InfraMonitoringAttribute = NonNullable<
paths['/platform/projects/{ref}/infra-monitoring']['get']['parameters']['query']['attributes']
Expand Down
1 change: 1 addition & 0 deletions apps/studio/data/analytics/org-daily-stats-query.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'

import { getOrgDailyStats } from './org-daily-stats-query'

vi.mock('data/fetchers', () => ({
Expand Down
6 changes: 3 additions & 3 deletions apps/studio/data/analytics/org-daily-stats-query.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useQuery } from '@tanstack/react-query'

import type { components } from 'api-types'
import { get, handleError } from 'data/fetchers'
import type { ResponseError, UseCustomQueryOptions } from 'types'

import { analyticsKeys } from './keys'
import { get, handleError } from '@/data/fetchers'
import type { ResponseError, UseCustomQueryOptions } from '@/types'

export enum EgressType {
REST = 'egress_rest',
Expand Down
Loading
Loading