Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Servers/controllers/user.ctrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ async function getAllUsers(req: Request, res: Response): Promise<any> {

if (users && users.length > 0) {
logStructured('successful', `found ${users.length} users`, 'getAllUsers', 'user.ctrl.ts');
console.log('✅ Sending successful response with users:', users.map((user) => user.toSafeJSON()));
return res
.status(200)
.json(STATUS_CODE[200](users.map((user) => user.toSafeJSON())));
Expand Down
2 changes: 2 additions & 0 deletions Servers/infrastructure.layer/driver/autoDriver.driver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ export async function insertMockData(
risk_approval: users[1].id!,
approval_status: "In Progress",
date_of_assessment: new Date(Date.now()),
projects: [project.id!],
frameworks: [2, 3], // ISO frameworks
},
Comment on lines +171 to 173
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

🧩 Analysis chain

Avoid hardcoded framework IDs; align risk-framework association with the project.

Using literal [2, 3] may create inconsistent associations (risk linked to a project that doesn’t have those frameworks). Derive frameworks from the project’s current frameworks for correctness.

Apply this diff:

-          projects: [project.id!],
-          frameworks: [2, 3], // ISO frameworks
+          projects: [project.id!],
+          frameworks: projectFrameworkIds.map((x) => x.framework_id),

Add this helper just above the createRiskQuery call:

// Derive frameworks from the created project
const projectFrameworkIds = (await sequelize.query(
  `SELECT framework_id FROM "${tenant}".projects_frameworks WHERE project_id = :project_id`,
  {
    replacements: { project_id: project.id },
    transaction,
  }
)) as [{ framework_id: number }[], number];

If the intent was to attach this risk to ISO frameworks, consider associating it with the organizational project instead (and then derive frameworks from that project). Confirm intended behavior.


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Finding autoDriver.driver.ts..."
file=$(rg -n --hidden --glob '!node_modules' -g '**/autoDriver.driver.ts' -l || true)
if [ -z "$file" ]; then
  echo "NOT FOUND"
else
  echo "FOUND: $file"
  echo "---- snippet lines 1-260 ----"
  sed -n '1,260p' "$file" || true
fi

echo "---- matches for frameworks array literals ----"
rg -nP -C3 --hidden --glob '!node_modules' "frameworks\s*:\s*\[[^\]]+\]" || true

echo "---- matches for projects_frameworks ----"
rg -nP -C3 --hidden --glob '!node_modules' "projects_frameworks" || true

echo "---- matches for sequelize.query ----"
rg -nP -C3 --hidden --glob '!node_modules' "sequelize\.query\(" || true

echo "---- matches for createRiskQuery ----"
rg -nP -C3 --hidden --glob '!node_modules' "createRiskQuery" || true

echo "---- matches for tenant variable usage ----"
rg -nP -C3 --hidden --glob '!node_modules' "\$\{tenant\}" || true

echo "---- matches for transaction variable usage ----"
rg -nP -C3 --hidden --glob '!node_modules' "\btransaction\b" || true

Length of output: 1591


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "1) Locate file(s) named autoDriver.driver.ts"
mapfile -t files < <(find . -type f -iname 'autoDriver.driver.ts' -print)
if [ "${#files[@]}" -eq 0 ]; then
  echo "NOT FOUND"
else
  for f in "${files[@]}"; do
    echo "FOUND: $f"
    echo "---- snippet lines 1-260 ----"
    sed -n '1,260p' "$f" || true
  done
fi

echo
echo "2) Search for frameworks array literals (pattern: frameworks: [ ... ])"
rg --no-ignore -nP -C3 "frameworks\s*:\s*\[[^\]]+\]" || true

echo
echo "3) Search for projects_frameworks usages"
rg --no-ignore -nP -C3 "projects_frameworks" || true

echo
echo "4) Search for sequelize.query calls"
rg --no-ignore -nP -C3 "sequelize\.query\(" || true

echo
echo "5) Search for createRiskQuery"
rg --no-ignore -nP -C3 "createRiskQuery" || true

echo
echo "6) Search for \${tenant} template usage"
rg --no-ignore -nP -C3 "\\$\\{tenant\\}" || true

echo
echo "7) Search for transaction variable references"
rg --no-ignore -nP -C3 "\\btransaction\\b" || true

Length of output: 101


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "1) Locate autoDriver.driver.ts files"
files=( $(find . -type f -iname 'autoDriver.driver.ts' -print 2>/dev/null) )
if [ "${#files[@]}" -eq 0 ]; then
  echo "NOT FOUND"
else
  for f in "${files[@]}"; do
    echo "FOUND: $f"
    echo "---- snippet lines 1-260 ----"
    sed -n '1,260p' "$f" || true
    echo "---- snippet lines 150-200 ----"
    sed -n '150,200p' "$f" || true
  done
fi

echo
echo "2) Search for exact frameworks: [2, 3] occurrences"
if command -v rg >/dev/null 2>&1; then
  rg -nP -C3 --hidden -g '!node_modules' "frameworks\s*:\s*\[\s*2\s*,\s*3\s*\]" || true
else
  grep -RniP --exclude-dir=node_modules "frameworks\s*:\s*\[\s*2\s*,\s*3\s*\]" . || true
fi

echo
echo "3) Search for any frameworks: [ ... ] array literals"
if command -v rg >/dev/null 2>&1; then
  rg -nP -C3 --hidden -g '!node_modules' "frameworks\s*:\s*\[[^\]]+\]" || true
else
  grep -RniP --exclude-dir=node_modules "frameworks\s*:\s*\[[^\]]+\]" . || true
fi

echo
echo "4) Search for createRiskQuery usage"
if command -v rg >/dev/null 2>&1; then
  rg -nP -C3 --hidden -g '!node_modules' "createRiskQuery" || true
else
  grep -Rni --exclude-dir=node_modules "createRiskQuery" . || true
fi

echo
echo "5) Search for projects_frameworks table usage"
if command -v rg >/dev/null 2>&1; then
  rg -nP -C3 --hidden -g '!node_modules' "projects_frameworks" || true
else
  grep -Rni --exclude-dir=node_modules "projects_frameworks" . || true
fi

echo
echo "6) Search for sequelize.query usages"
if command -v rg >/dev/null 2>&1; then
  rg -nP -C3 --hidden -g '!node_modules' "sequelize\.query\(" || true
else
  grep -Rni --exclude-dir=node_modules "sequelize\.query(" . || true
fi

echo
echo "7) Search for project.id! occurrences"
if command -v rg >/dev/null 2>&1; then
  rg -nP -C3 --hidden -g '!node_modules' "project\.id!" || true
else
  grep -Rni --exclude-dir=node_modules "project\.id!" . || true
fi

echo
echo "8) Search for tenant template usage (\${tenant})"
if command -v rg >/dev/null 2>&1; then
  rg -nP -C3 --hidden -g '!node_modules' "\$\{tenant\}" || true
else
  grep -Rni --exclude-dir=node_modules "\${tenant}" . || true
fi

echo
echo "9) Search for transaction variable references"
if command -v rg >/dev/null 2>&1; then
  rg -nP -C3 --hidden -g '!node_modules' "\\btransaction\\b" || true
else
  grep -Rni --exclude-dir=node_modules "\\btransaction\\b" . || true
fi

Length of output: 12852


Avoid hardcoded framework IDs — derive frameworks from the project

Hardcoding frameworks: [2, 3] assigns ISO frameworks to project.id (the created project uses different frameworks), causing inconsistent risk→project→framework associations.

Location: Servers/infrastructure.layer/driver/autoDriver.driver.ts — createRiskQuery call (around lines 171–173).

Apply this diff:

-          projects: [project.id!],
-          frameworks: [2, 3], // ISO frameworks
+          projects: [project.id!],
+          frameworks: projectFrameworkIds.map((x) => x.framework_id),

Add this helper just above the createRiskQuery call:

// Derive frameworks from the created project
const projectFrameworkIds = (await sequelize.query(
  `SELECT framework_id FROM "${tenant}".projects_frameworks WHERE project_id = :project_id`,
  {
    replacements: { project_id: project.id },
    transaction,
  }
)) as [{ framework_id: number }[], number];

If the intent was to attach this risk to ISO frameworks, associate it with the organizational project (projectOrg) instead and derive frameworks from that project.

🤖 Prompt for AI Agents
In Servers/infrastructure.layer/driver/autoDriver.driver.ts around lines
171–173, the code hardcodes frameworks as [2, 3] when calling createRiskQuery
which mismatches the actual frameworks linked to the created project; replace
the hardcoded list by querying projects_frameworks for the created project just
above the createRiskQuery call (use sequelize.query with replacements {
project_id: project.id } and the current transaction) to derive
projectFrameworkIds and pass those IDs to createRiskQuery; if the intended
target is the organizational project (ISO frameworks), perform the same query
against projectOrg instead and use those framework IDs.

tenant,
transaction
Expand Down
15 changes: 8 additions & 7 deletions Servers/utils/project.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ export const updateProjectUpdatedByIdQuery = async (
byTable:
| "controls"
| "answers"
| "projectrisks"
// | "projectrisks"
| "vendors"
| "subclauses"
| "annexcategories"
Expand All @@ -316,9 +316,9 @@ export const updateProjectUpdatedByIdQuery = async (
const queryMap = {
controls: `SELECT pf.project_id as id FROM "${tenant}".controls_eu c JOIN "${tenant}".projects_frameworks pf ON pf.id = c.projects_frameworks_id WHERE c.id = :id;`,
answers: `SELECT pf.project_id as id FROM "${tenant}".assessments a JOIN "${tenant}".answers_eu ans ON ans.assessment_id = a.id JOIN "${tenant}".projects_frameworks pf ON pf.id = a.projects_frameworks_id WHERE ans.id = :id;`,
projectrisks: `SELECT p.id FROM
"${tenant}".projects p JOIN "${tenant}".projectrisks pr ON p.id = pr.project_id
WHERE pr.id = :id;`,
// projectrisks: `SELECT p.id FROM
// "${tenant}".projects p JOIN "${tenant}".projectrisks pr ON p.id = pr.project_id
// WHERE pr.id = :id;`,
vendors: `SELECT project_id as id FROM "${tenant}".vendors_projects WHERE vendor_id = :id;`,
subclauses: `SELECT pf.project_id as id FROM "${tenant}".subclauses_iso sc JOIN "${tenant}".projects_frameworks pf ON pf.id = sc.projects_frameworks_id WHERE sc.id = :id;`,
annexcategories: `SELECT pf.project_id as id FROM "${tenant}".annexcategories_iso a JOIN "${tenant}".projects_frameworks pf ON pf.id = a.projects_frameworks_id WHERE a.id = :id;`,
Expand Down Expand Up @@ -480,7 +480,8 @@ export const deleteHelper = async (
let childIds: any = {};
if (
childTableName !== "projects_members" &&
childTableName !== "projects_frameworks"
childTableName !== "projects_frameworks" &&
childTableName !== "projects_risks"
) {
if (childTableName === "vendors") {
childIds = await sequelize.query(
Expand Down Expand Up @@ -555,7 +556,7 @@ export const deleteProjectByIdQuery = async (
},
},
{ files: { foreignKey: "project_id", model: FileModel } },
{ projectrisks: { foreignKey: "project_id", model: RiskModel } },
{ projects_risks: { foreignKey: "project_id", model: RiskModel } },
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

🧩 Analysis chain

Cascade deletion updated to projects_risks is right.

Deleting join rows by project fixes the prior project delete bug while preserving risks.

Confirm foreign key on projects_risks (project_id) is indexed for delete performance:


🏁 Script executed:

#!/bin/bash
# Grep migrations for projects_risks FK/index on project_id
rg -nP -C2 'CREATE INDEX.*projects_risks.*project_id|projects_risks.*FOREIGN KEY.*project_id'

Length of output: 1364


Add an index on projects_risks.project_id

FK exists (projects_risks_project_id_fkey in Servers/database/migrations/20250918172152-migrate-project-risks.js and Servers/scripts/createNewTenant.ts) but no standalone index was found; the PK is (risk_id, project_id) so the btree PK index won’t help lookups by project_id alone — add an index to avoid full-table scans on project deletes.

Suggested change (migration + tenant script):
CREATE INDEX projects_risks_project_id_idx ON "${tenantHash}".projects_risks(project_id);

{
projects_members: {
foreignKey: "project_id",
Expand Down Expand Up @@ -604,7 +605,7 @@ export const calculateProjectRisks = async (
risk_level_autocalculated: string;
count: string;
}>(
`SELECT risk_level_autocalculated, count(*) AS count FROM "${tenant}".projectrisks WHERE project_id = :project_id GROUP BY risk_level_autocalculated`,
`SELECT risk_level_autocalculated, count(*) AS count FROM "${tenant}".risks r JOIN "${tenant}".projects_risks pr ON r.id = pr.risk_id WHERE pr.project_id = :project_id GROUP BY risk_level_autocalculated`,
{
replacements: { project_id },
type: QueryTypes.SELECT,
Expand Down
6 changes: 4 additions & 2 deletions Servers/utils/reporting.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@ import { IProjectsMembers } from "../domain.layer/interfaces/i.projectMember";
export const getProjectRisksReportQuery = async (projectId: number, tenant: string) => {
const query = `
SELECT
risk.*,
risk.*,
pr.project_id AS project_id,
u.name AS risk_owner_name,
u.surname AS risk_owner_surname
FROM "${tenant}".projectrisks risk
FROM "${tenant}".risks risk
JOIN "${tenant}".projects_risks pr ON risk.id = pr.risk_id
LEFT JOIN public.users u ON risk.risk_owner = u.id
WHERE project_id = :project_id
ORDER BY created_at DESC, id ASC
Expand Down
2 changes: 1 addition & 1 deletion Servers/utils/user.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ export const deleteUserByIdQuery = async (
// fields: ["approver", "owner", "reviewer"],
// },
{
table: "projectrisks",
table: "risks",
model: RiskModel,
fields: ["risk_owner", "risk_approval"],
},
Expand Down