veza/apps/web/src/services/2fa-service.ts
senke 6fad0ad68d fix: stabilize frontend — 98 TS errors to 0, align API endpoints, optimize bundle
- Fix 98 TypeScript errors across 37 files:
  - Service layer double-unwrapping (subscriptionService, distributionService, gearService)
  - Self-referencing variables in SearchPageResults
  - FeedView/ExploreView .posts→.items alignment
  - useQueueSync Zustand subscribe API
  - AdminAuditLogsView missing interface fields
  - Toast proxy type, interceptor type narrowing
  - 22 unused imports/variables removed
  - 5 storybook mock data fixes

- Align frontend API calls with backend endpoints:
  - Analytics: useAnalyticsView now calls /creator/analytics/dashboard (was /analytics)
  - Chat: chatService uses /conversations (was mock data), WS URL from backend token
  - Dashboard StatsSection: uses real /dashboard API data (was hardcoded zeros)
  - Settings: suppress 2FA toast error when endpoint unavailable

- Fix marketplace products: seed uses 'active' status (was 'published')
- Enrich seed: admin follows all creators (feed has content)

- Optimize bundle: vendor catch-all 793KB→318KB gzip (-60%)
  Split into vendor-charts, vendor-emoji, vendor-swagger, vendor-media, etc.

- Clean repo: remove ~100 orphaned screenshots, audit reports, logs from root

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 21:18:49 +01:00

59 lines
1.8 KiB
TypeScript

import { apiClient } from './api/client';
import { requireFeature, FEATURES } from '@/config/features';
interface TwoFactorSetupResponse {
secret: string;
qr_code_url: string;
recovery_codes: string[];
}
interface TwoFactorStatus {
enabled: boolean;
}
/**
* Two-Factor Authentication Service
*
* Backend endpoints: /auth/2fa/setup, /auth/2fa/verify, /auth/2fa/disable, /auth/2fa/status
*
* @see FEATURES.TWO_FACTOR_AUTH
*/
class TwoFactorService {
async getStatus(): Promise<TwoFactorStatus> {
requireFeature('TWO_FACTOR_AUTH');
// apiClient unwraps { success, data } format automatically
const response = await apiClient.get<TwoFactorStatus>('/auth/2fa/status', {
_disableToast: true,
} as Record<string, unknown>);
return response.data;
}
async setup(): Promise<TwoFactorSetupResponse> {
requireFeature('TWO_FACTOR_AUTH');
// apiClient unwraps { success, data } format automatically
const response =
await apiClient.post<TwoFactorSetupResponse>('/auth/2fa/setup');
return response.data;
}
async verify(secret: string, code: string): Promise<void> {
requireFeature('TWO_FACTOR_AUTH');
// Backend expects { secret, code } and returns { success: true, data: { message: "2FA enabled successfully" } }
await apiClient.post('/auth/2fa/verify', { secret, code });
}
async disable(password: string): Promise<void> {
requireFeature('TWO_FACTOR_AUTH');
// Backend expects { password } and returns { success: true, data: { message: "2FA disabled successfully" } }
await apiClient.post('/auth/2fa/disable', { password });
}
}
export const twoFactorService = new TwoFactorService();
/**
* Check if 2FA is enabled (for UI conditional rendering)
*/
export function is2FAEnabled(): boolean {
return FEATURES.TWO_FACTOR_AUTH;
}