mirror of
https://github.com/9technologygroup/patchmon.net.git
synced 2025-11-04 22:13:21 +00:00
278 lines
8.5 KiB
JavaScript
278 lines
8.5 KiB
JavaScript
import axios from "axios";
|
|
|
|
const API_BASE_URL = import.meta.env.VITE_API_URL || "/api/v1";
|
|
|
|
// Create axios instance with default config
|
|
const api = axios.create({
|
|
baseURL: API_BASE_URL,
|
|
timeout: 10000,
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
});
|
|
|
|
// Request interceptor
|
|
api.interceptors.request.use(
|
|
(config) => {
|
|
// Add auth token if available
|
|
const token = localStorage.getItem("token");
|
|
if (token) {
|
|
config.headers.Authorization = `Bearer ${token}`;
|
|
}
|
|
return config;
|
|
},
|
|
(error) => {
|
|
return Promise.reject(error);
|
|
},
|
|
);
|
|
|
|
// Response interceptor
|
|
api.interceptors.response.use(
|
|
(response) => response,
|
|
(error) => {
|
|
if (error.response?.status === 401) {
|
|
// Don't redirect if we're on the login page or if it's a TFA verification error
|
|
const currentPath = window.location.pathname;
|
|
const isTfaError = error.config?.url?.includes("/verify-tfa");
|
|
|
|
if (currentPath !== "/login" && !isTfaError) {
|
|
// Handle unauthorized
|
|
localStorage.removeItem("token");
|
|
localStorage.removeItem("user");
|
|
window.location.href = "/login";
|
|
}
|
|
}
|
|
return Promise.reject(error);
|
|
},
|
|
);
|
|
|
|
// Dashboard API
|
|
export const dashboardAPI = {
|
|
getStats: () => api.get("/dashboard/stats"),
|
|
getHosts: () => api.get("/dashboard/hosts"),
|
|
getPackages: () => api.get("/dashboard/packages"),
|
|
getHostDetail: (hostId, params = {}) => {
|
|
const queryString = new URLSearchParams(params).toString();
|
|
const url = `/dashboard/hosts/${hostId}${queryString ? `?${queryString}` : ""}`;
|
|
return api.get(url);
|
|
},
|
|
getPackageTrends: (params = {}) => {
|
|
const queryString = new URLSearchParams(params).toString();
|
|
const url = `/dashboard/package-trends${queryString ? `?${queryString}` : ""}`;
|
|
return api.get(url);
|
|
},
|
|
getRecentUsers: () => api.get("/dashboard/recent-users"),
|
|
getRecentCollection: () => api.get("/dashboard/recent-collection"),
|
|
};
|
|
|
|
// Admin Hosts API (for management interface)
|
|
export const adminHostsAPI = {
|
|
create: (data) => api.post("/hosts/create", data),
|
|
list: () => api.get("/hosts/admin/list"),
|
|
delete: (hostId) => api.delete(`/hosts/${hostId}`),
|
|
deleteBulk: (hostIds) => api.delete("/hosts/bulk", { data: { hostIds } }),
|
|
regenerateCredentials: (hostId) =>
|
|
api.post(`/hosts/${hostId}/regenerate-credentials`),
|
|
updateGroup: (hostId, hostGroupId) =>
|
|
api.put(`/hosts/${hostId}/group`, { hostGroupId }),
|
|
bulkUpdateGroup: (hostIds, hostGroupId) =>
|
|
api.put("/hosts/bulk/group", { hostIds, hostGroupId }),
|
|
toggleAutoUpdate: (hostId, autoUpdate) =>
|
|
api.patch(`/hosts/${hostId}/auto-update`, { auto_update: autoUpdate }),
|
|
updateFriendlyName: (hostId, friendlyName) =>
|
|
api.patch(`/hosts/${hostId}/friendly-name`, {
|
|
friendly_name: friendlyName,
|
|
}),
|
|
updateNotes: (hostId, notes) =>
|
|
api.patch(`/hosts/${hostId}/notes`, {
|
|
notes: notes,
|
|
}),
|
|
};
|
|
|
|
// Host Groups API
|
|
export const hostGroupsAPI = {
|
|
list: () => api.get("/host-groups"),
|
|
get: (id) => api.get(`/host-groups/${id}`),
|
|
create: (data) => api.post("/host-groups", data),
|
|
update: (id, data) => api.put(`/host-groups/${id}`, data),
|
|
delete: (id) => api.delete(`/host-groups/${id}`),
|
|
getHosts: (id) => api.get(`/host-groups/${id}/hosts`),
|
|
};
|
|
|
|
// Admin Users API (for user management)
|
|
export const adminUsersAPI = {
|
|
list: () => api.get("/auth/admin/users"),
|
|
create: (userData) => api.post("/auth/admin/users", userData),
|
|
update: (userId, userData) =>
|
|
api.put(`/auth/admin/users/${userId}`, userData),
|
|
delete: (userId) => api.delete(`/auth/admin/users/${userId}`),
|
|
resetPassword: (userId, newPassword) =>
|
|
api.post(`/auth/admin/users/${userId}/reset-password`, { newPassword }),
|
|
};
|
|
|
|
// Permissions API (for role management)
|
|
export const permissionsAPI = {
|
|
getRoles: () => api.get("/permissions/roles"),
|
|
getRole: (role) => api.get(`/permissions/roles/${role}`),
|
|
updateRole: (role, permissions) =>
|
|
api.put(`/permissions/roles/${role}`, permissions),
|
|
deleteRole: (role) => api.delete(`/permissions/roles/${role}`),
|
|
getUserPermissions: () => api.get("/permissions/user-permissions"),
|
|
};
|
|
|
|
// Settings API
|
|
export const settingsAPI = {
|
|
get: () => api.get("/settings"),
|
|
update: (settings) => api.put("/settings", settings),
|
|
getServerUrl: () => api.get("/settings/server-url"),
|
|
};
|
|
|
|
// Agent File Management API
|
|
export const agentFileAPI = {
|
|
getInfo: () => api.get("/hosts/agent/info"),
|
|
upload: (scriptContent) => api.post("/hosts/agent/upload", { scriptContent }),
|
|
download: () => api.get("/hosts/agent/download", { responseType: "blob" }),
|
|
};
|
|
|
|
// Repository API
|
|
export const repositoryAPI = {
|
|
list: () => api.get("/repositories"),
|
|
getById: (repositoryId) => api.get(`/repositories/${repositoryId}`),
|
|
getByHost: (hostId) => api.get(`/repositories/host/${hostId}`),
|
|
update: (repositoryId, data) =>
|
|
api.put(`/repositories/${repositoryId}`, data),
|
|
delete: (repositoryId) => api.delete(`/repositories/${repositoryId}`),
|
|
toggleHostRepository: (hostId, repositoryId, isEnabled) =>
|
|
api.patch(`/repositories/host/${hostId}/repository/${repositoryId}`, {
|
|
isEnabled,
|
|
}),
|
|
getStats: () => api.get("/repositories/stats/summary"),
|
|
cleanupOrphaned: () => api.delete("/repositories/cleanup/orphaned"),
|
|
};
|
|
|
|
// Dashboard Preferences API
|
|
export const dashboardPreferencesAPI = {
|
|
get: () => api.get("/dashboard-preferences"),
|
|
update: (preferences) => api.put("/dashboard-preferences", { preferences }),
|
|
getDefaults: () => api.get("/dashboard-preferences/defaults"),
|
|
};
|
|
|
|
// Hosts API (for agent communication - kept for compatibility)
|
|
export const hostsAPI = {
|
|
// Legacy register endpoint (now deprecated)
|
|
register: (data) => api.post("/hosts/register", data),
|
|
|
|
// Updated to use API credentials
|
|
update: (apiId, apiKey, data) =>
|
|
api.post("/hosts/update", data, {
|
|
headers: {
|
|
"X-API-ID": apiId,
|
|
"X-API-KEY": apiKey,
|
|
},
|
|
}),
|
|
getInfo: (apiId, apiKey) =>
|
|
api.get("/hosts/info", {
|
|
headers: {
|
|
"X-API-ID": apiId,
|
|
"X-API-KEY": apiKey,
|
|
},
|
|
}),
|
|
ping: (apiId, apiKey) =>
|
|
api.post(
|
|
"/hosts/ping",
|
|
{},
|
|
{
|
|
headers: {
|
|
"X-API-ID": apiId,
|
|
"X-API-KEY": apiKey,
|
|
},
|
|
},
|
|
),
|
|
toggleAutoUpdate: (id, autoUpdate) =>
|
|
api.patch(`/hosts/${id}/auto-update`, { auto_update: autoUpdate }),
|
|
};
|
|
|
|
// Packages API
|
|
export const packagesAPI = {
|
|
getAll: (params = {}) => api.get("/packages", { params }),
|
|
getById: (packageId) => api.get(`/packages/${packageId}`),
|
|
getCategories: () => api.get("/packages/categories/list"),
|
|
getHosts: (packageId, params = {}) =>
|
|
api.get(`/packages/${packageId}/hosts`, { params }),
|
|
update: (packageId, data) => api.put(`/packages/${packageId}`, data),
|
|
search: (query, params = {}) =>
|
|
api.get(`/packages/search/${query}`, { params }),
|
|
};
|
|
|
|
// Utility functions
|
|
export const formatError = (error) => {
|
|
if (error.response?.data?.message) {
|
|
return error.response.data.message;
|
|
}
|
|
if (error.response?.data?.error) {
|
|
return error.response.data.error;
|
|
}
|
|
if (error.message) {
|
|
return error.message;
|
|
}
|
|
return "An unexpected error occurred";
|
|
};
|
|
|
|
export const formatDate = (date) => {
|
|
return new Date(date).toLocaleString();
|
|
};
|
|
|
|
// Version API
|
|
export const versionAPI = {
|
|
getCurrent: () => api.get("/version/current"),
|
|
checkUpdates: () => api.get("/version/check-updates"),
|
|
testSshKey: (data) => api.post("/version/test-ssh-key", data),
|
|
};
|
|
|
|
// Auth API
|
|
export const authAPI = {
|
|
login: (username, password) =>
|
|
api.post("/auth/login", { username, password }),
|
|
verifyTfa: (username, token, remember_me = false) =>
|
|
api.post("/auth/verify-tfa", { username, token, remember_me }),
|
|
signup: (username, email, password, firstName, lastName) =>
|
|
api.post("/auth/signup", {
|
|
username,
|
|
email,
|
|
password,
|
|
firstName,
|
|
lastName,
|
|
}),
|
|
};
|
|
|
|
// TFA API
|
|
export const tfaAPI = {
|
|
setup: () => api.get("/tfa/setup"),
|
|
verifySetup: (data) => api.post("/tfa/verify-setup", data),
|
|
disable: (data) => api.post("/tfa/disable", data),
|
|
status: () => api.get("/tfa/status"),
|
|
regenerateBackupCodes: () => api.post("/tfa/regenerate-backup-codes"),
|
|
verify: (data) => api.post("/tfa/verify", data),
|
|
};
|
|
|
|
export const formatRelativeTime = (date) => {
|
|
const now = new Date();
|
|
const diff = now - new Date(date);
|
|
const seconds = Math.floor(diff / 1000);
|
|
const minutes = Math.floor(seconds / 60);
|
|
const hours = Math.floor(minutes / 60);
|
|
const days = Math.floor(hours / 24);
|
|
|
|
if (days > 0) return `${days} day${days > 1 ? "s" : ""} ago`;
|
|
if (hours > 0) return `${hours} hour${hours > 1 ? "s" : ""} ago`;
|
|
if (minutes > 0) return `${minutes} minute${minutes > 1 ? "s" : ""} ago`;
|
|
return `${seconds} second${seconds > 1 ? "s" : ""} ago`;
|
|
};
|
|
|
|
// Search API
|
|
export const searchAPI = {
|
|
global: (query) => api.get("/search", { params: { q: query } }),
|
|
};
|
|
|
|
export default api;
|