Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
b93f266
Added user route for uploading bulk users to database
Raman-pro Aug 31, 2025
2b9cd57
shifted code to authControler and authRouter as well as added random …
Raman-pro Aug 31, 2025
93cbbb1
added functionality for adding role to /signup and /post-add-users
Raman-pro Sep 2, 2025
0b5525d
feat : updated workflow file for new repo and pm2 process name
Shobhit141141 Aug 31, 2025
04f7c3d
Fix: Update submodule 'commonlib' to the latest commit
Shobhit141141 Aug 31, 2025
e5720c2
feat : update workflows
Shobhit141141 Aug 31, 2025
8d6a9ec
feat: fallback to deployment workflow
Shobhit141141 Aug 31, 2025
6bf0465
fix : github workflow
Shobhit141141 Aug 31, 2025
ec6ea40
fix: remove --delete in deployment workflow
Shobhit141141 Aug 31, 2025
49a0eec
fix: run PM2 restart command with root
Shobhit141141 Aug 31, 2025
c4b2a04
fix: update PM2 restart command to use full path
Shobhit141141 Aug 31, 2025
f0de5ad
Use sudo to restart application with PM2
Shobhit141141 Aug 31, 2025
7c99906
Refactor deployment workflow in main.yml
Shobhit141141 Aug 31, 2025
5a68d6c
fix the deployment workflow
Shobhit141141 Aug 31, 2025
6748879
Added user route for uploading bulk users to database
Raman-pro Aug 31, 2025
e92a57a
refactor: roll out registration mails for bulk user addition
Shobhit141141 Sep 5, 2025
b8873b2
Merge branch 'main' into main
Shobhit141141 Sep 5, 2025
2bb3649
chore ran npm run lint
Raman-pro Sep 5, 2025
58fd951
Added functionality of checking email if already exists or not in aut…
Raman-pro Sep 5, 2025
970d1d6
Merge branch 'update'
Raman-pro Sep 5, 2025
9ba4214
refactor: improve response messages in postBulkUserController for use…
Shobhit141141 Sep 6, 2025
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
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ name: Deploy on push
on:
# Triggers the workflow on push or pull request events but only for the "main" branch
push:
branches: [ "main" ]
branches: ["main"]

# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:

Expand Down
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,23 @@ Refer to .env.local file and create your own .env file as required
# Backup Overview

1. **Backup Existence**: The project has a robust backup system in place to ensure data integrity and availability.
2. **MongoDB Backup**:
- **Scope**: All user accounts, passwords, blogs, and other data (excluding images) are backed up.
- **Frequency**: Backups are performed daily.
- **Storage**: The backups are stored on the server and uploaded to the Telegram channel.
2. **MongoDB Backup**:
- **Scope**: All user accounts, passwords, blogs, and other data (excluding images) are backed up.
- **Frequency**: Backups are performed daily.
- **Storage**: The backups are stored on the server and uploaded to the Telegram channel.
3. **Image Backup**:
- **Scope**: All image data is backed up.
- **Frequency**: Backups are performed twice a month (every 15 days).
- **Storage**: Image backups are stored on the server.
- **Notifications**: Notifications are delivered on the same Telegram channel whenever an image backup is completed.
- **Scope**: All image data is backed up.
- **Frequency**: Backups are performed twice a month (every 15 days).
- **Storage**: Image backups are stored on the server.
- **Notifications**: Notifications are delivered on the same Telegram channel whenever an image backup is completed.

## Accessing Server Backups

To access server backups, log in using the following credentials:

- **Username**: dvishal485
- Managed via cron jobs

```bash
crontab -e
```
Expand Down
9 changes: 5 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

53 changes: 50 additions & 3 deletions src/api/controllers/authController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ export const refresh = asyncErrorHandler(async (req, res, next) => {
*/

export const signup = asyncErrorHandler(async (req, res, next) => {
const { name, username: email } = req.body;
const { name, username: email, teamRole: role_id } = req.body;

if (!email || !name) {
const error = new CustomError(
Expand All @@ -153,7 +153,6 @@ export const signup = asyncErrorHandler(async (req, res, next) => {
}

const isDuplicate = await UserService.checkUserExists({ email: email });
console.log(isDuplicate);

if (isDuplicate) {
const error = new CustomError(
Expand All @@ -163,14 +162,15 @@ export const signup = asyncErrorHandler(async (req, res, next) => {
return next(error);
}

await UserService.createNewUser(name, email);
await UserService.createNewUser(name, email, role_id);

res.status(StatusCode.CREATED).json({
status: "success",
message: "User successfully created!",
data: {
name,
email,
role_id,
},
});
});
Expand Down Expand Up @@ -261,6 +261,53 @@ export const login = asyncErrorHandler(async (req, res, next) => {
}
});

/**
* @description Adds user list to users database.
* @route POST /add-members
* @param req - The HTTP request object.
* @param res - The HTTP response object.
* @param next - The next middleware function in the stack.
* @returns A JSON response containing the user database.
* @returns status - Indicates the success status of the operation ('success').
* @returns message - Describes the outcome of the operation ('User Data successfully inserted').
* @returns data - Contains the data added to the users database.
* @howItWorks
* - Retrieves the array of users from `req.params.users`.
* - Checks for any duplicate email and returns the list of duplicate email found
* - Hashes all the password being added.
* - adds all the data to users models
*/

export const postBulkUserController = asyncErrorHandler(
async (req, res, next) => {
const usersData = req.body.users;
if (!Array.isArray(usersData)) {
return res.status(400).json({ error: "User data must be an array" });
}

const { createdUsers, existingUsers } =
await UserService.createNewUsers(usersData);

if (existingUsers.length > 0) {
return res.status(StatusCode.CONFLICT).json({
message:
createdUsers.length > 0
? "Some users were added, but some already exist."
: "All provided users already exist.",
data: {
createdUsers,
existingUsers,
},
});
}

res.status(StatusCode.OK).json({
message: "User Data inserted successfully",
data: createdUsers,
});
},
);

/**
* Handle user password reset request. Send a mail to user with password reset link.
*/
Expand Down
20 changes: 9 additions & 11 deletions src/api/controllers/eventController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,15 @@ import asyncErrorHandler from "../helpers/asyncErrorHandler";
import StatusCode from "@static/types/backend/httpStatusCode";
import { Event, IEvent } from "../models/eventModel";

export const getEventsController = asyncErrorHandler(
async (req, res, next) => {
const events = await Event.find().sort();

res.status(StatusCode.OK).json({
status: "success",
message: "Events fetched successfully",
data: events,
});
},
);
export const getEventsController = asyncErrorHandler(async (req, res, next) => {
const events = await Event.find().sort();

res.status(StatusCode.OK).json({
status: "success",
message: "Events fetched successfully",
data: events,
});
});

export const createEventController = asyncErrorHandler(
async (req, res, next) => {
Expand Down
40 changes: 40 additions & 0 deletions src/api/controllers/userController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,46 @@ export const getUserController = asyncErrorHandler(async (req, res, next) => {
});
});

/**
* @description Adds user list to users database.
* @route POST /post-add-users
* @param req - The HTTP request object.
* @param res - The HTTP response object.
* @param next - The next middleware function in the stack.
* @returns A JSON response containing the user database.
* @returns status - Indicates the success status of the operation ('success').
* @returns message - Describes the outcome of the operation ('User Data successfully inserted').
* @returns data - Contains the data added to the users database.
* @howItWorks
* - Retrieves the array of users from `req.params.users`.
* - Hashes all the password being added.
* - adds all the data to users models
*/

export const postBulkUserController = asyncErrorHandler(
async (req, res, next) => {
const usersData = req.body.users;

if (!Array.isArray(usersData)) {
return res.status(400).json({ error: "user data must be an array" });
}

const hashedUsers = await Promise.all(
usersData.map(async (user) => ({
...user,
password: await bcrypt.hash(user.password, 10),
})),
);

const userDocsInserted = await User.insertMany(hashedUsers);

res.status(StatusCode.OK).json({
message: "User Data successfully inserted",
data: userDocsInserted,
});
},
);

/**
* @description Updates user details including name, email, password, and bio.
* @route PUT /update-user
Expand Down
4 changes: 4 additions & 0 deletions src/api/routes/authRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
forgotPassword,
resetPassword,
logout,
postBulkUserController,
} from "../controllers/authController";
import protected_route from "../middlewares/permsMiddlewareInit";
import Permission from "@static/types/permissions";
Expand All @@ -17,6 +18,9 @@ const signup_protect = protected_route([Permission.CreateProfile]);

router.route("/signup").post(protect, signup_protect, signup);
router.post("/login", login);
router
.route("/add-members")
.post(protect, signup_protect, postBulkUserController);
router.get("/refresh", refresh);
router.post("/logout", logout);
router.post("/forgotPassword", forgotPassword);
Expand Down
6 changes: 6 additions & 0 deletions src/api/routes/userRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import {
permsUpdateController,
updateUserController,
deleteUserController,
postBulkUserController,
} from "../controllers/userController";
import { protect } from "../middlewares/authMiddleware";
import protected_route from "../middlewares/permsMiddlewareInit";
import Permission from "@static/types/permissions";

const router = express.Router();

const createBulkProfileProtect = protected_route([Permission.CreateProfile]);
const updateProfileProtect = protected_route([Permission.UpdateProfile]);
const deleteProfileProtect = protected_route([Permission.DeleteProfile]);

Expand All @@ -25,6 +27,10 @@ router.route("/current-user").get(protect, getCurrentUserController);

router.route("/get-user/:id").get(protect, getUserController);

router
.route("/post-add-users")
.post(protect, createBulkProfileProtect, postBulkUserController);

router
.route("/update-user")
.put(
Expand Down
32 changes: 31 additions & 1 deletion src/api/services/userService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,19 @@ export const getAllUsers = async (
return allUsers;
};

export const createNewUser = async (name: string, email: string) => {
export const createNewUser = async (
name: string,
email: string,
role_id: string,
) => {
const password: string = generateRandomPassword(7);
const hashed_password: string = await bcrypt.hash(password, 10);

const user = await User.create({
name: name,
email: email,
password: hashed_password,
role_id: role_id,
});

const reg_mail = new RegisterationMail(user, password);
Expand All @@ -81,3 +86,28 @@ export const createNewUser = async (name: string, email: string) => {

return user;
};

export const createNewUsers = async (users: Array<IUser>) => {
const createdUsers: HydratedDocument<IUser>[] = [];
const incomingEmails = users.map((user) => user.email);
const existingUsers = await User.find({ email: { $in: incomingEmails } });
const existingEmails = existingUsers.map((user) => user.email);

console.log(existingEmails);

for (const user of users) {
if (existingEmails.includes(user.email)) {
continue;
}
const password: string = generateRandomPassword(7);
const hashed_password: string = await bcrypt.hash(password, 10);
const newUser = await User.create({
...user,
password: hashed_password,
});
const reg_mail = new RegisterationMail(newUser, password);
await reg_mail.sendTo(newUser.email);
createdUsers.push(newUser);
}
return { createdUsers, existingUsers };
};
54 changes: 21 additions & 33 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,35 +1,23 @@
{
"compilerOptions": {
"module": "NodeNext",
"moduleResolution": "nodenext",
"target": "ESNext",
"sourceMap": false,
"outDir": "dist",
"allowJs": false,
"strictNullChecks": true,
"typeRoots": [
"./src/types",
"./node_modules/@types"
],
"baseUrl": ".",
"paths": { // Adjust based on your project structure
"@/*": [
"./src/*"
],
"@static/*": [
"./src/commonlib/*"
]
},
"resolveJsonModule": true
"compilerOptions": {
"module": "NodeNext",
"moduleResolution": "nodenext",
"target": "ESNext",
"sourceMap": false,
"outDir": "dist",
"allowJs": false,
"strictNullChecks": true,
"typeRoots": ["./src/types", "./node_modules/@types"],
"baseUrl": ".",
"paths": {
// Adjust based on your project structure
"@/*": ["./src/*"],
"@static/*": ["./src/commonlib/*"]
},
"ts-node": {
"require": [
"tsconfig-paths/register"
]
},
"exclude": [
"node_modules",
"dist",
"src/scripts"
],
}
"resolveJsonModule": true
},
"ts-node": {
"require": ["tsconfig-paths/register"]
},
"exclude": ["node_modules", "dist", "src/scripts"]
}