feat: enhance audit logging, add MCP settings, and production docker setup
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
- Implemented comprehensive audit logging for Tasks, Users, Settings, Goals, Labels, AI Chat, and Rewards. - Added Admin UI for MCP Server settings and Audit Logs. - Created docker-compose-production.yml with Traefik configuration. - Fixed backend bugs (missing storage methods, route closure). - Added Audit Logging Guidelines.
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useState, useEffect } from "react";
|
||||
import { Loader2, Server, Save } from "lucide-react";
|
||||
import { useToast } from "@/hooks/use-toast";
|
||||
|
||||
export function McpSettingsCard() {
|
||||
const { t } = useTranslation();
|
||||
const { toast } = useToast();
|
||||
const queryClient = useQueryClient();
|
||||
const [formData, setFormData] = useState({
|
||||
mcp_enabled: false,
|
||||
mcp_port: "5001" // Default to main app port unless specific override logic is added
|
||||
});
|
||||
|
||||
const { data: settings, isLoading } = useQuery<any>({
|
||||
queryKey: ['/api/admin/settings'],
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (settings) {
|
||||
setFormData({
|
||||
mcp_enabled: settings.mcp_enabled === true,
|
||||
mcp_port: settings.mcp_port || "5001"
|
||||
});
|
||||
}
|
||||
}, [settings]);
|
||||
|
||||
const mutation = useMutation({
|
||||
mutationFn: async (data: any) => {
|
||||
const res = await fetch("/api/admin/settings", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
if (!res.ok) throw new Error("Failed to save settings");
|
||||
return res.json();
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['/api/admin/settings'] });
|
||||
toast({ title: t('settings.saved', 'Settings saved') });
|
||||
},
|
||||
onError: () => {
|
||||
toast({ title: t('settings.error', 'Failed to save settings'), variant: "destructive" });
|
||||
}
|
||||
});
|
||||
|
||||
const handleSave = () => {
|
||||
mutation.mutate({
|
||||
mcp_enabled: formData.mcp_enabled,
|
||||
mcp_port: formData.mcp_port
|
||||
});
|
||||
};
|
||||
|
||||
if (isLoading) return <div className="flex justify-center p-4"><Loader2 className="animate-spin" /></div>;
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<div className="flex items-center gap-2">
|
||||
<Server className="h-5 w-5 text-primary" />
|
||||
<CardTitle>MCP Server Configuration</CardTitle>
|
||||
</div>
|
||||
<CardDescription>
|
||||
Configure the Model Context Protocol (MCP) server settings.
|
||||
The MCP server runs on the same port as the application (/api/mcp).
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<Label htmlFor="mcp_enabled" className="flex flex-col gap-1">
|
||||
<span>Enable MCP Server</span>
|
||||
<span className="font-normal text-xs text-muted-foreground">
|
||||
Allow external AI tools to connect via MCP protocol.
|
||||
</span>
|
||||
</Label>
|
||||
<Switch
|
||||
id="mcp_enabled"
|
||||
checked={formData.mcp_enabled}
|
||||
onCheckedChange={(checked) => setFormData(prev => ({ ...prev, mcp_enabled: checked }))}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="mcp_port">Port (Informational)</Label>
|
||||
<Input
|
||||
id="mcp_port"
|
||||
value={formData.mcp_port}
|
||||
onChange={(e) => setFormData(prev => ({ ...prev, mcp_port: e.target.value }))}
|
||||
placeholder="5001"
|
||||
disabled
|
||||
className="bg-muted"
|
||||
/>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Currently runs on the main application port. Separate port configuration coming soon.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Button onClick={handleSave} disabled={mutation.isPending}>
|
||||
{mutation.isPending && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
|
||||
<Save className="mr-2 h-4 w-4" />
|
||||
{t('settings.save', 'Save Changes')}
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user