diff --git a/backend/app/services/plugin_schemas.py b/backend/app/services/plugin_schemas.py index 7c869c6..2ed0271 100644 --- a/backend/app/services/plugin_schemas.py +++ b/backend/app/services/plugin_schemas.py @@ -164,196 +164,6 @@ def get_zammad_configuration_schema() -> Dict[str, Any]: } -def get_signal_configuration_schema() -> Dict[str, Any]: - """ - Returns the configuration schema for the Signal Bot plugin. - Based on the existing Signal module implementation. - """ - return { - "type": "object", - "title": "Signal Bot Configuration", - "description": "Configure AI-powered Signal messaging bot with role-based permissions", - "properties": { - # Basic Settings - "enable_signal_bot": { - "type": "boolean", - "title": "Enable Signal Bot", - "description": "Turn the Signal bot on/off", - "default": False, - "required": True - }, - "signal_service_url": { - "type": "url", - "title": "Signal Service URL", - "description": "Signal service endpoint (e.g., signal-cli-rest-api)", - "required": True, - "placeholder": "http://localhost:8080", - "depends_on": { - "field": "enable_signal_bot", - "value": True - } - }, - "bot_phone_number": { - "type": "string", - "title": "Bot Phone Number", - "description": "Registered Signal phone number for the bot", - "required": True, - "placeholder": "+1234567890", - "pattern": "^\\+[1-9]\\d{1,14}$", - "depends_on": { - "field": "enable_signal_bot", - "value": True - } - }, - - # AI Settings - "model": { - "type": "select", - "title": "AI Model", - "description": "Choose the AI model for responses", - "required": False, - "default": "privatemode-llama-3-70b", - "options": [], # Will be populated from available models - "depends_on": { - "field": "enable_signal_bot", - "value": True - } - }, - "temperature": { - "type": "number", - "title": "Response Creativity", - "description": "Control response creativity (0.0-1.0)", - "required": False, - "default": 0.7, - "minimum": 0.0, - "maximum": 1.0, - "depends_on": { - "field": "enable_signal_bot", - "value": True - } - }, - "max_tokens": { - "type": "integer", - "title": "Max Response Length", - "description": "Maximum tokens in AI responses", - "required": False, - "default": 500, - "minimum": 50, - "maximum": 2000, - "depends_on": { - "field": "enable_signal_bot", - "value": True - } - }, - "memory_length": { - "type": "integer", - "title": "Conversation Memory", - "description": "Number of message pairs to remember per user", - "required": False, - "default": 10, - "minimum": 1, - "maximum": 50, - "depends_on": { - "field": "enable_signal_bot", - "value": True - } - }, - - # Permission Settings - "default_role": { - "type": "select", - "title": "Default User Role", - "description": "Role assigned to new Signal users", - "required": False, - "default": "user", - "options": [ - {"value": "admin", "label": "Admin"}, - {"value": "user", "label": "User"}, - {"value": "disabled", "label": "Disabled"} - ], - "depends_on": { - "field": "enable_signal_bot", - "value": True - } - }, - "auto_register": { - "type": "boolean", - "title": "Auto-Register New Users", - "description": "Automatically register new Signal users", - "default": True, - "required": False, - "depends_on": { - "field": "enable_signal_bot", - "value": True - } - }, - "admin_phone_numbers": { - "type": "textarea", - "title": "Admin Phone Numbers", - "description": "Phone numbers with admin privileges (one per line)", - "required": False, - "placeholder": "+1234567890\n+0987654321", - "rows": 3, - "depends_on": { - "field": "enable_signal_bot", - "value": True - } - }, - - # Bot Behavior - "command_prefix": { - "type": "string", - "title": "Command Prefix", - "description": "Prefix for bot commands", - "required": False, - "default": "!", - "placeholder": "!", - "depends_on": { - "field": "enable_signal_bot", - "value": True - } - }, - "log_conversations": { - "type": "boolean", - "title": "Log Conversations", - "description": "Enable conversation logging for analytics", - "default": False, - "required": False, - "depends_on": { - "field": "enable_signal_bot", - "value": True - } - } - }, - "required": ["enable_signal_bot"], - "field_groups": [ - { - "title": "Basic Settings", - "fields": ["enable_signal_bot", "signal_service_url", "bot_phone_number"] - }, - { - "title": "AI Configuration", - "fields": ["model", "temperature", "max_tokens", "memory_length"] - }, - { - "title": "Permission Settings", - "fields": ["default_role", "auto_register", "admin_phone_numbers"] - }, - { - "title": "Bot Behavior", - "fields": ["command_prefix", "log_conversations"] - } - ], - "validation": { - "signal_test": { - "endpoint": "/api/v1/signal/test-connection", - "method": "POST", - "fields": ["signal_service_url", "bot_phone_number"], - "success_message": "Signal service connection successful", - "error_field": "Signal connection failed" - } - } - } def get_email_assistant_configuration_schema() -> Dict[str, Any]: @@ -471,7 +281,6 @@ def get_plugin_configuration_schema(plugin_id: str) -> Optional[Dict[str, Any]]: """ schemas = { "zammad": get_zammad_configuration_schema, - "signal": get_signal_configuration_schema, "email-assistant": get_email_assistant_configuration_schema } diff --git a/backend/tests/api/test_tee_endpoints.py b/backend/tests/api/test_tee_endpoints.py deleted file mode 100644 index f2bf12b..0000000 --- a/backend/tests/api/test_tee_endpoints.py +++ /dev/null @@ -1,137 +0,0 @@ -""" -Test TEE API endpoints. -""" -import pytest -from httpx import AsyncClient -from unittest.mock import patch, AsyncMock - - -class TestTEEEndpoints: - """Test TEE API endpoints.""" - - @pytest.mark.asyncio - async def test_tee_health_check(self, client: AsyncClient): - """Test TEE health check endpoint.""" - mock_health = { - "status": "healthy", - "timestamp": "2024-01-01T00:00:00Z", - "version": "1.0.0" - } - - with patch("app.services.tee_service.TEEService.health_check") as mock_check: - mock_check.return_value = mock_health - - response = await client.get( - "/api/v1/tee/health", - headers={"Authorization": "Bearer test-api-key"} - ) - - assert response.status_code == 200 - data = response.json() - assert data["status"] == "healthy" - - @pytest.mark.asyncio - async def test_tee_capabilities(self, client: AsyncClient): - """Test TEE capabilities endpoint.""" - mock_capabilities = { - "hardware_security": True, - "encryption_at_rest": True, - "memory_protection": True, - "supported_models": ["gpt-3.5-turbo", "claude-3-haiku"] - } - - with patch("app.services.tee_service.TEEService.get_tee_capabilities") as mock_caps: - mock_caps.return_value = mock_capabilities - - response = await client.get( - "/api/v1/tee/capabilities", - headers={"Authorization": "Bearer test-api-key"} - ) - - assert response.status_code == 200 - data = response.json() - assert data["hardware_security"] is True - assert "supported_models" in data - - @pytest.mark.asyncio - async def test_tee_attestation(self, client: AsyncClient): - """Test TEE attestation endpoint.""" - mock_attestation = { - "attestation_document": "base64_encoded_document", - "signature": "signature_data", - "timestamp": "2024-01-01T00:00:00Z", - "valid": True - } - - with patch("app.services.tee_service.TEEService.get_attestation") as mock_att: - mock_att.return_value = mock_attestation - - response = await client.get( - "/api/v1/tee/attestation", - headers={"Authorization": "Bearer test-api-key"} - ) - - assert response.status_code == 200 - data = response.json() - assert data["valid"] is True - assert "attestation_document" in data - - @pytest.mark.asyncio - async def test_tee_session_creation(self, client: AsyncClient): - """Test TEE secure session creation.""" - mock_session = { - "session_id": "secure-session-123", - "public_key": "public_key_data", - "expires_at": "2024-01-01T01:00:00Z" - } - - with patch("app.services.tee_service.TEEService.create_secure_session") as mock_session_create: - mock_session_create.return_value = mock_session - - response = await client.post( - "/api/v1/tee/session", - json={"model": "gpt-3.5-turbo"}, - headers={"Authorization": "Bearer test-api-key"} - ) - - assert response.status_code == 200 - data = response.json() - assert "session_id" in data - assert "public_key" in data - - @pytest.mark.asyncio - async def test_tee_metrics(self, client: AsyncClient): - """Test TEE metrics endpoint.""" - mock_metrics = { - "total_requests": 1000, - "successful_requests": 995, - "failed_requests": 5, - "avg_response_time": 0.125, - "privacy_score": 95.8, - "security_level": "high" - } - - with patch("app.services.tee_service.TEEService.get_privacy_metrics") as mock_metrics_get: - mock_metrics_get.return_value = mock_metrics - - response = await client.get( - "/api/v1/tee/metrics", - headers={"Authorization": "Bearer test-api-key"} - ) - - assert response.status_code == 200 - data = response.json() - assert data["privacy_score"] == 95.8 - assert data["security_level"] == "high" - - @pytest.mark.asyncio - async def test_tee_unauthorized(self, client: AsyncClient): - """Test TEE endpoints without authentication.""" - response = await client.get("/api/v1/tee/health") - assert response.status_code == 401 - - response = await client.get("/api/v1/tee/capabilities") - assert response.status_code == 401 - - response = await client.get("/api/v1/tee/attestation") - assert response.status_code == 401 \ No newline at end of file diff --git a/frontend/src/app/settings/page.tsx b/frontend/src/app/settings/page.tsx index aaac510..558a9fd 100644 --- a/frontend/src/app/settings/page.tsx +++ b/frontend/src/app/settings/page.tsx @@ -29,7 +29,6 @@ import { } from "lucide-react"; import { useToast } from "@/hooks/use-toast"; import { apiClient } from "@/lib/api-client"; -import ConfidentialityDashboard from "@/components/settings/ConfidentialityDashboard"; interface SystemSettings { // Security Settings @@ -262,11 +261,10 @@ function SettingsPageContent() { )} - + Security API Notifications - Confidentiality @@ -852,9 +850,6 @@ function SettingsPageContent() { - - - ); diff --git a/frontend/src/app/signal/page.tsx b/frontend/src/app/signal/page.tsx deleted file mode 100644 index ccc993f..0000000 --- a/frontend/src/app/signal/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -"use client" - -import { ProtectedRoute } from "@/components/auth/ProtectedRoute" -import { SignalConfig } from "@/components/modules/SignalConfig" - -export default function SignalPage() { - return ( - -
- -
-
- ) -} \ No newline at end of file diff --git a/frontend/src/components/modules/SignalConfig.tsx b/frontend/src/components/modules/SignalConfig.tsx deleted file mode 100644 index e288150..0000000 --- a/frontend/src/components/modules/SignalConfig.tsx +++ /dev/null @@ -1,465 +0,0 @@ -"use client" - -import { useState, useEffect } from "react" -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" -import { Button } from "@/components/ui/button" -import { Input } from "@/components/ui/input" -import { Label } from "@/components/ui/label" -import { Switch } from "@/components/ui/switch" -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" -import { Textarea } from "@/components/ui/textarea" -import { Slider } from "@/components/ui/slider" -import { Badge } from "@/components/ui/badge" -import { Alert, AlertDescription } from "@/components/ui/alert" -import { useToast } from "@/hooks/use-toast" -import { Settings, Save, RefreshCw, Phone, Bot, Zap } from "lucide-react" -import { config } from "@/lib/config" -import { apiClient } from "@/lib/api-client" - -interface SignalConfig { - enabled: boolean - signal_service: string - signal_phone_number: string - model: string - temperature: number - max_tokens: number - memory_length: number - command_prefix: string - default_role: string - auto_register: boolean - admin_phone_numbers: string[] - fallback_responses: string[] - log_conversations: boolean - connection_timeout: number -} - -interface ConfigSchema { - title: string - properties: Record - required: string[] -} - -export function SignalConfig() { - const { toast } = useToast() - - // Get default Signal service URL from environment or use localhost fallback - const getDefaultSignalService = () => { - return process.env.NEXT_PUBLIC_DEFAULT_SIGNAL_SERVICE || "localhost:8080" - } - const [config, setConfig] = useState(null) - const [schema, setSchema] = useState(null) - const [loading, setLoading] = useState(true) - const [saving, setSaving] = useState(false) - const [newAdminPhone, setNewAdminPhone] = useState("") - const [newFallbackResponse, setNewFallbackResponse] = useState("") - - useEffect(() => { - fetchConfig() - }, []) - - const fetchConfig = async () => { - try { - setLoading(true) - const data = await apiClient.get("/api-internal/v1/modules/signal/config") - setSchema(data.schema) - - // Set default config if none exists - const defaultConfig: SignalConfig = { - enabled: false, - signal_service: getDefaultSignalService(), - signal_phone_number: "", - model: "gpt-3.5-turbo", - temperature: 0.7, - max_tokens: 1000, - memory_length: 10, - command_prefix: "!", - default_role: "disabled", - auto_register: false, - admin_phone_numbers: [], - fallback_responses: [ - "I'm not sure how to help with that. Could you please rephrase your question?", - "I don't have enough information to answer that question accurately.", - "That's outside my knowledge area. Is there something else I can help you with?" - ], - log_conversations: true, - connection_timeout: 30 - } - - setConfig({ ...defaultConfig, ...data.current_config }) - } catch (error) { - console.error("Error fetching Signal config:", error) - toast({ - title: "Error", - description: "Failed to load Signal bot configuration", - variant: "destructive" - }) - } finally { - setLoading(false) - } - } - - const saveConfig = async () => { - if (!config) return - - try { - setSaving(true) - await apiClient.post("/api-internal/v1/modules/signal/config", config) - - toast({ - title: "Success", - description: "Signal bot configuration saved successfully" - }) - } catch (error) { - console.error("Error saving config:", error) - toast({ - title: "Error", - description: error instanceof Error ? error.message : "Failed to save configuration", - variant: "destructive" - }) - } finally { - setSaving(false) - } - } - - const updateConfig = (key: keyof SignalConfig, value: any) => { - if (!config) return - setConfig({ ...config, [key]: value }) - } - - const addAdminPhone = () => { - if (!config || !newAdminPhone.trim()) return - if (!newAdminPhone.match(/^\+[1-9]\d{1,14}$/)) { - toast({ - title: "Invalid Format", - description: "Phone number must be in international format (e.g., +1234567890)", - variant: "destructive" - }) - return - } - updateConfig("admin_phone_numbers", [...config.admin_phone_numbers, newAdminPhone.trim()]) - setNewAdminPhone("") - } - - const removeAdminPhone = (index: number) => { - if (!config) return - const phones = [...config.admin_phone_numbers] - phones.splice(index, 1) - updateConfig("admin_phone_numbers", phones) - } - - const addFallbackResponse = () => { - if (!config || !newFallbackResponse.trim()) return - updateConfig("fallback_responses", [...config.fallback_responses, newFallbackResponse.trim()]) - setNewFallbackResponse("") - } - - const removeFallbackResponse = (index: number) => { - if (!config) return - const responses = [...config.fallback_responses] - responses.splice(index, 1) - updateConfig("fallback_responses", responses) - } - - if (loading) { - return ( - - -
-
-
- ) - } - - if (!config || !schema) { - return ( - - - Failed to load Signal bot configuration. Please try refreshing the page. - - - ) - } - - return ( -
- {/* Header */} -
-
-

Signal Bot Configuration

-

Configure your AI-powered Signal messaging bot

-
-
- - -
-
- - {/* Enable/Disable Switch */} - - -
-
- - - Signal Bot Status - - Enable or disable the Signal bot -
- updateConfig("enabled", enabled)} - /> -
-
-
- - {/* Basic Configuration */} - - - - - Basic Configuration - - - -
-
- - updateConfig("signal_service", e.target.value)} - placeholder={getDefaultSignalService()} - /> -
-
- - updateConfig("signal_phone_number", e.target.value)} - placeholder="+1234567890" - /> -
-
-
-
- - {/* AI Configuration */} - - - - - AI Configuration - - - -
-
- - -
-
- - updateConfig("command_prefix", e.target.value)} - placeholder="!" - maxLength={5} - /> -
-
- -
-
- - updateConfig("temperature", value[0])} - max={1} - min={0} - step={0.1} - className="w-full" - /> -

- 0.0 = focused and deterministic, 1.0 = creative and diverse -

-
- -
-
- - updateConfig("max_tokens", value[0])} - max={4000} - min={50} - step={50} - className="w-full" - /> -
-
- - updateConfig("memory_length", value[0])} - max={50} - min={1} - step={1} - className="w-full" - /> -
-
-
-
-
- - {/* User Management */} - - - - - User Management - - - -
-
- -

- Automatically register new Signal contacts -

-
- updateConfig("auto_register", enabled)} - /> -
- -
- - -
- -
- -
- setNewAdminPhone(e.target.value)} - placeholder="+1234567890" - /> - -
-
- {config.admin_phone_numbers.map((phone, index) => ( - removeAdminPhone(index)}> - {phone} × - - ))} -
-
-
-
- - {/* Advanced Settings */} - - - Advanced Settings - - -
- -
-