mirror of
https://github.com/BreizhHardware/Jellystat.git
synced 2026-01-18 16:27:20 +01:00
added fix for sql injection in custom query constructor for history
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
const { pool } = require("../db.js");
|
||||
const pgp = require("pg-promise")();
|
||||
|
||||
function wrapField(field) {
|
||||
if (field === "*") {
|
||||
@@ -43,9 +44,9 @@ function buildWhereClause(conditions) {
|
||||
const { column, field, operator, value, type } = condition;
|
||||
const conjunction = index === 0 ? "" : type ? type.toUpperCase() : "AND";
|
||||
if (operator == "LIKE") {
|
||||
return `${conjunction} ${column ? wrapField(column) : field} ${operator} '%${value}%'`;
|
||||
return `${conjunction} ${column ? wrapField(column) : field} ${operator} ${value}`;
|
||||
}
|
||||
return `${conjunction} ${column ? wrapField(column) : field} ${operator} '${value}'`;
|
||||
return `${conjunction} ${column ? wrapField(column) : field} ${operator} ${value}`;
|
||||
}
|
||||
return "";
|
||||
})
|
||||
@@ -67,7 +68,7 @@ function buildCTE(cte) {
|
||||
.map((condition, index) => {
|
||||
const conjunction = index === 0 ? "" : condition.type ? condition.type.toUpperCase() : "AND";
|
||||
return `${conjunction} ${wrapField(condition.first)} ${condition.operator} ${
|
||||
condition.second ? wrapField(condition.second) : `'${condition.value}'`
|
||||
condition.second ? wrapField(condition.second) : `${condition.value}`
|
||||
}`;
|
||||
})
|
||||
.join(" ");
|
||||
@@ -102,6 +103,7 @@ async function query({
|
||||
alias,
|
||||
joins = [],
|
||||
where = [],
|
||||
values = [],
|
||||
order_by = "Id",
|
||||
sort_order = "desc",
|
||||
pageNumber = 1,
|
||||
@@ -119,7 +121,7 @@ async function query({
|
||||
.map((condition, index) => {
|
||||
const conjunction = index === 0 ? "" : condition.type ? condition.type.toUpperCase() : "AND";
|
||||
return `${conjunction} ${wrapField(condition.first)} ${condition.operator} ${
|
||||
condition.second ? wrapField(condition.second) : `'${condition.value}'`
|
||||
condition.second ? wrapField(condition.second) : `${condition.value}`
|
||||
}`;
|
||||
})
|
||||
.join(" ");
|
||||
@@ -140,10 +142,10 @@ async function query({
|
||||
query += ` LIMIT ${pageSize} OFFSET ${(pageNumber - 1) * pageSize}`;
|
||||
|
||||
// Execute the query
|
||||
const result = await client.query(query);
|
||||
const result = await client.query(query, values);
|
||||
|
||||
// Count total rows
|
||||
const countResult = await client.query(countQuery);
|
||||
const countResult = await client.query(countQuery, values);
|
||||
const totalRows = parseInt(countResult.rows[0].count, 10);
|
||||
|
||||
// Return the structured response
|
||||
|
||||
@@ -152,9 +152,11 @@ function buildFilterList(query, filtersArray) {
|
||||
query.where.push({
|
||||
column: column,
|
||||
operator: ">=",
|
||||
value: filter.min,
|
||||
value: `$${query.values.length + 1}`,
|
||||
});
|
||||
|
||||
query.values.push(filter.min);
|
||||
|
||||
if (applyToCTE) {
|
||||
if (query.cte) {
|
||||
if (!query.cte.where) {
|
||||
@@ -163,8 +165,10 @@ function buildFilterList(query, filtersArray) {
|
||||
query.cte.where.push({
|
||||
column: column,
|
||||
operator: ">=",
|
||||
value: filter.min,
|
||||
value: `$${query.values.length + 1}`,
|
||||
});
|
||||
|
||||
query.values.push(filter.min);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -173,9 +177,11 @@ function buildFilterList(query, filtersArray) {
|
||||
query.where.push({
|
||||
column: column,
|
||||
operator: "<=",
|
||||
value: filter.max,
|
||||
value: `$${query.values.length + 1}`,
|
||||
});
|
||||
|
||||
query.values.push(filter.max);
|
||||
|
||||
if (applyToCTE) {
|
||||
if (query.cte) {
|
||||
if (!query.cte.where) {
|
||||
@@ -184,8 +190,10 @@ function buildFilterList(query, filtersArray) {
|
||||
query.cte.where.push({
|
||||
column: column,
|
||||
operator: "<=",
|
||||
value: filter.max,
|
||||
value: `$${query.values.length + 1}`,
|
||||
});
|
||||
|
||||
query.values.push(filter.max);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -193,8 +201,11 @@ function buildFilterList(query, filtersArray) {
|
||||
if (filter.value) {
|
||||
const whereClause = {
|
||||
operator: "LIKE",
|
||||
value: filter.value.toLowerCase(),
|
||||
value: `$${query.values.length + 1}`,
|
||||
};
|
||||
|
||||
query.values.push(`%${filter.value.toLowerCase()}%`);
|
||||
|
||||
if (isColumn) {
|
||||
whereClause.column = column;
|
||||
} else {
|
||||
@@ -207,7 +218,10 @@ function buildFilterList(query, filtersArray) {
|
||||
if (!query.cte.where) {
|
||||
query.cte.where = [];
|
||||
}
|
||||
whereClause.value = `$${query.values.length + 1}`;
|
||||
query.cte.where.push(whereClause);
|
||||
|
||||
query.values.push(`%${filter.value.toLowerCase()}%`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1227,6 +1241,8 @@ router.get("/getHistory", async (req, res) => {
|
||||
|
||||
const sortField = groupedSortMap.find((item) => item.field === sort)?.column || "a.ActivityDateInserted";
|
||||
|
||||
const values = [];
|
||||
|
||||
try {
|
||||
const cte = {
|
||||
cteAlias: "activity_results",
|
||||
@@ -1291,11 +1307,15 @@ router.get("/getHistory", async (req, res) => {
|
||||
END
|
||||
)`,
|
||||
operator: "LIKE",
|
||||
value: `${search.toLowerCase()}`,
|
||||
value: `$${values.length + 1}`,
|
||||
},
|
||||
];
|
||||
|
||||
values.push(`%${search.toLowerCase()}%`);
|
||||
}
|
||||
|
||||
query.values = values;
|
||||
|
||||
buildFilterList(query, filtersArray);
|
||||
const result = await dbHelper.query(query);
|
||||
|
||||
@@ -1378,6 +1398,7 @@ router.post("/getLibraryHistory", async (req, res) => {
|
||||
}
|
||||
|
||||
const sortField = groupedSortMap.find((item) => item.field === sort)?.column || "a.ActivityDateInserted";
|
||||
const values = [];
|
||||
|
||||
const cte = {
|
||||
cteAlias: "activity_results",
|
||||
@@ -1420,7 +1441,7 @@ router.post("/getLibraryHistory", async (req, res) => {
|
||||
alias: "i",
|
||||
conditions: [
|
||||
{ first: "i.Id", operator: "=", second: "a.NowPlayingItemId" },
|
||||
{ first: "i.ParentId", operator: "=", value: libraryid },
|
||||
{ first: "i.ParentId", operator: "=", value: `$${values.length + 1}` },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -1441,6 +1462,8 @@ router.post("/getLibraryHistory", async (req, res) => {
|
||||
pageSize: size,
|
||||
};
|
||||
|
||||
values.push(libraryid);
|
||||
|
||||
if (search && search.length > 0) {
|
||||
query.where = [
|
||||
{
|
||||
@@ -1451,11 +1474,15 @@ router.post("/getLibraryHistory", async (req, res) => {
|
||||
END
|
||||
)`,
|
||||
operator: "LIKE",
|
||||
value: `${search.toLowerCase()}`,
|
||||
value: `$${values.length + 1}`,
|
||||
},
|
||||
];
|
||||
|
||||
values.push(`%${search.toLowerCase()}%`);
|
||||
}
|
||||
|
||||
query.values = values;
|
||||
|
||||
buildFilterList(query, filtersArray);
|
||||
|
||||
const result = await dbHelper.query(query);
|
||||
@@ -1541,7 +1568,7 @@ router.post("/getItemHistory", async (req, res) => {
|
||||
}
|
||||
|
||||
const sortField = unGroupedSortMap.find((item) => item.field === sort)?.column || "a.ActivityDateInserted";
|
||||
|
||||
const values = [];
|
||||
const query = {
|
||||
select: [
|
||||
"a.*",
|
||||
@@ -1559,9 +1586,9 @@ router.post("/getItemHistory", async (req, res) => {
|
||||
alias: "a",
|
||||
where: [
|
||||
[
|
||||
{ column: "a.EpisodeId", operator: "=", value: itemid },
|
||||
{ column: "a.SeasonId", operator: "=", value: itemid, type: "or" },
|
||||
{ column: "a.NowPlayingItemId", operator: "=", value: itemid, type: "or" },
|
||||
{ column: "a.EpisodeId", operator: "=", value: `$${values.length + 1}` },
|
||||
{ column: "a.SeasonId", operator: "=", value: `$${values.length + 2}`, type: "or" },
|
||||
{ column: "a.NowPlayingItemId", operator: "=", value: `$${values.length + 3}`, type: "or" },
|
||||
],
|
||||
],
|
||||
order_by: sortField,
|
||||
@@ -1570,6 +1597,10 @@ router.post("/getItemHistory", async (req, res) => {
|
||||
pageSize: size,
|
||||
};
|
||||
|
||||
values.push(itemid);
|
||||
values.push(itemid);
|
||||
values.push(itemid);
|
||||
|
||||
if (search && search.length > 0) {
|
||||
query.where = [
|
||||
{
|
||||
@@ -1580,11 +1611,13 @@ router.post("/getItemHistory", async (req, res) => {
|
||||
END
|
||||
)`,
|
||||
operator: "LIKE",
|
||||
value: `${search.toLowerCase()}`,
|
||||
value: `$${values.length + 1}`,
|
||||
},
|
||||
];
|
||||
values.push(`%${search.toLowerCase()}%`);
|
||||
}
|
||||
|
||||
query.values = values;
|
||||
buildFilterList(query, filtersArray);
|
||||
const result = await dbHelper.query(query);
|
||||
|
||||
@@ -1667,6 +1700,7 @@ router.post("/getUserHistory", async (req, res) => {
|
||||
|
||||
const sortField = unGroupedSortMap.find((item) => item.field === sort)?.column || "a.ActivityDateInserted";
|
||||
|
||||
const values = [];
|
||||
const query = {
|
||||
select: [
|
||||
"a.*",
|
||||
@@ -1682,13 +1716,15 @@ router.post("/getUserHistory", async (req, res) => {
|
||||
],
|
||||
table: "jf_playback_activity_with_metadata",
|
||||
alias: "a",
|
||||
where: [[{ column: "a.UserId", operator: "=", value: userid }]],
|
||||
where: [[{ column: "a.UserId", operator: "=", value: `$${values.length + 1}` }]],
|
||||
order_by: sortField,
|
||||
sort_order: desc ? "desc" : "asc",
|
||||
pageNumber: page,
|
||||
pageSize: size,
|
||||
};
|
||||
|
||||
values.push(userid);
|
||||
|
||||
if (search && search.length > 0) {
|
||||
query.where = [
|
||||
{
|
||||
@@ -1699,11 +1735,14 @@ router.post("/getUserHistory", async (req, res) => {
|
||||
END
|
||||
)`,
|
||||
operator: "LIKE",
|
||||
value: `${search.toLowerCase()}`,
|
||||
value: `$${values.length + 1}`,
|
||||
},
|
||||
];
|
||||
values.push(`%${search.toLowerCase()}%`);
|
||||
}
|
||||
|
||||
query.values = values;
|
||||
|
||||
buildFilterList(query, filtersArray);
|
||||
|
||||
const result = await dbHelper.query(query);
|
||||
|
||||
Reference in New Issue
Block a user