Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Noter API Documentation

Welcome to the Noter API! This is a backend service for a content-sharing platform where users can sign up, share posts (with PDF and thumbnail content), and interact with each other through likes, comments, and follows.

Table of Contents


Features

  • User Authentication: Secure user registration (with OTP email verification) and login using JWT.
  • Profile Management: Users can view and edit their profiles, including profile pictures.
  • Post Management: Create, read, and manage posts.
  • File Uploads: Handles PDF and image uploads, storing them securely on Cloudinary.
  • Content Moderation: Automatic check for NSFW (Not Safe For Work) content on image uploads.
  • Social Interactions:
    • Like and comment on posts.
    • Save posts for later.
    • Follow and unfollow other users.
  • Pagination: Efficiently loads posts with paginated responses.

Tech Stack

  • Backend: Node.js, Express.js
  • Database: MongoDB with Mongoose ODM
  • Authentication: JSON Web Tokens (JWT), bcryptjs for hashing
  • File Storage: Cloudinary for cloud-based media storage
  • Email Service: Nodemailer for sending OTP emails
  • Content Moderation: Sightengine API
  • Middleware: CORS, Cookie-Parser, Multer for file handling

Setup & Installation

Prerequisites

  • Node.js (v16 or higher)
  • npm or yarn
  • MongoDB instance (local or cloud-based like MongoDB Atlas)

Environment Variables

Before starting the server, you must create a .env file in the root api/ directory and populate it with the following keys.

Variable Description Example
PORT The port for the server to run on. 5000
MONGODB_URI Your MongoDB connection string. mongodb+srv://<user>:<pass>@cluster/...
JWT_SECRET A secret key for signing JWT tokens. a-very-strong-and-secret-key
EMAIL The Gmail address to send OTPs from. youremail@gmail.com
EMAIL_PASS Your Gmail App Password. your-gmail-app-password
CLOUDINARY_CLOUD_NAME Your Cloudinary cloud name. your-cloud-name
CLOUDINARY_API_KEY Your Cloudinary API key. 123456789012345
CLOUDINARY_API_SECRET Your Cloudinary API secret. your-cloudinary-secret
SIGHTENGINE_USER Your Sightengine API user. your-sightengine-user
SIGHTENGINE_SECRET Your Sightengine API secret. your-sightengine-secret

Running the Server

  1. Clone the repository (if you haven't already).

  2. Navigate to the API directory:

    cd api
  3. Install dependencies:

    npm install
  4. Start the development server:

    npm run dev

    The server will start on the port specified in your .env file (e.g., http://localhost:5000).


API Endpoints

All endpoints are prefixed with /api.

Authentication

Handles user registration, login, and logout. Authentication is managed via an httpOnly cookie named token.

POST /auth/signup

Registers a new user and sends an OTP to their email for verification.

  • Request Body:
    {
      "userName": "johndoe",
      "fullName": "John Doe",
      "email": "john.doe@example.com",
      "password": "password123"
    }
  • Success Response (201):
    {
      "success": true,
      "message": "Otp sent successfully"
    }
  • Error Response (409 - User Exists):
    {
      "success": false,
      "message": "User already exist! Please Login"
    }

POST /auth/otp

Verifies the OTP sent to the user's email, creates the user account, and logs them in.

  • Request Body:
    {
      "otp": "123456",
      "email": "john.doe@example.com"
    }
  • Success Response (201):
    • Sets a token cookie.
    {
      "success": true,
      "message": "User registered successfully",
      "user": {
        "_id": "60d0fe4f5311236168a109ca",
        "fullName": "John Doe",
        "userName": "johndoe",
        "email": "john.doe@example.com",
        "posts": [],
        "followers": [],
        "following": []
      }
    }
  • Error Response (400 - Invalid OTP):
    {
      "success": false,
      "message": "Invalid OTP !"
    }

POST /auth/signin

Logs in an existing user.

  • Request Body:
    {
      "userName": "johndoe",
      "password": "password123"
    }
  • Success Response (200):
    • Sets a token cookie.
    {
      "success": true,
      "message": {
        "_id": "60d0fe4f5311236168a109ca",
        "fullName": "John Doe",
        "userName": "johndoe",
        "email": "john.doe@example.com"
      }
    }
  • Error Response (403 - Incorrect Credentials):
    {
      "success": false,
      "message": "Incorrect id or password !"
    }

GET /auth/signout

Logs out the current user by clearing the token cookie.

  • Success Response (200):
    {
      "success": true,
      "message": "signOut successfully"
    }

Users

Endpoints for managing user profiles and interactions.

GET /user/current

Retrieves the profile of the currently logged-in user.

  • Authentication: Requires a valid token sent as an httpOnly cookie.
  • Success Response (200):
    {
      "_id": "60d0fe4f5311236168a109ca",
      "fullName": "John Doe",
      "userName": "johndoe",
      "email": "john.doe@example.com",
      "profileImage": "https://res.cloudinary.com/...",
      "bio": "Software developer and coffee enthusiast.",
      "gender": "male",
      "followers": [],
      "following": [],
      "posts": [
        {
          "_id": "60d0fe4f5311236168a109cb",
          "title": "My First Post"
        }
      ],
      "saved": []
    }

GET /user/getProfile/:userName

Retrieves the public profile of a user by their username.

  • Authentication: Requires a valid token sent as an httpOnly cookie.
  • Success Response (200):
    {
      "_id": "60d0fe4f5311236168a109df",
      "fullName": "Jane Smith",
      "userName": "janesmith",
      "profileImage": "http://...",
      "bio": "A short bio about Jane."
    }
  • Error Response (400 - User Not Found):
    {
        "message": "user not found"
    }

GET /user/follow/:targetUserId

Follows or unfollows another user.

  • Authentication: Requires a valid token sent as an httpOnly cookie.
  • Success Response (200):
    • When following:
    {
      "following": true,
      "message": "follow successfully"
    }
    • When unfollowing:
    {
      "following": false,
      "message": "unfollow successfully"
    }

POST /user/editProfile

Updates the profile of the currently logged-in user.

  • Authentication: Requires a valid token sent as an httpOnly cookie.
  • Request: multipart/form-data
    • name (String)
    • userName (String)
    • bio (String)
    • gender (String: "male" or "female")
    • profileImage (File, optional)
  • Success Response (200):
    {
        "_id": "60d0fe4f5311236168a109ca",
        "name": "Johnathan Doe",
        "userName": "johnathandoe",
        "bio": "Updated bio here.",
        "gender": "male",
        "profileImage": "https://res.cloudinary.com/..."
    }
  • Error Response (400 - Username Taken):
    {
        "message": "username already exist"
    }

Posts

Endpoints for managing posts and post-related interactions.

POST /post/upload

Creates a new post.

  • Authentication: Requires a valid token sent as an httpOnly cookie.
  • Request: multipart/form-data
    • title (String)
    • description (String)
    • tags (String, comma-separated)
    • pdf (File, required)
    • thumbnail (File, required)
  • Success Response (201):
    {
      "_id": "60d0fe4f5311236168a109cb",
      "title": "Understanding APIs",
      "description": "A deep dive into REST APIs.",
      "postImage": "https://res.cloudinary.com/...",
      "pdf": "https://res.cloudinary.com/...",
      "createdBy": {
        "_id": "60d0fe4f5311236168a109ca",
        "fullName": "John Doe",
        "userName": "johndoe",
        "profileImage": "http://..."
      },
      "tags": ["api", "development"],
      "likes": [],
      "comments": []
    }
  • Error Response (400 - Inappropriate Content):
    {
        "message": "Inappropriate or unsafe content detected.",
        "score": 0.95
    }

GET /post/getdata

Retrieves a paginated list of all posts, sorted by creation date.

  • Query Parameters:
    • page (Number, optional, default: 1)
    • limit (Number, optional, default: 20)
  • Success Response (200):
    {
      "page": 1,
      "limit": 20,
      "total": 50,
      "totalPages": 3,
      "data": [
        {
          "_id": "...",
          "title": "Post Title",
          "postImage": "https://...",
          "createdBy": {
            "fullName": "Author Name",
            "userName": "author_username",
            "profileImage": "https://..."
          }
        }
      ]
    }

GET /post/getOne/:postId

Retrieves a single post by its ID.

  • Success Response (200):
    {
      "_id": "60d0fe4f5311236168a109cb",
      "title": "Understanding APIs",
      "description": "A deep dive into REST APIs.",
      "postImage": "https://res.cloudinary.com/...",
      "pdf": "https://res.cloudinary.com/...",
      "createdBy": {
        "_id": "60d0fe4f5311236168a109ca",
        "fullName": "John Doe",
        "userName": "johndoe",
        "profileImage": "http://..."
      },
      "tags": ["api", "development"],
      "likes": ["60d0fe4f5311236168a109df"],
      "comments": [
          {
            "createdBy": {
                "_id": "60d0fe4f5311236168a109df",
                "fullName": "Jane Smith",
                "userName": "janesmith"
            },
            "message": "This is a great post!",
            "timestamp": "2023-10-27T10:00:00.000Z"
          }
      ],
      "createdAt": "2023-10-27T09:00:00.000Z",
      "updatedAt": "2023-10-27T10:00:00.000Z"
    }

GET /post/getAll

Retrieves all posts created by the logged-in user.

  • Authentication: Requires a valid token sent as an httpOnly cookie.
  • Success Response (200):
    [
      {
        "_id": "60d0fe4f5311236168a109cb",
        "title": "Understanding APIs",
        "description": "A deep dive into REST APIs.",
        "postImage": "https://res.cloudinary.com/...",
        "pdf": "https://res.cloudinary.com/...",
        "createdBy": {
            "_id": "60d0fe4f5311236168a109ca",
            "fullName": "John Doe",
            "userName": "johndoe",
            "profileImage": "http://..."
        },
        "tags": ["api", "development"],
        "likes": [],
        "comments": []
      }
    ]

GET /post/like/:postId

Toggles a "like" on a post for the logged-in user.

  • Authentication: Requires a valid token sent as an httpOnly cookie.
  • Success Response (200): The updated post object with the new likes array.
    {
      "_id": "60d0fe4f5311236168a109cb",
      "title": "Understanding APIs",
      "likes": [ "60d0fe4f5311236168a109ca" ],
      "comments": [],
      "createdBy": {
        "_id": "...",
        "fullName": "John Doe"
      }
    }

GET /post/saved/:postId

Toggles a "save" on a post for the logged-in user.

  • Authentication: Requires a valid token sent as an httpOnly cookie.
  • Success Response (200): The updated user object with the populated saved array.
    {
        "_id": "60d0fe4f5311236168a109ca",
        "fullName": "John Doe",
        "userName": "johndoe",
        "saved": [
            {
                "_id": "60d0fe4f5311236168a109cb",
                "title": "Understanding APIs",
                "description": "A deep dive into REST APIs."
            }
        ]
    }

POST /post/comment/:postId

Adds a comment to a specific post.

  • Authentication: Requires a valid token sent as an httpOnly cookie.
  • Request Body:
    {
      "message": "This is a great post!"
    }
  • Success Response (200): The updated post object with the new comment included.
{
    "_id": "60d0fe4f5311236168a109cb",
    "title": "Understanding APIs",
    "comments": [
        {
            "createdBy": {
                "_id": "...",
                "fullName": "Jane Smith",
                "userName": "janesmith",
                "profileImage": "http://..."
            },
            "message": "This is a great post!",
            "timestamp": "2023-10-27T10:00:00.000Z",
            "_id": "..."
        }
    ]
}

Further Improvements & Suggestions

While this API provides a solid foundation, here are some suggestions for enhancing it for a production environment:

  • API Rate Limiting: To prevent abuse and ensure service stability, implement rate limiting on endpoints. Libraries like express-rate-limit can be easily integrated.

  • Advanced Input Validation: Add more robust validation and sanitization for all user inputs to enhance security and data integrity. Consider using libraries like express-validator or Joi.

  • Automated Testing: Introduce a testing framework (e.g., Jest, Mocha with Supertest) to write unit and integration tests. This will help ensure the reliability of your API as you add new features.

  • Centralized Error Handling: Create a dedicated middleware for handling all errors. This makes error responses more consistent and keeps your controller logic cleaner.

  • API Versioning: For future scalability, consider versioning your API (e.g., /api/v1/...). This allows you to introduce breaking changes without affecting existing client applications.

  • Security Headers: Use a library like helmet to set various HTTP headers that can help protect your application from common web vulnerabilities like Cross-Site Scripting (XSS) and clickjacking.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages