diff --git a/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreview.constants.tsx b/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreview.constants.tsx
index 9a56fd87b21..03d791ca891 100644
--- a/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreview.constants.tsx
+++ b/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreview.constants.tsx
@@ -1,6 +1,13 @@
import { LOCAL_STORAGE_KEYS } from 'common'
export const FEATURE_PREVIEWS = [
+ {
+ key: LOCAL_STORAGE_KEYS.UI_PREVIEW_SECURITY_NOTIFICATIONS,
+ name: 'Security notification templates',
+ discussionsUrl: undefined,
+ isNew: true,
+ isPlatformOnly: true,
+ },
{
key: LOCAL_STORAGE_KEYS.UI_PREVIEW_NEW_STORAGE_UI,
name: 'New Storage interface',
diff --git a/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewContext.tsx b/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewContext.tsx
index 885724aca13..bb2b449c4d5 100644
--- a/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewContext.tsx
+++ b/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewContext.tsx
@@ -115,6 +115,11 @@ export const useIsNewStorageUIEnabled = () => {
return flags[LOCAL_STORAGE_KEYS.UI_PREVIEW_NEW_STORAGE_UI]
}
+export const useIsSecurityNotificationsEnabled = () => {
+ const { flags } = useFeaturePreviewContext()
+ return flags[LOCAL_STORAGE_KEYS.UI_PREVIEW_SECURITY_NOTIFICATIONS]
+}
+
export const useFeaturePreviewModal = () => {
const [featurePreviewModal, setFeaturePreviewModal] = useQueryState('featurePreviewModal')
@@ -122,6 +127,7 @@ export const useFeaturePreviewModal = () => {
const advisorRulesEnabled = useFlag('advisorRules')
const isUnifiedLogsPreviewAvailable = useFlag('unifiedLogs')
const isNewStorageUIAvailable = useFlag('storageAnalyticsVector')
+ const isSecurityNotificationsAvailable = useFlag('securityNotifications')
const selectedFeatureKeyFromQuery = featurePreviewModal?.trim() ?? null
const showFeaturePreviewModal = selectedFeatureKeyFromQuery !== null
@@ -138,11 +144,19 @@ export const useFeaturePreviewModal = () => {
return isUnifiedLogsPreviewAvailable
case 'new-storage-ui':
return isNewStorageUIAvailable
+ case 'security-notifications':
+ return isSecurityNotificationsAvailable
default:
return true
}
},
- [gitlessBranchingEnabled, advisorRulesEnabled, isUnifiedLogsPreviewAvailable]
+ [
+ gitlessBranchingEnabled,
+ advisorRulesEnabled,
+ isUnifiedLogsPreviewAvailable,
+ isNewStorageUIAvailable,
+ isSecurityNotificationsAvailable,
+ ]
)
const selectedFeatureKey = (
diff --git a/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewModal.tsx b/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewModal.tsx
index ec463be8a64..3fa262e4b12 100644
--- a/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewModal.tsx
+++ b/apps/studio/components/interfaces/App/FeaturePreview/FeaturePreviewModal.tsx
@@ -16,6 +16,7 @@ import { useFeaturePreviewContext, useFeaturePreviewModal } from './FeaturePrevi
import { InlineEditorPreview } from './InlineEditorPreview'
import { NewStorageUIPreview } from './NewStorageUIPreview'
import { UnifiedLogsPreview } from './UnifiedLogsPreview'
+import { SecurityNotificationsPreview } from './SecurityNotificationsPreview'
const FEATURE_PREVIEW_KEY_TO_CONTENT: {
[key: string]: ReactNode
@@ -27,6 +28,7 @@ const FEATURE_PREVIEW_KEY_TO_CONTENT: {
[LOCAL_STORAGE_KEYS.UI_PREVIEW_CLS]: ,
[LOCAL_STORAGE_KEYS.UI_PREVIEW_UNIFIED_LOGS]: ,
[LOCAL_STORAGE_KEYS.UI_PREVIEW_NEW_STORAGE_UI]: ,
+ [LOCAL_STORAGE_KEYS.UI_PREVIEW_SECURITY_NOTIFICATIONS]: ,
}
const FeaturePreviewModal = () => {
diff --git a/apps/studio/components/interfaces/App/FeaturePreview/SecurityNotificationsPreview.tsx b/apps/studio/components/interfaces/App/FeaturePreview/SecurityNotificationsPreview.tsx
new file mode 100644
index 00000000000..8857881dfa4
--- /dev/null
+++ b/apps/studio/components/interfaces/App/FeaturePreview/SecurityNotificationsPreview.tsx
@@ -0,0 +1,46 @@
+import Image from 'next/image'
+
+import { useParams } from 'common'
+import { InlineLink } from 'components/ui/InlineLink'
+import { BASE_PATH } from 'lib/constants'
+import { useIsSecurityNotificationsEnabled } from './FeaturePreviewContext'
+
+export const SecurityNotificationsPreview = () => {
+ const { ref } = useParams()
+ const isSecurityNotificationsEnabled = useIsSecurityNotificationsEnabled()
+
+ return (
+
+
+
+
+ Try out our expanded set of{' '}
+
+ email templates
+ {' '}
+ with support for security-related notifications.
+
+
Enabling this preview will:
+
+ - Add a dedicated sidebar section for contact methods like email and SMS
+ - Add new email templates for security-related notifications
+ - Move each (existing and new) template into its own dynamic route
+
+
+ These changes are necessary to support incoming security-related notification templates.
+ Given that the list of our email templates is doubling in size, this change requires some
+ wider interface changes. Ones that we think make for a clearer experience overall. Win
+ win!
+
+
+
+ )
+}
diff --git a/apps/studio/components/layouts/AuthLayout/AuthLayout.tsx b/apps/studio/components/layouts/AuthLayout/AuthLayout.tsx
index 70c4cfe7b3d..5e869db10b5 100644
--- a/apps/studio/components/layouts/AuthLayout/AuthLayout.tsx
+++ b/apps/studio/components/layouts/AuthLayout/AuthLayout.tsx
@@ -1,20 +1,21 @@
import { useRouter } from 'next/router'
import { PropsWithChildren } from 'react'
-import { useParams } from 'common'
+import { useFlag, useParams } from 'common'
+import { useIsSecurityNotificationsEnabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext'
import { ProductMenu } from 'components/ui/ProductMenu'
import { useAuthConfigPrefetch } from 'data/auth/auth-config-query'
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
import { withAuth } from 'hooks/misc/withAuth'
import { ProjectLayout } from '../ProjectLayout/ProjectLayout'
import { generateAuthMenu } from './AuthLayout.utils'
-import { useFlag } from 'common'
const AuthProductMenu = () => {
const router = useRouter()
const { ref: projectRef = 'default' } = useParams()
const authenticationShowOverview = useFlag('authOverviewPage')
+ const authenticationShowSecurityNotifications = useIsSecurityNotificationsEnabled()
const {
authenticationSignInProviders,
@@ -46,6 +47,7 @@ const AuthProductMenu = () => {
authenticationAttackProtection,
authenticationAdvanced,
authenticationShowOverview,
+ authenticationShowSecurityNotifications,
})}
/>
)
diff --git a/apps/studio/components/layouts/AuthLayout/AuthLayout.utils.ts b/apps/studio/components/layouts/AuthLayout/AuthLayout.utils.ts
index 67bad8717a3..27f0a52e396 100644
--- a/apps/studio/components/layouts/AuthLayout/AuthLayout.utils.ts
+++ b/apps/studio/components/layouts/AuthLayout/AuthLayout.utils.ts
@@ -11,6 +11,7 @@ export const generateAuthMenu = (
authenticationAttackProtection: boolean
authenticationAdvanced: boolean
authenticationShowOverview: boolean
+ authenticationShowSecurityNotifications: boolean
}
): ProductMenuGroup[] => {
const {
@@ -21,6 +22,7 @@ export const generateAuthMenu = (
authenticationAttackProtection,
authenticationAdvanced,
authenticationShowOverview,
+ authenticationShowSecurityNotifications,
} = flags ?? {}
return [
@@ -33,6 +35,26 @@ export const generateAuthMenu = (
{ name: 'Users', key: 'users', url: `/project/${ref}/auth/users`, items: [] },
],
},
+ ...(authenticationEmails && authenticationShowSecurityNotifications && IS_PLATFORM
+ ? [
+ {
+ title: 'Notifications',
+ items: [
+ ...(authenticationEmails
+ ? [
+ {
+ name: 'Email',
+ key: 'email',
+ pages: ['templates', 'smtp'],
+ url: `/project/${ref}/auth/templates`,
+ items: [],
+ },
+ ]
+ : []),
+ ],
+ },
+ ]
+ : []),
{
title: 'Configuration',
items: [
@@ -71,7 +93,7 @@ export const generateAuthMenu = (
},
]
: []),
- ...(authenticationEmails
+ ...(authenticationEmails && !authenticationShowSecurityNotifications
? [
{
name: 'Emails',
diff --git a/apps/studio/public/img/previews/security-notifications-preview.png b/apps/studio/public/img/previews/security-notifications-preview.png
new file mode 100644
index 00000000000..262ed16f4d9
Binary files /dev/null and b/apps/studio/public/img/previews/security-notifications-preview.png differ
diff --git a/packages/common/constants/local-storage.ts b/packages/common/constants/local-storage.ts
index c77786c7661..3784822e32b 100644
--- a/packages/common/constants/local-storage.ts
+++ b/packages/common/constants/local-storage.ts
@@ -18,6 +18,7 @@ export const LOCAL_STORAGE_KEYS = {
UI_PREVIEW_BRANCHING_2_0: 'supabase-ui-branching-2-0',
UI_PREVIEW_ADVISOR_RULES: 'supabase-ui-advisor-rules',
UI_PREVIEW_NEW_STORAGE_UI: 'new-storage-ui',
+ UI_PREVIEW_SECURITY_NOTIFICATIONS: 'security-notifications',
NEW_LAYOUT_NOTICE_ACKNOWLEDGED: 'new-layout-notice-acknowledge',
TABS_INTERFACE_ACKNOWLEDGED: 'tabs-interface-acknowledge',