init commit

This commit is contained in:
2025-07-07 00:52:41 +05:30
commit 2dd24927bc
81 changed files with 10274 additions and 0 deletions

View File

@ -0,0 +1,94 @@
const User = require("../models/User");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
// Generate JWT Token
const generateToken = (userId) => {
return jwt.sign({ id: userId }, process.env.JWT_SECRET, { expiresIn: "7d" });
};
// @desc Register a new user
// @route POST /api/auth/register
// @access Public
const registerUser = async (req, res) => {
try {
const { name, email, password, profileImageUrl } = req.body;
// Check if user already exists
const userExists = await User.findOne({ email });
if (userExists) {
return res.status(400).json({ message: "User already exists" });
}
// Hash password
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(password, salt);
// Create new user
const user = await User.create({
name,
email,
password: hashedPassword,
profileImageUrl,
});
// Return user data with JWT
res.status(201).json({
_id: user._id,
name: user.name,
email: user.email,
profileImageUrl: user.profileImageUrl,
token: generateToken(user._id),
});
} catch (error) {
res.status(500).json({ message: "Server error", error: error.message });
}
};
// @desc Login user
// @route POST /api/auth/login
// @access Public
const loginUser = async (req, res) => {
try {
const { email, password } = req.body;
const user = await User.findOne({ email });
if (!user) {
return res.status(500).json({ message: "Invalid email or password" });
}
// Compare password
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return res.status(500).json({ message: "Invalid email or password" });
}
// Return user data with JWT
res.json({
_id: user._id,
name: user.name,
email: user.email,
profileImageUrl: user.profileImageUrl,
token: generateToken(user._id),
});
} catch (error) {
res.status(500).json({ message: "Server error", error: error.message });
}
};
// @desc Get user profile
// @route GET /api/auth/profile
// @access Private (Requires JWT)
const getUserProfile = async (req, res) => {
try {
const user = await User.findById(req.user.id).select("-password");
if (!user) {
return res.status(404).json({ message: "User not found" });
}
res.json(user);
} catch (error) {
res.status(500).json({ message: "Server error", error: error.message });
}
};
module.exports = { registerUser, loginUser, getUserProfile };

View File

@ -0,0 +1,204 @@
const fs = require("node:fs");
const path = require("node:path");
const Resume = require("../models/Resume");
// @desc Create a new resume
// @route POST /api/resumes
// @access Private
const createResume = async (req, res) => {
try {
const { title } = req.body;
// Default template
const defaultResumeData = {
profileInfo: {
profileImg: null,
previewUrl: "",
fullName: "",
designation: "",
summary: "",
},
contactInfo: {
email: "",
phone: "",
location: "",
linkedin: "",
github: "",
website: "",
},
workExperience: [
{
company: "",
role: "",
startDate: "",
endDate: "",
description: "",
},
],
education: [
{
degree: "",
institution: "",
startDate: "",
endDate: "",
},
],
skills: [
{
name: "",
progress: 0,
},
],
projects: [
{
title: "",
description: "",
github: "",
liveDemo: "",
},
],
certifications: [
{
title: "",
issuer: "",
year: "",
},
],
languages: [
{
name: "",
progress: 0,
},
],
interests: [""],
};
const newResume = await Resume.create({
userId: req.user._id,
title,
...defaultResumeData,
});
res.status(201).json(newResume);
} catch (error) {
res
.status(500)
.json({ message: "Failed to create resume", error: error.message });
}
};
// @desc Get all resumes for logged-in user
// @route GET /api/resumes
// @access Private
const getUserResumes = async (req, res) => {
try {
const resumes = await Resume.find({ userId: req.user._id }).sort({
updatedAt: -1,
});
res.json(resumes);
} catch (error) {
res
.status(500)
.json({ message: "Failed to create resume", error: error.message });
}
};
// @desc Get single resume by ID
// @route GET /api/resumes/:id
// @access Private
const getResumeById = async (req, res) => {
try {
const resume = await Resume.findOne({ _id: req.params.id, userId: req.user._id });
if (!resume) {
return res.status(404).json({ message: "Resume not found" });
}
res.json(resume);
} catch (error) {
res
.status(500)
.json({ message: "Failed to create resume", error: error.message });
}
};
// @desc Update a resume
// @route PUT /api/resumes/:id
// @access Private
const updateResume = async (req, res) => {
try {
const resume = await Resume.findOne({
_id: req.params.id,
userId: req.user._id,
});
if (!resume) {
return res.status(404).json({ message: "Resume not found or unauthorized" });
}
// Merge updates from req.body into existing resume
Object.assign(resume, req.body);
// Save updated resume
const savedResume = await resume.save();
res.json(savedResume);
} catch (error) {
res
.status(500)
.json({ message: "Failed to create resume", error: error.message });
}
};
// @desc Delete a resume
// @route DELETE /api/resumes/:id
// @access Private
const deleteResume = async (req, res) => {
try {
const resume = await Resume.findOne({
_id: req.params.id,
userId: req.user._id,
});
if (!resume) {
return res.status(404).json({ message: "Resume not found or unauthorized" });
}
// Delete thumbnailLink and profilePreviewUrl images from uploads folder
const uploadsFolder = path.join(__dirname, '..', 'uploads');
const baseUrl = `${req.protocol}://${req.get("host")}`;
if(resume.thumbnailLink){
const oldThumbnail = path.join(uploadsFolder, path.basename(resume.thumbnailLink));
if (fs.existsSync(oldThumbnail)) fs.unlinkSync(oldThumbnail);
}
if(resume.profileInfo?.profilePreviewUrl){
const oldProfile = path.join(uploadsFolder, path.basename(resume.profileInfo.profilePreviewUrl));
if (fs.existsSync(oldProfile)) fs.unlinkSync(oldProfile);
}
const deleted = await Resume.findOneAndDelete({
_id: req.params.id,
userId: req.user._id,
});
if (!deleted) {
return res.status(404).json({ message: "Resume not found or unauthorized" });
}
res.json({ message: "Resume deleted successfully" });
} catch (error) {
res
.status(500)
.json({ message: "Failed to create resume", error: error.message });
}
};
module.exports = {
createResume,
getUserResumes,
getResumeById,
updateResume,
deleteResume,
};

View File

@ -0,0 +1,58 @@
const fs = require("fs");
const path = require("path");
const Resume = require("../models/Resume");
const upload = require("../middlewares/uploadMiddleware");
const uploadResumeImages = async (req, res) => {
try {
upload.fields([{ name: 'thumbnail' }, { name: 'profileImage' }])(req, res, async (err) => {
if (err) {
return res.status(400).json({ message: "File upload failed", error: err.message });
}
const resumeId = req.params.id;
const resume = await Resume.findOne({ _id: resumeId, userId: req.user._id });
if (!resume) {
return res.status(404).json({ message: "Resume not found or unauthorized" });
}
const uploadsFolder = path.join(__dirname, '..', 'uploads');
const baseUrl = `${req.protocol}://${req.get("host")}`;
const newThumbnail = req.files.thumbnail?.[0];
const newProfileImage = req.files.profileImage?.[0];
// If new thumbnail uploaded, delete old one
if (newThumbnail) {
if(resume.thumbnailLink){
const oldThumbnail = path.join(uploadsFolder, path.basename(resume.thumbnailLink));
if (fs.existsSync(oldThumbnail)) fs.unlinkSync(oldThumbnail);
}
resume.thumbnailLink = `${baseUrl}/uploads/${newThumbnail.filename}`;
}
// If new profile image uploaded, delete old one
if (newProfileImage) {
if(resume.profileInfo?.profilePreviewUrl){
const oldProfile = path.join(uploadsFolder, path.basename(resume.profileInfo.profilePreviewUrl));
if (fs.existsSync(oldProfile)) fs.unlinkSync(oldProfile);
}
resume.profileInfo.profilePreviewUrl = `${baseUrl}/uploads/${newProfileImage.filename}`;
}
await resume.save();
res.status(200).json({
message: "Images uploaded successfully",
thumbnailLink: resume.thumbnailLink,
profilePreviewUrl: resume.profileInfo.profilePreviewUrl,
});
});
} catch (err) {
console.error("Error uploading images:", err);
res.status(500).json({ message: "Failed to upload images", error: err.message });
}
};
module.exports = { uploadResumeImages };