Files
resman/backend/routes/domains.js
T
2026-04-06 17:54:27 +02:00

246 lines
5.5 KiB
JavaScript

const express = require('express');
const router = express.Router();
const pool = require('../db');
const { moveByPosition, isMissingPositionColumn } = require("../helpers/positionMove");
const clean = (value) => value === "" ? null : value;
const normalizeCost = (value) => {
if (value === undefined || value === null || value === "") return null;
return String(value).replace(",", ".");
};
const mapDomainError = (err, fallbackMessage) => {
let message = fallbackMessage;
let status = 500;
if (err.code === "WARN_DATA_TRUNCATED") {
status = 400;
message = "Ungueltiges Preisformat";
}
if (err.code === "ER_DUP_ENTRY") {
status = 400;
message = "Domain existiert bereits";
}
return { status, message };
};
// GET ALL DOMAINS
router.get('/', async (req, res) => {
try {
let rows;
try {
[rows] = await pool.query(`
SELECT
d.id,
d.domain_name,
d.provider,
d.ip_address,
d.yearly_cost,
d.notes,
d.position,
r.name AS resource_name
FROM domains d
LEFT JOIN resource_ips ip ON d.ip_address = ip.ip
LEFT JOIN resources r ON ip.resource_id = r.id
ORDER BY COALESCE(d.position, d.id) ASC, d.domain_name ASC
`);
} catch (err) {
if (!isMissingPositionColumn(err)) throw err;
[rows] = await pool.query(`
SELECT
d.id,
d.domain_name,
d.provider,
d.ip_address,
d.yearly_cost,
d.notes,
r.name AS resource_name
FROM domains d
LEFT JOIN resource_ips ip ON d.ip_address = ip.ip
LEFT JOIN resources r ON ip.resource_id = r.id
ORDER BY d.domain_name ASC
`);
}
res.json(rows);
} catch (err) {
console.error("GET domains error:", err);
res.status(500).json({ error: "DB error" });
}
});
// GET SINGLE DOMAIN
router.get('/:id', async (req, res) => {
try {
const [rows] = await pool.query(
`SELECT * FROM domains WHERE id = ?`,
[req.params.id]
);
if (rows.length === 0) {
return res.status(404).json({ error: "Domain not found" });
}
res.json(rows[0]);
} catch (err) {
console.error("GET domain error:", err);
res.status(500).json({ error: "DB error" });
}
});
// CREATE DOMAIN
router.post('/', async (req, res) => {
try {
const domainName = req.body.domain_name ? String(req.body.domain_name).trim() : "";
if (!domainName) {
return res.status(400).json({ error: "Domain darf nicht leer sein" });
}
let result;
try {
const [[positionRow]] = await pool.query(
"SELECT COALESCE(MAX(position), 0) + 1 AS nextPosition FROM domains"
);
[result] = await pool.query(
`INSERT INTO domains
(domain_name, provider, ip_address, yearly_cost, notes, position)
VALUES (?, ?, ?, ?, ?, ?)`,
[
domainName,
clean(req.body.provider),
clean(req.body.ip_address),
normalizeCost(req.body.yearly_cost),
clean(req.body.notes),
positionRow.nextPosition
]
);
} catch (err) {
if (!isMissingPositionColumn(err)) throw err;
[result] = await pool.query(
`INSERT INTO domains
(domain_name, provider, ip_address, yearly_cost, notes)
VALUES (?, ?, ?, ?, ?)`,
[
domainName,
clean(req.body.provider),
clean(req.body.ip_address),
normalizeCost(req.body.yearly_cost),
clean(req.body.notes)
]
);
}
res.json({
message: "Domain created",
id: result.insertId
});
}catch (err) {
console.error("CREATE domain error:", err);
const { status, message } = mapDomainError(err, "Domain konnte nicht gespeichert werden");
res.status(status).json({
error: message
});
}
});
// UPDATE DOMAIN
router.put('/:id', async (req, res) => {
try {
const domainName = req.body.domain_name ? String(req.body.domain_name).trim() : "";
if (!domainName) {
return res.status(400).json({ error: "Domain darf nicht leer sein" });
}
await pool.query(
`UPDATE domains SET
domain_name = ?,
provider = ?,
ip_address = ?,
yearly_cost = ?,
notes = ?
WHERE id = ?`,
[
domainName,
clean(req.body.provider),
clean(req.body.ip_address),
normalizeCost(req.body.yearly_cost),
clean(req.body.notes),
req.params.id
]
);
res.json({ message: "Domain updated" });
} catch (err) {
console.error("UPDATE domain error:", err);
const { status, message } = mapDomainError(err, "Domain konnte nicht gespeichert werden");
res.status(status).json({ error: message });
}
});
router.post('/:id/move', async (req, res) => {
try {
const { direction } = req.body
const result = await moveByPosition({
db: pool,
table: "domains",
id: req.params.id,
direction,
selectQuery: "SELECT id FROM domains ORDER BY position, domain_name, id",
missingColumnMessage: "Position-Spalte in domains fehlt noch",
notFoundMessage: "Domain nicht gefunden",
});
res.status(result.status).json(result.body);
} catch (err) {
console.error("MOVE domain error:", err);
res.status(500).json({ error: "Reihenfolge konnte nicht geaendert werden" })
}
});
// DELETE DOMAIN
router.delete('/:id', async (req, res) => {
try {
await pool.query(
`DELETE FROM domains WHERE id = ?`,
[req.params.id]
);
res.json({ message: "Domain deleted" });
} catch (err) {
console.error("DELETE domain error:", err);
res.status(500).json({ error: "Domain konnte nicht geloescht werden" });
}
});
module.exports = router;