Download as pdf or txt
Download as pdf or txt
You are on page 1of 53

Question Bank

Course Code and Name : R19CS653 Full Stack Technologies


Year/Semester : II / IV Semester
MODULE 4 – NODEJS AND EXPRESSJS

PART A (16 QUESTIONS)

S.NO QUESTIONS BT COGNIZAN


LEVEL CE LEVEL

1. Define Node Module in Node.js K1 Remember


Ans:
A Node Module in Node.js is a reusable piece of code
organized into separate files, each containing
functions, objects, or variables that can be exported
and used in other parts of a Node.js application.
Modules facilitate code organization, encapsulation,
and reusability in Node.js.

2. Explain the purpose of the require function in K2 Understand


Node.js. Ans:
The require function in Node.js is used to include and
import external modules into a Node.js application. It
allows access to the functionality and code defined in
other files, making it possible to reuse and organize
code efficiently. The require function returns the
exported content of the specified module, enabling
the use of its functions, variables, or objects within
the current file.
3. How do you initialize a new Node.js project with K2 Understand
NPM, and what file does it generate to manage
project dependencies?
Ans:
To initialize a new Node.js project with NPM,
you use the following command:
npm init
This command prompts you to provide
information about your project, and it generates
a package.json file. The package.json file
contains metadata about the project and its
dependencies, and it serves as a configuration
file for NPM. It

allows you to specify project details, scripts,


and dependencies, making it essential for
managing Node.js projects.

4. Explain the role of HTTP methods (such as GET, K2 Understand


POST, and DELETE) in building RESTful APIs using
Express.

Ans:
In building RESTful APIs using Express, HTTP methods
play a crucial role in defining the operations that can be
performed on resources. For example:

GET: Retrieves data from the server.


POST: Submits data to be processed to a specified
resource. DELETE: Requests the removal of a resource.
● By mapping these HTTP methods to specific routes and
handlers in Express, developers can create APIs that
follow REST principles, enabling clients to interact with
resources in a predictable and standardized way.
5. How does middleware contribute to the development of K2` Understand
RESTful APIs in Express, and provide an example of a
common middleware?

Ans:
Middleware in Express enhances the functionality of the
application by allowing developers to perform additional
tasks during the request-response cycle. Middleware
functions can be used to handle tasks such as logging,
authentication, or parsing request bodies. For example, the
body-parser middleware is commonly used to parse
incoming request bodies in JSON format. This is crucial
when dealing with POST requests that contain data.

Example:
const express = require('express');
const bodyParser = require('body-parser');

const app = express();

// Middleware to parse incoming JSON


requests app.use(bodyParser.json());

// Define API routes and handlers...

6. Define feature defects. K1 Remember


Ans:
Features may be described as distinguishing characteristics
of a software component or system. The defects that are
appearing in those components are known as feature
defects.
7. What keyword is commonly used in JavaScript to K1 Remember
declare a function as asynchronous, and how is it used?

Ans:
The async keyword is used to declare a function as
asynchronous in JavaScript. When a function is marked as
async, it allows the use of the await keyword within the
function body to handle asynchronous operations. The
await keyword is used to pause the execution of the async
function until the promise is resolved, simplifying
asynchronous code.

Example:
async function fetchData() {
// Asynchronous operation using 'await'
const result = await
someAsyncFunction(); return result;
}

8. Explain the concept of callback functions in K2 Understand


asynchronous JavaScript and provide a simple
example.

Ans:
Callback functions in asynchronous JavaScript are
functions that are passed as arguments to other functions
and are executed after the completion of an
asynchronous operation. They help handle asynchronous
tasks by specifying what should happen once the
operation is complete.
For example:
function fetchData(callback) {
// Simulate an asynchronous operation
setTimeout(() => {
const data = 'Async data';
callback(data);
}, 1000);
}

// Using the callback function


fetchData((result) => {
console.log(result); // Output: Async data
});

9. Explain the role of Mongoose in the context of K2 Understand


MongoDB and CRUD operations.

Ans:
Mongoose is an ODM (Object-Document Mapper) for
MongoDB and Node.js. It provides a schema-based
solution to model and interact with MongoDB documents
in a more structured manner. When it comes to CRUD
operations:

Create (C): Mongoose allows developers to define models


with schemas, making it easier to create and insert
documents into MongoDB collections.

Read (R): Models in Mongoose simplify querying by


providing methods to find, filter, and retrieve documents
from MongoDB collections.

Update (U): Mongoose facilitates updates by providing


methods to modify existing documents, either partially or
entirely.

Delete (D): Mongoose enables the removal of documents


from MongoDB collections using predefined methods.

10. How does Mongoose handle validation during the K2 Understand


creation of documents, and why is it important?

Ans:
Mongoose allows developers to define schema
structures, including data types and constraints. During
the creation of documents, Mongoose automatically
validates data based on these defined schemas. This
validation ensures that the data adheres to the specified
rules, such as required fields, data types, and custom
validations. It is crucial for maintaining data integrity
and consistency, preventing the insertion of invalid or
incorrect data into the MongoDB database. Validation
in Mongoose helps to enforce a predefined structure and
enhances the reliability of the data being stored.

11. How does Mongoose handle custom validation in K2 Understand


MongoDB schemas?

Ans:

Mongoose allows developers to define custom validation


functions within the schema definition. These functions are
executed during the validation process, providing a way to
implement specific business rules or complex validation
logic. For example:

12. What is the role of the required property in K1 Remember


Mongoose schema for MongoDB data validation?

Ans:
The required property in a Mongoose schema is used to
specify whether a particular field must have a value before
a document can be saved to the MongoDB collection. If
required is set to true for a field, it means that the field
must be present and non-null in the document. This helps
enforce the presence of essential data, ensuring that
documents meet specific criteria.

13. Explain the concept of population in Mongoose K2 Understand


when modeling relationships between documents.
Ans:
In Mongoose, population is a way to associate
documents from one collection with documents from
another collection by using references. It involves
replacing specified paths in a document with actual
documents from another collection during queries. This
helps in establishing relationships between connected
data without embedding the entire related document.
By using population, you can retrieve and display
information from multiple collections in a more
efficient and organized manner.
14. Differentiate between embedding and referencing K2 Understand
when modeling relationships in Mongoose.

Ans:

Embedding: In embedding, documents from one


collection are nested within documents of another
collection. This results in a denormalized structure where
related data is physically stored together. While it can
improve read performance, updates may require
modifications to multiple documents.

Referencing: Referencing involves storing references


(e.g., ObjectId) to documents in another collection. This
creates a

normalized structure, reducing data redundancy. While it


may require additional queries to fetch related data,
updates are typically simpler. Mongoose's population
feature facilitates referencing relationships.

15. How does JSON Web Token (JWT) contribute to K2 Undersstand


authentication in a connected data environment?

Ans:
JSON Web Tokens (JWT) are a compact, URL-safe
means of representing claims to be transferred between
two parties. In the context of authentication, JWTs are
commonly used to securely transmit information about
the user between the client and the server. Once a user is
authenticated, the server issues a JWT that contains
relevant information (claims) about the user. The client
can then include this token in subsequent requests,
allowing the server to verify the user's identity and grant
access based on the information stored in the JWT.
16. What is the primary purpose of MongoDB's K1 Remember
"sharding" in a deployment?

Ans:
Sharding in MongoDB is a technique used for horizontal
scaling, which involves dividing large amounts of data
across multiple servers or clusters. The primary purpose
of sharding is to distribute the data and workload across
multiple machines, improving performance, and enabling
the system to handle large amounts of data and high
traffic.

PART B (8 QUESTIONS)

1. Explain the key concepts of the Node Module System in K2 Understand


Node.js, focusing on module creation, export, and
import mechanisms. Provide examples to illustrate
these concepts.

Ans:

The Node Module System in Node.js is fundamental for


organizing and modularizing code. It consists of several
key concepts:

1.Module Creation:

In Node.js, each file is treated as a separate module. A


module encapsulates a piece of code with its own scope,
preventing
global scope pollution.

To create a module, you use the module.exports or exports


object to expose functions, variables, or objects for use in
other modules.

Example (myModule.js):
// myModule.js
const privateVariable = 'I am private';

const publicFunction = () => {


console.log('Public function called');
};

module.exports = {
publicFunction,
};
2.Exporting Functionality:

Exporting functionality from a module is achieved using


the module.exports or exports object.

You can attach variables, functions, or objects to the


module.exports object.

Example (myModule.js):

// myModule.js
const myFunction = () => {
console.log('Hello from my function');
};

module.exports = myFunction;
3.Importing and Using Modules:
To use a module, you use the require function in another file,

specifying the path to the module.

The result of the require function is an object containing


the exported functionality.

Example (app.js):
// app.js
const myFunction = require('./myModule');

myFunction(); // Outputs: Hello from my function


These concepts allow developers to create modular and
reusable code, enhancing maintainability and scalability in
Node.js applications. The module.exports and require
mechanisms enable effective communication between
modules, promoting a clean and organized code structure.
2. Explain the key concepts of Node Package Manager K2 Understand
(NPM), focusing on package management,
package.json, and dependency management. Provide
examples to illustrate these concepts.

Ans:

Node Package Manager (NPM) is a crucial tool in the


Node.js ecosystem, facilitating the management of
packages and dependencies. The key concepts include:

Package Management:

NPM simplifies the process of installing, managing, and


sharing packages (libraries or tools) in Node.js projects.

To install a package locally, you use the npm install


command followed by the package name. For example:

npm install express


package.json File:

The package.json file is a configuration file for Node.js


projects. It contains metadata about the project, including
dependencies, scripts, and other project-specific
information.
You can initialize a new package.json file using the npm
init command. It prompts you to provide details about the
project.

Example (package.json):

json
Copy code
{
"name": "my-node-project",
"version": "1.0.0",
"description": "A description of my project",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"express": "^4.17.1"
},
"devDependencies": {
"nodemon": "^2.0.12"
},
"keywords": ["node", "npm"],
"author": "Your Name",
"license": "MIT"
}
Dependency Management:
Dependencies are specified in the dependencies or
devDependencies section of the package.json
file.Dependencies include packages required for the
application to run, while devDependencies include
packages needed for development purposes.

Example (package.json):

"dependencies": {
"express": "^4.17.1",
"mongoose": "^6.0.12"
},
"devDependencies": {

"nodemon": "^2.0.12",
"eslint": "^7.32.0"
}
These concepts allow developers to manage project
dependencies efficiently, ensuring consistency across
different environments and simplifying collaboration.
NPM's package.json plays a central role in defining project
configurations and dependencies, providing a standardized
way to structure and share Node.js projects.
3. Explain the key concepts of building RESTful APIs K2 Understand
using Express, focusing on route handling, middleware,
request/response handling, and CRUD operations.
Provide examples to illustrate these concepts.

Ans:

Building RESTful APIs with Express involves several


key concepts that contribute to creating scalable,
maintainable, and standardized APIs. Let's explore
these concepts:

Route Handling:

In Express, routes define the endpoints of the API and are


associated with specific HTTP methods (GET, POST,
PUT, DELETE).

Route handlers are functions executed when a specific


route is matched.

Example (app.js):

javascript
const express = require('express');
const app = express();

// Define a route handler for GET request to '/'


app.get('/', (req, res) => {
res.send('Hello, World!');
});

// Start the server


app.listen(3000, () => {
console.log('Server is running on port 3000');
});
Middleware:
Middleware functions in Express execute during the
request response cycle and can modify the request or
response objects.

Middleware is applied using app.use() or within


specific route handlers.

Example (app.js):

javascript
const express = require('express');
const app = express();

// Custom middleware function


const loggerMiddleware = (req, res, next)
console.log(`Request received at: ${new
Date()}`); next();
};

// Apply middleware globally


app.use(loggerMiddleware);

// Route handler
app.get('/', (req, res) => {
res.send('Hello, World!');
});

// Start the server


app.listen(3000, () => {
console.log('Server is running on port 3000');
});
Request/Response Handling:

Express provides methods and properties on the req


(request) and res (response) objects for handling
incoming requests and constructing responses.

Example (app.js):

javascript
const express = require('express');
const app = express();

// Route handler for handling POST request


app.post('/api/users', (req, res) => {
const { username, email } = req.body;
// Perform logic to create a new user
res.status(201).json({ message: 'User created
successfully' });
});

// Start the server


app.listen(3000, () => {
console.log('Server is running on port 3000');
});
CRUD Operations:

RESTful APIs often involve CRUD (Create, Read,


Update, Delete) operations.

Express routes and handlers are used to implement


these operations for different resources.

Example (app.js):

javascript
const express = require('express');
const app = express();

// Simulated in-memory database


let users = [];

// Create (POST) a new user


app.post('/api/users', (req, res) => {
const { username, email } = req.body;
const newUser = { id: users.length + 1, username, email
}; users.push(newUser);
res.status(201).json(newUser);
});

// Read (GET) all users


app.get('/api/users', (req, res) => {
res.json(users);
});

// Update (PUT) a user by ID


app.put('/api/users/:id', (req, res) => {
const userId = parseInt(req.params.id);
const { username, email } = req.body;
const user = users.find(u => u.id === userId);
if (user) {

user.username = username;
user.email = email;
res.json(user);
} else {
res.status(404).json({ message: 'User not found'
}); }
});

// Delete (DELETE) a user by ID


app.delete('/api/users/:id', (req, res) => {
const userId = parseInt(req.params.id);
users = users.filter(u => u.id !== userId);
res.json({ message: 'User deleted successfully'
}); });

// Start the server


app.listen(3000, () => {
console.log('Server is running on port 3000');
});
These concepts form the foundation of building RESTful
APIs using Express. The ability to define routes, utilize
middleware, handle requests and responses, and
implement CRUD operations enables developers to
create robust and scalable APIs in the Node.js
environment.
4. Explain the key concepts of asynchronous JavaScript, focusing K2 Understand
on callback functions, Promises, and the async/await syntax.
Provide examples to illustrate these concepts.

Ans:

Asynchronous JavaScript is crucial for handling operations that


may take time to complete, such as fetching data from a server
or reading a file. Let's explore the key concepts:

Callback Functions:

Callback functions are functions that are passed as arguments to


other functions and executed later, usually after the completion
of an asynchronous operation.

Example (callbackExample.js):

javascript

// Function with a callback


const fetchData = (callback) => {

setTimeout(() => {

const data = 'Async data';

callback(data);

}, 1000);

};

// Using the callback function

fetchData((result) => {

console.log(result); // Output: Async data

});

Promises:

Promises are a more structured way to handle asynchronous


operations. A Promise represents the eventual completion or
failure of an asynchronous operation, and it has states: pending,
fulfilled, or rejected.

Example (promiseExample.js):

javascript

// Function returning a Promise

const fetchData = () => {

return new Promise((resolve, reject) => {

setTimeout(() => {

const success = true;

if (success) {
resolve('Async data');

} else {

reject('Error fetching data');

}, 1000);

});

};

// Using the Promise

fetchData()

.then((result) => {

console.log(result); // Output: Async data

})

.catch((error) => {

console.error(error);

});

async/await Syntax:

The async/await syntax provides a more concise way to work


with Promises, making asynchronous code appear more like
synchronous code.

Example (asyncAwaitExample.js):

javascript

// Function using async/await

const fetchData = async () => {


try {

const result = await new Promise((resolve) => {

setTimeout(() => {

resolve('Async data');

}, 1000);

});

console.log(result); // Output: Async data

} catch (error) {

console.error(error);

};

// Calling the async function

fetchData();

These concepts help developers manage the flow of


asynchronous operations, making the code more readable and
maintainable. Callbacks are the foundation, Promises provide a
structured approach, and async/await simplifies asynchronous
code, especially when dealing with multiple asynchronous
operations.
5. Imagine you are developing a Node.js application with K3 Apply
MongoDB using Mongoose to manage data related to a
library. The application needs to perform CRUD
operations (Create, Read, Update, Delete) on a
collection of books. Provide a detailed explanation and
code examples for each CRUD operation using
Mongoose.
Ans:
1. Create (Insert) Operation:
To add a new book to the MongoDB database using
Mongoose.

Example (createBook.js):
const mongoose = require('mongoose');
const Book = require('./models/book'); // Assuming a
Mongoose model named 'Book'

// Create a new book


const newBook = new Book({
title: 'The Great Gatsby',
author: 'F. Scott Fitzgerald',
genre: 'Fiction',
});

// Save the new book to the database


newBook.save()
.then((savedBook) => {
console.log('Book created successfully:', savedBook);
})
.catch((error) => {
console.error('Error creating book:', error);
});
2. Read (Retrieve) Operation:
To retrieve information about books from the MongoDB
database using Mongoose.

Example (readBooks.js):

const mongoose = require('mongoose');


const Book = require('./models/book');

// Retrieve all books


Book.find()
.then((books) => {
console.log('All Books:', books);
})
.catch((error) => {
console.error('Error retrieving books:', error);
});

// Retrieve a specific book by title


Book.findOne({ title: 'The Great Gatsby' })
.then((book) => {
console.log('Book by Title:', book);
})
.catch((error) => {
console.error('Error retrieving book by title:', error);
});
3. Update Operation:
To modify the details of an existing book in the MongoDB
database using Mongoose.

Example (updateBook.js):

const mongoose = require('mongoose');


const Book = require('./models/book');

// Update a book by title


Book.findOneAndUpdate({ title: 'The Great Gatsby' }, {
genre: 'Classic Fiction' }, { new: true })
.then((updatedBook) => {
console.log('Book updated successfully:', updatedBook);
})
.catch((error) => {
console.error('Error updating book:', error);
});
4. Delete Operation:
To remove a book from the MongoDB database using
Mongoose.

Example (deleteBook.js):

const mongoose = require('mongoose');


const Book = require('./models/book');

// Delete a book by title


Book.findOneAndDelete({ title: 'The Great Gatsby'
}) .then((deletedBook) => {
console.log('Book deleted successfully:', deletedBook);
})
.catch((error) => {
console.error('Error deleting book:', error);
});
These examples demonstrate how to perform CRUD
operations on a MongoDB collection of books using
Mongoose in a Node.js application. The Book model
assumes a Mongoose schema and model are defined
elsewhere in the codebase.
6. Explain the importance of data validation in MongoDB K2 Understand
using Mongoose, focusing on built-in validators and
custom validation functions. Provide examples to
illustrate these concepts.

Ans:

Data validation is crucial in MongoDB to ensure the


integrity and consistency of the data stored. Mongoose
provides mechanisms for both built-in and custom data
validation.

Built-in Validators:

Mongoose supports a variety of built-in validators that can


be applied to schema fields.

Example (userModel.js):

const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({


username: {
type: String,
required: true,
minlength: [5, 'Username must be at least 5 characters
long'],
maxlength: 20,
},
email: {
type: String,
required: true,
unique: true,
validate: {
validator: function (value) {
// Custom email validation logic
return /\S+@\S+\.\S+/.test(value);
},
message: 'Invalid email format',
},
},
age: {
type: Number,
min: [18, 'Age must be at least 18'],
max: 100,
},
});

const User = mongoose.model('User', userSchema);

module.exports = User;
Custom Validation Functions:

Mongoose allows the definition of custom validation


functions for specific fields.

Example (productModel.js):

javascript
Copy code
const mongoose = require('mongoose');

const productSchema = new


mongoose.Schema({ productName: {
type: String,
required: true,
validate: {
validator: function (value) {
// Custom validation logic for product name return
value.length <= 50;
},
message: 'Product name must be at most 50 characters
long',
},
},
price: {
type: Number,
required: true,
min: [0.01, 'Price must be greater than or equal to 0.01'],
},
});

const Product = mongoose.model('Product',


productSchema); module.exports = Product;

In this context, data validation using Mongoose ensures


that the data adheres to specified rules and constraints,
preventing the insertion of invalid or inconsistent data into
the MongoDB database. Whether using built-in validators
or custom

validation functions, developers can enforce a predefined


structure and enhance the reliability of the data being
stored in MongoDB.
7. Consider a scenario where you are developing a social K3 Apply
media application using Node.js and MongoDB. The
application has two main entities: Users and Posts.
Users can create multiple posts, and each post is
associated with a specific user. Using Mongoose,
explain how you would model and implement the
relationship between Users and Posts. Provide code
examples for creating schemas, defining relationships,
and performing queries to retrieve related data.
Ans:

1. Modeling the Schemas:


Define Mongoose schemas for Users and Posts,
establishing a relationship between them.
Example (userModel.js):

javascript
Copy code
const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({


username: {
type: String,
required: true,
unique: true,
},
email: {
type: String,
required: true,
unique: true,
},
// Other user fields...
});

const User = mongoose.model('User', userSchema);

module.exports = User;
Example (postModel.js):

const mongoose = require('mongoose');

const postSchema = new mongoose.Schema({


title: {
type: String,
required: true,
},
content: {
type: String,
required: true,
},
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User', // Reference to the User model
required: true,
},
// Other post fields...
});

const Post = mongoose.model('Post',

postSchema); module.exports = Post;

2. Establishing Relationships
Use the ref property to establish a reference between the
Post schema and the User schema.
Example (postModel.js):

const postSchema = new mongoose.Schema({


// ... (Previous fields)
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User', // Reference to the User model
required: true,
},
// ... (Other post fields)
});

// ... (Rest of the code)


3. Creating and Associating Data
Create users and posts, associating each post with a
specific user.
Example (seedData.js for demonstration purposes):

const mongoose = require('mongoose');


const User = require('./userModel');
const Post = require('./postModel');
// Connect to MongoDB (assuming a connection has been
established)

// Create users
const user1 = new User({ username: 'user1', email:
'user1@example.com' });
const user2 = new User({ username: 'user2', email:
'user2@example.com' });

// Save users
user1.save();
user2.save();

// Create posts associated with users


const post1 = new Post({ title: 'Post 1', content: 'Content 1',
user: user1 });
const post2 = new Post({ title: 'Post 2', content: 'Content 2',
user: user2 });

// Save posts
post1.save();
post2.save();
4. Querying for Related Data:
Retrieve posts along with user details using Mongoose
population.
Example (fetchPosts.js):

javascript
Copy code
const mongoose = require('mongoose');
const Post = require('./postModel');

// Connect to MongoDB (assuming a connection has been


established)

// Fetch posts with user details using


population Post.find()
.populate('user', 'username email') // Populate the 'user'
field with specified fields
.exec()
.then((posts) => {
console.log('Posts with User Details:', posts);
})
.catch((error) => {
console.error('Error fetching posts:', error);
});

In this scenario, the Mongoose models for User and Post


are designed to establish a relationship between the two
entities. The ref property in the Post schema is used to
reference the User model, creating a connection. When
querying for posts, the populate method is employed to
fetch user details along with the posts, providing a
comprehensive view of the connected data. This modeling
and implementation approach ensures efficient handling of
relationships in a social media application.
8 Consider a scenario where you are developing a secure K3 Apply
web application using Node.js, Express, and MongoDB.
The application requires user authentication and
authorization. Explain how you would implement user
authentication, including user registration, login, and
token-based authentication. Additionally, detail the
process of implementing authorization using roles and
access control. Provide code examples to illustrate these
concepts.

Ans:

1. User Authentication:
User Registration:
Create a Mongoose model for users, and implement
routes and controllers for user registration.
Example (userModel.js):

const mongoose = require('mongoose');


const bcrypt = require('bcrypt');

const userSchema = new mongoose.Schema({


username: {
type: String,
required: true,
unique: true,
},
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
});

// Hash password before saving


userSchema.pre('save', async function (next) {
const user = this;
if (user.isModified('password')) {
const salt = await bcrypt.genSalt(10);
user.password = await bcrypt.hash(user.password, salt);
}
next();
});

const User = mongoose.model('User', userSchema);

module.exports = User;
Example (authController.js):

const User = require('../models/userModel');

const registerUser = async (req, res) => {


try {
const newUser = new User(req.body);
await newUser.save();
res.status(201).json({ message: 'User registered
successfully' });
} catch (error) {
res.status(400).json({ message: 'Registration failed',
error: error.message });
}
};
module.exports = { registerUser };
User Login:
Implement a login route and controller to authenticate
users.
Example (authController.js):

const bcrypt = require('bcrypt');


const jwt = require('jsonwebtoken');
const User = require('../models/userModel');

const loginUser = async (req, res) => {


try {
const { email, password } = req.body;
const user = await User.findOne({ email });

if (!user) {
return res.status(401).json({ message: 'Invalid
credentials' });
}

const isPasswordValid = await


bcrypt.compare(password, user.password);
if (!isPasswordValid) {
return res.status(401).json({ message: 'Invalid
credentials' });
}

const token = jwt.sign({ userId: user._id }, 'secretKey',


{ expiresIn: '1h' });
res.json({ token });
} catch (error) {
res.status(400).json({ message: 'Login failed', error:
error.message });
}
};

module.exports = { loginUser };
Token-based Authentication:
Generate a JWT (JSON Web Token) upon successful login
for secure and stateless authentication.
Example (authMiddleware.js):

const jwt = require('jsonwebtoken');

const authenticateUser = (req, res, next) => {


const token = req.header('Authorization');
if (!token) {
return res.status(401).json({ message: 'Unauthorized -
Missing token' });
}

try {
const decoded = jwt.verify(token, 'secretKey');
req.userId = decoded.userId;
next();
} catch (error) {
res.status(401).json({ message: 'Unauthorized - Invalid
token' });
}
};

module.exports = { authenticateUser };
2. User Authorization:
Roles and Access Control:
Define roles for users (e.g., 'admin', 'user') and
implement middleware for role-based access control.
Example (authMiddleware.js):

javascript
Copy code
const checkUserRole = (roles) => {
return (req, res, next) => {
if (!roles.includes(req.userRole)) {
return res.status(403).json({ message: 'Forbidden -
Insufficient privileges' });
}
next();
};
};

module.exports = { checkUserRole };
Protecting Routes with Authorization Middleware:
Apply the authorization middleware to routes that require
specific roles.
Example (adminController.js):

javascript
Copy code
const getAdminData = (req, res) => {
res.json({ message: 'Admin data retrieved successfully'
});
};

module.exports = { getAdminData };
Example (routes.js):

javascript
Copy code
const express = require('express');
const authMiddleware =
require('./middlewares/authMiddleware');
const { checkUserRole } =
require('./middlewares/authMiddleware');
const adminController =
require('./controllers/adminController');

const router = express.Router();

// Protected route accessible by admins only


router.get('/admin-data',
authMiddleware.authenticateUser,
checkUserRole(['admin']),
adminController.getAdminData);

module.exports = router;
In this scenario, the provided code examples illustrate the
implementation of user authentication, including user

registration, login with token-based authentication, and


user authorization with roles and access control. The
application employs JWT for secure authentication, bcrypt
for password hashing, and role-based middleware for
controlling access to specific routes based on user roles.
These measures contribute to the development of a secure
and controlled web application.
9. Imagine you are responsible for deploying a MongoDB K3 Apply
database for a production environment. Explain the step
you would take to deploy MongoDB securely an
efficiently. Discuss considerations such as server setup
security measures, monitoring, and scaling. Provide cod
snippets or configuration examples where appropriate.

Ans

1. Server Setup:
Choose Deployment Environment:

Decide whether to deploy MongoDB on-premise or in


the cloud. Common cloud providers include AWS,
Azure, and Google Cloud.
Select Server Configuration:

Choose server instances based on expected workloads,


considering factors like CPU, RAM, and storage.
Utilize SSDs for better performance.
Install MongoDB:

Install MongoDB on the chosen servers. The installation


steps may vary based on the operating system.
Example (Ubuntu):

sudo apt-get update


sudo apt-get install -y mongodb
2. Security Measures:
Enable Authentication:
Require users to authenticate before accessing the
database. Set up user accounts with appropriate roles.
Example (Mongo Shell):

use admin
db.createUser({
user: 'adminUser',
pwd: 'adminPassword',
roles: ['userAdminAnyDatabase', 'dbAdminAnyDatabase',
'readWriteAnyDatabase'],
})
Enable Encryption:
Enable SSL/TLS encryption to secure data in
transit. Example (MongoD Configuration):

yaml
Copy code
net:
port: 27017
ssl:
mode: requireSSL
PEMKeyFile: /path/to/mongodb.pem
Implement Network Security:
Configure firewalls and network security groups to
restrict access to MongoDB ports.
3. Monitoring:
Set Up Monitoring Tools:

Implement monitoring tools like MongoDB Cloud


Manager, Ops Manager, or third-party solutions to track
performance metrics.
Monitor Key Metrics:

Keep an eye on critical metrics such as query


performance, disk usage, and connection statistics.
Example (Mongo Shell for Query Performance):

db.currentOp({ op: 'query', 'execStats.executionTimeMillis'


{ $gt: 100 } })
4. Scaling:
Horizontal Scaling:
Implement sharding for horizontal scaling. Distribute
data across multiple nodes to handle increased loads.
Example (Sharding a Collection):

sh.enableSharding('myDatabase')
sh.shardCollection('myDatabase.myCollection', {
shardKey: 1 })
Vertical Scaling:

Upgrade server hardware (CPU, RAM, etc.) to


handle increased loads on a single node.
Auto-Scaling:

Use auto-scaling features provided by cloud providers


to dynamically adjust resources based on demand.
5. Backup and Recovery:
Scheduled Backups:
Set up regular backups to ensure data integrity and
facilitate recovery in case of failures.
Example (Mongo Shell for Backup):

mongodump --host <hostname> --port <port>


--out /path/to/backup/directory
Point-in-Time Recovery:
Implement tools or strategies for point-in-time recovery
to restore data to a specific state.
6. Performance Optimization:
Indexing:
Create appropriate indexes to enhance query
performance. Example (Mongo Shell for Indexing):
db.myCollection.createIndex({ fieldName: 1 })
Query Optimization:
Analyze and optimize queries to improve overall
database performance.
Example (Explain Query Execution):

javascript
Copy code
db.myCollection.find({ fieldName: 'value'
}).explain('executionStats')
7. Regular Maintenance:
Update MongoDB Version:
Keep MongoDB up-to-date with the latest stable releases
to benefit from bug fixes and improvements.
Example (Upgrade MongoDB Version):

sudo apt-get update


sudo apt-get install -y mongodb-org
Log Rotation:
Implement log rotation to manage log files
efficiently. Example (Logrotate Configuration):

ini
Copy code
/path/to/mongodb/logs/mongodb.log {
daily
rotate 7
compress
missingok
notifempty
}
8. Documentation and Training:
Document Deployment Processes:

Create comprehensive documentation for


deployment processes, configurations, and any
custom scripts. Training and Knowledge Transfer:

Train the operations team on MongoDB best


practices, monitoring, and troubleshooting.
In summary, deploying MongoDB for a production
environment involves careful consideration of server
setup, security, monitoring, scaling strategies, backup
procedures, performance optimization, and regular
maintenance. These steps, along with continuous
learning and adaptation, contribute to a robust and
reliable MongoDB deployment.

You might also like