Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

058 Dec 19 Calculate Assessment and Compliance Tracker progress #367

Conversation

HarshP4585
Copy link
Contributor

@HarshP4585 HarshP4585 commented Dec 19, 2024

Describe your changes

  • Added code to calculate the progress of Assessment and Compliance Tracker in /users route
  • Updated the swagger with the added endpoint
  • Response from the API
  •   "controls": {
          "projects": [
              {
                  "projectId": 1,
                  "totalSubControls": 12,
                  "doneSubControls": 1
              }
          ],
          "totalSubControls": 12,
          "doneSubControls": 1,
          "percentageComplete": 8.33
      },
      "questions": {
          "projects": [
              {
                  "projectId": 1,
                  "totalQuestions": 34,
                  "doneQuestions": 0
              }
          ],
          "totalQuestions": 34,
          "doneQuestions": 0,
          "percentageComplete": 0
      }
    
    

Issue number

Please ensure all items are checked off before requesting a review:

  • I deployed the code locally.
  • I have performed a self-review of my code.
  • I have included the issue # in the PR.
  • I have labelled the PR correctly.
  • The issue I am working on is assigned to me.
  • I didn't use any hardcoded values (otherwise it will not scale, and will make it difficult to maintain consistency across the application).
  • I made sure font sizes, color choices etc are all referenced from the theme.
  • My PR is granular and targeted to one specific feature.
  • I took a screenshot or a video and attached to this PR if there is a UI change.

Summary by CodeRabbit

  • New Features

    • Introduced a new endpoint to retrieve user progress metrics by user ID.
    • Added multiple utility functions for enhanced project and assessment data retrieval.
  • Bug Fixes

    • Improved error handling for the new progress calculation feature.
  • Documentation

    • Updated API specifications to include the new progress calculation endpoint and its response structure.

@HarshP4585 HarshP4585 added the backend Backend related tasks/issues label Dec 19, 2024
@HarshP4585 HarshP4585 self-assigned this Dec 19, 2024
Copy link

coderabbitai bot commented Dec 19, 2024

Walkthrough

This pull request introduces several new utility functions and an API endpoint for calculating user project progress. Changes are made across multiple files in the Servers directory, including the user controller, routes, Swagger specification, and utility functions. The key addition is the calculateProgress function, which computes detailed progress metrics for a user's projects, controls, and questions based on their user ID.

Changes

File Change Summary
Servers/controllers/user.ctrl.ts Added calculateProgress function to compute user project progress and updated exports.
Servers/routes/user.route.ts Added new GET route /:id/calculate-progress for progress retrieval.
Servers/swagger.yaml Added new API endpoint specification for progress calculation.
Servers/utils/user.utils.ts Added multiple utility functions for retrieving project, assessment, and control data.

Possibly related PRs

Suggested reviewers

  • MuhammadKhalilzadeh

Poem

🐰 Hopping through code with glee,
Progress tracking, now set free!
User metrics, crisp and bright,
Calculations taking flight!
A rabbit's leap of data might! 🚀

Tip

CodeRabbit's docstrings feature is now available as part of our Early Access Program! Simply use the command @coderabbitai generate docstrings to have CodeRabbit automatically generate docstrings for your pull request. We would love to hear your feedback on Discord.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
Servers/controllers/user.ctrl.ts (1)

342-420: Use consistent naming convention for enumerations/status checks.
Right now, subControl status is compared to the string "Done" (line 368). This is fine for an MVP. However, consider extracting status to a constant or enum (like SUBCONTROL_STATUS.Done) to avoid typos or to manage new statuses easily in the future.

Servers/swagger.yaml (1)

3858-3941: Ensure route documentation covers all realistic responses.
The new /users/{id}/calculate-progress endpoint only defines 200 and 500 errors in the spec. Consider adding 404 if the user does not exist or 401 if authentication fails. This promotes a robust and clear API contract.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1955a0d and a195924.

📒 Files selected for processing (4)
  • Servers/controllers/user.ctrl.ts (3 hunks)
  • Servers/routes/user.route.ts (2 hunks)
  • Servers/swagger.yaml (1 hunks)
  • Servers/utils/user.utils.ts (1 hunks)
🔇 Additional comments (3)
Servers/controllers/user.ctrl.ts (2)

342-420: Check for potential null or empty array returns.
The for-loops assume that userProjects (line 358), controlcategories (line 361), controls (line 363), subControls (line 365), etc. will return valid arrays. If any of these is empty or null, the logic still works without errors, but consider gracefully handling or logging edge cases where data might be absent.

Would you like to add explicit checks (e.g. if length is 0 => skip) or do you prefer continuing to rely on the for-of loops which safely handle empty arrays?


432-432: All necessary exports are present.
Exporting calculateProgress here ensures the route can use it. Looks good.

Servers/utils/user.utils.ts (1)

232-295: Review each new SQL statement for correctness and performance.
You’ve added multiple small functions for retrieving data (getUserProjects, getControlCategoriesForProject, etc.). Each function is parameterized with ID in the WHERE clause (good for preventing SQL injection). Ensure that the correct columns and table references exist and that indexes are present on these columns for performance if needed.

Comment on lines 342 to 420
async function calculateProgress(
req: Request,
res: Response
): Promise<Response> {
try {
const id = parseInt(req.params.id)
const userProjects = await getUserProjects(id)

let questionsMetadata = []
let allTotalQuestions = 0
let allDoneQuestions = 0

let controlsMetadata = []
let allTotalSubControls = 0
let allDoneSubControls = 0

for (const userProject of userProjects) {
let totalSubControls = 0
let doneSubControls = 0
const controlcategories = await getControlCategoriesForProject(userProject.id)
for (const controlcategory of controlcategories) {
const controls = await getControlForControlCategory(controlcategory.id)
for (const control of controls) {
const subControls = await getSubControlForControl(control.id)
for (const subControl of subControls) {
totalSubControls++;
if (subControl.status === "Done") {
doneSubControls++;
}
}
}
}
allTotalSubControls += totalSubControls
allDoneSubControls += doneSubControls
controlsMetadata.push({ projectId: userProject.id, totalSubControls, doneSubControls })

let totalQuestions = 0
let doneQuestions = 0
const assessments = await getAssessmentsForProject(userProject.id)
for (const assessment of assessments) {
const topics = await getTopicsForAssessment(assessment.id)
for (const topic of topics) {
const subTopics = await getSubTopicsForTopic(topic.id)
for (const subTopic of subTopics) {
const questions = await getQuestionsForSubTopic(subTopic.id)
for (const question of questions) {
totalQuestions++;
if (question.answer) {
doneQuestions++
}
}
}
}
}
allTotalQuestions += totalQuestions
allDoneQuestions += doneQuestions
questionsMetadata.push({ projectId: userProject.id, totalQuestions, doneQuestions })
}

const response = {
controls: {
projects: controlsMetadata,
totalSubControls: allTotalSubControls,
doneSubControls: allDoneSubControls,
percentageComplete: Number(((allDoneSubControls / allTotalSubControls) * 100).toFixed(2))
},
questions: {
projects: questionsMetadata,
totalQuestions: allTotalQuestions,
doneQuestions: allDoneQuestions,
percentageComplete: Number(((allDoneQuestions / allTotalQuestions) * 100).toFixed(2))
}
}
return res.status(200).json(response)
} catch (error) {
console.log(error);
return res.status(500).json({ message: "Internal server error" });
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Validate numeric calculations for percentageComplete.
If there are zero total sub-controls or questions, the code divides by zero on lines 406 and 412. Consider adding a safety check to avoid NaN or Infinity values.

- percentageComplete: Number(((allDoneSubControls / allTotalSubControls) * 100).toFixed(2))
+ percentageComplete: allTotalSubControls !== 0 
+   ? Number(((allDoneSubControls / allTotalSubControls) * 100).toFixed(2))
+   : 0
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async function calculateProgress(
req: Request,
res: Response
): Promise<Response> {
try {
const id = parseInt(req.params.id)
const userProjects = await getUserProjects(id)
let questionsMetadata = []
let allTotalQuestions = 0
let allDoneQuestions = 0
let controlsMetadata = []
let allTotalSubControls = 0
let allDoneSubControls = 0
for (const userProject of userProjects) {
let totalSubControls = 0
let doneSubControls = 0
const controlcategories = await getControlCategoriesForProject(userProject.id)
for (const controlcategory of controlcategories) {
const controls = await getControlForControlCategory(controlcategory.id)
for (const control of controls) {
const subControls = await getSubControlForControl(control.id)
for (const subControl of subControls) {
totalSubControls++;
if (subControl.status === "Done") {
doneSubControls++;
}
}
}
}
allTotalSubControls += totalSubControls
allDoneSubControls += doneSubControls
controlsMetadata.push({ projectId: userProject.id, totalSubControls, doneSubControls })
let totalQuestions = 0
let doneQuestions = 0
const assessments = await getAssessmentsForProject(userProject.id)
for (const assessment of assessments) {
const topics = await getTopicsForAssessment(assessment.id)
for (const topic of topics) {
const subTopics = await getSubTopicsForTopic(topic.id)
for (const subTopic of subTopics) {
const questions = await getQuestionsForSubTopic(subTopic.id)
for (const question of questions) {
totalQuestions++;
if (question.answer) {
doneQuestions++
}
}
}
}
}
allTotalQuestions += totalQuestions
allDoneQuestions += doneQuestions
questionsMetadata.push({ projectId: userProject.id, totalQuestions, doneQuestions })
}
const response = {
controls: {
projects: controlsMetadata,
totalSubControls: allTotalSubControls,
doneSubControls: allDoneSubControls,
percentageComplete: Number(((allDoneSubControls / allTotalSubControls) * 100).toFixed(2))
},
questions: {
projects: questionsMetadata,
totalQuestions: allTotalQuestions,
doneQuestions: allDoneQuestions,
percentageComplete: Number(((allDoneQuestions / allTotalQuestions) * 100).toFixed(2))
}
}
return res.status(200).json(response)
} catch (error) {
console.log(error);
return res.status(500).json({ message: "Internal server error" });
}
}
async function calculateProgress(
req: Request,
res: Response
): Promise<Response> {
try {
const id = parseInt(req.params.id)
const userProjects = await getUserProjects(id)
let questionsMetadata = []
let allTotalQuestions = 0
let allDoneQuestions = 0
let controlsMetadata = []
let allTotalSubControls = 0
let allDoneSubControls = 0
for (const userProject of userProjects) {
let totalSubControls = 0
let doneSubControls = 0
const controlcategories = await getControlCategoriesForProject(userProject.id)
for (const controlcategory of controlcategories) {
const controls = await getControlForControlCategory(controlcategory.id)
for (const control of controls) {
const subControls = await getSubControlForControl(control.id)
for (const subControl of subControls) {
totalSubControls++;
if (subControl.status === "Done") {
doneSubControls++;
}
}
}
}
allTotalSubControls += totalSubControls
allDoneSubControls += doneSubControls
controlsMetadata.push({ projectId: userProject.id, totalSubControls, doneSubControls })
let totalQuestions = 0
let doneQuestions = 0
const assessments = await getAssessmentsForProject(userProject.id)
for (const assessment of assessments) {
const topics = await getTopicsForAssessment(assessment.id)
for (const topic of topics) {
const subTopics = await getSubTopicsForTopic(topic.id)
for (const subTopic of subTopics) {
const questions = await getQuestionsForSubTopic(subTopic.id)
for (const question of questions) {
totalQuestions++;
if (question.answer) {
doneQuestions++
}
}
}
}
}
allTotalQuestions += totalQuestions
allDoneQuestions += doneQuestions
questionsMetadata.push({ projectId: userProject.id, totalQuestions, doneQuestions })
}
const response = {
controls: {
projects: controlsMetadata,
totalSubControls: allTotalSubControls,
doneSubControls: allDoneSubControls,
percentageComplete: allTotalSubControls !== 0
? Number(((allDoneSubControls / allTotalSubControls) * 100).toFixed(2))
: 0
},
questions: {
projects: questionsMetadata,
totalQuestions: allTotalQuestions,
doneQuestions: allDoneQuestions,
percentageComplete: Number(((allDoneQuestions / allTotalQuestions) * 100).toFixed(2))
}
}
return res.status(200).json(response)
} catch (error) {
console.log(error);
return res.status(500).json({ message: "Internal server error" });
}
}

Comment on lines +7 to +13
getAssessmentsForProject,
getControlCategoriesForProject,
getControlForControlCategory,
getQuestionsForSubTopic,
getSubControlForControl,
getSubTopicsForTopic,
getTopicsForAssessment,
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Missing test coverage for critical utility functions

The utility functions imported from Servers/utils/user.utils.ts lack test coverage. These functions are used in critical progress calculation logic but:

  • No test files (*.test.ts, *.spec.ts) were found in the Servers directory
  • The functions are only referenced in their implementation file and the controller

Action items:

  • Add unit tests for all utility functions in Servers/utils/user.utils.ts, particularly:
    • getControlCategoriesForProject
    • getAssessmentsForProject
    • getControlForControlCategory
    • getQuestionsForSubTopic
    • getSubControlForControl
    • getSubTopicsForTopic
    • getTopicsForAssessment
🔗 Analysis chain

Ensure all newly added utility functions are tested and consistently reused.
You have introduced several function imports at lines 7-13 and 16 (e.g. getControlCategoriesForProject, getUserProjects, etc.). Verify these are tested thoroughly, as they appear critical to the progress calculation in the new controller method.

Also applies to: 16-16


Let me gather more information about the test coverage for these utility functions.


Let me check for test files specifically in the Servers directory since we found the utility functions in Servers/utils/user.utils.ts.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Automated check to find references to these utility functions in the codebase (other than these lines).
# This helps ensure they are indeed used consistently and tested in related unit tests or integration tests.

ast-grep --pattern $'getControlCategoriesForProject($_)' 
ast-grep --pattern $'getUserProjects($_)' 
# Repeat for the other added utility functions...

Length of output: 310


Script:

#!/bin/bash
# Search for test files that might contain these utility functions
rg -l "getControlCategoriesForProject|getAssessmentsForProject|getControlForControlCategory|getQuestionsForSubTopic|getSubControlForControl|getSubTopicsForTopic|getTopicsForAssessment" --type=test

# Look for the actual implementation of these functions to understand their source
fd -e ts -e js | xargs rg "export (const|function) (getControlCategoriesForProject|getAssessmentsForProject|getControlForControlCategory|getQuestionsForSubTopic|getSubControlForControl|getSubTopicsForTopic|getTopicsForAssessment)"

Length of output: 1274


Script:

#!/bin/bash
# Search for test files in the Servers directory
fd -e test.ts -e spec.ts -e test.js -e spec.js . Servers/

# Look for any test files that might reference these utilities
rg -l "user\.utils" Servers/

Length of output: 151

Comment on lines +152 to +153
router.get("/:id/calculate-progress", calculateProgress)

Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Authentication middleware is missing for sensitive user progress data

Looking at the route patterns in user.route.ts, it's clear that several sensitive endpoints are protected with authenticateJWT middleware, including user deletion and email-based retrieval. The newly added progress calculation endpoint lacks this protection, while being user-specific (:id parameter). This could expose sensitive user progress data.

  • Servers/routes/user.route.ts: Add authenticateJWT middleware to the progress calculation route:
router.get("/:id/calculate-progress", authenticateJWT, calculateProgress)
🔗 Analysis chain

Consider authentication for progress route.
Unlike some other GET routes, this added endpoint (line 152) is not behind authenticateJWT. If the progress data is sensitive, you may want to protect it with authentication and/or role checks.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Searching the route usage and verifying if we have an associated test that expects 401 or 403 for unauthenticated requests
rg -A 5 '"\/:id\/calculate-progress"' 

Length of output: 134


Script:

#!/bin/bash
# Search for the route pattern with proper escaping
rg -A 5 "/:id/calculate-progress"

# Check if calculateProgress function has any authentication checks
ast-grep --pattern 'function calculateProgress($_) { $$$ }'

# Look for other routes in the same file to compare authentication patterns
rg "router\.(get|post|put|delete)" "Servers/routes/user.route.ts"

Length of output: 781

@gorkem-bwl
Copy link
Contributor

If "questions" in the response is from assessments page, can you change it to "assessments"? We can only fix this area and the rest (output) can stay the same:

image

@HarshP4585
Copy link
Contributor Author

If "questions" in the response is from assessments page, can you change it to "assessments"? We can only fix this area and the rest (output) can stay the same:

image

@gorkem-bwl Done

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
Servers/controllers/user.ctrl.ts (1)

358-399: Consider refactoring nested loops for better maintainability

The deep nesting of loops (4 levels deep) makes the code harder to maintain and potentially impacts performance. Consider extracting the inner loops into separate async functions.

+async function calculateControlProgress(projectId: number) {
+  let totalSubControls = 0;
+  let doneSubControls = 0;
+  const controlcategories = await getControlCategoriesForProject(projectId);
+  for (const controlcategory of controlcategories) {
+    const controls = await getControlForControlCategory(controlcategory.id);
+    for (const control of controls) {
+      const subControls = await getSubControlForControl(control.id);
+      for (const subControl of subControls) {
+        totalSubControls++;
+        if (subControl.status === "Done") {
+          doneSubControls++;
+        }
+      }
+    }
+  }
+  return { totalSubControls, doneSubControls };
+}

+async function calculateAssessmentProgress(projectId: number) {
+  let totalAssessments = 0;
+  let doneAssessments = 0;
+  const assessments = await getAssessmentsForProject(projectId);
+  for (const assessment of assessments) {
+    const topics = await getTopicsForAssessment(assessment.id);
+    for (const topic of topics) {
+      const subTopics = await getSubTopicsForTopic(topic.id);
+      for (const subTopic of subTopics) {
+        const questions = await getQuestionsForSubTopic(subTopic.id);
+        for (const question of questions) {
+          totalAssessments++;
+          if (question.answer) {
+            doneAssessments++;
+          }
+        }
+      }
+    }
+  }
+  return { totalAssessments, doneAssessments };
+}
Servers/swagger.yaml (1)

3858-3941: Add missing error response codes

The endpoint documentation should include additional error responses to match the implementation:

  • 400 for invalid user ID
  • 404 for when no projects are found
      responses:
        "200":
          description: user
          content:
            application/json:
              type: object
              properties:
                controls:
                  type: object
                  # ... existing properties ...
+       "400":
+         description: invalid request
+         content:
+           application/json:
+             type: object
+             properties:
+               message:
+                 type: string
+                 example: "Invalid user ID"
+       "404":
+         description: no content to display
+         content:
+           application/json:
+             type: object
+             properties:
+               message:
+                 type: string
+                 example: "No projects found for user"
        "500":
          description: internal server error
          # ... existing properties ...
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a195924 and 43f358d.

📒 Files selected for processing (2)
  • Servers/controllers/user.ctrl.ts (3 hunks)
  • Servers/swagger.yaml (1 hunks)
🔇 Additional comments (2)
Servers/controllers/user.ctrl.ts (2)

7-13: Missing test coverage for critical utility functions

The utility functions imported from Servers/utils/user.utils.ts lack test coverage. These functions are used in critical progress calculation logic but:

  • No test files (*.test.ts, *.spec.ts) were found in the Servers directory
  • The functions are only referenced in their implementation file and the controller

Also applies to: 16-16


432-432: LGTM!

The export statement correctly includes the new calculateProgress function.

projects: controlsMetadata,
totalSubControls: allTotalSubControls,
doneSubControls: allDoneSubControls,
percentageComplete: Number(((allDoneSubControls / allTotalSubControls) * 100).toFixed(2))
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add safety check for division by zero

The percentage calculations could throw errors if there are no controls or assessments.

-percentageComplete: Number(((allDoneSubControls / allTotalSubControls) * 100).toFixed(2))
+percentageComplete: allTotalSubControls > 0 ? Number(((allDoneSubControls / allTotalSubControls) * 100).toFixed(2)) : 0

-percentageComplete: Number(((allDoneAssessments / allTotalAssessments) * 100).toFixed(2))
+percentageComplete: allTotalAssessments > 0 ? Number(((allDoneAssessments / allTotalAssessments) * 100).toFixed(2)) : 0

Also applies to: 412-412

Comment on lines +347 to +348
const id = parseInt(req.params.id)
const userProjects = await getUserProjects(id)
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add input validation for user ID

The function should validate that the user ID is positive and exists before proceeding with calculations.

const id = parseInt(req.params.id)
+if (isNaN(id) || id <= 0) {
+  return res.status(400).json({ message: "Invalid user ID" });
+}
const userProjects = await getUserProjects(id)
+if (!userProjects?.length) {
+  return res.status(404).json({ message: "No projects found for user" });
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const id = parseInt(req.params.id)
const userProjects = await getUserProjects(id)
const id = parseInt(req.params.id)
if (isNaN(id) || id <= 0) {
return res.status(400).json({ message: "Invalid user ID" });
}
const userProjects = await getUserProjects(id)
if (!userProjects?.length) {
return res.status(404).json({ message: "No projects found for user" });
}

Comment on lines +416 to +419
} catch (error) {
console.log(error);
return res.status(500).json({ message: "Internal server error" });
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve error handling

The catch block should distinguish between different types of errors and return appropriate status codes.

  } catch (error) {
    console.log(error);
-   return res.status(500).json({ message: "Internal server error" });
+   if (error instanceof TypeError) {
+     return res.status(400).json({ message: "Invalid data structure" });
+   }
+   return res.status(500).json({ 
+     message: "Internal server error",
+     error: error instanceof Error ? error.message : "Unknown error"
+   });
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} catch (error) {
console.log(error);
return res.status(500).json({ message: "Internal server error" });
}
} catch (error) {
console.log(error);
if (error instanceof TypeError) {
return res.status(400).json({ message: "Invalid data structure" });
}
return res.status(500).json({
message: "Internal server error",
error: error instanceof Error ? error.message : "Unknown error"
});
}

@MuhammadKhalilzadeh MuhammadKhalilzadeh merged commit fe48aeb into bluewave-labs:master Dec 23, 2024
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend Backend related tasks/issues
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants