init commit
This commit is contained in:
94
backend/controllers/authController.js
Normal file
94
backend/controllers/authController.js
Normal 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 };
|
||||
204
backend/controllers/resumeController.js
Normal file
204
backend/controllers/resumeController.js
Normal 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,
|
||||
};
|
||||
58
backend/controllers/uploadImages.js
Normal file
58
backend/controllers/uploadImages.js
Normal 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 };
|
||||
Reference in New Issue
Block a user