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

038 Nov 5 Add Swagger for Subrequirements #204

Conversation

HarshP4585
Copy link
Contributor

@HarshP4585 HarshP4585 commented Nov 5, 2024

  • Added Swagger YAML for subrequirements
  • Fixed controller for subrequirements

Affected Issue: #155

Summary by CodeRabbit

  • New Features

    • Introduced a new API endpoint for managing subrequirements, allowing users to create, retrieve, update, and delete subrequirements.
    • Required fields for creating and updating subrequirements now include requirement_id, name, description, and status.
  • Bug Fixes

    • Improved error messages for missing fields in subrequirement creation and update requests.
  • Documentation

    • Updated API documentation to reflect new endpoints and required fields for subrequirements.

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

coderabbitai bot commented Nov 5, 2024

Caution

Review failed

The pull request is closed.

Walkthrough

The changes in this pull request involve updates to the createSubrequirement and updateSubrequirementById functions in Servers/controllers/subrequirement.ctrl.ts, introducing new required fields requirement_id and status. Corresponding updates were made to the Swagger API documentation to define new endpoints for managing subrequirements and to include a new schema. Additionally, the utility functions for creating and updating subrequirements were modified to accommodate these new fields in their SQL queries.

Changes

File Change Summary
Servers/controllers/subrequirement.ctrl.ts - Updated createSubrequirement and updateSubrequirementById to require requirement_id and status in the request body.
- Modified error messages for missing fields.
Servers/swagger.yaml - Added new endpoints: GET /subrequirements, POST /subrequirements, GET /subrequirements/{id}, PUT /subrequirements/{id}, DELETE /subrequirements/{id}.
- Introduced SubRequirement schema in components.
Servers/utils/subrequirement.util.ts - Updated createNewSubrequirementQuery to include requirement_id and status in the input parameter type and SQL insert query.
- Modified updateSubrequirementByIdQuery to handle optional requirement_id and status.

Possibly related PRs

  • 034 Nov 5 Add Swagger for Requirement #197: The changes in this PR involve the addition of a new required field, status, in the createRequirement and updateRequirementById functions, similar to the addition of status in the createSubrequirement and updateSubrequirementById functions in the main PR. Both PRs modify function signatures to require additional fields in their respective request bodies.
  • 037 Nov 5 Add Swagger for Section #201: This PR also introduces new required fields in the createSection and updateSectionById functions, which parallels the changes made in the main PR regarding the addition of required fields in the request body.

Suggested reviewers

  • MuhammadKhalilzadeh

Poem

In the burrow deep, where the subrequirements grow,
A new field has sprouted, with a status to show.
With requirement_id now in the mix,
Our queries are richer, a clever little fix.
Hop along, dear friends, let’s celebrate this day,
For our code is now better, hip-hip-hooray! 🐇✨


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 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: 5

🧹 Outside diff range and nitpick comments (3)
Servers/utils/subrequirement.util.ts (1)

24-25: Consider wrapping creation in a transaction.

The query is well-structured, but consider wrapping it in a transaction to ensure referential integrity with the requirements table.

export const createNewSubrequirementQuery = async (subrequirement: {
  requirement_id: number;
  name: string;
  description: string;
  status: string;
}): Promise<Subrequirement> => {
  console.log("createNewSubrequirement", subrequirement);
+  const client = await pool.connect();
+  try {
+    await client.query('BEGIN');
+    // Verify requirement exists
+    const reqCheck = await client.query(
+      'SELECT id FROM requirements WHERE id = $1',
+      [subrequirement.requirement_id]
+    );
+    if (reqCheck.rows.length === 0) {
+      throw new Error('Referenced requirement does not exist');
+    }
+    const result = await client.query(
      "INSERT INTO subrequirements (requirement_id, name, description, status) VALUES ($1, $2, $3, $4) RETURNING *",
      [subrequirement.requirement_id, subrequirement.name, subrequirement.description, subrequirement.status]
    );
+    await client.query('COMMIT');
    return result.rows[0];
+  } catch (e) {
+    await client.query('ROLLBACK');
+    throw e;
+  } finally {
+    client.release();
+  }
};
Servers/controllers/subrequirement.ctrl.ts (2)

79-89: Consider adding field validations.

While the presence check is good, consider adding:

  1. Type validations (requirement_id should be a number)
  2. Status value validation (should be from a predefined set)
  3. Existence check for the referenced requirement_id

Example validation:

+ const validStatuses = ['PENDING', 'IN_PROGRESS', 'COMPLETED'];  // Add your actual status values
  if (
    !requirement_id ||
    !name ||
    !description ||
    !status
  ) {
    return res
      .status(400)
      .json(
        STATUS_CODE[400]({ message: "requirement_id, name, description and status are required" })
      );
  }
+ if (typeof requirement_id !== 'number') {
+   return res.status(400).json(STATUS_CODE[400]({ message: "requirement_id must be a number" }));
+ }
+ if (!validStatuses.includes(status)) {
+   return res.status(400).json(STATUS_CODE[400]({ message: `status must be one of: ${validStatuses.join(', ')}` }));
+ }

Line range hint 127-127: Remove debug console.log statement.

Debug logging should be removed before merging.

- console.log("updateSubrequirementById");
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 3ed888a and 01c36ff.

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

32-37: 🛠️ Refactor suggestion

Ensure consistent validation with create operation.

The optional fields are well-defined, but ensure that the same validation rules from the create operation (once implemented) are applied here for status and requirement_id.

#!/bin/bash
# Check if update endpoint in controller has validation
ast-grep --pattern 'async function updateSubrequirementById($$$) {
  $$$
  // Look for validation logic
  if ($$$status$$$) {
    $$$
  }
  $$$
}'
Servers/controllers/subrequirement.ctrl.ts (1)

Line range hint 131-169: Consider applying the same field validations as suggested for create.

The validation suggestions from the create function should also be applied here for consistency.

Comment on lines +44 to +65
if(subrequirement.requirement_id) {
fields.push("requirement_id = $1")
values.push(subrequirement.requirement_id)
}
if(subrequirement.name) {
fields.push("name = $2")
values.push(subrequirement.name)
}
if(subrequirement.description) {
fields.push("description = $3")
values.push(subrequirement.description)
}
if (subrequirement.description) {
fields.push("description = $2");
values.push(subrequirement.description);
if(subrequirement.status) {
fields.push("status = $4")
values.push(subrequirement.status)
}

if (fields.length === 0) {
throw new Error("No fields to update");
}

query += fields.join(", ") + " WHERE id = $3 RETURNING *";
query += fields.join(", ") + " WHERE id = $5 RETURNING *";
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 query parameter handling robustness.

The current implementation has several potential issues:

  1. Hardcoded parameter indices ($1, $2, etc.) are brittle and error-prone
  2. No validation that values array matches the number of parameters
  3. Query construction could be more maintainable

Consider this more robust approach:

export const updateSubrequirementByIdQuery = async (
  id: number,
  subrequirement: {
    requirement_id?: number;
    name?: string;
    description?: string;
    status?: string;
  }
): Promise<Subrequirement | null> => {
  console.log("updateSubrequirementById", id, subrequirement);
  
  const updates: { field: string; value: any }[] = [];
  if (subrequirement.requirement_id !== undefined) {
    updates.push({ field: 'requirement_id', value: subrequirement.requirement_id });
  }
  if (subrequirement.name !== undefined) {
    updates.push({ field: 'name', value: subrequirement.name });
  }
  if (subrequirement.description !== undefined) {
    updates.push({ field: 'description', value: subrequirement.description });
  }
  if (subrequirement.status !== undefined) {
    updates.push({ field: 'status', value: subrequirement.status });
  }

  if (updates.length === 0) {
    throw new Error("No fields to update");
  }

  const setClause = updates
    .map((update, index) => `${update.field} = $${index + 1}`)
    .join(', ');
  const values = updates.map(update => update.value);
  values.push(id);

  const query = `UPDATE subrequirements SET ${setClause} WHERE id = $${values.length} RETURNING *`;
  
  const result = await pool.query(query, values);
  return result.rows.length ? result.rows[0] : null;
};

Comment on lines +17 to +20
requirement_id: number;
name: string;
description: string;
status: string;
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

🛠️ Refactor suggestion

Add type safety for subrequirement status values

The verification reveals:

  1. The database schema uses varchar(50) for status without constraints
  2. The controller validates presence but not values of status
  3. No enum/type exists for subrequirement status, unlike other entities (e.g., MitigationStatus)

Recommendations:

  • Add a SubrequirementStatus enum in a shared location
  • Add value validation in the controller
  • Consider adding a CHECK constraint in the database
🔗 Analysis chain

Consider adding input validation and type safety.

While adding requirement_id and status fields is good, consider:

  1. Adding an enum for valid status values
  2. Validating that the referenced requirement exists before insertion

Consider adding this type definition:

export enum SubrequirementStatus {
  PENDING = 'PENDING',
  IN_PROGRESS = 'IN_PROGRESS',
  COMPLETED = 'COMPLETED'
}
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if there's a status enum or type definition
rg -t typescript "type.*Status|enum.*Status" 

# Check if requirement validation exists in the controller
ast-grep --pattern 'async function createSubrequirement($$$) {
  $$$
  // Look for requirement validation
  const requirement = $$$
  $$$
}'

Length of output: 307


Script:

#!/bin/bash
# Let's try a different approach to find status-related types/enums
rg -t typescript "status.*=.*['\"](PENDING|IN_PROGRESS|COMPLETED)" -B2 -A2

# Check for requirement validation in controller or service layer
rg -t typescript "createSubrequirement.*\{" -A 10

# Look for any status validation
rg -t typescript "status.*validation|validateStatus|checkStatus" -B2 -A2

# Check database schema or type definitions for status constraints
fd -e sql -e prisma -e ts "schema|type|interface" --exec cat {}

Length of output: 378


Script:

#!/bin/bash
# Search without file type restriction since typescript extension isn't recognized
rg "status.*=.*['\"](PENDING|IN_PROGRESS|COMPLETED)" -B2 -A2

# Look for requirement validation in any relevant files
rg "createSubrequirement.*\{" -A 10

# Check for any status-related types or enums
rg "enum.*Status|type.*Status|interface.*Status" -B1 -A3

# Look for schema definitions
rg "CREATE TABLE.*subrequirement|CREATE TYPE.*status" -i

Length of output: 4864


Script:

#!/bin/bash
# Let's check the subrequirements table definition
rg -A 10 "CREATE TABLE subrequirements\(" 

# Let's also check if there's any validation in the controller
rg -A 15 "!requirement_id \|\|" Servers/controllers/subrequirement.ctrl.ts

# Check for any existing status constants or validation
rg "const.*status.*=.*\[" -A 5

Length of output: 2296

Comment on lines +72 to +111
const {
requirement_id,
name,
description,
status
} = req.body;

if (
!requirement_id ||
!name ||
!description ||
!status
) {
return res
.status(400)
.json(
STATUS_CODE[400]({ message: "name and description are required" })
STATUS_CODE[400]({ message: "requirement_id, name, description and status are required" })
);
}

if (MOCK_DATA_ON === "true") {
const newSubrequirement = createMockSubrequirement({ name, description });
const newSubrequirement = createMockSubrequirement({
requirement_id,
name,
description,
status
});

if (newSubrequirement) {
return res.status(201).json(STATUS_CODE[201](newSubrequirement));
}

return res.status(503).json(STATUS_CODE[503]({}));
} else {
const newSubrequirement = await createNewSubrequirementQuery({ name, description });
const newSubrequirement = await createNewSubrequirementQuery({
requirement_id,
name,
description,
status
});
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

Add requirement_id validation to prevent orphaned subrequirements

The code review reveals that while the requirement_id is properly added as a required field, there's no validation to ensure it references an existing requirement. This could lead to orphaned subrequirements in the database.

  • Add a check in createSubrequirement to verify the requirement exists before creating the subrequirement
  • Consider adding a foreign key constraint in the database schema
  • Add validation for the status field to ensure it only accepts valid values

Example validation to add before creating the subrequirement:

const requirement = await getRequirementByIdQuery(requirement_id);
if (!requirement) {
  return res.status(404).json(
    STATUS_CODE[404]({ message: "Requirement not found" })
  );
}
🔗 Analysis chain

LGTM! The implementation looks clean and consistent.

The changes properly handle the new required fields and maintain consistency between mock and real database implementations.

Let's verify the requirement_id references:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if requirement_id is properly validated against existing requirements

# Test: Search for requirement validation logic
rg -A 5 "requirement_id.*exist|validate.*requirement"

Length of output: 55


Script:

#!/bin/bash
# Let's try a broader search to understand requirement validation
# First, check for any requirement-related queries or validations
rg -l "requirement" --type ts

# Then look for database queries related to requirements
ast-grep --pattern 'async function $name($_) {
  $$$
  requirement
  $$$
}'

Length of output: 1578


Script:

#!/bin/bash
# Let's check the requirement model and validation logic
cat Servers/models/Subrequirement.ts

# Also check the database query implementation
cat Servers/utils/subrequirement.util.ts

# And the requirement controller for any validation patterns
cat Servers/controllers/requirement.ctrl.ts

Length of output: 7755

Comment on lines +1680 to +1940
content:
application/json:
schema:
type: object
properties:
requirement_id:
type: integer
example: 1
name:
type: string
example: "Privacy Policy Update"
description:
type: string
example: "Ensure the privacy policy reflects changes regarding user consent."
status:
type: string
example: "Completed"
required: true
responses:
"202":
description: subrequirement
content:
application/json:
schema:
type: object
properties:
message:
type: string
example: accepted
data:
$ref: "#components/schemas/SubRequirement"
"404":
description: no content to display
content:
application/json:
type: object
properties:
message:
type: string
example: not found
data:
type: object
"500":
description: internal server error
content:
application/json:
type: object
properties:
message:
type: string
example: internal server error
error:
type: object
delete:
tags: [subrequirements]
security:
- JWTAuth: []
parameters:
- in: path
name: id
schema:
type: integer
required: true
description: id of the subrequirement to delete
responses:
"202":
description: subrequirement
content:
application/json:
schema:
type: object
properties:
message:
type: string
example: accepted
data:
type: boolean
example: true
"404":
description: no content to display
content:
application/json:
type: object
properties:
message:
type: string
example: not found
data:
type: object
"500":
description: internal server error
content:
application/json:
type: object
properties:
message:
type: string
example: internal server error
error:
type: object
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance the subrequirements API endpoints with additional specifications.

While the basic CRUD operations are well-defined, consider the following improvements:

  /subrequirements:
    get:
      tags: [subrequirements]
      security:
        - JWTAuth: []
+     parameters:
+       - in: query
+         name: status
+         schema:
+           type: string
+           enum: ["Pending", "In Progress", "Completed", "Failed"]
+         required: false
+         description: Filter subrequirements by status
+       - in: query
+         name: requirement_id
+         schema:
+           type: integer
+         required: false
+         description: Filter subrequirements by requirement ID
+       - in: query
+         name: page
+         schema:
+           type: integer
+           minimum: 1
+           default: 1
+         required: false
+         description: Page number for pagination
+       - in: query
+         name: limit
+         schema:
+           type: integer
+           minimum: 1
+           maximum: 100
+           default: 20
+         required: false
+         description: Number of items per page
      responses:
        "200":
          content:
            application/json:
              schema:
                properties:
                  data:
+                   type: object
+                   properties:
+                     items:
+                       type: array
+                       items:
+                         $ref: "#components/schemas/SubRequirement"
+                     total:
+                       type: integer
+                       description: Total number of items
+                     page:
+                       type: integer
+                       description: Current page number
+                     totalPages:
+                       type: integer
+                       description: Total number of pages
    post:
      requestBody:
        content:
          application/json:
            schema:
              properties:
                requirement_id:
                  type: integer
+                 description: ID of the parent requirement
+                 minimum: 1
+               required: ["requirement_id", "name", "status"]

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +2106 to +2123
SubRequirement:
type: object
properties:
id:
type: integer
example: 1
requirement_id:
type: integer
example: 1
name:
type: string
example: "Privacy Policy Update"
description:
type: string
example: "Ensure the privacy policy reflects changes regarding user consent."
status:
type: string
example: "Completed"
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance the SubRequirement schema with additional constraints and timestamps.

The schema needs more specific constraints and additional fields for proper data validation and tracking.

 SubRequirement:
   type: object
   properties:
     id:
       type: integer
       example: 1
+      readOnly: true
     requirement_id:
       type: integer
       example: 1
+      minimum: 1
     name:
       type: string
       example: "Privacy Policy Update"
+      minLength: 1
+      maxLength: 255
     description:
       type: string
       example: "Ensure the privacy policy reflects changes regarding user consent."
+      maxLength: 1000
     status:
       type: string
       example: "Completed"
+      enum: ["Pending", "In Progress", "Completed", "Failed"]
+    created_at:
+      type: string
+      format: date-time
+      example: "2024-01-01T00:00:00Z"
+      readOnly: true
+    updated_at:
+      type: string
+      format: date-time
+      example: "2024-01-01T00:00:00Z"
+      readOnly: true
+   required:
+     - requirement_id
+     - name
+     - status
📝 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
SubRequirement:
type: object
properties:
id:
type: integer
example: 1
requirement_id:
type: integer
example: 1
name:
type: string
example: "Privacy Policy Update"
description:
type: string
example: "Ensure the privacy policy reflects changes regarding user consent."
status:
type: string
example: "Completed"
SubRequirement:
type: object
properties:
id:
type: integer
example: 1
readOnly: true
requirement_id:
type: integer
example: 1
minimum: 1
name:
type: string
example: "Privacy Policy Update"
minLength: 1
maxLength: 255
description:
type: string
example: "Ensure the privacy policy reflects changes regarding user consent."
maxLength: 1000
status:
type: string
example: "Completed"
enum: ["Pending", "In Progress", "Completed", "Failed"]
created_at:
type: string
format: date-time
example: "2024-01-01T00:00:00Z"
readOnly: true
updated_at:
type: string
format: date-time
example: "2024-01-01T00:00:00Z"
readOnly: true
required:
- requirement_id
- name
- status

@MuhammadKhalilzadeh
Copy link
Collaborator

🔃

Copy link
Collaborator

@MuhammadKhalilzadeh MuhammadKhalilzadeh left a comment

Choose a reason for hiding this comment

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

❌❌

@MuhammadKhalilzadeh
Copy link
Collaborator

⛔️❌️

@MuhammadKhalilzadeh MuhammadKhalilzadeh merged commit 151b9d3 into bluewave-labs:master Nov 7, 2024
1 check was pending
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.

2 participants