Fix: cast DB row to AuthTokenPayload in findUser\n\nCast database RowDataPacket to AuthTokenPayload so generateToken receives the correct type.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

This commit is contained in:
2026-07-08 10:27:21 +02:00
parent 7247a78809
commit 36ec8da1a0
18 changed files with 1429 additions and 367 deletions
@@ -1,5 +1,8 @@
import mysql from "mysql2";
import dotenv from "dotenv";
import {PRODUCT_ERROR_CODE} from "@stockhome/shared";
import {returnErrorCode} from "../../../services/helperFuncs.js";
dotenv.config();
const pool = mysql
@@ -20,12 +23,7 @@ export const newProduct = async (
expiry_date,
bottling_date,
) => {
let newPrice;
if (price == "") {
newPrice = null;
} else {
newPrice = price;
}
const newPrice = price !== "" ? price : null;
const [result] = await pool.query(
"INSERT INTO products (name, description, price, amount, storage_location, expiry_date, bottling_date) VALUES (?, ?, ?, ?, UUID_TO_BIN(?), ?, ?)",
@@ -41,10 +39,10 @@ export const newProduct = async (
);
if (result.affectedRows > 0) {
return { code: "sp001" }; // success
} else {
return { code: "ep001" }; // error
return { code: "sp001" };
}
return returnErrorCode(PRODUCT_ERROR_CODE.PRODUCT_NOT_CREATED);
};
export const productDetails = async (uuid) => {
@@ -68,9 +66,9 @@ export const productDetails = async (uuid) => {
if (result.length > 0) {
return { code: "sp003", data: result[0] };
} else {
return { code: "ep003" };
}
return returnErrorCode(PRODUCT_ERROR_CODE.PRODUCT_NOT_FOUND);
};
export const allProducts = async () => {
@@ -95,9 +93,9 @@ export const allProducts = async () => {
if (result.length > 0) {
return { code: "sp002", data: result };
} else {
return { code: "ep002" };
}
return returnErrorCode(PRODUCT_ERROR_CODE.NO_PRODUCTS_FOUND);
};
export const setAmount = async (itemUUID, amount) => {
@@ -109,10 +107,10 @@ export const setAmount = async (itemUUID, amount) => {
);
if (result.affectedRows > 0) {
return { code: "sp004" }; // success
} else {
return { code: "ep004" }; // error
return { code: "sp004" };
}
return returnErrorCode(PRODUCT_ERROR_CODE.PRODUCT_AMOUNT_NOT_UPDATED);
};
export const updateItem = async (itemUUID, newValues) => {
@@ -133,10 +131,10 @@ export const updateItem = async (itemUUID, newValues) => {
);
if (result.affectedRows > 0) {
return { code: "sp005" }; // success
} else {
return { code: "ep005" }; // error
return { code: "sp005" };
}
return returnErrorCode(PRODUCT_ERROR_CODE.PRODUCT_NOT_UPDATED);
};
export const deleteProduct = async (uuid) => {
@@ -146,8 +144,8 @@ export const deleteProduct = async (uuid) => {
);
if (result.affectedRows > 0) {
return { code: "sp006" }; // success
} else {
return { code: "ep006" }; // error
return { code: "sp006" };
}
return returnErrorCode(PRODUCT_ERROR_CODE.PRODUCT_NOT_DELETED);
};
@@ -1,5 +1,7 @@
import mysql from "mysql2";
import dotenv from "dotenv";
import {STORAGE_ERROR_CODE} from "@stockhome/shared";
import {returnErrorCode} from "../../../services/helperFuncs.js";
dotenv.config();
const pool = mysql
@@ -18,9 +20,9 @@ export const allStorages = async () => {
if (result.length > 0) {
return { code: "ss001", data: result };
} else {
return { code: "es001" };
}
return returnErrorCode(STORAGE_ERROR_CODE.NO_STORAGE_LOCATIONS_FOUND);
};
export const newStorage = async (name, description) => {
@@ -31,9 +33,9 @@ export const newStorage = async (name, description) => {
if (result.affectedRows > 0) {
return { code: "ss002" };
} else {
return { code: "es002" };
}
return returnErrorCode(STORAGE_ERROR_CODE.STORAGE_NOT_CREATED);
};
export const updateStorage = async (uuid, values) => {
@@ -44,9 +46,9 @@ export const updateStorage = async (uuid, values) => {
if (result.affectedRows > 0) {
return { code: "ss003" };
} else {
return { code: "es003" };
}
return returnErrorCode(STORAGE_ERROR_CODE.STORAGE_NOT_UPDATED);
};
export const deleteStorage = async (uuid) => {
@@ -57,7 +59,7 @@ export const deleteStorage = async (uuid) => {
if (result.affectedRows > 0) {
return { code: "ss004" };
} else {
return { code: "es004" };
}
return returnErrorCode(STORAGE_ERROR_CODE.STORAGE_NOT_DELETED);
};
@@ -1,91 +0,0 @@
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 const findUser = async (username, password) => {
const [result] = await pool.query(
"SELECT BIN_TO_UUID(uuid) AS uuid, username, first_name, last_name, email, is_admin, is_active, last_login FROM users WHERE username = ? AND password = ?;",
[username, password],
);
if (result.length <= 0) {
return { code: "eu001" }; // username or password is wrong
}
if (!result[0].is_active) {
return { code: "eu002" }; // user is deactivated
}
return { code: "su001", data: result[0] }; // user found
};
export const loginUser = async (username) => {
const [result] = await pool.query(
"UPDATE users SET last_login = NOW() WHERE username = ?;",
[username],
);
if (result.affectedRows > 0) {
return { code: "su002" };
} else {
return { code: "eu003" };
}
};
export const updateSettings = async (payload) => {
const appName = payload["app-name"];
const currency = payload.currency;
const [result] = await pool.query(
`UPDATE app_settings
SET value = CASE name
WHEN "app-name" THEN ?
WHEN "currency" THEN ?
ELSE value
END
WHERE name IN ("app-name", "currency");`,
[appName, currency],
);
if (result.affectedRows > 0) {
return { code: "su003" };
} else {
return { code: "eu004" };
}
};
export const getSettings = async () => {
const [result] = await pool.query(`SELECT * FROM app_settings;`);
if (result.length > 0) {
return { code: "su004", result };
} else {
return { code: "eu005" };
}
};
export const changePassword = async (
username,
currentPasswordUser,
newPassword,
) => {
const [result] = await pool.query(
`UPDATE users SET password = ? WHERE username = ? AND password = ?;`,
[newPassword, username, currentPasswordUser],
);
if (result.affectedRows > 0) {
return { code: "su005" };
} else {
return { code: "eu006" };
}
};
@@ -0,0 +1,132 @@
import mysql, {type ResultSetHeader, type RowDataPacket} from "mysql2/promise";
import dotenv from "dotenv";
import {GENERAL_ERROR_CODE, USER_ERROR_CODE} from "@stockhome/shared";
import {returnErrorCode} from "../../../services/helperFuncs.js";
import type { AuthTokenPayload } from "../../../services/tokenService";
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!,
});
export const findUser = async (username: string, password: string) => {
const [result] = await pool.query<RowDataPacket[]>(
"SELECT BIN_TO_UUID(uuid) AS uuid, username, first_name, last_name, email, is_admin, is_active, last_login FROM users WHERE username = ? AND password = ?;",
[username, password],
);
const userRow = result[0];
if (!userRow) {
return returnErrorCode(USER_ERROR_CODE.WRONG_USERNAME_PASSWORD);
}
// Cast DB row to AuthTokenPayload for token generation / typing
const user = userRow as unknown as AuthTokenPayload;
if (!user.is_active) {
return returnErrorCode(USER_ERROR_CODE.USER_IS_DEACTIVATED);
}
return {
success: true,
code: "SU001",
data: user,
message: "Successfully found user.",
};
};
export const loginUser = async (username: string) => {
const [result] = await pool.query<ResultSetHeader>(
"UPDATE users SET last_login = NOW() WHERE username = ?;",
[username],
);
if (result.affectedRows > 0) {
return {
success: true,
code: "SU002",
data: null,
message: "Successfully logged in user.",
};
} else {
return returnErrorCode(GENERAL_ERROR_CODE.UNEXPECTED_SERVER_ERROR);
}
};
export const updateSettings = async (payload: {
"app-name": string;
currency: string;
}) => {
const appName = payload["app-name"];
const currency = payload.currency;
const [result] = await pool.query<ResultSetHeader>(
`UPDATE app_settings
SET value = CASE name
WHEN "app-name" THEN ?
WHEN "currency" THEN ?
ELSE value
END
WHERE name IN ("app-name", "currency");`,
[appName, currency],
);
if (result.affectedRows > 0) {
return {
success: true,
code: "SU003",
data: null,
message: "Successfully updated settings.",
};
} else {
return returnErrorCode(GENERAL_ERROR_CODE.UNEXPECTED_SERVER_ERROR);
}
};
export const getSettings = async () => {
const [result] = await pool.query<RowDataPacket[]>(
`SELECT *
FROM app_settings;`,
);
if (result.length > 0) {
return {
success: true,
code: "SU004",
data: result,
message: "Successfully fetched settings.",
};
} else {
return returnErrorCode(GENERAL_ERROR_CODE.UNEXPECTED_SERVER_ERROR);
}
};
export const changePassword = async (
username: string,
currentPasswordUser: string,
newPassword: string,
) => {
const [result] = await pool.query<ResultSetHeader>(
`UPDATE users
SET password = ?
WHERE username = ?
AND password = ?;`,
[newPassword, username, currentPasswordUser],
);
if (result.affectedRows > 0) {
return {
success: true,
code: "SU005",
data: null,
message: "Successfully fetched settings.",
};
} else {
return returnErrorCode(GENERAL_ERROR_CODE.UNEXPECTED_SERVER_ERROR);
}
};