Path: blob/master/gate-controller/components/RelaySettingsTab.tsx
1080 views
'use client';12import { useState, useEffect } from 'react';3import { invoke } from '@tauri-apps/api/core';4import { Button } from '@/components/ui/button';5import { Input } from '@/components/ui/input';6import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';7import { toast } from 'sonner';8import { Copy, Eye, EyeOff, RefreshCw } from 'lucide-react';910export function RelaySettingsTab() {11const [token, setToken] = useState<string | null>(null);12const [showToken, setShowToken] = useState(false);1314const fetchToken = async () => {15try {16const currentToken = await invoke<string | null>('get_webhook_token');17setToken(currentToken);18} catch (error) {19toast.error('Failed to load webhook token', { description: String(error) });20}21};2223const regenerateToken = async () => {24try {25const newToken = await invoke<string>('regenerate_webhook_token');26setToken(newToken);27toast.success('New webhook token generated!');28} catch (error) {29toast.error('Failed to generate new token', { description: String(error) });30}31};3233const copyToClipboard = () => {34if (token) {35navigator.clipboard.writeText(token);36toast.success('Token copied to clipboard!');37}38};3940useEffect(() => {41fetchToken();42}, []);4344return (45<div className="p-4 space-y-6 h-full overflow-y-auto">46<Card>47<CardHeader>48<CardTitle>Webhook Security <span className="text-red-500">*</span></CardTitle>49<CardDescription>50Protect your webhook endpoint with a secret token. This is mandatory for all API requests. Include this token in the `Authorization` header of your requests as a Bearer token.51</CardDescription>52</CardHeader>53<CardContent className="space-y-4">54<div className="flex items-center gap-2">55<Input56type={showToken ? 'text' : 'password'}57readOnly58value={token || 'No token generated yet'}59className="font-mono"60/>61<Button variant="outline" size="icon" onClick={() => setShowToken(!showToken)} disabled={!token}>62{showToken ? <EyeOff className="w-4 h-4" /> : <Eye className="w-4 h-4" />}63</Button>64<Button variant="outline" size="icon" onClick={copyToClipboard} disabled={!token}>65<Copy className="w-4 h-4" />66</Button>67</div>68<Button onClick={regenerateToken}>69<RefreshCw className="w-4 h-4 mr-2" />70{token ? 'Regenerate Token' : 'Generate Token'}71</Button>72</CardContent>73</Card>7475<Card>76<CardHeader>77<CardTitle>API Usage Example</CardTitle>78<CardDescription>Example of how to trigger a relay using `curl`.</CardDescription>79</CardHeader>80<CardContent className='font-mono text-sm bg-muted p-4 rounded-lg'>81<pre><code>82{`curl -X POST http://localhost:4848/webhook \83-H "Content-Type: application/json" \84-H "Authorization: Bearer ${token || '<YOUR_TOKEN>'}" \85-d '{ "id": "<YOUR_RELAY_ID>", "action": "on", "channel": 1 }'`}86</code></pre>87</CardContent>88</Card>89</div>90);91}929394