chore: initial project scaffold with admin web, backend, desktop client, and deployment setup

Add monorepo structure for NexaVPN WireGuard control plane including:
- .gitignore for node_modules, build artifacts, and environment files
- README with project overview, monorepo layout, and quick start guide
- Admin web UI with React, Vite, TypeScript, and nginx reverse proxy
- API client with type definitions for users, devices, policies, gateways, and audit logs
- Admin pages for dashboard, users, devices, policies, g
This commit is contained in:
2026-03-15 16:32:34 +01:00
commit 830491cb0d
91 changed files with 5279 additions and 0 deletions

View File

@@ -0,0 +1,75 @@
const API_BASE = import.meta.env.VITE_API_BASE_URL ?? "/api/v1";
export type User = {
id: string;
username: string;
display_name: string;
role: string;
is_active: boolean;
};
export type Device = {
id: string;
name: string;
user_id?: string;
platform: string;
status: string;
assigned_ip?: string;
};
export type Policy = {
id: string;
name: string;
description: string;
priority: number;
effect: string;
full_tunnel: boolean;
is_active: boolean;
destinations?: string[];
};
export type Gateway = {
id: string;
name: string;
endpoint: string;
public_key: string;
listen_port: number;
vpn_cidr: string;
dns_servers: string[];
is_active: boolean;
};
export type AuditEvent = {
id: string;
event_type: string;
entity_type: string;
status: string;
message: string;
created_at: string;
};
async function request<T>(path: string, init?: RequestInit): Promise<T> {
const token = localStorage.getItem("nexavpn_admin_token");
const response = await fetch(`${API_BASE}${path}`, {
...init,
headers: {
"Content-Type": "application/json",
...(token ? { Authorization: `Bearer ${token}` } : {}),
...(init?.headers ?? {})
}
});
if (!response.ok) {
throw new Error(`Request failed: ${response.status}`);
}
return response.json() as Promise<T>;
}
export const api = {
users: () => request<User[]>("/admin/users"),
devices: () => request<Device[]>("/admin/devices"),
policies: () => request<Policy[]>("/admin/policies"),
gateways: () => request<Gateway[]>("/admin/gateways"),
audit: () => request<AuditEvent[]>("/admin/audit-logs")
};