Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 1 addition & 2 deletions backend/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Explicitly tell module-alias where to find package.json in backend directory
// @ts-ignore - module-alias doesn't have types
// @ts-expect-error - module-alias doesn't have types
import moduleAlias from "module-alias";

moduleAlias(require.resolve("../package.json"));
import type { VercelRequest, VercelResponse } from "@vercel/node";
import mongoose from "mongoose";
Expand Down
9 changes: 2 additions & 7 deletions backend/src/controllers/InterviewQuestionController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import asyncHandler from "express-async-handler";
import createHttpError from "http-errors";
import Company from "../models/Company";
import mongoose from "mongoose";
import User from "../models/User";

// Interface for creating/updating an interview question
interface InterviewQuestionCreate {
company: mongoose.Types.ObjectId;
userId: string;
question: string;
date: Date;
date?: Date;
}

interface InterviewQuestionUpdate extends Partial<InterviewQuestionCreate> {}
Expand All @@ -25,7 +25,6 @@ export const getAllInterviewQuestions = asyncHandler(async (req, res, _) => {
// TODO: Implement with paginated date, for now it will just return all interview questions for testing
const interviewQuestions = await InterviewQuestion.find()
.populate({ path: "company", model: Company })
.populate({ path: "user", model: User })
.lean()
.exec();

Expand Down Expand Up @@ -63,7 +62,6 @@ export const createInterviewQuestion = asyncHandler(async (req, res, next) => {
question: interviewQuestionData.question,
})
.populate({ path: "company", model: Company })
.populate({ path: "user", model: User })
.lean()
.exec();

Expand Down Expand Up @@ -93,7 +91,6 @@ export const getInterviewQuestionById = asyncHandler(async (req, res, next) => {
// Find interview question by ID
const interviewQuestion = await InterviewQuestion.findById(id)
.populate({ path: "company", model: Company })
.populate({ path: "user", model: User })
.lean()
.exec();

Expand Down Expand Up @@ -125,7 +122,6 @@ export const getInterviewQuestionsByCompanyId = asyncHandler(
company: companyId,
})
.populate({ path: "company", model: Company })
.populate({ path: "user", model: User })
.lean()
.exec();

Expand Down Expand Up @@ -176,7 +172,6 @@ export const updateInterviewQuestion = asyncHandler(async (req, res, next) => {
{ new: true, runValidators: true },
)
.populate({ path: "company", model: Company })
.populate({ path: "user", model: User })
.lean()
.exec();

Expand Down
1 change: 1 addition & 0 deletions backend/src/controllers/applicationController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import mongoose, { PipelineStage } from "mongoose";
interface ApplicationCreate {
userId: string;
company: mongoose.Types.ObjectId;
companyName: string;
position: string;
link?: string;
location?: string;
Expand Down
8 changes: 1 addition & 7 deletions backend/src/controllers/leetcodeQuestionController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@ import validationErrorParser from "../util/validationErrorParser";
import createHttpError from "http-errors";
import Company from "../models/Company";
import mongoose from "mongoose";
import User from "../models/User";

// interface for creating/updating leetcodeQuestions
interface leetcodeQuestionCreate {
company: mongoose.Types.ObjectId;
user: mongoose.Types.ObjectId;
userId: string;
title: string;
url: string;
difficulty: Difficulty;
Expand Down Expand Up @@ -61,7 +60,6 @@ export const getLeetcodeQuestions = asyncHandler(async (req, res, next) => {
.skip(page * perPage)
.limit(perPage)
.populate({ path: "company", model: Company })
.populate({ path: "user", model: User })
.lean()
.exec(),
]);
Expand Down Expand Up @@ -106,7 +104,6 @@ export const createLeetcodeQuestion = asyncHandler(async (req, res, next) => {
newLeetcodeQuestion._id,
)
.populate({ path: "company", model: Company })
.populate({ path: "user", model: User })
.lean()
.exec();

Expand Down Expand Up @@ -134,7 +131,6 @@ export const getLeetcodeQuestionById = asyncHandler(async (req, res, next) => {
// Find leetcodeQuestion by ID
const leetcodeQuestion = await LeetcodeQuestion.findById(id)
.populate({ path: "company", model: Company })
.populate({ path: "user", model: User })
.lean()
.exec();

Expand Down Expand Up @@ -176,7 +172,6 @@ export const updateLeetcodeQuestion = asyncHandler(async (req, res, next) => {
{ new: true, runValidators: true },
)
.populate({ path: "company", model: Company })
.populate({ path: "user", model: User })
.lean()
.exec();

Expand Down Expand Up @@ -226,7 +221,6 @@ export const getLeetcodeQuestionByCompanyId = asyncHandler(
company: companyId,
})
.populate({ path: "company", model: Company })
.populate({ path: "user", model: User })
.lean()
.exec();

Expand Down
1 change: 1 addition & 0 deletions backend/src/controllers/savedApplicationController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import mongoose, { PipelineStage } from "mongoose";
interface SavedApplicationCreate {
userId: string;
company: mongoose.Types.ObjectId;
companyName: string;
position: string;
location?: string;
link?: string;
Expand Down
8 changes: 1 addition & 7 deletions backend/src/controllers/tipController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ import asyncHandler from "express-async-handler";
import createHttpError from "http-errors";
import { Schema } from "mongoose";
import Company from "../models/Company";
import User from "../models/User";

// Interface for creating/updating a tip
interface TipCreate {
user: string;
userId: string;
company: Schema.Types.ObjectId;
text: string;
}
Expand All @@ -25,7 +24,6 @@ export const getAllTips = asyncHandler(async (req, res, _) => {
// Retrieve all tips from the database
const tips = await Tip.find()
.populate({ path: "company", model: Company })
.populate({ path: "user", model: User })
.lean()
.exec();

Expand Down Expand Up @@ -55,7 +53,6 @@ export const createTip = asyncHandler(async (req, res, next) => {

const populatedTip = await Tip.findById(newTip._id)
.populate({ path: "company", model: Company })
.populate({ path: "user", model: User })
.lean()
.exec();

Expand All @@ -82,7 +79,6 @@ export const getTipById = asyncHandler(async (req, res, next) => {
// Find the tip by ID
const tip = await Tip.findById(id)
.populate({ path: "company", model: Company })
.populate({ path: "user", model: User })
.lean()
.exec();

Expand Down Expand Up @@ -130,7 +126,6 @@ export const updateTipById = asyncHandler(async (req, res, next) => {
{ new: true, runValidators: true },
)
.populate({ path: "company", model: Company })
.populate({ path: "user", model: User })
.lean()
.exec();

Expand Down Expand Up @@ -189,7 +184,6 @@ export const getTipsByCompanyId = asyncHandler(async (req, res, next) => {
// Find tips for the specified company with pagination
const tips = await Tip.find({ company: id })
.populate({ path: "company", model: Company })
.populate({ path: "user", model: User })
.lean()
.exec();

Expand Down
8 changes: 7 additions & 1 deletion backend/src/middlewares/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,14 @@ export const logEvents = async (message: string, logFileName: string) => {
const dateTime = new Date();
const logItem = `${dateTime}\t${message}\n`;

// Skip file logging on Vercel (read-only filesystem)
if (process.env.VERCEL === "1") {
console.log(logItem);
return;
}

try {
// Create logs directory if it doesn't exist
// Create logs directory if it doesn't exist (local only)
if (!fs.existsSync(path.join(__dirname, "..", "logs"))) {
await fsPromises.mkdir(path.join(__dirname, "..", "logs"));
}
Expand Down
5 changes: 5 additions & 0 deletions backend/src/models/Application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ const applicationSchema = new Schema(
type: Schema.Types.ObjectId,
required: true,
},
companyName: {
type: String,
required: true,
trim: true,
},
position: {
type: String,
required: true,
Expand Down
2 changes: 1 addition & 1 deletion backend/src/models/InterviewQuestion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const interviewQuestionSchema = new Schema({
type: Schema.Types.ObjectId,
required: true,
},
user: {
userId: {
type: String,
required: true,
},
Expand Down
4 changes: 2 additions & 2 deletions backend/src/models/LeetcodeQuestion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const leetcodeQuestionSchema = new Schema({
type: Schema.Types.ObjectId,
required: true,
},
user: {
userId: {
type: String,
required: true,
},
Expand Down Expand Up @@ -40,7 +40,7 @@ type LeetcodeQuestion = InferSchemaType<typeof leetcodeQuestionSchema>;
// Add indexes for better performance
leetcodeQuestionSchema.index({ difficulty: 1 }); // Difficulty filtering
leetcodeQuestionSchema.index({ company: 1 }); // Company filtering
leetcodeQuestionSchema.index({ user: 1 }); // User's questions
leetcodeQuestionSchema.index({ userId: 1 }); // User's questions
leetcodeQuestionSchema.index({ title: "text" }); // Title search

export default model<LeetcodeQuestion>(
Expand Down
5 changes: 5 additions & 0 deletions backend/src/models/SavedApplication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ const savedApplicationSchema = new Schema(
type: Schema.Types.ObjectId,
required: true,
},
companyName: {
type: String,
required: true,
trim: true,
},
location: {
type: String,
required: false,
Expand Down
2 changes: 1 addition & 1 deletion backend/src/models/Tips.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { InferSchemaType, Schema, model } from "mongoose";

const tipSchema = new Schema(
{
user: {
userId: {
type: String,
required: true,
},
Expand Down
9 changes: 9 additions & 0 deletions backend/src/validators/applicationValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ const validateCompany = body("company")
.withMessage("invalid company. (Must be a Mongo ObjectID.)")
.trim();

const validateCompanyName = body("companyName")
.isString()
.withMessage("companyName must be a string.")
.trim()
.notEmpty()
.withMessage("companyName must be a non-empty string.");

const validatePosition = body("position")
.isString()
.withMessage("position must be a string.")
Expand Down Expand Up @@ -116,6 +123,7 @@ const validateProcess = [
export const createApplicationValidator = [
validateUserId,
validateCompany,
validateCompanyName,
validatePosition,
validateLink,
validateLocation,
Expand All @@ -128,6 +136,7 @@ export const updateApplicationValidator = [
validateId,
validateUserId.optional(),
validateCompany.optional(),
validateCompanyName.optional(),
validatePosition.optional(),
validateLocation.optional(),
validateLink.optional(),
Expand Down
12 changes: 7 additions & 5 deletions backend/src/validators/interviewQuestionValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ const validateCompanyIdParam = param("companyId")
.withMessage("invalid company id. (Must be a Mongo ObjectID.)")
.trim();

const validateUser = body("user")
const validateUserId = body("userId")
.isString()
.withMessage("invalid user id. (Must be a string)")
.trim();
.withMessage("invalid userId. (Must be a string)")
.trim()
.notEmpty()
.withMessage("userId must be a non-empty string.");

const validateQuestion = body("question")
.isString()
Expand Down Expand Up @@ -68,7 +70,7 @@ export const getInterviewQuestionsValidator = [

export const createInterviewQuestionValidator = [
validateCompany,
validateUser,
validateUserId,
validateQuestion,
validateDate,
];
Expand All @@ -77,7 +79,7 @@ export const getInterviewQuestionByIdValidator = [validateIdParam];

export const updateInterviewQuestionValidator = [
validateIdParam,
validateUser.optional(),
validateUserId.optional(),
validateCompany.optional(),
validateQuestion.optional(),
validateDate,
Expand Down
12 changes: 7 additions & 5 deletions backend/src/validators/leetcodeQuestionValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ const validateCompanyIdParam = param("companyId")
.withMessage("invalid company id. (Must be a Mongo ObjectID.)")
.trim();

const validateUser = body("user")
const validateUserId = body("userId")
.isString()
.withMessage("invalid user id. (Must be a string)")
.trim();
.withMessage("invalid userId. (Must be a string)")
.trim()
.notEmpty()
.withMessage("userId must be a non-empty string.");

const validateTitle = body("title")
.isString()
Expand Down Expand Up @@ -105,7 +107,7 @@ export const getLeetcodeQuestionsValidator = [

export const createLeetcodeQuestionValidator = [
validateCompany,
validateUser,
validateUserId,
validateTitle,
validateURL,
validateDifficulty,
Expand All @@ -116,7 +118,7 @@ export const getLeetcodeQuestionByIdValidator = [validateIdParam];

export const updateLeetcodeQuestionValidator = [
validateIdParam,
validateUser.optional(),
validateUserId.optional(),
validateCompany.optional(),
validateTitle.optional(),
validateURL.optional(),
Expand Down
9 changes: 9 additions & 0 deletions backend/src/validators/savedApplicationValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ const validateCompany = body("company")
.withMessage("invalid company id. (Must be a Mongo ObjectID.)")
.trim();

const validateCompanyName = body("companyName")
.isString()
.withMessage("companyName must be a string.")
.trim()
.notEmpty()
.withMessage("companyName must be a non-empty string.");

const validateLocation = body("location")
.optional()
.isString()
Expand Down Expand Up @@ -81,6 +88,7 @@ const validatePerPage = query("perPage")
export const createSavedApplicationValidator = [
validateUserId,
validateCompany,
validateCompanyName,
validatePosition,
validateLocation,
validateLink,
Expand All @@ -93,6 +101,7 @@ export const getSavedApplicationValidator = [validateParamId];
export const updateSavedApplicationValidator = [
validateParamId,
validateCompany.optional(),
validateCompanyName.optional(),
validatePosition.optional(),
validateLink.optional(),
validateLocation.optional(),
Expand Down
Loading