Refactor loan and user management components and backend routes

- Updated LoanTable component to fetch loan data from new API endpoint and display notes.
- Enhanced UserTable component to include additional user fields (first name, last name, email, admin status) and updated input handling.
- Modified fetcher utility to use new user data API endpoint.
- Adjusted login functionality to point to the new admin login endpoint and handle unauthorized access.
- Refactored user actions utility to align with updated API endpoints for user management.
- Updated backend routes for user and loan data management to reflect new structure and naming conventions.
- Revised SQL schema and mock data to accommodate new fields and constraints.
- Changed Docker configuration to use the new database name.
This commit is contained in:
2025-11-11 17:08:45 +01:00
parent 974a5a75d8
commit a8b4ac3d60
26 changed files with 605 additions and 347 deletions

View File

@@ -8,21 +8,21 @@ dotenv.config();
import {
getAllApiKeys,
createAPIentry,
deleteAPIKey,
deleteAPKey,
} from "./database/apiDataMgmt.database.js";
router.get("/get-api-keys", authenticateAdmin, async (req, res) => {
const result = await getAllApiKeys();
if (result.success) {
return res.status(200).json({ apiKeys: result.data });
return res.status(200).json(result.data);
}
return res.status(500).json({ message: "Failed to retrieve API keys" });
});
router.post("/create-api-key", authenticateAdmin, async (req, res) => {
const apiKey = req.body.apiKey;
const username = req.body.username;
const result = await createAPIentry(apiKey, username);
const entryName = req.body.entryName;
const result = await createAPIentry(apiKey, entryName);
if (result.success) {
return res.status(201).json({ message: "API key created successfully" });
}
@@ -31,7 +31,7 @@ router.post("/create-api-key", authenticateAdmin, async (req, res) => {
router.delete("/delete-api-key/:id", authenticateAdmin, async (req, res) => {
const apiKeyId = req.params.id;
const result = await deleteAPIKey(apiKeyId);
const result = await deleteAPKey(apiKeyId);
if (result.success) {
return res.status(200).json({ message: "API key deleted successfully" });
}

View File

@@ -19,10 +19,10 @@ export const getAllApiKeys = async () => {
return { success: false };
};
export const createAPIentry = async (apiKey, user) => {
export const createAPIentry = async (apiKey, entryName) => {
const [result] = await pool.query(
"INSERT INTO apiKeys (api_key, username) VALUES (?, ?)",
[apiKey, user]
"INSERT INTO apiKeys (api_key, entry_name) VALUES (?, ?)",
[apiKey, entryName]
);
if (result.affectedRows > 0) return { success: true };
return { success: false };

View File

@@ -26,7 +26,7 @@ export const deleteItemById = async (itemId) => {
export const createItem = async (item_name, can_borrow_role, in_safe) => {
const [result] = await pool.query(
"INSERT INTO items (item_name, can_borrow_role, in_safe) VALUES (?, ?, ?)",
[item_name, can_borrow_role, in_safe]
[item_name, can_borrow_role, true]
);
if (result.affectedRows > 0) return { success: true };
return { success: false };
@@ -34,9 +34,37 @@ export const createItem = async (item_name, can_borrow_role, in_safe) => {
export const editItemById = async (itemId, item_name, can_borrow_role) => {
const [result] = await pool.query(
"UPDATE items SET item_name = ?, can_borrow_role = ? WHERE id = ?",
"UPDATE items SET item_name = ?, can_borrow_role = ?, entry_updated_at = NOW() WHERE id = ?",
[item_name, can_borrow_role, itemId]
);
if (result.affectedRows > 0) return { success: true };
return { success: false };
};
export const changeSafeState = async (itemId) => {
const currentState = await pool.query(
"SELECT in_safe FROM items WHERE id = ?",
[itemId]
);
if (currentState[0].length === 0) {
return { success: false };
}
if (currentState[0][0].in_safe) {
const [result] = await pool.query(
"UPDATE items SET in_safe = false WHERE id = ?",
[itemId]
);
if (result.affectedRows > 0) return { success: true };
}
if (!currentState[0][0].in_safe) {
const [result] = await pool.query(
"UPDATE items SET in_safe = true WHERE id = ?",
[itemId]
);
if (result.affectedRows > 0) return { success: true };
}
return { success: false };
};

View File

@@ -61,7 +61,7 @@ export const editUserById = async (
export const getAllUsers = async () => {
const [result] = await pool.query(
"SELECT id, username, first_name, last_name, role, email, is_admin FROM users"
"SELECT id, username, first_name, last_name, role, email, is_admin, entry_created_at, entry_updated_at FROM users"
);
if (result.length > 0) return { success: true, data: result };
return { success: false };

View File

@@ -16,7 +16,7 @@ import {
router.get("/all-items", authenticateAdmin, async (req, res) => {
const result = await getAllItems();
if (result.success) {
return res.status(200).json({ items: result.data });
return res.status(200).json(result.data);
}
return res.status(500).json({ message: "Failed to retrieve items" });
});
@@ -31,8 +31,8 @@ router.delete("/delete-item/:id", authenticateAdmin, async (req, res) => {
});
router.post("/create-item", authenticateAdmin, async (req, res) => {
const { item_name, can_borrow_role, in_safe } = req.body;
const result = await createItem(item_name, can_borrow_role, in_safe);
const { item_name, can_borrow_role } = req.body;
const result = await createItem(item_name, can_borrow_role);
if (result.success) {
return res.status(201).json({ message: "Item created successfully" });
}
@@ -55,8 +55,7 @@ router.post("/edit-item/:id", authenticateAdmin, async (req, res) => {
router.post("/change-safe-state/:id", authenticateAdmin, async (req, res) => {
const itemId = req.params.id;
const { in_safe } = req.body;
const result = await changeSafeState(itemId, in_safe);
const result = await changeSafeState(itemId);
if (result.success) {
return res.status(200).json({ message: "Safe state changed successfully" });
}

View File

@@ -13,7 +13,7 @@ import {
router.get("/all-loans", authenticateAdmin, async (req, res) => {
const result = await getAllLoans();
if (result.success) {
return res.status(200).json({ loans: result.data });
return res.status(200).json(result.data);
}
return res.status(500).json({ message: "Failed to retrieve loans" });
});

View File

@@ -47,7 +47,6 @@ router.delete("/delete-user/:id", authenticateAdmin, async (req, res) => {
});
router.post("/edit-user/:id", authenticateAdmin, async (req, res) => {
const password = req.body.password;
const first_name = req.body.first_name;
const last_name = req.body.last_name;
const role = req.body.role;
@@ -57,7 +56,6 @@ router.post("/edit-user/:id", authenticateAdmin, async (req, res) => {
const result = await editUserById(
userId,
password,
first_name,
last_name,
role,
@@ -109,7 +107,7 @@ router.post("/edit-user/:id", authenticateAdmin, async (req, res) => {
router.get("/users", authenticateAdmin, async (req, res) => {
const result = await getAllUsers();
if (result.success) {
return res.status(200).json({ users: result.data });
return res.status(200).json(result.data);
}
return res.status(500).json({ message: "Failed to retrieve users" });
});

View File

@@ -1,7 +1,9 @@
import express from "express";
import { authenticate, generateToken } from "../../services/authentication.js";
import {
generateToken,
authenticateAdmin,
} from "../../services/authentication.js";
const router = express.Router();
import nodemailer from "nodemailer";
import dotenv from "dotenv";
dotenv.config();
@@ -9,7 +11,12 @@ dotenv.config();
import { loginAdmin } from "./database/userMgmt.database.js";
router.post("/login", async (req, res) => {
const result = await loginAdmin(req.body.username, req.body.password);
const { username, password } = req.body || {};
if (!username || !password) {
return res.status(400).json({ message: "Missing username or password" });
}
const result = await loginAdmin(username, password);
if (result.success) {
const token = await generateToken({
@@ -18,7 +25,11 @@ router.post("/login", async (req, res) => {
last_name: result.data.last_name,
admin: result.data.is_admin,
});
return res.status(200).json({ message: "Login erfolgreich", token });
return res.status(200).json({
message: "Login erfolgreich",
token,
first_name: result.data.first_name,
});
}
if (result.reason === "not_admin") {
@@ -27,3 +38,9 @@ router.post("/login", async (req, res) => {
return res.status(401).json({ message: "Ungültige Anmeldedaten" });
});
router.get("/verify-token", authenticateAdmin, async (req, res) => {
return res.status(200).json({ message: "Token is valid" });
});
export default router;