mirror of
https://github.com/9technologygroup/patchmon.net.git
synced 2025-10-25 00:53:48 +00:00
feat(backend): Update routes to use machine_id for host identification
- Auto-enrollment endpoints now require and validate machine_id - Check for duplicates by machine_id instead of friendly_name - Added /hosts/check-machine-id endpoint for agent installer - Bulk enrollment updated to handle machine_id - Multiple hosts with same hostname now supported
This commit is contained in:
@@ -521,6 +521,9 @@ router.post(
|
|||||||
body("friendly_name")
|
body("friendly_name")
|
||||||
.isLength({ min: 1, max: 255 })
|
.isLength({ min: 1, max: 255 })
|
||||||
.withMessage("Friendly name is required"),
|
.withMessage("Friendly name is required"),
|
||||||
|
body("machine_id")
|
||||||
|
.isLength({ min: 1, max: 255 })
|
||||||
|
.withMessage("Machine ID is required"),
|
||||||
body("metadata").optional().isObject(),
|
body("metadata").optional().isObject(),
|
||||||
],
|
],
|
||||||
async (req, res) => {
|
async (req, res) => {
|
||||||
@@ -530,15 +533,15 @@ router.post(
|
|||||||
return res.status(400).json({ errors: errors.array() });
|
return res.status(400).json({ errors: errors.array() });
|
||||||
}
|
}
|
||||||
|
|
||||||
const { friendly_name } = req.body;
|
const { friendly_name, machine_id } = req.body;
|
||||||
|
|
||||||
// Generate host API credentials
|
// Generate host API credentials
|
||||||
const api_id = `patchmon_${crypto.randomBytes(8).toString("hex")}`;
|
const api_id = `patchmon_${crypto.randomBytes(8).toString("hex")}`;
|
||||||
const api_key = crypto.randomBytes(32).toString("hex");
|
const api_key = crypto.randomBytes(32).toString("hex");
|
||||||
|
|
||||||
// Check if host already exists
|
// Check if host already exists by machine_id (not hostname)
|
||||||
const existing_host = await prisma.hosts.findUnique({
|
const existing_host = await prisma.hosts.findUnique({
|
||||||
where: { friendly_name },
|
where: { machine_id },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (existing_host) {
|
if (existing_host) {
|
||||||
@@ -546,7 +549,10 @@ router.post(
|
|||||||
error: "Host already exists",
|
error: "Host already exists",
|
||||||
host_id: existing_host.id,
|
host_id: existing_host.id,
|
||||||
api_id: existing_host.api_id,
|
api_id: existing_host.api_id,
|
||||||
message: "This host is already enrolled in PatchMon",
|
machine_id: existing_host.machine_id,
|
||||||
|
friendly_name: existing_host.friendly_name,
|
||||||
|
message:
|
||||||
|
"This machine is already enrolled in PatchMon (matched by machine ID)",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -554,6 +560,7 @@ router.post(
|
|||||||
const host = await prisma.hosts.create({
|
const host = await prisma.hosts.create({
|
||||||
data: {
|
data: {
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
|
machine_id,
|
||||||
friendly_name,
|
friendly_name,
|
||||||
os_type: "unknown",
|
os_type: "unknown",
|
||||||
os_version: "unknown",
|
os_version: "unknown",
|
||||||
@@ -648,17 +655,26 @@ router.post(
|
|||||||
|
|
||||||
for (const host_data of hosts) {
|
for (const host_data of hosts) {
|
||||||
try {
|
try {
|
||||||
const { friendly_name } = host_data;
|
const { friendly_name, machine_id } = host_data;
|
||||||
|
|
||||||
// Check if host already exists
|
if (!machine_id) {
|
||||||
|
results.failed.push({
|
||||||
|
friendly_name,
|
||||||
|
error: "Machine ID is required",
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if host already exists by machine_id
|
||||||
const existing_host = await prisma.hosts.findUnique({
|
const existing_host = await prisma.hosts.findUnique({
|
||||||
where: { friendly_name },
|
where: { machine_id },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (existing_host) {
|
if (existing_host) {
|
||||||
results.skipped.push({
|
results.skipped.push({
|
||||||
friendly_name,
|
friendly_name,
|
||||||
reason: "Already exists",
|
machine_id,
|
||||||
|
reason: "Machine already enrolled",
|
||||||
api_id: existing_host.api_id,
|
api_id: existing_host.api_id,
|
||||||
});
|
});
|
||||||
continue;
|
continue;
|
||||||
@@ -672,6 +688,7 @@ router.post(
|
|||||||
const host = await prisma.hosts.create({
|
const host = await prisma.hosts.create({
|
||||||
data: {
|
data: {
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
|
machine_id,
|
||||||
friendly_name,
|
friendly_name,
|
||||||
os_type: "unknown",
|
os_type: "unknown",
|
||||||
os_version: "unknown",
|
os_version: "unknown",
|
||||||
|
|||||||
@@ -1151,6 +1151,48 @@ export CURL_FLAGS="${curlFlags}"
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Check if machine_id already exists (requires auth)
|
||||||
|
router.post("/check-machine-id", validateApiCredentials, async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { machine_id } = req.body;
|
||||||
|
|
||||||
|
if (!machine_id) {
|
||||||
|
return res.status(400).json({
|
||||||
|
error: "machine_id is required",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if a host with this machine_id exists
|
||||||
|
const existing_host = await prisma.hosts.findUnique({
|
||||||
|
where: { machine_id },
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
friendly_name: true,
|
||||||
|
machine_id: true,
|
||||||
|
api_id: true,
|
||||||
|
status: true,
|
||||||
|
created_at: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (existing_host) {
|
||||||
|
return res.status(200).json({
|
||||||
|
exists: true,
|
||||||
|
host: existing_host,
|
||||||
|
message: "This machine is already enrolled",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status(200).json({
|
||||||
|
exists: false,
|
||||||
|
message: "Machine not yet enrolled",
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error checking machine_id:", error);
|
||||||
|
res.status(500).json({ error: "Failed to check machine_id" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Serve the removal script (public endpoint - no authentication required)
|
// Serve the removal script (public endpoint - no authentication required)
|
||||||
router.get("/remove", async (_req, res) => {
|
router.get("/remove", async (_req, res) => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user