Add VPN configuration tools and agent documentation
Created comprehensive VPN setup tooling for Peaceful Spirit L2TP/IPsec connection and enhanced agent documentation framework. VPN Configuration (PST-NW-VPN): - Setup-PST-L2TP-VPN.ps1: Automated L2TP/IPsec setup with split-tunnel and DNS - Connect-PST-VPN.ps1: Connection helper with PPP adapter detection, DNS (192.168.0.2), and route config (192.168.0.0/24) - Connect-PST-VPN-Standalone.ps1: Self-contained connection script for remote deployment - Fix-PST-VPN-Auth.ps1: Authentication troubleshooting for CHAP/MSChapv2 - Diagnose-VPN-Interface.ps1: Comprehensive VPN interface and routing diagnostic - Quick-Test-VPN.ps1: Fast connectivity verification (DNS/router/routes) - Add-PST-VPN-Route-Manual.ps1: Manual route configuration helper - vpn-connect.bat, vpn-disconnect.bat: Simple batch file shortcuts - OpenVPN config files (Windows-compatible, abandoned for L2TP) Key VPN Implementation Details: - L2TP creates PPP adapter with connection name as interface description - UniFi auto-configures DNS (192.168.0.2) but requires manual route to 192.168.0.0/24 - Split-tunnel enabled (only remote traffic through VPN) - All-user connection for pre-login auto-connect via scheduled task - Authentication: CHAP + MSChapv2 for UniFi compatibility Agent Documentation: - AGENT_QUICK_REFERENCE.md: Quick reference for all specialized agents - documentation-squire.md: Documentation and task management specialist agent - Updated all agent markdown files with standardized formatting Project Organization: - Moved conversation logs to dedicated directories (guru-connect-conversation-logs, guru-rmm-conversation-logs) - Cleaned up old session JSONL files from projects/msp-tools/ - Added guru-connect infrastructure (agent, dashboard, proto, scripts, .gitea workflows) - Added guru-rmm server components and deployment configs Technical Notes: - VPN IP pool: 192.168.4.x (client gets 192.168.4.6) - Remote network: 192.168.0.0/24 (router at 192.168.0.10) - PSK: rrClvnmUeXEFo90Ol+z7tfsAZHeSK6w7 - Credentials: pst-admin / 24Hearts$ Files: 15 VPN scripts, 2 agent docs, conversation log reorganization, guru-connect/guru-rmm infrastructure additions Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
204
projects/msp-tools/guru-rmm/dashboard/src/api/client.ts
Normal file
204
projects/msp-tools/guru-rmm/dashboard/src/api/client.ts
Normal file
@@ -0,0 +1,204 @@
|
||||
import axios from "axios";
|
||||
|
||||
// Default to production URL, override with VITE_API_URL for local dev
|
||||
const API_URL = import.meta.env.VITE_API_URL || "https://rmm-api.azcomputerguru.com";
|
||||
|
||||
export const api = axios.create({
|
||||
baseURL: API_URL,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
// Add auth token to requests
|
||||
api.interceptors.request.use((config) => {
|
||||
const token = localStorage.getItem("token");
|
||||
if (token) {
|
||||
config.headers.Authorization = `Bearer ${token}`;
|
||||
}
|
||||
return config;
|
||||
});
|
||||
|
||||
// Handle auth errors
|
||||
api.interceptors.response.use(
|
||||
(response) => response,
|
||||
(error) => {
|
||||
if (error.response?.status === 401) {
|
||||
localStorage.removeItem("token");
|
||||
window.location.href = "/login";
|
||||
}
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
// API types
|
||||
export interface Agent {
|
||||
id: string;
|
||||
hostname: string;
|
||||
os_type: string;
|
||||
os_version: string | null;
|
||||
agent_version: string | null;
|
||||
status: "online" | "offline" | "error";
|
||||
last_seen: string | null;
|
||||
created_at: string;
|
||||
device_id: string | null;
|
||||
site_id: string | null;
|
||||
site_name: string | null;
|
||||
client_id: string | null;
|
||||
client_name: string | null;
|
||||
}
|
||||
|
||||
export interface Metrics {
|
||||
id: number;
|
||||
agent_id: string;
|
||||
timestamp: string;
|
||||
cpu_percent: number;
|
||||
memory_percent: number;
|
||||
memory_used_bytes: number;
|
||||
disk_percent: number;
|
||||
disk_used_bytes: number;
|
||||
network_rx_bytes: number;
|
||||
network_tx_bytes: number;
|
||||
// Extended metrics
|
||||
uptime_seconds?: number;
|
||||
boot_time?: number;
|
||||
logged_in_user?: string;
|
||||
user_idle_seconds?: number;
|
||||
public_ip?: string;
|
||||
memory_total_bytes?: number;
|
||||
disk_total_bytes?: number;
|
||||
}
|
||||
|
||||
export interface NetworkInterface {
|
||||
name: string;
|
||||
mac_address?: string;
|
||||
ipv4_addresses: string[];
|
||||
ipv6_addresses: string[];
|
||||
}
|
||||
|
||||
export interface AgentState {
|
||||
agent_id: string;
|
||||
network_interfaces?: NetworkInterface[];
|
||||
network_state_hash?: string;
|
||||
uptime_seconds?: number;
|
||||
boot_time?: number;
|
||||
logged_in_user?: string;
|
||||
user_idle_seconds?: number;
|
||||
public_ip?: string;
|
||||
network_updated_at?: string;
|
||||
metrics_updated_at?: string;
|
||||
}
|
||||
|
||||
export interface Command {
|
||||
id: string;
|
||||
agent_id: string;
|
||||
command_type: string;
|
||||
command_text: string;
|
||||
status: "pending" | "running" | "completed" | "failed";
|
||||
exit_code: number | null;
|
||||
stdout: string | null;
|
||||
stderr: string | null;
|
||||
created_at: string;
|
||||
completed_at: string | null;
|
||||
}
|
||||
|
||||
export interface User {
|
||||
id: string;
|
||||
email: string;
|
||||
name: string | null;
|
||||
role: string;
|
||||
}
|
||||
|
||||
export interface Client {
|
||||
id: string;
|
||||
name: string;
|
||||
code: string | null;
|
||||
notes: string | null;
|
||||
is_active: boolean;
|
||||
created_at: string;
|
||||
site_count: number;
|
||||
}
|
||||
|
||||
export interface Site {
|
||||
id: string;
|
||||
client_id: string;
|
||||
client_name: string | null;
|
||||
name: string;
|
||||
site_code: string;
|
||||
address: string | null;
|
||||
notes: string | null;
|
||||
is_active: boolean;
|
||||
created_at: string;
|
||||
agent_count: number;
|
||||
}
|
||||
|
||||
export interface CreateSiteResponse {
|
||||
site: Site;
|
||||
api_key: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface LoginRequest {
|
||||
email: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
export interface LoginResponse {
|
||||
token: string;
|
||||
user: User;
|
||||
}
|
||||
|
||||
export interface RegisterRequest {
|
||||
email: string;
|
||||
password: string;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
// API functions
|
||||
export const authApi = {
|
||||
login: (data: LoginRequest) => api.post<LoginResponse>("/api/auth/login", data),
|
||||
register: (data: RegisterRequest) => api.post<LoginResponse>("/api/auth/register", data),
|
||||
me: () => api.get<User>("/api/auth/me"),
|
||||
};
|
||||
|
||||
export const agentsApi = {
|
||||
list: () => api.get<Agent[]>("/api/agents"),
|
||||
listUnassigned: () => api.get<Agent[]>("/api/agents/unassigned"),
|
||||
get: (id: string) => api.get<Agent>(`/api/agents/${id}`),
|
||||
delete: (id: string) => api.delete(`/api/agents/${id}`),
|
||||
move: (id: string, siteId: string | null) =>
|
||||
api.post<Agent>(`/api/agents/${id}/move`, { site_id: siteId }),
|
||||
getMetrics: (id: string, hours?: number) =>
|
||||
api.get<Metrics[]>(`/api/agents/${id}/metrics`, { params: { hours } }),
|
||||
getState: (id: string) => api.get<AgentState>(`/api/agents/${id}/state`),
|
||||
};
|
||||
|
||||
export const commandsApi = {
|
||||
send: (agentId: string, command: { command_type: string; command: string }) =>
|
||||
api.post<Command>(`/api/agents/${agentId}/command`, command),
|
||||
list: () => api.get<Command[]>("/api/commands"),
|
||||
get: (id: string) => api.get<Command>(`/api/commands/${id}`),
|
||||
};
|
||||
|
||||
export const clientsApi = {
|
||||
list: () => api.get<Client[]>("/api/clients"),
|
||||
get: (id: string) => api.get<Client>(`/api/clients/${id}`),
|
||||
create: (data: { name: string; code?: string; notes?: string }) =>
|
||||
api.post<Client>("/api/clients", data),
|
||||
update: (id: string, data: { name?: string; code?: string; notes?: string; is_active?: boolean }) =>
|
||||
api.put<Client>(`/api/clients/${id}`, data),
|
||||
delete: (id: string) => api.delete(`/api/clients/${id}`),
|
||||
};
|
||||
|
||||
export const sitesApi = {
|
||||
list: () => api.get<Site[]>("/api/sites"),
|
||||
get: (id: string) => api.get<Site>(`/api/sites/${id}`),
|
||||
listByClient: (clientId: string) => api.get<Site[]>(`/api/clients/${clientId}/sites`),
|
||||
create: (data: { client_id: string; name: string; address?: string; notes?: string }) =>
|
||||
api.post<CreateSiteResponse>("/api/sites", data),
|
||||
update: (id: string, data: { name?: string; address?: string; notes?: string; is_active?: boolean }) =>
|
||||
api.put<Site>(`/api/sites/${id}`, data),
|
||||
delete: (id: string) => api.delete(`/api/sites/${id}`),
|
||||
regenerateApiKey: (id: string) =>
|
||||
api.post<{ api_key: string; message: string }>(`/api/sites/${id}/regenerate-key`),
|
||||
};
|
||||
Reference in New Issue
Block a user