added new feature: service config; Currently implemented in: loanMgmt and userMgmt (only Backend)

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
2026-04-26 14:40:53 +02:00
parent 5442f2f1f3
commit 0964109c4b
4 changed files with 279 additions and 169 deletions
+56 -14
View File
@@ -1,5 +1,9 @@
import express from "express";
import { authenticate, generateToken } from "../../services/authentication.js";
import {
checkIfServiceIsActive,
checkIfServiceIsActive2,
} from "../../services/functions.js";
const router = express.Router();
import dotenv from "dotenv";
dotenv.config();
@@ -18,7 +22,11 @@ import {
} from "./database/loansMgmt.database.js";
import { sendMailLoan } from "./services/mailer.js";
router.post("/createLoan", authenticate, async (req, res) => {
router.post(
"/createLoan",
checkIfServiceIsActive("Loan Service"),
authenticate,
async (req, res) => {
try {
const { items, startDate, endDate, note } = req.body || {};
@@ -54,6 +62,7 @@ router.post("/createLoan", authenticate, async (req, res) => {
);
if (result.success) {
if (await checkIfServiceIsActive2("Loan Mailer")) {
const mailInfo = await getLoanInfoWithID(result.data.id);
console.log(mailInfo);
sendMailLoan(
@@ -64,6 +73,8 @@ router.post("/createLoan", authenticate, async (req, res) => {
mailInfo.data.created_at,
mailInfo.data.note,
);
}
return res.status(201).json({
message: "Loan created successfully",
loanId: result.data.id,
@@ -86,9 +97,14 @@ router.post("/createLoan", authenticate, async (req, res) => {
console.error("createLoan error:", err);
return res.status(500).json({ message: "Failed to create loan" });
}
});
},
);
router.get("/loans", authenticate, async (req, res) => {
router.get(
"/loans",
checkIfServiceIsActive("Loan Service"),
authenticate,
async (req, res) => {
const result = await getLoansFromDatabase(req.user.username);
if (result.success) {
res.status(200).json(result.data);
@@ -97,9 +113,14 @@ router.get("/loans", authenticate, async (req, res) => {
} else {
res.status(500).json({ message: "Failed to fetch loans" });
}
});
},
);
router.post("/set-return-date/:loan_code", authenticate, async (req, res) => {
router.post(
"/set-return-date/:loan_code",
checkIfServiceIsActive("Loan Service"),
authenticate,
async (req, res) => {
const loanCode = req.params.loan_code;
const result = await setReturnDate(loanCode);
if (result.success) {
@@ -107,9 +128,14 @@ router.post("/set-return-date/:loan_code", authenticate, async (req, res) => {
} else {
res.status(500).json({ message: "Failed to set return date" });
}
});
},
);
router.post("/set-take-date/:loan_code", authenticate, async (req, res) => {
router.post(
"/set-take-date/:loan_code",
checkIfServiceIsActive("Loan Service"),
authenticate,
async (req, res) => {
const loanCode = req.params.loan_code;
const result = await setTakeDate(loanCode);
if (result.success) {
@@ -117,7 +143,8 @@ router.post("/set-take-date/:loan_code", authenticate, async (req, res) => {
} else {
res.status(500).json({ message: "Failed to set take date" });
}
});
},
);
router.get("/all-items", authenticate, async (req, res) => {
const result = await getItems();
@@ -128,7 +155,11 @@ router.get("/all-items", authenticate, async (req, res) => {
}
});
router.delete("/delete-loan/:id", authenticate, async (req, res) => {
router.delete(
"/delete-loan/:id",
checkIfServiceIsActive("Loan Service"),
authenticate,
async (req, res) => {
const loanId = req.params.id;
const result = await SETdeleteLoanFromDatabase(loanId);
if (result.success) {
@@ -146,18 +177,28 @@ router.delete("/delete-loan/:id", authenticate, async (req, res) => {
res.status(500).json({ message: "Failed to delete loan" });
}
});
},
);
router.get("/all-loans", authenticate, async (req, res) => {
router.get(
"/all-loans",
checkIfServiceIsActive("Loan Service"),
authenticate,
async (req, res) => {
const result = await getALLLoans();
if (result.success) {
res.status(200).json(result.data);
} else {
res.status(500).json({ message: "Failed to fetch loans" });
}
});
},
);
router.post("/borrowable-items", authenticate, async (req, res) => {
router.post(
"/borrowable-items",
checkIfServiceIsActive("Loan Service"),
authenticate,
async (req, res) => {
const { startDate, endDate } = req.body || {};
if (!startDate || !endDate) {
return res
@@ -178,6 +219,7 @@ router.post("/borrowable-items", authenticate, async (req, res) => {
.status(500)
.json({ message: "Failed to fetch borrowable items" });
}
});
},
);
export default router;
+21 -6
View File
@@ -1,5 +1,6 @@
import express from "express";
import { authenticate, generateToken } from "../../services/authentication.js";
import { checkIfServiceIsActive } from "../../services/functions.js";
const router = express.Router();
import dotenv from "dotenv";
dotenv.config();
@@ -8,7 +9,10 @@ dotenv.config();
import { loginFunc, changePassword } from "./database/userMgmt.database.js";
import { sendMail } from "./services/mailer_v2.js";
router.post("/login", async (req, res) => {
router.post(
"/login",
checkIfServiceIsActive("User Frontend"),
async (req, res) => {
const result = await loginFunc(req.body.username, req.body.password);
if (result.success) {
const token = await generateToken({
@@ -22,9 +26,14 @@ router.post("/login", async (req, res) => {
} else {
res.status(401).json({ message: "Invalid credentials" });
}
});
},
);
router.post("/change-password", authenticate, async (req, res) => {
router.post(
"/change-password",
checkIfServiceIsActive("User Frontend"),
authenticate,
async (req, res) => {
const oldPassword = req.body.oldPassword;
const newPassword = req.body.newPassword;
const username = req.user.username;
@@ -34,15 +43,21 @@ router.post("/change-password", authenticate, async (req, res) => {
} else {
res.status(500).json({ message: "Failed to change password" });
}
});
},
);
router.post("/contact", authenticate, async (req, res) => {
router.post(
"/contact",
checkIfServiceIsActive("Contact Form Service"),
authenticate,
async (req, res) => {
const message = req.body.message;
const username = req.user.username;
sendMail(username, message);
res.status(200).json({ message: "Contact message sent successfully" });
});
},
);
export default router;
+11
View File
@@ -55,3 +55,14 @@ CREATE TABLE apiKeys (
PRIMARY KEY (id),
CHECK (api_key REGEXP '^[0-9]{8}$')
) ENGINE=InnoDB;
CREATE TABLE functions (
id INT NOT NULL AUTO_INCREMENT,
function_name VARCHAR(500) NOT NULL UNIQUE,
active BOOLEAN NOT NULL DEFAULT true,
entry_updated_at timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
entry_created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id)
) ENGINE=InnoDB;
INSERT INTO functions (function_name) VALUES ("Loan Mailer"), ("Loan Service"), ("Contact Form Service"), ("User Frontend"), ("API")
+42
View File
@@ -0,0 +1,42 @@
import mysql from "mysql2";
import dotenv from "dotenv";
dotenv.config();
const pool = mysql
.createPool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
})
.promise();
export function checkIfServiceIsActive(service) {
return async (req, res, next) => {
const [result] = await pool.query(
"SELECT * FROM functions WHERE function_name = ? AND active = 1;",
[service],
);
if (result.length > 0) {
return next();
}
return res
.status(503)
.json({ message: `-${service}- is currently unavailable.` });
};
}
export async function checkIfServiceIsActive2(service) {
const [result] = await pool.query(
"SELECT * FROM functions WHERE function_name = ? AND active = 1;",
[service],
);
if (result.length > 0) {
return true;
}
return false;
}