Skip to content

fix: enhance Note schema validation for better data integrity#17

Open
jikrana1 wants to merge 5 commits into
niharika-mente:mainfrom
jikrana1:fix/enhance-note-schema-validation
Open

fix: enhance Note schema validation for better data integrity#17
jikrana1 wants to merge 5 commits into
niharika-mente:mainfrom
jikrana1:fix/enhance-note-schema-validation

Conversation

@jikrana1

@jikrana1 jikrana1 commented Jun 2, 2026

Copy link
Copy Markdown

Description

The current Note schema only uses basic required validation for the title and content fields. While this works, additional schema-level validation can help improve data integrity and ensure more consistent data storage.

Current Schema

  • Uses required: true for title
  • Uses required: true for content

Proposed Improvements

  • Add custom validation messages for required fields
  • Add trim: true to automatically remove leading and trailing whitespace
  • Add reasonable length constraints for fields using maxlength
  • Improve overall schema validation and data consistency

Benefits

  • Better user feedback through meaningful validation messages
  • Prevents storing unnecessary whitespace
  • Avoids excessively large field values
  • Improves data quality and maintainability

Expected Outcome

The Note schema should provide stronger validation rules while maintaining compatibility with the existing API and application behavior.

Summary by CodeRabbit

  • Bug Fixes
    • Improved validation for note titles and content, enforcing required fields and maximum lengths for consistent formatting and data integrity.
    • Enhanced note updates to trim string inputs and ensure validation runs during update operations.
    • Return more accurate responses for invalid input by sending HTTP 400 with clear validation error details instead of generic server errors.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR strengthens the Note Mongoose schema validation to improve data integrity and provide clearer validation feedback when creating/updating notes.

Changes:

  • Added custom required validation messages for title and content
  • Enabled trim: true on string fields to reduce stored whitespace
  • Added maxlength constraints to bound title and content size

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 23 to 25
);

const Note = mongoose.model("Note", noteSchema);
@SparshM8

SparshM8 commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator

Hey @jikrana1, welcome to the project and thank you for your first contribution! Adding schema-level validation like this is a massive win for our data integrity.

Before we merge this, there is one classic Mongoose quirk we need to account for. Mongoose runs these validations automatically when creating a new document, but it actually bypasses them on update operations (like findByIdAndUpdate) by default.

To ensure these new rules apply when a user updates an existing note, we need to enforce them. Could you implement one of the following fixes?

Option 1: Accept the Copilot suggestion above, which adds a pre hook to the schema to catch updates.
Option 2: Head over to the updateNote function in backend/src/controllers/notesController.js and add runValidators: true to the options object of the findByIdAndUpdate call. (e.g., { new: true, runValidators: true }).

Let me know which approach you prefer or if you have any questions! Great work on this so far.

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown

Review Change Stack

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b01dcaf0-94e8-4e70-8dff-5463eedda3db

📥 Commits

Reviewing files that changed from the base of the PR and between 9531882 and 54c199e.

📒 Files selected for processing (2)
  • backend/src/controllers/notesController.js
  • backend/src/models/Note.js

📝 Walkthrough

Walkthrough

The Note schema is enhanced with field-level validation rules including string trimming, required constraints with custom error messages, and maximum length limits for title and content. A pre-update hook normalizes incoming updates and forces Mongoose validation. The controllers now distinguish Mongoose validation errors from other failures, returning HTTP 400 for validation issues and HTTP 500 for unexpected errors.

Changes

Note Validation Flow

Layer / File(s) Summary
Schema validation constraints and pre-update hook
backend/src/models/Note.js
The title and content fields gain trim, required constraints with custom error messages, and maxlength limits. A pre("findOneAndUpdate") hook trims values in incoming updates and enables Mongoose validators during update operations.
Validation error responses
backend/src/controllers/notesController.js
The createNote and updateNote controllers catch mongoose.Error.ValidationError separately, returning HTTP 400 with an errors array derived from schema validation failures, while other errors return HTTP 500.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related issues

Possibly related PRs

  • niharika-mente/ThinkBoard#12: Both PRs enforce title/content normalization and validation on note updates, with this PR implementing schema-level trimming and validators while the other applies controller-side trimming and runValidators: true on update operations.

Suggested labels

SSoC26

Poem

🐰 A schema stands firm with rules so bright,
Trim the strings, keep content tight,
Controllers catch what slips through,
Validation flows from schema true! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main change: enhancing Note schema validation for data integrity, which aligns with the core objective of strengthening field validation with trimming, custom messages, and constraints.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Biome (2.5.0)
backend/src/models/Note.js

File contains syntax errors that prevent linting: Line 18: expected , but instead found :; Line 19: expected , but instead found type; Line 19: expected , but instead found :; Line 20: expected , but instead found default; Line 24: Expected an expression but instead found 'default'.; Line 25: Expected a statement but instead found ',
parentId:'.; Line 28: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 30: Expected a statement but instead found ',
position:'.; Line 33: Expected an expression but instead found 'default'.; Line 35: Expected a statement but instead found ')'.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/src/models/Note.js`:
- Around line 7-15: Controller error handling currently converts all errors into
HTTP 500, masking Mongoose validation messages; update the controller methods
that call Note.save()/Note.create()/Note.findByIdAndUpdate (e.g., createNote,
updateNote) to detect Mongoose ValidationError (err.name === "ValidationError"),
map err.errors to a simple field->message object, and respond with
res.status(400).json({ errors: mappedErrors }) instead of a 500; otherwise keep
existing 500 behavior for unexpected errors.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 580bcbff-993c-4315-a5f6-e5d829652529

📥 Commits

Reviewing files that changed from the base of the PR and between 819b2ac and 9531882.

📒 Files selected for processing (1)
  • backend/src/models/Note.js

Comment thread backend/src/models/Note.js
@jikrana1

jikrana1 commented Jun 8, 2026

Copy link
Copy Markdown
Author

Hey @SpanishMB,
I've implemented Option 1 by adding a pre('findOneAndUpdate') hook to the schema.
This ensures runValidators runs on all update operations automatically.

Please review!

Thank you !

@SparshM8

Copy link
Copy Markdown
Collaborator

Hey @jikrana1, thanks for putting this together! The schema validation and the findOneAndUpdate hook look great and are exactly what we need for data integrity.

However, before we can merge this in, we need to handle how these new validation errors are caught by the server. Right now, if a validation fails, Mongoose will throw an error that gets caught by our generic catch blocks in backend/src/controllers/notesController.js, resulting in a 500 Internal Server Error.

Could you please update the controller methods (like createNote and updateNote) to specifically catch Mongoose ValidationErrors and return them as a 400 Bad Request?

Something like this inside the catch blocks:

JavaScript
if (error instanceof mongoose.Error.ValidationError) { return res.status(400).json({ message: "Validation failed", errors: Object.values(error.errors).map((e) => e.message), }); }
Once that controller error handling is added, this will be good to go! Let me know when you've pushed the update.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
backend/src/models/Note.js (1)

3-35: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

createdAt sort contract is broken after removing schema timestamps.

getAllNotes sorts on createdAt (in backend/src/controllers/notesController.js, Line 6), but this schema no longer enables timestamps. That makes sort behavior unreliable/ineffective for note recency.

Suggested fix
-const noteSchema = new mongoose.Schema(
-  { ... }
-);
+const noteSchema = new mongoose.Schema(
+  { ... },
+  { timestamps: true }
+);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/models/Note.js` around lines 3 - 35, The noteSchema definition in
the Note.js file is missing timestamp configuration which is required for the
`getAllNotes` controller to properly sort notes by `createdAt`. Fix the
mongoose.Schema constructor call for `noteSchema` by adding a second parameter
(options object) that includes `{ timestamps: true }`. This will automatically
create and maintain the `createdAt` and `updatedAt` fields on all note
documents, ensuring the sort behavior in `getAllNotes` works reliably.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/src/controllers/notesController.js`:
- Line 22: Remove the `process.env.MONGO_URI &&` condition from the ObjectId
validation check in all three handlers: getNoteById, updateNote, and deleteNote.
The validation should be unconditional so that invalid IDs are properly caught
and return a 400 error regardless of whether MONGO_URI is set. Change each
condition from `if (process.env.MONGO_URI &&
!mongoose.Types.ObjectId.isValid(id))` to simply `if
(!mongoose.Types.ObjectId.isValid(id))` to ensure ID format validation happens
consistently.

In `@backend/src/models/Note.js`:
- Around line 18-34: The schema field definitions for content, isGroup,
parentId, and position are currently outside the object parameter passed to the
mongoose.Schema constructor, causing a JavaScript parse error. Locate the
opening brace of the object passed to `new mongoose.Schema({` and ensure all
field definitions including these four fields are properly nested within that
object, then verify the closing brace of the object and parenthesis of the
constructor call are correctly placed at the end of all field definitions.

---

Outside diff comments:
In `@backend/src/models/Note.js`:
- Around line 3-35: The noteSchema definition in the Note.js file is missing
timestamp configuration which is required for the `getAllNotes` controller to
properly sort notes by `createdAt`. Fix the mongoose.Schema constructor call for
`noteSchema` by adding a second parameter (options object) that includes `{
timestamps: true }`. This will automatically create and maintain the `createdAt`
and `updatedAt` fields on all note documents, ensuring the sort behavior in
`getAllNotes` works reliably.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b01dcaf0-94e8-4e70-8dff-5463eedda3db

📥 Commits

Reviewing files that changed from the base of the PR and between 9531882 and 54c199e.

📒 Files selected for processing (2)
  • backend/src/controllers/notesController.js
  • backend/src/models/Note.js

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
backend/src/models/Note.js (1)

3-35: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

createdAt sort contract is broken after removing schema timestamps.

getAllNotes sorts on createdAt (in backend/src/controllers/notesController.js, Line 6), but this schema no longer enables timestamps. That makes sort behavior unreliable/ineffective for note recency.

Suggested fix
-const noteSchema = new mongoose.Schema(
-  { ... }
-);
+const noteSchema = new mongoose.Schema(
+  { ... },
+  { timestamps: true }
+);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/models/Note.js` around lines 3 - 35, The noteSchema definition in
the Note.js file is missing timestamp configuration which is required for the
`getAllNotes` controller to properly sort notes by `createdAt`. Fix the
mongoose.Schema constructor call for `noteSchema` by adding a second parameter
(options object) that includes `{ timestamps: true }`. This will automatically
create and maintain the `createdAt` and `updatedAt` fields on all note
documents, ensuring the sort behavior in `getAllNotes` works reliably.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/src/controllers/notesController.js`:
- Line 22: Remove the `process.env.MONGO_URI &&` condition from the ObjectId
validation check in all three handlers: getNoteById, updateNote, and deleteNote.
The validation should be unconditional so that invalid IDs are properly caught
and return a 400 error regardless of whether MONGO_URI is set. Change each
condition from `if (process.env.MONGO_URI &&
!mongoose.Types.ObjectId.isValid(id))` to simply `if
(!mongoose.Types.ObjectId.isValid(id))` to ensure ID format validation happens
consistently.

In `@backend/src/models/Note.js`:
- Around line 18-34: The schema field definitions for content, isGroup,
parentId, and position are currently outside the object parameter passed to the
mongoose.Schema constructor, causing a JavaScript parse error. Locate the
opening brace of the object passed to `new mongoose.Schema({` and ensure all
field definitions including these four fields are properly nested within that
object, then verify the closing brace of the object and parenthesis of the
constructor call are correctly placed at the end of all field definitions.

---

Outside diff comments:
In `@backend/src/models/Note.js`:
- Around line 3-35: The noteSchema definition in the Note.js file is missing
timestamp configuration which is required for the `getAllNotes` controller to
properly sort notes by `createdAt`. Fix the mongoose.Schema constructor call for
`noteSchema` by adding a second parameter (options object) that includes `{
timestamps: true }`. This will automatically create and maintain the `createdAt`
and `updatedAt` fields on all note documents, ensuring the sort behavior in
`getAllNotes` works reliably.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b01dcaf0-94e8-4e70-8dff-5463eedda3db

📥 Commits

Reviewing files that changed from the base of the PR and between 9531882 and 54c199e.

📒 Files selected for processing (2)
  • backend/src/controllers/notesController.js
  • backend/src/models/Note.js
🛑 Comments failed to post (2)
backend/src/controllers/notesController.js (1)

22-22: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

ObjectId validation should not depend on process.env.MONGO_URI.

The current guard can skip ID validation and let invalid IDs fall through to cast errors (500 path) when MONGO_URI is unset/misconfigured. ID format validation should be unconditional.

Suggested fix
-if (process.env.MONGO_URI && !mongoose.Types.ObjectId.isValid(id)) {
+if (!mongoose.Types.ObjectId.isValid(id)) {
   return res.status(400).json({
     message: "Invalid note id",
   });
}

Apply this in all three handlers (getNoteById, updateNote, deleteNote).

Also applies to: 89-89, 144-144

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/controllers/notesController.js` at line 22, Remove the
`process.env.MONGO_URI &&` condition from the ObjectId validation check in all
three handlers: getNoteById, updateNote, and deleteNote. The validation should
be unconditional so that invalid IDs are properly caught and return a 400 error
regardless of whether MONGO_URI is set. Change each condition from `if
(process.env.MONGO_URI && !mongoose.Types.ObjectId.isValid(id))` to simply `if
(!mongoose.Types.ObjectId.isValid(id))` to ensure ID format validation happens
consistently.
backend/src/models/Note.js (1)

18-34: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Schema definition is currently unparsable (server boot blocker).

The block starting at Line 18 is outside the schema object passed to new mongoose.Schema(...), which causes a JS parse failure. This prevents the model from loading at all.

Suggested fix
 const noteSchema = new mongoose.Schema(
     {
         title: {
             type: String,
             required: [true, "Title is required"],
             trim: true,
             maxlength: [100, "Title cannot exceed 100 characters"],
         },
         content: {
             type: String,
             required: [true, "Content is required"],
             trim: true,
             maxlength: [5000, "Content cannot exceed 5000 characters"],
+            default: "",
         },
+        isGroup: {
+            type: Boolean,
+            default: false,
+        },
+        parentId: {
+            type: mongoose.Schema.Types.ObjectId,
+            ref: "Note",
+            default: null,
+        },
+        position: {
+            type: Number,
+            default: 0,
+        },
-    },
-    content: {
-        type: String,
-        default: ""
-    },
-    isGroup: {
-        type: Boolean,
-        default: false
-    },
-    parentId: {
-        type: mongoose.Schema.Types.ObjectId,
-        ref: "Note",
-        default: null
-    },
-    position: {
-        type: Number,
-        default: 0
     }
 );
🧰 Tools
🪛 Biome (2.5.0)

[error] 18-18: expected , but instead found :

(parse)


[error] 19-19: expected , but instead found type

(parse)


[error] 19-19: expected , but instead found :

(parse)


[error] 20-20: expected , but instead found default

(parse)


[error] 24-24: Expected an expression but instead found 'default'.

(parse)


[error] 25-26: Expected a statement but instead found ',
parentId:'.

(parse)


[error] 28-28: Expected a semicolon or an implicit semicolon after a statement, but found none

(parse)


[error] 30-31: Expected a statement but instead found ',
position:'.

(parse)


[error] 33-33: Expected an expression but instead found 'default'.

(parse)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/models/Note.js` around lines 18 - 34, The schema field
definitions for content, isGroup, parentId, and position are currently outside
the object parameter passed to the mongoose.Schema constructor, causing a
JavaScript parse error. Locate the opening brace of the object passed to `new
mongoose.Schema({` and ensure all field definitions including these four fields
are properly nested within that object, then verify the closing brace of the
object and parenthesis of the constructor call are correctly placed at the end
of all field definitions.

Source: Linters/SAST tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants