diff --git a/src/admin.js b/src/admin.js new file mode 100644 index 0000000..e9fbbef --- /dev/null +++ b/src/admin.js @@ -0,0 +1,127 @@ +// node src/admin.js --purge-node-id 123 +// node src/admin.js --purge-node-id '!AABBCCDD' + +const commandLineArgs = require("command-line-args"); +const commandLineUsage = require("command-line-usage"); + +// create prisma db client +const { PrismaClient } = require("@prisma/client"); +const NodeIdUtil = require("./utils/node_id_util"); +const prisma = new PrismaClient(); + +const optionsList = [ + { + name: 'help', + alias: 'h', + type: Boolean, + description: 'Display this usage guide.' + }, + { + name: "purge-node-id", + type: String, + description: "Purges all records for the provided node id.", + }, +]; + +// parse command line args +const options = commandLineArgs(optionsList); + +// show help +if(options.help){ + const usage = commandLineUsage([ + { + header: 'Meshtastic Map Admin', + content: 'Command line admin tool for the Meshtastic Map', + }, + { + header: 'Options', + optionList: optionsList, + }, + ]); + console.log(usage); + return; +} + +// get options and fallback to default values +const purgeNodeId = options["purge-node-id"] ?? null; + +async function purgeNodeById(nodeId) { + + // convert to numeric id + nodeId = NodeIdUtil.convertToNumeric(nodeId); + + // purge environment metrics + await prisma.environmentMetric.deleteMany({ + where: { + node_id: nodeId, + }, + }); + + // purge map reports + await prisma.mapReport.deleteMany({ + where: { + node_id: nodeId, + }, + }); + + // purge neighbour infos + await prisma.neighbourInfo.deleteMany({ + where: { + node_id: nodeId, + }, + }); + + // purge this node + await prisma.node.deleteMany({ + where: { + node_id: nodeId, + }, + }); + + // purge positions + await prisma.position.deleteMany({ + where: { + node_id: nodeId, + }, + }); + + // purge power metrics + await prisma.powerMetric.deleteMany({ + where: { + node_id: nodeId, + }, + }); + + // purge text messages + await prisma.textMessage.deleteMany({ + where: { + from: nodeId, + }, + }); + + // purge traceroutes + await prisma.traceRoute.deleteMany({ + where: { + from: nodeId, + }, + }); + + // purge waypoints + await prisma.waypoint.deleteMany({ + where: { + from: nodeId, + }, + }); + + console.log(`✅ Node '${nodeId}' has been purged from the database.`); + +} + +(async () => { + + // purge node by id + if(purgeNodeId){ + await purgeNodeById(purgeNodeId); + } + +})(); diff --git a/src/utils/node_id_util.js b/src/utils/node_id_util.js new file mode 100644 index 0000000..5397df1 --- /dev/null +++ b/src/utils/node_id_util.js @@ -0,0 +1,23 @@ +class NodeIdUtil { + + /** + * Converts the provided hex id to a numeric id, for example: !FFFFFFFF to 4294967295 + * Anything else will be converted as is to a BigInt, for example "4294967295" to 4294967295 + * @param hexIdOrNumber a node id in hex format with a prepended "!", or a numeric node id as a string or number + * @returns {bigint} the node id in numeric form + */ + static convertToNumeric(hexIdOrNumber) { + + // check if this is a hex id, and convert to numeric + if(hexIdOrNumber.toString().startsWith("!")){ + return BigInt('0x' + hexIdOrNumber.replaceAll("!", "")); + } + + // convert string or number to numeric + return BigInt(hexIdOrNumber); + + } + +} + +module.exports = NodeIdUtil; diff --git a/src/utils/node_id_util.test.js b/src/utils/node_id_util.test.js new file mode 100644 index 0000000..494c3bb --- /dev/null +++ b/src/utils/node_id_util.test.js @@ -0,0 +1,9 @@ +const NodeIdUtil = require("./node_id_util"); + +test('can convert hex id to numeric id', () => { + expect(NodeIdUtil.convertToNumeric("!FFFFFFFF")).toBe(BigInt(4294967295)); +}); + +test('can convert numeric id to numeric id', () => { + expect(NodeIdUtil.convertToNumeric(4294967295)).toBe(BigInt(4294967295)); +});