feat: Add security center and warning for exceeding bounce/complaint rates
This commit is contained in:
@@ -15,15 +15,18 @@ import Link from 'next/link';
|
||||
import {ApiKeyDisplay} from '../components/ApiKeyDisplay';
|
||||
import {DashboardLayout} from '../components/DashboardLayout';
|
||||
import {QuickStart} from '../components/QuickStart';
|
||||
import {SecurityWarningBanner} from '../components/SecurityWarningBanner';
|
||||
import {useActiveProject} from '../lib/contexts/ActiveProjectProvider';
|
||||
import {useDashboardStats} from '../lib/hooks/useDashboardStats';
|
||||
import {useProjectSetupState} from '../lib/hooks/useProjectSetupState';
|
||||
import {useProjectSecurity} from '../lib/hooks/useProjectSecurity';
|
||||
import {useConfig} from '../lib/hooks/useConfig';
|
||||
|
||||
export default function Index() {
|
||||
const {activeProject} = useActiveProject();
|
||||
const {totalContacts, totalEmailsSent, totalCampaigns, openRate, isLoading} = useDashboardStats();
|
||||
const {setupState, isLoading: isLoadingSetupState} = useProjectSetupState(activeProject?.id);
|
||||
const {securityMetrics} = useProjectSecurity(activeProject?.id);
|
||||
const {data: config} = useConfig();
|
||||
|
||||
const stats = [
|
||||
@@ -68,6 +71,11 @@ export default function Index() {
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
{/* Security Warning Banner */}
|
||||
{activeProject && !activeProject.disabled && securityMetrics && (
|
||||
<SecurityWarningBanner status={securityMetrics.status} />
|
||||
)}
|
||||
|
||||
{/* Subscription Warning Banner */}
|
||||
{activeProject &&
|
||||
!activeProject.disabled &&
|
||||
|
||||
@@ -37,7 +37,16 @@ import {
|
||||
} from '@plunk/ui';
|
||||
import {AnimatePresence, motion} from 'framer-motion';
|
||||
import {NextSeo} from 'next-seo';
|
||||
import {AlertTriangle, CreditCard, Database, Globe, Mail, Settings as SettingsIcon, Users} from 'lucide-react';
|
||||
import {
|
||||
AlertTriangle,
|
||||
CreditCard,
|
||||
Database,
|
||||
Globe,
|
||||
Mail,
|
||||
Settings as SettingsIcon,
|
||||
Shield,
|
||||
Users,
|
||||
} from 'lucide-react';
|
||||
import type {z} from 'zod';
|
||||
import {useRouter} from 'next/router';
|
||||
import {DashboardLayout} from '../../components/DashboardLayout';
|
||||
@@ -50,14 +59,16 @@ import {ApiKeyDisplay} from '../../components/ApiKeyDisplay';
|
||||
import {SmtpSettings} from '../../components/SmtpSettings';
|
||||
import {DataManagementSettings} from '../../components/DataManagementSettings';
|
||||
import {TeamSettings} from '../../components/TeamSettings';
|
||||
import {SecuritySettings} from '../../components/SecuritySettings';
|
||||
import {useActiveProject} from '../../lib/contexts/ActiveProjectProvider';
|
||||
import {network} from '../../lib/network';
|
||||
import {useProjects} from '../../lib/hooks/useProject';
|
||||
import {useConfig} from '../../lib/hooks/useConfig';
|
||||
import {useUser} from '../../lib/hooks/useUser';
|
||||
import {useProjectSecurity} from '../../lib/hooks/useProjectSecurity';
|
||||
import useSWR from 'swr';
|
||||
|
||||
type TabId = 'general' | 'billing' | 'domains' | 'smtp' | 'data' | 'team';
|
||||
type TabId = 'general' | 'billing' | 'domains' | 'smtp' | 'data' | 'team' | 'security';
|
||||
|
||||
interface Tab {
|
||||
id: TabId;
|
||||
@@ -71,6 +82,7 @@ const buildTabs = (options: {billingEnabled: boolean; smtpEnabled: boolean}): Ta
|
||||
const allTabs: Tab[] = [
|
||||
{id: 'general', label: 'General', icon: SettingsIcon},
|
||||
{id: 'team', label: 'Team', icon: Users},
|
||||
{id: 'security', label: 'Security', icon: Shield},
|
||||
{id: 'billing', label: 'Billing', icon: CreditCard, condition: billingEnabled},
|
||||
{id: 'domains', label: 'Domains', icon: Globe},
|
||||
{id: 'smtp', label: 'SMTP', icon: Mail, condition: smtpEnabled},
|
||||
@@ -103,6 +115,8 @@ export default function Settings() {
|
||||
const currentUserMembership = membershipData?.data.find(m => m.userId === user?.id);
|
||||
const currentUserRole = currentUserMembership?.role || 'MEMBER';
|
||||
|
||||
const {securityMetrics, isLoading: isLoadingSecurityMetrics} = useProjectSecurity(activeProject?.id);
|
||||
|
||||
const billingEnabled = config?.features.billing.enabled ?? false;
|
||||
const smtpEnabled = config?.features.smtp.enabled ?? false;
|
||||
const trackingToggleEnabled = config?.features.email.trackingToggleEnabled ?? false;
|
||||
@@ -691,6 +705,24 @@ export default function Settings() {
|
||||
/>
|
||||
</TabsContent>
|
||||
|
||||
{/* Security Tab */}
|
||||
<TabsContent value="security">
|
||||
{securityMetrics ? (
|
||||
<SecuritySettings metrics={securityMetrics} isLoading={isLoadingSecurityMetrics} />
|
||||
) : (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Security Overview</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p className="text-sm text-neutral-500">
|
||||
{isLoadingSecurityMetrics ? 'Loading...' : 'Unable to load security metrics'}
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
</TabsContent>
|
||||
|
||||
{/* Domains Tab */}
|
||||
<TabsContent value="domains">
|
||||
<DomainsSettings projectId={activeProject.id} />
|
||||
|
||||
Reference in New Issue
Block a user