Aller au contenu principal

Database Models

Overview​

The Notes App uses MongoDB as its database with Mongoose as the Object Document Mapper (ODM). Mongoose provides a schema-based solution to model application data, adding structure and validation to the flexible MongoDB documents.

What is Mongoose?​

Mongoose is a JavaScript library that acts as a bridge between Node.js and MongoDB. It provides:

  • Schema definitions - Structure for documents with data types and validation
  • Model creation - JavaScript classes that represent collections in MongoDB
  • Query building - Methods to interact with the database
  • Middleware - Functions that run before or after certain operations

Database Connection​

The application connects to MongoDB using the connection string from config.json:

const mongoose = require("mongoose");
const config = require("./config.json");
const db_url = config.connectionString;
mongoose.connect(db_url);

This establishes a connection to the MongoDB database when the server starts.

User Model​

File: backend/models/user.model.js

The User model represents user accounts in the system.

const userSchema = new Schema({
fullName: {type: String},
email: {type: String},
password: {type: String},
createOn: {type: Date, default: new Date().getTime()},
})

Schema Fields Explained​

  • fullName: Stores the user's display name as a string
  • email: Stores the user's email address for login identification
  • password: Stores the user's password (stored as plain text - security concern)
  • createOn: Timestamp of when the account was created, defaults to current time

Key Characteristics​

  • No validation: The schema doesn't enforce required fields or email format validation
  • Plain text passwords: Passwords are stored without encryption (not recommended for production)
  • Simple structure: Minimal fields for basic user management

Usage in Application​

The User model is used for:

  • Account creation (/create-account endpoint)
  • User authentication (/login endpoint)
  • User information retrieval (/get-user endpoint)

Note Model​

File: backend/models/note.model.js

The Note model represents individual notes created by users.

const noteSchema = new Schema({
title: {type: String, required: true},
content: {type: String, required: true},
tags: {type: [String], default: []},
isPinned: {type: Boolean, default: false},
title: {type: String, required: true}, // Duplicate field
userId: {type: String, required : true},
createOn: {type: Date, default: new Date().getTime()},
})

Schema Fields Explained​

  • title: The note's title (required field, appears twice due to error)
  • content: The main text content of the note (required)
  • tags: Array of string tags for categorization (defaults to empty array)
  • isPinned: Boolean flag to mark important notes (defaults to false)
  • userId: Links the note to its owner (required for data isolation)
  • createOn: Timestamp of note creation

Key Characteristics​

  • Required fields: Title, content, and userId must be provided
  • Default values: Tags default to empty array, isPinned defaults to false
  • User association: Each note belongs to a specific user via userId
  • Schema error: Title field is defined twice (line 4 and 8)

Usage in Application​

The Note model supports all note operations:

  • Creating notes (/add-note endpoint)
  • Editing notes (/edit-note/:noteId endpoint)
  • Deleting notes (/delete-note/:noteId endpoint)
  • Pinning/unpinning (/update-note-pinned/:noteId endpoint)
  • Retrieving all notes (/get-all-notes endpoint)
  • Searching notes (/search-notes endpoint)

Data Relationships​

User to Notes Relationship​

The application implements a one-to-many relationship:

  • One User can have many Notes
  • Each Note belongs to exactly one User

This is achieved through the userId field in the Note model, which stores the User's MongoDB _id.

// When creating a note
const note = new Note({
title,
content,
tags: tags || [],
userId: user._id, // Links note to user
});

Data Isolation​

User data is isolated by always filtering notes by userId:

// Get user's notes only
const notes = await Note.find({ userId: user._id });

// Edit only user's own notes
const note = await Note.findOne({ _id: noteId, userId: user._id });

Database Operations​

Common Query Patterns​

Find by user: Note.find({ userId: user._id }) Sort by pinned status: .sort({ isPinned: -1 }) (pinned notes first) Search with regex: { title: { $regex: new RegExp(query, "i") } } (case-insensitive) Find one specific note: Note.findOne({ _id: noteId, userId: user._id })

MongoDB Features Used​

  • Regular expressions for search functionality
  • Sorting to prioritize pinned notes
  • Array fields for tags storage
  • Boolean fields for pinned status
  • Date fields with default values

Security Considerations​

Current Issues​

  1. Plain text passwords: User passwords are stored without hashing
  2. No input validation: Schema lacks validation rules for email format
  3. No field constraints: Missing length limits or format requirements

Data Access Control​

The application properly implements user data isolation by always including userId in database queries, ensuring users can only access their own notes.