Skip to content
sharmanayan668-codePublic

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

# Secure To-Do List Application (MERN Stack) A complete, full-stack MERN (MongoDB, Express.js, React, Node.js) web application that combines a **JWT-based User Authentication API** and a **Personal To-Do List REST API** into a single cohesive project. Users can securely register and log in to manage their personal tasks with end-to-end access control, protected routes, and a responsive modern user interface. --- ## Table of Contents - [Project Overview](#project-overview) - [Key Features](#key-features) - [Technology Stack](#technology-stack) - [Project Structure](#project-structure) - [Installation Guide](#installation-guide) - [Environment Configuration](#environment-configuration) - [MongoDB Setup](#mongodb-setup) - [Running the Application](#running-the-application) - [API Documentation](#api-documentation) - [JWT Authentication Explanation](#jwt-authentication-explanation) - [Postman Testing Guide](#postman-testing-guide) - [Security Best Practices](#security-best-practices) --- ## Project Overview This project was built by combining two core modules: 1. **User Authentication API**: Secure registration, login, password encryption using bcryptjs, JWT generation, and protected `/me` profile retrieval. 2. **To-Do List REST API**: Full CRUD (Create, Read, Update, Delete) task operations and state toggling where every task is strictly bound to its owner's MongoDB ID. ### Key Architecture Highlights - **Strict Data Isolation**: Users can **only** read, edit, toggle, or delete tasks that belong to their own account. - **Stateless Authorization**: Protected endpoints require a valid JSON Web Token (`Bearer `). - **Responsive Client**: Built with React 18, React Router, and Axios with custom request and response interceptors. --- ## Key Features ### Backend Features - **User Registration**: Validates email format, prevents duplicate emails, and securely hashes passwords with `bcryptjs`. - **User Authentication**: Compares salted hashes and issues signed JSON Web Tokens (JWT) with configurable expiry. - **Protected Routes**: Centralized `authMiddleware` that parses the `Authorization: Bearer ` header and injects the authenticated user into `req.user`. - **Task Management**: - `POST /api/tasks` — Create new tasks with title and optional description. - `GET /api/tasks` — Fetch all tasks belonging exclusively to the authenticated user. - `GET /api/tasks/:id` — Retrieve a single task by ID with ownership verification. - `PUT /api/tasks/:id` — Update task title, description, or completion status. - `PATCH /api/tasks/:id/toggle` — Toggle task completion status between `true` and `false`. - `DELETE /api/tasks/:id` — Delete a task with ownership verification. - **Centralized Error Handling**: Unified responses for validation errors, duplicate keys (11000), cast errors (invalid ObjectIds), and expired/invalid tokens. ### Frontend Features - **Modern Responsive Design**: Works seamlessly across mobile, tablet, and desktop viewports. - **Authentication Flows**: - Register with client-side validation and password match checks. - Login with token and user persistence in `localStorage`. - Seamless redirection from `/register` -> `/login` -> `/dashboard`. - **Dashboard**: - Live statistics: **Total Tasks**, **Completed Tasks**, and **Pending Tasks**. - Interactive search bar to filter tasks by title or description. - Status filter buttons: **All**, **Pending**, and **Completed**. - Create and edit tasks with validation and feedback alerts. - Mark tasks complete or pending with a single click. - Delete confirmation. - One-click Logout with automatic session cleanup. - **Route Protection**: - Unauthenticated access to `/dashboard` redirects to `/login`. - Authenticated visits to `/login` or `/register` automatically redirect to `/dashboard`. - **Axios Interceptors**: Automatically injects JWT into headers and clears expired credentials on `401 Unauthorized`. --- ## Technology Stack ### Frontend - **React.js (v18)** — Component-based UI library - **React Router (v6)** — Declarative client-side routing and protected routes - **Axios** — Promise-based HTTP client with request/response interceptors - **Vite** — Fast frontend build tool and dev server - **Vanilla CSS** — Custom responsive design system (Plus Jakarta Sans, cards, badges, focus rings) - **JavaScript (ES6+)** — (No TypeScript, purely JavaScript as specified) ### Backend - **Node.js** — JavaScript runtime environment - **Express.js** — Fast, unopinionated web framework for Node.js - **MongoDB** — NoSQL document database - **Mongoose** — Elegant MongoDB object modeling for Node.js - **bcryptjs** — Salt-hashed password encryption - **jsonwebtoken (JWT)** — Token creation and verification - **cors** — Cross-Origin Resource Sharing middleware - **dotenv** — Environment variable loader - **nodemon** — Development server auto-reloader --- ## Project Structure ``` project-root/ │ ├── backend/ │ ├── config/ │ │ └── db.js # MongoDB connection setup │ ├── controllers/ │ │ ├── authController.js # User registration, login, and profile │ │ └── taskController.js # Task CRUD and toggle logic │ ├── middleware/ │ │ ├── authMiddleware.js # JWT Bearer token verification │ │ └── errorMiddleware.js # 404 and central error handling │ ├── models/ │ │ ├── User.js # User Schema with bcrypt hashing │ │ └── Task.js # Task Schema with User reference │ ├── routes/ │ │ ├── authRoutes.js # /api/auth routes │ │ └── taskRoutes.js # /api/tasks routes │ ├── .env # Local environment configuration │ ├── .env.example # Example environment template │ ├── package.json # Backend dependencies and scripts │ └── server.js # Express server entry point │ ├── frontend/ │ ├── src/ │ │ ├── components/ │ │ │ ├── Navbar.jsx # Top navigation header & user profile │ │ │ ├── TaskForm.jsx # Task creation and editing form │ │ │ └── TaskItem.jsx # Individual task card with actions │ │ ├── pages/ │ │ │ ├── Login.jsx # User login page │ │ │ ├── Register.jsx # User registration page │ │ │ └── Dashboard.jsx # Main user dashboard with stats and tasks │ │ ├── services/ │ │ │ └── api.js # Axios instance with auth interceptors │ │ ├── context/ │ │ │ └── AuthContext.jsx # Global authentication state │ │ ├── App.jsx # Application routing and route guards │ │ ├── main.jsx # React DOM mounting │ │ └── index.css # Responsive styling and design system │ ├── index.html # HTML template │ ├── vite.config.js # Vite configuration │ ├── package.json # Frontend dependencies and scripts │ ├── .env # Local frontend environment variables │ └── .env.example # Frontend environment template │ └── README.md # Project documentation ``` --- ## Installation Guide ### Prerequisites - **Node.js**: v18.0.0 or higher ([Download Node.js](https://nodejs.org/)) - **npm**: v9.0.0 or higher - **MongoDB**: Either a local MongoDB instance running on port 27017 or a free [MongoDB Atlas](https://www.mongodb.com/cloud/atlas) cluster connection URI. ### Step 1: Install Backend Dependencies ```bash cd backend npm install ``` ### Step 2: Install Frontend Dependencies ```bash cd ../frontend npm install ``` --- ## Environment Configuration ### Backend Environment (`backend/.env`) Create a file named `.env` inside the `backend/` directory by copying `.env.example`: ```bash cp backend/.env.example backend/.env ``` Contents of `backend/.env`: ```env PORT=5000 MONGO_URI=mongodb://127.0.0.1:27017/secure_todo_app JWT_SECRET=your_super_secret_jwt_key_here_change_in_production JWT_EXPIRES_IN=7d ``` > **Security Note:** Never commit your `.env` file to version control. Replace `JWT_SECRET` with a long, random string in production. ### Frontend Environment (`frontend/.env`) Create a file named `.env` inside the `frontend/` directory by copying `.env.example`: ```bash cp frontend/.env.example frontend/.env ``` Contents of `frontend/.env`: ```env VITE_API_URL=http://localhost:5000/api ``` --- ## MongoDB Setup You can use either a **Local MongoDB Community Server** or **MongoDB Atlas Cloud Database**. ### Option A: Local MongoDB Community Server (Recommended for offline local development) 1. Download and install [MongoDB Community Server](https://www.mongodb.com/try/download/community). 2. Start the MongoDB service: - On Windows: Run `net start MongoDB` or verify the service in `services.msc`. - On macOS/Linux: `sudo systemctl start mongod` or `brew services start mongodb/brew/mongodb-community`. 3. In `backend/.env`, set: ```env MONGO_URI=mongodb://127.0.0.1:27017/secure_todo_app ``` ### Option B: MongoDB Atlas (Free Cloud Database) 1. Go to [MongoDB Atlas](https://www.mongodb.com/cloud/atlas) and sign in/up. 2. Create a free **M0 Sandbox** cluster. 3. In **Database Access**, create a database user (e.g. `todoUser`) and note down the password. 4. In **Network Access**, click **Add IP Address** and choose **Allow Access From Anywhere (`0.0.0.0/0`)** for development. 5. Click **Connect** -> **Connect your application** -> **Driver: Node.js**. 6. Copy the connection string and paste it into `backend/.env`: ```env MONGO_URI=mongodb+srv://:@cluster0.mongodb.net/secure_todo_app?retryWrites=true&w=majority ``` *(Replace `` and `` with your database credentials).* --- ## Running the Application ### 1. Start the Backend Server From the root directory: ```bash cd backend npm run dev ``` The backend will run at: **`http://localhost:5000`** Expected terminal output: ``` Server is running in development mode on port 5000 MongoDB Connected: 127.0.0.1 ``` *(To run without nodemon, use `npm start`)* ### 2. Start the Frontend Application In a new terminal window, from the root directory: ```bash cd frontend npm run dev ``` The React application will run at: **`http://localhost:5173`** (or the port specified by Vite). Open your browser and navigate to `http://localhost:5173`. --- ## API Documentation Base URL: `http://localhost:5000/api` ### 1. Authentication Endpoints (`/api/auth`) | Method | Endpoint | Access | Description | | :--- | :--- | :--- | :--- | | `POST` | `/api/auth/register` | Public | Register a new user | | `POST` | `/api/auth/login` | Public | Authenticate user & get JWT token | | `GET` | `/api/auth/me` | Protected | Get current user's profile | --- ### 2. Task Endpoints (`/api/tasks`) *(All task endpoints require `Authorization: Bearer `)* | Method | Endpoint | Access | Description | | :--- | :--- | :--- | :--- | | `POST` | `/api/tasks` | Protected | Create a new task for the logged-in user | | `GET` | `/api/tasks` | Protected | Get all tasks belonging to the logged-in user | | `GET` | `/api/tasks/:id` | Protected | Get a specific task by ID | | `PUT` | `/api/tasks/:id` | Protected | Update task title, description, or completed | | `PATCH`| `/api/tasks/:id/toggle` | Protected | Toggle task completed between true/false | | `DELETE`| `/api/tasks/:id` | Protected | Delete a task | --- ## JWT Authentication Explanation ### How It Works: 1. **User Login**: When the user sends their email and password to `POST /api/auth/login`, the server verifies the password using `bcrypt.compare()`. 2. **Token Generation**: If valid, the server generates a JSON Web Token using `jwt.sign({ id: user._id }, process.env.JWT_SECRET, { expiresIn: '7d' })`. 3. **Client Storage**: The frontend stores this token in `localStorage`. 4. **Attaching Header**: For all subsequent protected requests, Axios attaches the token to the HTTP header: ```http Authorization: Bearer ``` 5. **Middleware Verification (`authMiddleware.js`)**: - Reads the `Authorization` header. - Verifies the signature using `jwt.verify(token, process.env.JWT_SECRET)`. - Decodes the user's `id`. - Queries MongoDB to find the user (`User.findById(decoded.id).select('-password')`). - Attaches the user object to `req.user`. - Calls `next()` to execute the controller. 6. **Error Handling**: If the token is invalid or expired, the middleware stops execution and returns `401 Unauthorized`. The frontend Axios interceptor intercepts this and redirects the user to `/login`. --- ## Postman Testing Guide Follow this sequential walkthrough to test the entire API using Postman. ### 1. Register a User - **Method**: `POST` - **URL**: `http://localhost:5000/api/auth/register` - **Headers**: - `Content-Type: application/json` - **Body** (raw JSON): ```json { "name": "John Doe", "email": "john@example.com", "password": "password123" } ``` - **Expected Status**: `201 Created` - **Sample Response**: ```json { "success": true, "message": "User registered successfully", "user": { "id": "679f2b841234567890abcdef", "name": "John Doe", "email": "john@example.com" } } ``` --- ### 2. Login User - **Method**: `POST` - **URL**: `http://localhost:5000/api/auth/login` - **Headers**: - `Content-Type: application/json` - **Body** (raw JSON): ```json { "email": "john@example.com", "password": "password123" } ``` - **Expected Status**: `200 OK` - **Sample Response**: ```json { "success": true, "message": "Login successful", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "user": { "id": "679f2b841234567890abcdef", "name": "John Doe", "email": "john@example.com" } } ``` > **Important:** Copy the `token` string from the response. You will need it for all subsequent requests! --- ### 3. Get Current User (`/api/auth/me`) - **Method**: `GET` - **URL**: `http://localhost:5000/api/auth/me` - **Authorization**: - Type: `Bearer Token` - Token: `` *(Or in Headers: `Authorization: Bearer `)* - **Expected Status**: `200 OK` - **Sample Response**: ```json { "success": true, "user": { "id": "679f2b841234567890abcdef", "name": "John Doe", "email": "john@example.com", "createdAt": "2026-10-02T15:00:00.000Z" } } ``` --- ### 4. Create Task - **Method**: `POST` - **URL**: `http://localhost:5000/api/tasks` - **Authorization**: `Bearer ` - **Headers**: - `Content-Type: application/json` - **Body** (raw JSON): ```json { "title": "Learn React", "description": "Complete React practice assignment and exercises" } ``` - **Expected Status**: `201 Created` - **Sample Response**: ```json { "success": true, "message": "Task created successfully", "task": { "_id": "679f2c101234567890abcdef", "title": "Learn React", "description": "Complete React practice assignment and exercises", "completed": false, "user": "679f2b841234567890abcdef", "createdAt": "2026-10-02T15:05:00.000Z", "updatedAt": "2026-10-02T15:05:00.000Z" } } ``` > **Note:** Copy the task's `_id` to test single task endpoints. --- ### 5. Get All Tasks - **Method**: `GET` - **URL**: `http://localhost:5000/api/tasks` - **Authorization**: `Bearer ` - **Expected Status**: `200 OK` - **Sample Response**: ```json { "success": true, "count": 1, "tasks": [ { "_id": "679f2c101234567890abcdef", "title": "Learn React", "description": "Complete React practice assignment and exercises", "completed": false, "user": "679f2b841234567890abcdef", "createdAt": "2026-10-02T15:05:00.000Z", "updatedAt": "2026-10-02T15:05:00.000Z" } ] } ``` --- ### 6. Get Task By ID - **Method**: `GET` - **URL**: `http://localhost:5000/api/tasks/679f2c101234567890abcdef` - **Authorization**: `Bearer ` - **Expected Status**: `200 OK` - **Sample Response**: ```json { "success": true, "task": { "_id": "679f2c101234567890abcdef", "title": "Learn React", "description": "Complete React practice assignment and exercises", "completed": false, "user": "679f2b841234567890abcdef" } } ``` --- ### 7. Update Task - **Method**: `PUT` - **URL**: `http://localhost:5000/api/tasks/679f2c101234567890abcdef` - **Authorization**: `Bearer ` - **Headers**: - `Content-Type: application/json` - **Body** (raw JSON): ```json { "title": "Master React and Node.js", "description": "Build high-performance full-stack MERN applications", "completed": true } ``` - **Expected Status**: `200 OK` - **Sample Response**: ```json { "success": true, "message": "Task updated successfully", "task": { "_id": "679f2c101234567890abcdef", "title": "Master React and Node.js", "description": "Build high-performance full-stack MERN applications", "completed": true, "user": "679f2b841234567890abcdef" } } ``` --- ### 8. Toggle Task Status - **Method**: `PATCH` - **URL**: `http://localhost:5000/api/tasks/679f2c101234567890abcdef/toggle` - **Authorization**: `Bearer ` - **Expected Status**: `200 OK` - **Sample Response**: ```json { "success": true, "message": "Task marked as pending", "task": { "_id": "679f2c101234567890abcdef", "title": "Master React and Node.js", "completed": false } } ``` --- ### 9. Delete Task - **Method**: `DELETE` - **URL**: `http://localhost:5000/api/tasks/679f2c101234567890abcdef` - **Authorization**: `Bearer ` - **Expected Status**: `200 OK` - **Sample Response**: ```json { "success": true, "message": "Task deleted successfully" } ``` --- ## Security Best Practices 1. **Password Hashing**: Uses `bcryptjs` with salt work factor of 10. Passwords are never stored in plaintext and never transmitted back in API responses. 2. **Token Security**: Tokens are signed with a cryptographically secure key stored in `.env`. 3. **Data Segregation**: All task queries (`find`, `findById`, `updateOne`, `deleteOne`) strictly scope by `user: req.user._id` so no user can access or modify another user's records. 4. **Input Sanitization**: Email format validation, password length checks, and title trimming prevent empty or malformed inputs. 5. **CORS Security**: Cross-Origin Resource Sharing is enabled to allow verified client requests while blocking malicious origin requests. 6. **Graceful Error Handling**: Database errors, invalid IDs, and unauthorized attempts return clean JSON errors without exposing server internals. --- ## License This project is licensed under the ISC License. Created for educational and production reference. # TodoApp

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages