/L2-B2-Assignment-4

Assignment-4: Enhanced User Authentication and Authorization System.

Assignment-4: Enhanced User Authentication and Authorization System

This assignment builds upon the foundation laid in Assignment 3, extending the system to include robust user authentication, authorization, and user-related information. To accomplish this, you are required to clone your Assignment 3 repository and make the necessary modifications as outlined below.

Private Repo

Create Private repo link: https://classroom.github.com/a/Kx-KeiOp

1. User Model:

  1. _id (Object ID): A distinctive identifier generated by MongoDB.
  2. username (string): The username of the user. This field holds a unique identifier for the user.
  3. email (string): The email address of the user. This field stores the user's email, ensuring it is unique.
  4. password (string): The password linked to the user's account, securely hashed. Strong password validation is encouraged, with specified format requirements. If implementing password strength validation, please provide the password format and appropriate error message for user guidance.
  5. role ('user' | 'admin'): The role of the user, which can be either 'user' or 'admin'. This field determines the user's level of access or permissions. The default role is set to 'user'.

2. Course Model:

  • _id (Object ID): A distinctive identifier generated by MongoDB.
  • title (String): A unique title of the course.
  • instructor (String): The instructor of the course.
  • categoryId (Object ID): A reference to the category collection.
  • price (Number): The price of the course.
  • tags(Array of Object): The "tags" field is an array of objects, each having a "name" (string) and "isDeleted" (boolean) property.
  • startDate (String): The start date of the course.
  • endDate (String): The end date of the course.
  • language (String): The language in which the course is conducted.
  • provider (String): The provider of the course.
  • durationInWeeks (Integer): This represents the course's overall duration in weeks, calculated by applying the ceil function to the numeric value derived from the start and end dates. The resulting number is rounded up to the nearest integer, ensuring that the duration is expressed solely as an integer with no allowance for floating-point numbers.
  • details (Object):
    • level (string): e.g., Beginner, Intermediate, Advanced.
    • description (string): Detailed description of the course
  • createdBy (Object ID): A reference to the user collection.

3. Category Model:

  • _id (Object ID): A distinctive identifier generated by MongoDB.
  • name (String): A unique name of the category.
  • createdBy (Object ID): A reference to the user collection.

4. Review Model:

  • _id (Object ID): A distinctive identifier generated by MongoDB.
  • courseId (Object ID): A reference to the course collection.
  • rating (Number): Rating, which falls within the range of 1 to 5.
  • review (String): The comment or review text provided by the user.
  • createdBy (Object ID): A reference to the user collection.

1. User Registration

  • Route: /api/auth/register

  • Method: POST

  • Request Body:

    {
        "username": "john_doe",
        "email": "john@example.com",
        "password": "123456",
        "role": "user"
    }
  • Response:

    • Make sure that the password field or any other security-related field is not included in the response data.
    {
        "success": true,
        "statusCode": 201,
        "message": "User registered successfully",
        "data": {
            "_id": "54321abcde67890fghij",
            "username": "john_doe",
            "email": "john@example.com",
            "role": "user",
            "createdAt": "2023-01-01T12:00:00.000Z",
            "updatedAt": "2023-01-01T12:00:00.000Z"
        }
    }

2. User Login

  • Route: /api/auth/login

  • Method: POST

  • Request Body:

    {
        "username": "john_doe",
        "password": "123456"
    }
  • Response:

    • Make sure that the password field or any other security-related field is not included in the response data.
    {
        "success": true,
        "statusCode": 200,
        "message": "User login successful",
        "data": {
            "user": {
                "_id": "54321abcde67890fghij",
                "username": "john_doe",
                "email": "john@example.com",
                "role": "user"
            },
            "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
        }
    }

In this example:

  • The request body includes the user's credentials, such as username and password.
  • The response includes a success indicator, status code, message, and data containing user details (such as _id, username, email, role) & JWT token.

JWT Token Payload:

{
  "_id": "54321abcde67890fghij", // User's _id
  "role": "user",               // User's role
  "email": "john@example.com",  // User's email
  "iat": 1626619535,            // Issued At (timestamp)
  "exp": 1626623535             // Expiration (timestamp)
}

3. Change Password

  • Route: /api/auth/change-password
  • Method: POST
  • Request Headers:
Authorization: <JWT_TOKEN>
  • Request Body:
{
    "currentPassword": "123456",
    "newPassword": "new123456"
}
  • currentPassword: The user's current password for verification.

  • newPassword: The new password the user wants to set.

  • Response:

    • Make sure that the password field or any other security-related field is not included in the response data.
{
    "success": true,
    "statusCode": 200,
    "message": "Password changed successfully",
    "data": {
        "_id": "54321abcde67890fghij",
        "username": "john_doe",
        "email": "john@example.com",
        "role": "user",
        "createdAt": "2023-01-01T12:00:00.000Z",
        "updatedAt": "2023-01-02T12:30:00.000Z"
    }
}
  • The response includes a success indicator, status code, message, and updated user details.

Password Change Rules:

  • The system stores only the last 2 previous passwords with timestamps.
  • During a password change attempt:
    • The user cannot reuse any of the last 2 passwords or the current one.
    • If the new password matches any of the previous 2 passwords or the current one, the password change fails.
    • If the new password is unique and different from the current password, the password change is successful.

[Hints: You can maintain a password change history by storing the changes along with timestamps. This information can be stored in a dedicated collection or optionally embedded within the user collection. The key is to ensure that your logic needs to fulfill our requirements]

Response (if password change failed):

{
    "success": false,
    "statusCode": 400,
    "message": "Password change failed. Ensure the new password is unique and not among the last 2 used (last used on 2023-01-01 at 12:00 PM).",
    "data": null
}

4**. Create a Course (Only Admin can do this)**

  • Endpoint: /api/courses

  • Method: POST

  • Request Headers:

    Authorization: <ADMIN_JWT_TOKEN>
  • Request Body:

    {
        "title": "Introduction to Web Development",
        "instructor": "John Smith",
        "categoryId": "12345abcde67890fghij",
        "price": 49.99,
        "tags": [
            {"name": "Programming", "isDeleted": false},
            {"name": "Web Development", "isDeleted": false}
        ],
        "startDate": "2023-02-01",
        "endDate": "2023-04-01",
        "language": "English",
        "provider": "Tech Academy",
        "durationInWeeks": 8,
        "details": {
            "level": "Beginner",
            "description": "A comprehensive introduction to web development."
        }
    }
  • Response:

    {
        "success": true,
        "statusCode": 201,
        "message": "Course created successfully",
        "data": {
            "_id": "67890fghij54321abcde",
            "title": "Introduction to Web Development",
            "instructor": "John Smith",
            "categoryId": "12345abcde67890fghij",
            "price": 49.99,
            "tags": [
                {"name": "Programming", "isDeleted": false},
                {"name": "Web Development", "isDeleted": false}
            ],
            "startDate": "2023-02-01",
            "endDate": "2023-04-01",
            "language": "English",
            "provider": "Tech Academy",
            "durationInWeeks": 8,
            "details": {
                "level": "Beginner",
                "description": "A comprehensive introduction to web development."
            },
            "createdBy": "adminUserId", // Include an addition during assignment 4
            "createdAt": "2023-01-15T12:00:00.000Z",
            "updatedAt": "2023-01-15T12:00:00.000Z"
        }
    }

5. Get Paginated and Filtered Courses.

  • Endpoint: /api/courses
  • Method: GET

Query Parameters for API Requests:

When interacting with the API, you can utilize the following query parameters to customize and filter the results according to your preferences.

  • page: (Optional) Specifies the page number for paginated results. Default is 1. Example: ?page=2

  • limit: (Optional) Sets the number of items per page. Default is a predefined limit. Example: ?limit=10

  • sortBy: (Optional) Specifies the field by which the results should be sorted. Only applicable to the following fields: title, price, startDate, endDate, language, durationInWeeks. Example: ?sortBy=startDate

  • sortOrder: (Optional) Determines the sorting order, either 'asc' (ascending) or 'desc' (descending). Example: ?sortOrder=desc

  • minPrice, maxPrice: (Optional) Filters results by a price range. Example: ?minPrice=20.00&maxPrice=50.00

  • tags: (Optional) Filters results by the name of a specific tag. Example: ?tags=Programming

  • startDate, endDate: (Optional) Filters results by a date range. Example: ?startDate=2023-01-01&endDate=2023-12-31

  • language: (Optional) Filters results by the language of the course. Example: ?language=English

  • provider: (Optional) Filters results by the course provider. Example: ?provider=Tech Academy

  • durationInWeeks: (Optional) Filters results by the duration of the course in weeks. Example: ?durationInWeeks=8

  • level: (Optional) Filters results by the difficulty level of the course. Example: ?level=Intermediate

  • Response:

    • Make sure that the password field or any other security-related field is not included in the response data.
    {
        "success": true,
        "statusCode": 200,
        "message": "Courses retrieved successfully",
    		"meta": {
            "page": 1,
            "limit": 10,
            "total": 50
        },
        "data": {
            "courses": [
                {
                    "_id": "67890fghij54321abcde",
                    "title": "Introduction to Web Development",
                    "instructor": "John Smith",
                    "categoryId": "12345abcde67890fghij",
                    "price": 49.99,
                    "tags": [
                        {"name": "Programming", "isDeleted": false},
                        {"name": "Web Development", "isDeleted": false}
                    ],
                    "startDate": "2023-02-01",
                    "endDate": "2023-04-01",
                    "language": "English",
                    "provider": "Tech Academy",
                    "durationInWeeks": 8,
                    "details": {
                        "level": "Beginner",
                        "description": "A comprehensive introduction to web development."
                    },
                    "createdBy": {  // Include an addition during assignment 4
                        "_id": "adminUserId",
                        "username": "adminUser",
                        "email": "admin@example.com",
                        "role": "admin"
                    },
                    "createdAt": "2023-01-15T12:00:00.000Z",
                    "updatedAt": "2023-01-15T12:00:00.000Z"
                },
                // ... other courses
            ]
        }
    }

6**. Create a Category (Only Admin can do this)**

  • Endpoint: /api/categories

  • Method: POST

  • Request Headers:

    Authorization: <ADMIN_JWT_TOKEN>
  • Request Body:

    {
        "name": "Web Development"
    }
  • Response:

    {
        "success": true,
        "statusCode": 201,
        "message": "Category created successfully",
        "data": {
            "_id": "12345abcde67890fghij",
            "name": "Web Development",
            "createdBy": "adminUserId",
            "createdAt": "2023-01-15T12:00:00.000Z",
            "updatedAt": "2023-01-15T12:00:00.000Z"
        }
    }

    7**. Get All Categories**

    • Endpoint: /api/categories

    • Method: GET

    • Response:

      • Make sure that the password field or any other security-related field is not included in the response data.
      {
          "success": true,
          "statusCode": 200,
          "message": "Categories retrieved successfully",
          "data": {
              "categories": [
                  {
                      "_id": "12345abcde67890fghij",
                      "name": "Web Development",
                      "createdBy": {  // Include an addition during assignment 4
                          "_id": "adminUserId",
                          "username": "adminUser",
                          "email": "admin@example.com",
                          "role": "admin"
                      },
                      "createdAt": "2023-01-15T12:00:00.000Z",
                      "updatedAt": "2023-01-15T12:00:00.000Z"
                  },
                  // ... other categories
              ]
          }
      }

    8**. Create a Review (Only the user can do this)**

    • Endpoint: /api/reviews

    • Method: POST

    • Request Headers:

      Authorization: <USER_JWT_TOKEN>
    • Request Body:

      {
          "courseId": "67890fghij54321abcde",
          "rating": 4,
          "review": "Great course, very informative and well-structured."
      }
    • Response:

      • Make sure that the password field or any other security-related field is not included in the response data.
      {
          "success": true,
          "statusCode": 201,
          "message": "Review created successfully",
          "data": {
              "_id": "98765fghij43210lkji",
              "courseId": "67890fghij54321abcde",
              "rating": 4,
              "review": "Great course, very informative and well-structured.",
              "createdBy": {   // Include an addition during assignment 4
                  "_id": "UserId",
                  "username": "username",
                  "email": "user@example.com",
                  "role": "user"
              },
              "createdAt": "2023-01-15T12:00:00.000Z",
              "updatedAt": "2023-01-15T12:00:00.000Z"
          }
      }

    9**. Update a Course (Only Admin can do this)**

    • Endpoint: /api/courses/:courseId

    • Method: PUT

    • Request Headers:

      Authorization: <ADMIN_JWT_TOKEN>
    • Request Body:

      {
          "price": 59.99,
          "tags": [
              {"name": "Programming", "isDeleted": false},
              {"name": "Web Development", "isDeleted": false},
              {"name": "JavaScript", "isDeleted": false}
          ],
          "details": {
              "level": "Intermediate",
              "description": "A comprehensive course on web development with a focus on JavaScript."
          }
      }
    • Response:

      • Make sure that the password field or any other security-related field is not included in the response data.
      {
          "success": true,
          "statusCode": 200,
          "message": "Course updated successfully",
          "data": {
              "_id": "67890fghij54321abcde",
              "title": "Introduction to Web Development",
              "instructor": "John Smith",
              "categoryId": "12345abcde67890fghij",
              "price": 59.99,
              "tags": [
                  {"name": "Programming", "isDeleted": false},
                  {"name": "Web Development", "isDeleted": false},
                  {"name": "JavaScript", "isDeleted": false}
              ],
              "startDate": "2023-02-01",
              "endDate": "2023-04-01",
              "language": "English",
              "provider": "Tech Academy",
              "durationInWeeks": 8,
              "details": {
                  "level": "Intermediate",
                  "description": "A comprehensive course on web development with a focus on JavaScript."
              },
              "createdBy": {   // Include an addition during assignment 4
                  "_id": "adminUserId",
                  "username": "adminUser",
                  "email": "admin@example.com",
                  "role": "admin"
              },
              "createdAt": "2023-01-15T12:00:00.000Z",
              "updatedAt": "2023-01-16T12:30:00.000Z"
          }
      }

    10**. Get Course by ID with Reviews**

    • Endpoint: /api/courses/:courseId/reviews

    • Method: GET

    • Response:

      {
          "success": true,
          "statusCode": 200,
          "message": "Course with reviews retrieved successfully",
          "data": {
              "course": {
                  "_id": "67890fghij54321abcde",
                  "title": "Introduction to Web Development",
                  "instructor": "John Smith",
                  "categoryId": "12345abcde67890fghij",
                  "price": 59.99,
                  "tags": [
                      {"name": "Programming", "isDeleted": false},
                      {"name": "Web Development", "isDeleted": false},
                      {"name": "JavaScript", "isDeleted": false}
                  ],
                  "startDate": "2023-02-01",
                  "endDate": "2023-04-01",
                  "language": "English",
                  "provider": "Tech Academy",
                  "durationInWeeks": 8,
                  "details": {
                      "level": "Intermediate",
                      "description": "A comprehensive course on web development with a focus on JavaScript."
                  },
                  "createdBy": {   // Include an addition during assignment 4
                      "_id": "adminUserId",
                      "username": "adminUser",
                      "email": "admin@example.com",
                      "role": "admin"
                  },
                  "createdAt": "2023-01-15T12:00:00.000Z",
                  "updatedAt": "2023-01-16T12:30:00.000Z"
              },
              "reviews": [
                  {
                      "_id": "98765fghij43210lkji",
                      "courseId": "67890fghij54321abcde",
                      "rating": 4,
                      "review": "Great course, very informative and well-structured.",
                      "createdBy": {    // Include an addition during assignment 4
                          "_id": "userid",
                          "username": "username",
                          "email": "user@example.com",
                          "role": "user"
                      },
                      "createdAt": "2023-01-15T12:00:00.000Z",
                      "updatedAt": "2023-01-15T12:00:00.000Z"
                  },
                  // ... other reviews
              ]
          }
      }

    11**. Get the Best Course Based on Average Review (Rating)**

    • Endpoint: /api/course/best

    • Method: GET

    • Response:

      {
          "success": true,
          "statusCode": 200,
          "message": "Best course retrieved successfully",
          "data": {
              "course": {
                  "_id": "23245dsfd453242348rFcg",
                  "title": "Best Book Title",
                  "instructor": "New Instructor",
                  "categoryId": "123456789012345678901234",
                  "price": 59.99,
                  "tags": [
                      {
                          "name": "Programming",
                          "isDeleted": false
                      },
                      {
                          "name": "Web Development",
                          "isDeleted": false
                      }
                  ],
                  "startDate": "2023-02-01",
                  "endDate":"2023-03-14",
                  "language": "Spanish",
                  "provider": "Code Masters",
                  "durationInWeeks": 6,
                  "details": {
                      "level": "Intermediate",
                      "description": "Detailed description of the course"
                  },
                  "createdBy": {
                      "_id": "userid",
                      "username": "username",
                      "email": "user@example.com",
                      "role": "user"
                  },
                  "createdAt": "2023-01-15T12:00:00.000Z",
                  "updatedAt": "2023-01-15T12:00:00.000Z"
              },
              "averageRating": 4.8,
              "reviewCount": 50
          }
      }

      Unauthorized Error Response:

      If an unauthorized access attempt is detected, the system will respond with the following error message:

      {
          "success": false,
          "message": "Unauthorized Access",
          "errorMessage": "You do not have the necessary permissions to access this resource.",
          "errorDetails": null,
          "stack": null
      }

      This error may occur under the following circumstances:

      • JWT Expiry: The provided JWT (JSON Web Token) has expired.
      • Invalid JWT: The JWT provided is invalid or malformed.
      • Undefined JWT: No JWT is provided in the request headers.
      • Not Authorized User: The user does not possess the required permissions for the requested action or resource.
      • Access Denied: The user is attempting to access a resource without the necessary authorization.

    Instructions

    Follow these steps to complete the assignment:

    1. Clone Repository:
      • Clone your Assignment 3 repository to create a new project for Assignment 4. (n.b: make sure to remove the previous .git from the folder, from the git bash terminal simply run the command rm -rf .git )
    2. Project Structure:
      • Organize your project structure to accommodate the new features and models outlined in the assignment requirements.
      • Ensure that your code follows best practices for project structure, readability, and maintainability.
    3. Implement User Authentication and Authorization:
      • Implement user registration, login, and password change functionalities as per the specified routes and request/response formats.
      • Ensure that the system securely stores and manages passwords using hashing.
      • Implement JWT-based authentication for user login.
      • Define user roles (user, admin) and enforce authorization checks for actions that require specific roles.
    4. Enhance User Model:
      • Update the User model to include the specified fields, including the security schema for managing password history.
    5. Update Course, Category, and Review Functionality:
      • Implement course and category creation, as well as review submission functionalities.
      • Ensure that only an admin user can create courses and categories.
      • Allow users to submit reviews for courses.
    6. Update Query Options for Courses:
      • Implement the ability to retrieve courses based on various query parameters, as specified in the assignment.
      • Implement pagination and filtering options.
    7. Error Handling:
      • Implement appropriate error handling for unauthorized access attempts.
      • Provide clear and informative error messages in case of authentication or authorization failures.
    8. Create Documentation:
      • Update or create API documentation to reflect the new endpoints, request/response formats, and query options.
      • Include examples and explanations for each endpoint.
    9. Create a New Repository:
      • Create a new GitHub repository specifically for Assignment 4.
      • Ensure that your commit history is well-organized and includes clear commit messages.
    10. Submission:
      • Provide a README.md file in your new repository explaining how to set up and run your project.
      • Share the GitHub repository link with the instructor for evaluation.
      • Live site link
      • Include user and admin login credentials that were submitted in the assignment submission input box. Follow the format below.
        • User Login:

          • Username: [User-Submitted-Username]
          • Password: [User-Submitted-Password]
        • Admin Login:

          • Username: [Admin-Submitted-Username]
          • Password: [Admin-Submitted-Password]

    Important Notes

    • Independent Submission: This assignment is meant to be submitted as a separate project/repository from Assignment 3. Do not make changes to the existing Assignment 3 repository.
    • Live Link: Provide a live link to your GitHub repository for evaluation.
    • Code Quality: Follow best practices for code quality, readability, and maintainability.
    • Documentation: Thoroughly document your API endpoints, request/response formats, and any other relevant information.
    • Security: Prioritize the security of user data, passwords, and access controls.

Deadline:

  • 60 marks: December 28, 2023 11.59PM
  • 50 marks: December 30, 2023 11.59PM

Good luck with your assignment!