| |
| |
| |
|
|
| |
|
|
| |
|
|
| from server import notifications as notif_service |
|
|
| class NotificationPrefsRequest(BaseModel): |
| email_enabled: bool = True |
| sms_enabled: bool = False |
| web_enabled: bool = True |
| crawl_complete: bool = True |
| analysis_complete: bool = True |
| alert_triggered: bool = True |
| weekly_report: bool = True |
|
|
| @app.get('/api/notifications') |
| async def api_get_notifications(request: Request, unread_only: bool = False): |
| """Get user notifications""" |
| try: |
| auth = request.headers.get('authorization', '') |
| token = auth.split(' ', 1)[1].strip() |
| uid = user_mgmt.verify_token(token) |
| if not uid: |
| return JSONResponse({'ok': False, 'error': 'unauthorized'}, status_code=401) |
| |
| notifs = notif_service.get_notifications(uid, unread_only) |
| return {'ok': True, 'notifications': notifs, 'count': len(notifs)} |
| except Exception as e: |
| return JSONResponse({'ok': False, 'error': str(e)}, status_code=500) |
|
|
| @app.post('/api/notifications/{notification_id}/read') |
| async def api_mark_notification_read(notification_id: int, request: Request): |
| """Mark notification as read""" |
| try: |
| notif_service.mark_as_read(notification_id) |
| return {'ok': True} |
| except Exception as e: |
| return JSONResponse({'ok': False, 'error': str(e)}, status_code=500) |
|
|
| @app.get('/api/notifications/preferences') |
| async def api_get_notification_prefs(request: Request): |
| """Get notification preferences""" |
| try: |
| auth = request.headers.get('authorization', '') |
| token = auth.split(' ', 1)[1].strip() |
| uid = user_mgmt.verify_token(token) |
| if not uid: |
| return JSONResponse({'ok': False, 'error': 'unauthorized'}, status_code=401) |
| |
| prefs = notif_service.get_preferences(uid) |
| return {'ok': True, 'preferences': prefs} |
| except Exception as e: |
| return JSONResponse({'ok': False, 'error': str(e)}, status_code=500) |
|
|
| @app.post('/api/notifications/preferences') |
| async def api_update_notification_prefs(req: NotificationPrefsRequest, request: Request): |
| """Update notification preferences""" |
| try: |
| auth = request.headers.get('authorization', '') |
| token = auth.split(' ', 1)[1].strip() |
| uid = user_mgmt.verify_token(token) |
| if not uid: |
| return JSONResponse({'ok': False, 'error': 'unauthorized'}, status_code=401) |
| |
| prefs_dict = req.dict() |
| notif_service.update_preferences(uid, prefs_dict) |
| return {'ok': True} |
| except Exception as e: |
| return JSONResponse({'ok': False, 'error': str(e)}, status_code=500) |
|
|
| |
|
|
| from server import two_factor_auth as tfa_service |
|
|
| @app.post('/api/2fa/setup') |
| async def api_setup_2fa(request: Request): |
| """Generate 2FA secret and QR code""" |
| try: |
| auth = request.headers.get('authorization', '') |
| token = auth.split(' ', 1)[1].strip() |
| uid = user_mgmt.verify_token(token) |
| if not uid: |
| return JSONResponse({'ok': False, 'error': 'unauthorized'}, status_code=401) |
| |
| user = user_mgmt.get_user(uid) |
| secret, qr_code = tfa_service.generate_secret(uid, user['email']) |
| |
| return { |
| 'ok': True, |
| 'secret': secret, |
| 'qr_code': qr_code, |
| 'backup_codes': tfa_service.get_backup_codes(uid) or [] |
| } |
| except Exception as e: |
| return JSONResponse({'ok': False, 'error': str(e)}, status_code=500) |
|
|
| @app.post('/api/2fa/enable') |
| async def api_enable_2fa(request: Request): |
| """Enable 2FA with verification""" |
| try: |
| data = await request.json() |
| secret = data.get('secret') |
| token_code = data.get('token') |
| |
| auth = request.headers.get('authorization', '') |
| token = auth.split(' ', 1)[1].strip() |
| uid = user_mgmt.verify_token(token) |
| if not uid: |
| return JSONResponse({'ok': False, 'error': 'unauthorized'}, status_code=401) |
| |
| |
| import pyotp |
| totp = pyotp.TOTP(secret) |
| if not totp.verify(token_code): |
| return JSONResponse({'ok': False, 'error': 'Invalid token'}, status_code=400) |
| |
| tfa_service.enable_2fa(uid, secret) |
| backup_codes = tfa_service.get_backup_codes(uid) |
| |
| return { |
| 'ok': True, |
| 'message': '2FA enabled successfully', |
| 'backup_codes': backup_codes |
| } |
| except Exception as e: |
| return JSONResponse({'ok': False, 'error': str(e)}, status_code=500) |
|
|
| @app.post('/api/2fa/disable') |
| async def api_disable_2fa(request: Request): |
| """Disable 2FA""" |
| try: |
| auth = request.headers.get('authorization', '') |
| token = auth.split(' ', 1)[1].strip() |
| uid = user_mgmt.verify_token(token) |
| if not uid: |
| return JSONResponse({'ok': False, 'error': 'unauthorized'}, status_code=401) |
| |
| tfa_service.disable_2fa(uid) |
| return {'ok': True, 'message': '2FA disabled'} |
| except Exception as e: |
| return JSONResponse({'ok': False, 'error': str(e)}, status_code=500) |
|
|
| @app.get('/api/2fa/status') |
| async def api_2fa_status(request: Request): |
| """Check 2FA status""" |
| try: |
| auth = request.headers.get('authorization', '') |
| token = auth.split(' ', 1)[1].strip() |
| uid = user_mgmt.verify_token(token) |
| if not uid: |
| return JSONResponse({'ok': False, 'error': 'unauthorized'}, status_code=401) |
| |
| enabled = tfa_service.is_2fa_enabled(uid) |
| return {'ok': True, 'enabled': enabled} |
| except Exception as e: |
| return JSONResponse({'ok': False, 'error': str(e)}, status_code=500) |
|
|
| @app.get('/api/2fa/login-history') |
| async def api_login_history(request: Request, days: int = 30): |
| """Get login history""" |
| try: |
| auth = request.headers.get('authorization', '') |
| token = auth.split(' ', 1)[1].strip() |
| uid = user_mgmt.verify_token(token) |
| if not uid: |
| return JSONResponse({'ok': False, 'error': 'unauthorized'}, status_code=401) |
| |
| history = tfa_service.get_login_history(uid, days) |
| return {'ok': True, 'history': history} |
| except Exception as e: |
| return JSONResponse({'ok': False, 'error': str(e)}, status_code=500) |
|
|
| @app.get('/api/2fa/suspicious-activity') |
| async def api_check_suspicious_activity(request: Request): |
| """Check for suspicious login activity""" |
| try: |
| auth = request.headers.get('authorization', '') |
| token = auth.split(' ', 1)[1].strip() |
| uid = user_mgmt.verify_token(token) |
| if not uid: |
| return JSONResponse({'ok': False, 'error': 'unauthorized'}, status_code=401) |
| |
| activity = tfa_service.detect_suspicious_activity(uid) |
| return {'ok': True, **activity} |
| except Exception as e: |
| return JSONResponse({'ok': False, 'error': str(e)}, status_code=500) |
|
|
| |
|
|
| from server import support as support_service |
|
|
| class SupportTicketRequest(BaseModel): |
| subject: str |
| description: str |
| category: str |
| priority: str = 'medium' |
|
|
| class TicketMessageRequest(BaseModel): |
| message: str |
| attachment_url: Optional[str] = None |
|
|
| @app.post('/api/support/tickets') |
| async def api_create_ticket(req: SupportTicketRequest, request: Request): |
| """Create support ticket""" |
| try: |
| auth = request.headers.get('authorization', '') |
| token = auth.split(' ', 1)[1].strip() |
| uid = user_mgmt.verify_token(token) |
| if not uid: |
| return JSONResponse({'ok': False, 'error': 'unauthorized'}, status_code=401) |
| |
| ticket_id = support_service.create_ticket( |
| uid, req.subject, req.description, req.category, req.priority |
| ) |
| return {'ok': True, 'ticket_id': ticket_id} |
| except Exception as e: |
| return JSONResponse({'ok': False, 'error': str(e)}, status_code=500) |
|
|
| @app.get('/api/support/tickets') |
| async def api_list_tickets(request: Request, status: Optional[str] = None): |
| """List user tickets""" |
| try: |
| auth = request.headers.get('authorization', '') |
| token = auth.split(' ', 1)[1].strip() |
| uid = user_mgmt.verify_token(token) |
| if not uid: |
| return JSONResponse({'ok': False, 'error': 'unauthorized'}, status_code=401) |
| |
| tickets = support_service.get_user_tickets(uid, status) |
| return {'ok': True, 'tickets': tickets, 'count': len(tickets)} |
| except Exception as e: |
| return JSONResponse({'ok': False, 'error': str(e)}, status_code=500) |
|
|
| @app.get('/api/support/tickets/{ticket_id}') |
| async def api_get_ticket(ticket_id: int, request: Request): |
| """Get ticket details""" |
| try: |
| ticket = support_service.get_ticket(ticket_id) |
| if not ticket: |
| return JSONResponse({'ok': False, 'error': 'Ticket not found'}, status_code=404) |
| |
| messages = support_service.get_ticket_messages(ticket_id) |
| return {'ok': True, 'ticket': ticket, 'messages': messages} |
| except Exception as e: |
| return JSONResponse({'ok': False, 'error': str(e)}, status_code=500) |
|
|
| @app.post('/api/support/tickets/{ticket_id}/messages') |
| async def api_add_ticket_message(ticket_id: int, req: TicketMessageRequest, request: Request): |
| """Add message to ticket""" |
| try: |
| auth = request.headers.get('authorization', '') |
| token = auth.split(' ', 1)[1].strip() |
| uid = user_mgmt.verify_token(token) |
| if not uid: |
| return JSONResponse({'ok': False, 'error': 'unauthorized'}, status_code=401) |
| |
| msg_id = support_service.add_ticket_message(ticket_id, uid, req.message, req.attachment_url) |
| return {'ok': True, 'message_id': msg_id} |
| except Exception as e: |
| return JSONResponse({'ok': False, 'error': str(e)}, status_code=500) |
|
|
| @app.post('/api/support/tickets/{ticket_id}/status') |
| async def api_update_ticket_status(ticket_id: int, request: Request): |
| """Update ticket status""" |
| try: |
| data = await request.json() |
| status = data.get('status') |
| |
| support_service.update_ticket_status(ticket_id, status) |
| return {'ok': True} |
| except Exception as e: |
| return JSONResponse({'ok': False, 'error': str(e)}, status_code=500) |
|
|
| @app.get('/api/support/kb') |
| async def api_get_kb_articles(category: Optional[str] = None): |
| """Get knowledge base articles""" |
| try: |
| articles = support_service.get_kb_articles(category) |
| return {'ok': True, 'articles': articles, 'count': len(articles)} |
| except Exception as e: |
| return JSONResponse({'ok': False, 'error': str(e)}, status_code=500) |
|
|
| @app.get('/api/support/kb/search') |
| async def api_search_kb(q: str): |
| """Search knowledge base""" |
| try: |
| results = support_service.search_kb(q) |
| return {'ok': True, 'results': results, 'count': len(results)} |
| except Exception as e: |
| return JSONResponse({'ok': False, 'error': str(e)}, status_code=500) |
|
|
| @app.get('/api/support/faqs') |
| async def api_get_faqs(category: Optional[str] = None): |
| """Get FAQs""" |
| try: |
| faqs = support_service.get_faqs(category) |
| return {'ok': True, 'faqs': faqs, 'count': len(faqs)} |
| except Exception as e: |
| return JSONResponse({'ok': False, 'error': str(e)}, status_code=500) |
|
|
| @app.get('/api/support/stats') |
| async def api_support_stats(): |
| """Get support statistics""" |
| try: |
| stats = support_service.get_ticket_stats() |
| return {'ok': True, 'stats': stats} |
| except Exception as e: |
| return JSONResponse({'ok': False, 'error': str(e)}, status_code=500) |
|
|