- 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>
59 lines
1.8 KiB
TypeScript
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;
|
|
}
|