mirror of
https://github.com/donavon04/licensetrackerbackend.git
synced 2025-01-18 08:40:57 -07:00
417 lines
15 KiB
JavaScript
417 lines
15 KiB
JavaScript
const express = require('express');
|
|
const mariadb = require('mariadb');
|
|
const cors = require('cors');
|
|
|
|
const app = express();
|
|
|
|
app.use(express.json());
|
|
app.use(cors());
|
|
|
|
const version = "V1.1";
|
|
|
|
const dbip = process.env.DBIP || "192.168.2.54";
|
|
const dbusername = process.env.DBUSERNAME || "root";
|
|
const dbpassword = process.env.DBPASSWORD || "U&P7UH1mhRG@JF2K";
|
|
const db = process.env.DB || "LicenseTracker";
|
|
|
|
|
|
// Database details
|
|
const pool = mariadb.createPool({
|
|
dbip,
|
|
dbusername,
|
|
dbpassword,
|
|
db
|
|
});
|
|
|
|
//Initialize pollrate variable
|
|
let pollrate = "5000"; // 5 Seconds
|
|
|
|
//Api Key
|
|
const token = "&v94gt8ZHFTTTeuT";
|
|
|
|
//Allows the clients to check if the server is alive
|
|
app.get('/api', (req, res) => {
|
|
console.log("Welcome to the MPE licenses api");
|
|
res.sendStatus(200).json({ success: "Welcome to the MPE licenses api" });
|
|
});
|
|
|
|
//Allows the clients to check if the server is alive
|
|
app.get('/api/healthcheck', (req, res) => {
|
|
res.sendStatus(200);
|
|
});
|
|
|
|
//This will show all of the records for a specific program. It takes a program name as a parameter in the body and returns all records that have that program name
|
|
app.post('/api/programRecords', async (req, res) => {
|
|
try {
|
|
const { programName } = req.body;
|
|
if (!programName) {
|
|
return res.status(400).json({ error: "Program name is required" });
|
|
}
|
|
|
|
// Get the records for the specified program name
|
|
const records = await getProgramRecords(programName);
|
|
res.status(200).json(records);
|
|
} catch (error) {
|
|
console.log("[ERROR]: There was an error retrieving the program records. More info: " + error);
|
|
res.status(500).json({ error: "Internal Server Error" });
|
|
}
|
|
});
|
|
|
|
//Test to see if a connection to the database is feasible
|
|
async function testDatabaseConnection() {
|
|
let connection;
|
|
|
|
try {
|
|
// Create a connection to the database
|
|
connection = await pool.getConnection();
|
|
|
|
// Test the connection
|
|
console.log('Database connection successful');
|
|
} catch (error) {
|
|
console.error('Database connection failed:', error.message);
|
|
} finally {
|
|
// Ensure the connection is closed
|
|
if (connection) {
|
|
try {
|
|
await connection.end();
|
|
} catch (endError) {
|
|
console.error('Error closing the connection:', endError.message);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
const getProgramRecords = async (programName) => {
|
|
let n = (pollRate / 1000) + ((pollRate / 1000) * 0.25); // Milliseconds to seconds
|
|
let records = [];
|
|
//console.log('Retrieving program records');
|
|
try {
|
|
const conn = await pool.getConnection();
|
|
try {
|
|
// Get the records for the specified program name within the time constraints
|
|
const query = `
|
|
SELECT * FROM usedLicenses
|
|
WHERE program = ? AND date >= DATE_SUB(NOW(), INTERVAL ? SECOND)
|
|
`;
|
|
records = await conn.query(query, [programName, n]);
|
|
} catch (error) {
|
|
console.log("[ERROR]: There was an error reading from the database. More info: " + error);
|
|
}
|
|
finally {
|
|
conn.release(); // Ensure the connection is released
|
|
}
|
|
} catch (error) {
|
|
console.log("[ERROR]: There was an error reading from the database. More info: " + error);
|
|
}
|
|
return records;
|
|
};
|
|
|
|
|
|
// This gives the client a list of all of the programs that are currently being requested
|
|
app.post('/api/licenseCount', async (req, res) => {
|
|
try {
|
|
const { programName } = req.body;
|
|
if (!programName) {
|
|
return res.status(400).json({ error: "Program name is required" });
|
|
}
|
|
|
|
// Call getLicensesCount function for the provided programName
|
|
const count = await getLicensesCount(programName);
|
|
//console.log(count.toString());
|
|
res.status(200).json({ program: programName, count: count.toString() });
|
|
} catch (error) {
|
|
console.log("[ERROR]: There was an error retrieving the license count. More info: " + error);
|
|
res.status(500).json({ error: "Internal Server Error" });
|
|
}
|
|
});
|
|
|
|
const getLicensesCount = async (programName) => {
|
|
let n = (pollRate / 1000) + ((pollRate / 1000) * 0.25); // Milliseconds to seconds
|
|
let count = 0;
|
|
try {
|
|
const conn = await pool.getConnection();
|
|
try {
|
|
// Get the current time minus n seconds
|
|
const query = `
|
|
SELECT COUNT(*) AS count FROM usedLicenses
|
|
WHERE program = ? AND date >= DATE_SUB(NOW(), INTERVAL ? SECOND)
|
|
`;
|
|
const result = await conn.query(query, [programName, n]);
|
|
count = result[0].count;
|
|
} catch (error) {
|
|
console.log("[ERROR]: There was an error reading from the database. More info: " + error);
|
|
} finally {
|
|
conn.release(); // Ensure the connection is released
|
|
}
|
|
} catch (error) {
|
|
console.log("[ERROR]: There was an error reading from the database. More info: " + error);
|
|
}
|
|
return count;
|
|
};
|
|
|
|
|
|
// This gives the client a list of all of the programs that are currently being requested
|
|
app.get('/api/programs', async (req, res) => {
|
|
try {
|
|
const programsResult = await getRequestedPrograms();
|
|
// Extract program names from the result
|
|
const programNames = programsResult.map(record => record.name);
|
|
res.status(200).json(programNames);
|
|
} catch (error) {
|
|
console.log("[ERROR]: There was an error retrieving the programs. More info: " + error);
|
|
res.status(500).json({ error: "Internal Server Error" });
|
|
}
|
|
});
|
|
|
|
const getRequestedPrograms = async () => {
|
|
let result = [];
|
|
try {
|
|
const conn = await pool.getConnection();
|
|
try {
|
|
// Query to get all requested programs
|
|
const query = `SELECT name FROM requestedLicenses`;
|
|
result = await conn.query(query);
|
|
} catch (error) {
|
|
console.log("[ERROR]: There was an error retrieving program names. More info: " + error);
|
|
} finally {
|
|
conn.release(); // Ensure the connection is released
|
|
}
|
|
} catch (error) {
|
|
console.log("[ERROR]: There was an error retrieving program names. More info: " + error);
|
|
}
|
|
return result;
|
|
};
|
|
|
|
|
|
// This tells the client how often to phone home
|
|
app.get('/api/pollrate', async (req, res) => {
|
|
try {
|
|
pollrate = await getPollRate();
|
|
// Used to change the poll rate
|
|
res.json({ pollrate: `${pollrate}` }); // In milliseconds
|
|
} catch (error) {
|
|
console.log("[ERROR]: There was an error retrieving the poll rate. More info: " + error);
|
|
res.status(500).json({ error: "Internal Server Error" });
|
|
}
|
|
});
|
|
|
|
const getPollRate = async () => {
|
|
// Debugging! console.log('Retrieving poll rate');
|
|
try {
|
|
const conn = await pool.getConnection();
|
|
try {
|
|
// Query to get the poll rate where sid = 1
|
|
const query = `SELECT pollrate FROM settings WHERE sid = 1`;
|
|
const result = await conn.query(query);
|
|
|
|
if (result.length > 0) {
|
|
pollRate = result[0].pollrate; // Extract poll rate from the result
|
|
} else {
|
|
console.log("[INFO]: No poll rate found for sid = 1.");
|
|
}
|
|
} catch (error) {
|
|
console.log("[ERROR]: There was an error retrieving the poll rate. More info: " + error);
|
|
} finally {
|
|
conn.release(); // Ensure the connection is released
|
|
}
|
|
} catch (error) {
|
|
console.log("[ERROR]: There was an error retrieving the poll rate. More info: " + error);
|
|
}
|
|
return pollRate;
|
|
};
|
|
|
|
// Retrieves currently used licenses from the database
|
|
app.get('/api/licenses', async (req, res) => {
|
|
try {
|
|
// Retrieve the currently used licenses from the database
|
|
const licenses = await getLicenses();
|
|
res.json(licenses);
|
|
} catch (error) {
|
|
console.log("[ERROR]: There was an error retrieving licenses. More info: " + error);
|
|
res.status(500).json({ error: "Internal Server Error" });
|
|
}
|
|
});
|
|
|
|
// Retrieves currently used licenses from the database
|
|
const getLicenses = async () => {
|
|
let n = (pollRate / 1000) + ((pollRate/1000) * 0.25); //Milliseconds to seconds
|
|
let records = [];
|
|
//console.log('Retrieving list');
|
|
try {
|
|
const conn = await pool.getConnection();
|
|
try {
|
|
// Get the current time minus n minutes
|
|
const query = `
|
|
SELECT * FROM usedLicenses
|
|
WHERE date >= DATE_SUB(NOW(), INTERVAL ? SECOND)
|
|
`;
|
|
records = await conn.query(query, [n]);
|
|
} catch (error) {
|
|
console.log("[ERROR]: There was an error reading from the database. More info: " + error);
|
|
} finally {
|
|
conn.release(); // Ensure the connection is released
|
|
}
|
|
} catch (error) {
|
|
console.log("[ERROR]: There was an error reading from the database. More info: " + error);
|
|
}
|
|
return records;
|
|
};
|
|
|
|
app.get('/api/count', async (req, res) => {
|
|
try {
|
|
// Retrieve the currently used licenses count along with the total and available licenses
|
|
const programs = await getLicenseCounts();
|
|
res.json({ programs });
|
|
} catch (error) {
|
|
console.log("[ERROR]: There was an error retrieving licenses. More info: " + error);
|
|
res.status(500).json({ error: "Internal Server Error" });
|
|
}
|
|
});
|
|
|
|
// Retrieves currently used licenses count, total licenses, and available licenses grouped by program
|
|
const getLicenseCounts = async () => {
|
|
let n = (pollRate / 1000) + ((pollRate / 1000) * 0.25); // Convert pollRate to seconds and add 25%
|
|
let records = [];
|
|
try {
|
|
const conn = await pool.getConnection();
|
|
try {
|
|
// Get the current time minus n seconds and count the number of licenses per program
|
|
const query = `
|
|
SELECT ul.program, COUNT(*) as activecount, rl.total,
|
|
(rl.total - COUNT(*)) as available
|
|
FROM usedLicenses ul
|
|
JOIN requestedLicenses rl ON ul.program = rl.name
|
|
WHERE ul.date >= DATE_SUB(NOW(), INTERVAL ? SECOND)
|
|
GROUP BY ul.program, rl.total
|
|
`;
|
|
const results = await conn.query(query, [n]);
|
|
|
|
// Convert the results to handle bigint serialization
|
|
records = results.map(row => ({
|
|
program: row.program,
|
|
activecount: String(row.activecount), // Convert bigint to string
|
|
total: String(row.total), // Convert bigint to string
|
|
available: String(row.available) // Convert bigint to string
|
|
}));
|
|
|
|
} catch (error) {
|
|
console.log("[ERROR]: There was an error reading from the database. More info: " + error);
|
|
} finally {
|
|
conn.release(); // Ensure the connection is released
|
|
}
|
|
} catch (error) {
|
|
console.log("[ERROR]: There was an error reading from the database. More info: " + error);
|
|
}
|
|
return records;
|
|
};
|
|
|
|
app.get('/api/zabbix', async (req, res) => {
|
|
try {
|
|
const programs = await getZabbixCounts();
|
|
res.json(programs); // Directly return the reshaped JSON
|
|
} catch (error) {
|
|
console.log("[ERROR]: There was an error retrieving licenses. More info: " + error);
|
|
res.status(500).json({ error: "Internal Server Error" });
|
|
}
|
|
});
|
|
|
|
const getZabbixCounts = async () => {
|
|
let n = (pollRate / 1000) + ((pollRate / 1000) * 0.25);
|
|
let records = {};
|
|
try {
|
|
const conn = await pool.getConnection();
|
|
try {
|
|
const query = `
|
|
SELECT ul.program, COUNT(*) as activecount, rl.total,
|
|
(rl.total - COUNT(*)) as available
|
|
FROM usedLicenses ul
|
|
JOIN requestedLicenses rl ON ul.program = rl.name
|
|
WHERE ul.date >= DATE_SUB(NOW(), INTERVAL ? SECOND)
|
|
GROUP BY ul.program, rl.total
|
|
`;
|
|
const results = await conn.query(query, [n]);
|
|
|
|
results.forEach(row => {
|
|
records[row.program] = {
|
|
activecount: String(row.activecount),
|
|
total: String(row.total),
|
|
available: String(row.available)
|
|
};
|
|
});
|
|
|
|
} catch (error) {
|
|
console.log("[ERROR]: There was an error reading from the database. More info: " + error);
|
|
} finally {
|
|
conn.release();
|
|
}
|
|
} catch (error) {
|
|
console.log("[ERROR]: There was an error reading from the database. More info: " + error);
|
|
}
|
|
return records;
|
|
};
|
|
|
|
|
|
|
|
|
|
// Clients use this route to tell the server what programs they have open
|
|
app.post('/api/currentPrograms', (req, res) => {
|
|
//console.log('Post request received:', JSON.stringify(req.body));
|
|
const { applicationName, machineName, apiKey } = req.body;
|
|
if(apiKey == token){ //Verify the client is one of our own
|
|
addProgram(applicationName, machineName);
|
|
}
|
|
// Handle the request further if needed
|
|
res.sendStatus(200);
|
|
});
|
|
|
|
// Adds a program and machine name to the database
|
|
const addProgram = async (programName, machineName) => {
|
|
// Get the current date and format it for MariaDB datetime
|
|
const date = new Date().toISOString().slice(0, 19).replace('T', ' ');
|
|
|
|
try {
|
|
const conn = await pool.getConnection();
|
|
try {
|
|
// Check if a record with the same machineName and programName already exists
|
|
const existingRecord = await conn.query('SELECT * FROM usedLicenses WHERE machine = ? AND program = ?', [machineName, programName]);
|
|
|
|
if (existingRecord.length > 0) {
|
|
// If record exists, update its timestamp
|
|
await conn.query('UPDATE usedLicenses SET date = ? WHERE machine = ? AND program = ?', [date, machineName, programName]);
|
|
//console.log("[SUCCESS]: Existing record updated in the database.");
|
|
} else {
|
|
// If no record exists, insert a new one
|
|
await conn.query('INSERT INTO usedLicenses (program, machine, date) VALUES (?, ?, ?)', [programName, machineName, date]);
|
|
//console.log("[SUCCESS]: New record added to the database.");
|
|
}
|
|
} finally {
|
|
conn.release(); // Ensure the connection is released
|
|
}
|
|
} catch (error) {
|
|
console.log("[ERROR]: There was an error adding/updating the record in the database. More info: " + error);
|
|
}
|
|
};
|
|
|
|
setTimeout(() => {
|
|
testDatabaseConnection();
|
|
}, 1000);
|
|
|
|
//Start the api and display the port it is running on
|
|
const port = process.env.PORT || 3000;
|
|
app.listen(port, () => {
|
|
console.log(`**********************************`);
|
|
console.log(`** **`);
|
|
console.log(`* MPE License Tracker API *`);
|
|
console.log(`** **`);
|
|
console.log(`* ${version} *`);
|
|
console.log(`** **`);
|
|
console.log(`**********************************`);
|
|
console.log(`API is running on port ${port}`);
|
|
|
|
// Run the function to test the database connection
|
|
//testDatabaseConnection();
|
|
//console.log(`Configured to use database IP ${dbip}`);
|
|
//console.log(`Using user ${dbusername} for database`);
|
|
});
|