Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Devops #459

Closed
wants to merge 57 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
fd48e1c
enhance-issue113 improved the lighthouse mobile scores
jjinendra3 Apr 15, 2024
468f9ed
enhance-issue113 improved the lighthouse mobile scores minor fix
jjinendra3 Apr 15, 2024
3c45a90
Merge branch 'main' into issue113
jjinendra3 Apr 15, 2024
d8314f0
enhance-issue113 improved the lighthouse mobile scores- minor fixes
jjinendra3 Apr 18, 2024
8e61786
enhance-issue113 improved the lighthouse mobile scores- minor fix
jjinendra3 Apr 18, 2024
26d9fdc
chore: fixed the url of the redis in the env.sample file
krishnaacharyaa Apr 18, 2024
0fbed1a
chore: Fixed the frontend test cases
krishnaacharyaa Apr 18, 2024
ea15e40
chore: Added additional flag to the frontend jest test cases run command
krishnaacharyaa Apr 18, 2024
6ad392d
enhance-issue113 improved the lighthouse mobile scores-format
jjinendra3 Apr 19, 2024
e9a4382
Enhancement-#113 - Better the lighthouse score in mobile device
krishnaacharyaa Apr 19, 2024
3fb8945
feat: Added auth middleware
0xmohitsen Apr 22, 2024
7766364
feat: Added env example
0xmohitsen Apr 22, 2024
0772354
feat: Added env variables
0xmohitsen Apr 22, 2024
026abe7
feat: Added logic to update user data with newly created posts
0xmohitsen Apr 22, 2024
70c4c4e
feat: Added checkauth middleware to protect the create post route
0xmohitsen Apr 22, 2024
570d2b8
feat: Imported env variables
0xmohitsen Apr 22, 2024
6f242ec
feat: Added context + interfaces
0xmohitsen Apr 22, 2024
5118647
feat: Changed toastify position to top-center
0xmohitsen Apr 22, 2024
614b125
feat: Wrapped all routes in user-contex-provider
0xmohitsen Apr 22, 2024
e3f9f1e
feat: Added onSubmit logic + appropriate error when user is invalid
0xmohitsen Apr 22, 2024
695c9aa
feat: Added token in req headers + added appropriate error
0xmohitsen Apr 22, 2024
2c7b0d5
feat: Added logic for logout + added login and logout icons + added c…
0xmohitsen Apr 22, 2024
43115c4
feat: Changed error msg to make it human understandable
0xmohitsen Apr 22, 2024
ceb0114
feat: Updated env sample
0xmohitsen Apr 22, 2024
1d85896
feat: Added proper error message
0xmohitsen Apr 22, 2024
4e3c7df
feat: fixed toast message to right corner
0xmohitsen Apr 24, 2024
28c4e8f
feat: Changed field name from createPosts to posts in user db schema
0xmohitsen Apr 24, 2024
537943d
feat: formatted the backend + changed auth middleware name to authent…
0xmohitsen Apr 24, 2024
bd1e115
feat: Removed hardcode response messages
0xmohitsen Apr 24, 2024
d167b8a
feat: Changed interface into type
0xmohitsen Apr 24, 2024
1dc59a7
feat: Removed catched errors to directly display on frontend + added …
0xmohitsen Apr 24, 2024
0f1909a
feat: Added login & logout svg icons + removed lucide-react icons
0xmohitsen Apr 24, 2024
78b6f82
feat: Added db check for username field
0xmohitsen Apr 24, 2024
98984e1
feat: Set errors with appropriate fields coming from backend response…
0xmohitsen Apr 24, 2024
658e174
feat: Changed login & logout icon name
0xmohitsen Apr 24, 2024
72cb5b6
feat: Reverted: Set errors with appropriate fields coming from backen…
0xmohitsen Apr 24, 2024
e03ee04
feat: Resize login icon
0xmohitsen Apr 24, 2024
98abeec
feat: Updated cookie-parser package
0xmohitsen Apr 24, 2024
1ecad14
feat: Removed contextApi + put the error msg in the input error msg
0xmohitsen Apr 26, 2024
dfe677f
feat: updated the cookieOptions when user logs out
0xmohitsen Apr 26, 2024
9912632
feat: Updated CORS configuration
0xmohitsen Apr 26, 2024
b7ee8ac
feat: Added client application's origin url
0xmohitsen Apr 26, 2024
2601a72
feat: Run format in both ends + removed localStorage + implemented si…
0xmohitsen Apr 27, 2024
c00d47e
feat: Added env for testing
0xmohitsen Apr 27, 2024
592cbfd
feat: removed cors configuration of credentials true
0xmohitsen Apr 27, 2024
ed122f4
feat-#146: Added Admin UI Screens to Frontend
devsharmagit Apr 17, 2024
4f67da6
added darkmode funtionalities
devsharmagit Apr 22, 2024
933fdbb
light mode navigation button updated
devsharmagit Apr 22, 2024
4f0a1fb
feat-#146: added mobile responsiveness
devsharmagit Apr 23, 2024
f41a897
feat-#146: layout and bug fixed
devsharmagit Apr 24, 2024
0dae320
feat-#146: added react outlet for admin routes
devsharmagit Apr 28, 2024
0225fef
feat-#169: added admin handler, user routes and protected post routes
devsharmagit Apr 30, 2024
01184cf
feat-#169: added author middleware, updated payload of token, removed…
devsharmagit May 1, 2024
f22ea21
feat-#169: added role to the paylot in signup
devsharmagit May 1, 2024
8f34f1c
feat-#169: changed name of middleware functions and updated isAuthorM…
devsharmagit May 2, 2024
9b11b76
feat-#169: fixed post model and user document update on deleting the…
devsharmagit May 5, 2024
a68aca9
feat:add docker file frontend and backend and docker-compose file
priyadarshi0811 Jul 25, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/.babelrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"presets": ["@babel/preset-env"]
}
}
4 changes: 2 additions & 2 deletions backend/.env.sample
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
MONGODB_URI="mongodb://127.0.0.1/wanderlust"
REDIS_URL="127.0.0.1:6379"
MONGODB_URI="mongodb://mongo/wanderlust"
CORS_ORIGIN="http://3.136.26.144:5000"
37 changes: 37 additions & 0 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#------------- stage1------------
FROM node:22 AS backend-builder

# setup the working dir
WORKDIR /app

# code
COPY . .


# package install
RUN npm i

# Test
#RUN npm run test

#-------------- stage2-------------

FROM node:22-slim

#setup the working dir
WORKDIR /app

# copy the above stage as compressed
COPY --from=backend-builder /app .

COPY .env.sample .env

#port
EXPOSE 5000

CMD ["npm", "start"]





18 changes: 17 additions & 1 deletion backend/config/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,21 @@ dotenv.config();
const PORT = process.env.PORT;
const MONGODB_URI = process.env.MONGODB_URI;
const REDIS_URL = process.env.REDIS_URL;
const ACCESS_COOKIE_MAXAGE = process.env.ACCESS_COOKIE_MAXAGE;
const ACCESS_TOKEN_EXPIRES_IN = process.env.ACCESS_TOKEN_EXPIRES_IN;
const REFRESH_COOKIE_MAXAGE = process.env.REFRESH_COOKIE_MAXAGE;
const REFRESH_TOKEN_EXPIRES_IN = process.env.REFRESH_TOKEN_EXPIRES_IN;
const JWT_SECRET = process.env.JWT_SECRET;
const FRONTEND_URL = process.env.FRONTEND_URL;

export { MONGODB_URI, PORT, REDIS_URL };
export {
MONGODB_URI,
PORT,
REDIS_URL,
ACCESS_COOKIE_MAXAGE,
ACCESS_TOKEN_EXPIRES_IN,
REFRESH_COOKIE_MAXAGE,
REFRESH_TOKEN_EXPIRES_IN,
JWT_SECRET,
FRONTEND_URL,
};
39 changes: 24 additions & 15 deletions backend/controllers/auth-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import jwt from 'jsonwebtoken';
import axios from 'axios';
import { HTTP_STATUS, RESPONSE_MESSAGES } from '../utils/constants.js';
import { accessCookieOptions, refreshCookieOptions } from '../utils/cookie_options.js';
import { ACCESS_TOKEN_EXPIRES_IN, JWT_SECRET, REFRESH_TOKEN_EXPIRES_IN } from '../config/utils.js';
const { hash, compareSync } = bcrypt;
const { sign } = jwt;

Expand All @@ -15,17 +16,23 @@ export const signUpWithEmail = async (req, res, next) => {
if (!name || !email || !password) {
throw new Error('All fields are required.');
}
const isExisitsUser = await User.findOne({ email });
if (isExisitsUser) {
throw new Error('User already exists.');
const isExisitsUserName = await User.findOne({ name });

if (isExisitsUserName) {
throw new Error('Name already exists.');
} else {
const isExisitsUserEmail = await User.findOne({ email });
if (isExisitsUserEmail) {
throw new Error('Email already exists.');
}
}
const hashedPassword = await hash(password, 10);
const newUser = await User.create({ name, email, password: hashedPassword });
const accessToken = sign({ name, _id: newUser._id }, process.env.JWT_SECRET, {
expiresIn: process.env.ACCESS_TOKEN_EXPIRES_IN,
const accessToken = sign({ name, _id: newUser._id, role: newUser.role }, JWT_SECRET, {
expiresIn: ACCESS_TOKEN_EXPIRES_IN,
});
const refreshToken = sign({ name, _id: newUser._id }, process.env.JWT_SECRET, {
expiresIn: process.env.REFRESH_TOKEN_EXPIRES_IN,
const refreshToken = sign({ name, _id: newUser._id, role: newUser.role }, JWT_SECRET, {
expiresIn: REFRESH_TOKEN_EXPIRES_IN,
});
res.cookie('access_token', accessToken, accessCookieOptions);
res.cookie('refresh_token', refreshToken, refreshCookieOptions);
Expand Down Expand Up @@ -60,19 +67,20 @@ export const signInWithEmail = async (req, res, next) => {
}
let accessToken;
let refreshToken;

if (isUserExists && compareSync(password, isUserExists.password)) {
accessToken = sign(
{ name: isUserExists.name, _id: isUserExists._id },
process.env.JWT_SECRET,
{ name: isUserExists.name, _id: isUserExists._id, role: isUserExists.role },
JWT_SECRET,
{
expiresIn: process.env.ACCESS_TOKEN_EXPIRES_IN,
expiresIn: ACCESS_TOKEN_EXPIRES_IN,
}
);
refreshToken = sign(
{ name: isUserExists.name, _id: isUserExists._id },
process.env.JWT_SECRET,
{ name: isUserExists.name, _id: isUserExists._id, role: isUserExists.role },
JWT_SECRET,
{
expiresIn: process.env.REFRESH_TOKEN_EXPIRES_IN,
expiresIn: REFRESH_TOKEN_EXPIRES_IN,
}
);
res.cookie('access_token', accessToken, accessCookieOptions);
Expand All @@ -94,6 +102,7 @@ export const signInWithEmail = async (req, res, next) => {
res.status(HTTP_STATUS.INTERNAL_SERVER_ERROR).json({
success: false,
message: error.message,
error,
});
}
};
Expand Down Expand Up @@ -377,8 +386,8 @@ export const signInWithGithub = async (req, res, next) => {
//Sign Out
export const signOutUser = async (req, res, next) => {
try {
res.cookie('access_token', '', { maxAge: 1 });
res.cookie('refresh_token', '', { maxAge: 1 });
res.cookie('access_token', '', { maxAge: 0 });
res.cookie('refresh_token', '', { maxAge: 0 });

res.status(200).json({ success: true, message: RESPONSE_MESSAGES.USERS.SIGNED_OUT });
} catch (error) {
Expand Down
8 changes: 8 additions & 0 deletions backend/controllers/posts-controller.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Post from '../models/post.js';
import User from '../models/user.js';
import {
deleteDataFromCache,
retrieveDataFromCache,
Expand All @@ -16,6 +17,8 @@ export const createPostHandler = async (req, res) => {
isFeaturedPost = false,
} = req.body;

const userId = req.user._id;

// Validation - check if all fields are filled
if (!title || !authorName || !imageLink || !description || !categories) {
return res
Expand Down Expand Up @@ -45,6 +48,7 @@ export const createPostHandler = async (req, res) => {
description,
categories,
isFeaturedPost,
authorId: req.user._id,
});

const [savedPost] = await Promise.all([
Expand All @@ -54,6 +58,9 @@ export const createPostHandler = async (req, res) => {
deleteDataFromCache(REDIS_KEYS.LATEST_POSTS), // Invalidate cache for latest posts
]);

// updating user doc to include the ObjectId of the created post
await User.findByIdAndUpdate(userId, { $push: { posts: savedPost._id } });

res.status(HTTP_STATUS.OK).json(savedPost);
} catch (err) {
res.status(HTTP_STATUS.INTERNAL_SERVER_ERROR).json({ message: err.message });
Expand Down Expand Up @@ -147,6 +154,7 @@ export const deletePostByIdHandler = async (req, res) => {
if (!post) {
return res.status(HTTP_STATUS.NOT_FOUND).json({ message: RESPONSE_MESSAGES.POSTS.NOT_FOUND });
}
await User.findByIdAndUpdate(post.authorId, { $pull: { posts: req.params.id } });

res.status(HTTP_STATUS.OK).json({ message: RESPONSE_MESSAGES.POSTS.DELETED });
} catch (err) {
Expand Down
52 changes: 52 additions & 0 deletions backend/controllers/user-controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { HTTP_STATUS, RESPONSE_MESSAGES } from '../utils/constants.js';
import User from '../models/user.js';

export const getAllUserHandler = async (req, res) => {
try {
const users = await User.find().select('_id name email');
return res.status(HTTP_STATUS.OK).json({ users });
} catch (error) {
res.status(HTTP_STATUS.INTERNAL_SERVER_ERROR).json({ message: err.message });
}
};

export const changeUserRoleHandler = async (req, res) => {
try {
const userId = req.params.userId;
const { role } = req.body;
if (role === 'user' || role === 'admin') {
const user = await User.findById(userId);
if (!user)
return res
.status(HTTP_STATUS.NOT_FOUND)
.json({ message: RESPONSE_MESSAGES.USERS.USER_NOT_EXISTS });
user.role = role;
user.save();
} else {
return res
.status(HTTP_STATUS.BAD_REQUEST)
.json({ message: RESPONSE_MESSAGES.COMMON.REQUIRED_FIELDS });
}
return res.status(HTTP_STATUS.OK).json({ message: RESPONSE_MESSAGES.USERS.UPDATE });
} catch (error) {
res
.status(HTTP_STATUS.INTERNAL_SERVER_ERROR)
.json({ message: RESPONSE_MESSAGES.COMMON.INTERNAL_SERVER_ERROR });
}
};

export const deleteUserHandler = async (req, res) => {
try {
const userId = req.params.userId;
const user = await User.findByIdAndDelete(userId);
if (!user)
return res
.status(HTTP_STATUS.NOT_FOUND)
.json({ message: RESPONSE_MESSAGES.USERS.USER_NOT_EXISTS });
res.status(HTTP_STATUS.NO_CONTENT).json({ message: RESPONSE_MESSAGES.USERS.DELETED });
} catch (error) {
res
.status(HTTP_STATUS.INTERNAL_SERVER_ERROR)
.json({ message: RESPONSE_MESSAGES.COMMON.INTERNAL_SERVER_ERROR });
}
};
45 changes: 45 additions & 0 deletions backend/middlewares/auth-middleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { JWT_SECRET } from '../config/utils.js';
import { HTTP_STATUS, RESPONSE_MESSAGES } from '../utils/constants.js';
import jwt from 'jsonwebtoken';

export const authMiddleware = async (req, res, next) => {
const authHeader = req.headers.access_token;

if (authHeader) {
const token = authHeader.split(' ')[1];

jwt.verify(token, JWT_SECRET, (error, payload) => {
if (error) {
return res.status(HTTP_STATUS.FORBIDDEN).json({
success: false,
message: RESPONSE_MESSAGES.USERS.INVALID_TOKEN,
});
}
req.user = payload;
next();
});
} else {
return res.status(HTTP_STATUS.UNAUTHORIZED).json({
success: false,
message: RESPONSE_MESSAGES.USERS.UNAUTHORIZED_USER,
});
}
};

export const isAdminMiddleware = async (req, res, next) => {
try {
const role = req.user.role;
if (role !== 'admin') {
return res.status(HTTP_STATUS.UNAUTHORIZED).json({
success: false,
message: RESPONSE_MESSAGES.USERS.UNAUTHORIZED_USER,
});
}
next();
} catch (error) {
return res.status(HTTP_STATUS.INTERNAL_SERVER_ERROR).json({
success: 'fail',
message: error.message,
});
}
};
23 changes: 23 additions & 0 deletions backend/middlewares/post-middleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import Post from '../models/post.js';
import { HTTP_STATUS, RESPONSE_MESSAGES } from '../utils/constants.js';

export const isAuthorMiddleware = async (req, res, next) => {
try {
const userId = req.user._id;
const postId = req.params.id;
const post = await Post.findById(postId);
if (!post) {
return res.status(HTTP_STATUS.NOT_FOUND).json({ message: RESPONSE_MESSAGES.POSTS.NOT_FOUND });
}

console.log(post.authorId, userId);
if (post.authorId.toString() !== userId) {
return res
.status(HTTP_STATUS.FORBIDDEN)
.json({ message: RESPONSE_MESSAGES.POSTS.NOT_ALLOWED });
}
next();
} catch (error) {
res.status(HTTP_STATUS.INTERNAL_SERVER_ERROR).json({ message: err.message });
}
};
7 changes: 6 additions & 1 deletion backend/models/post.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Schema, model } from 'mongoose';
import mongoose, { Schema, model } from 'mongoose';

const postSchema = new Schema({
authorName: String,
Expand All @@ -8,6 +8,11 @@ const postSchema = new Schema({
description: String,
isFeaturedPost: Boolean,
timeOfPost: { type: Date, default: Date.now },
authorId: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true,
},
});

export default model('Post', postSchema);
2 changes: 1 addition & 1 deletion backend/models/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const userSchema = new Schema({
type: String,
default: 'user',
},
createdPosts: [{ type: Schema.Types.ObjectId, ref: 'Post' }],
posts: [{ type: Schema.Types.ObjectId, ref: 'Post' }],
});

export default model('User', userSchema);
Loading